listfiles.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2001 The Exult Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #ifndef ALPHA_LINUX_CXX
00024 #  include <cstdlib>
00025 #  include <cctype>
00026 #  include <cstdio>
00027 #endif
00028 
00029 #include <vector>
00030 #include <string>
00031 #include <iostream>
00032 
00033 #ifndef UNDER_CE
00034 using std::vector;
00035 using std::cout;
00036 using std::cerr;
00037 using std::endl;
00038 using std::free;
00039 using std::malloc;
00040 using std::string;
00041 using std::strcat;
00042 using std::strcpy;
00043 using std::strlen;
00044 #endif
00045 
00046 #include "utils.h"
00047 #include "listfiles.h"
00048 
00049 #if defined(MACOS) || defined(BEOS)
00050 
00051 /*
00052  *  Match a string with a given pattern (DOS like syntax, using * and ?)
00053  */
00054 
00055 static bool MatchString( const char *str, const std::string& inPat );
00056 static bool MatchString( const char *str, const std::string& inPat )
00057 {
00058   const char *pat = inPat.c_str();
00059 
00060   const char *p = NULL;
00061   const char *q = NULL;
00062   
00063   for(;;)
00064   {
00065     switch(*pat)
00066     {
00067     case '*':
00068       p = ++pat;
00069       q = str;
00070       break;
00071 
00072     default:
00073       if(*pat != *str)
00074       {
00075         if(p)
00076         {
00077           pat = p;
00078           str = ++q;
00079           if(!*str)
00080             return !*pat;
00081           break;
00082         }
00083         else
00084           return false;
00085       }
00086       // fallthrough
00087     case '?':
00088       if(!*str)
00089         return !*pat;
00090       pat++;
00091       str++;
00092     }
00093   }
00094 }
00095 
00096 #endif
00097 
00098 
00099 // System Specific Code for Windows
00100 #if defined(WIN32)
00101 
00102 // Need this for _findfirst, _findnext, _findclose
00103 #include <windows.h>
00104 #include <malloc.h>
00105 #include <tchar.h>
00106 
00107 int U7ListFiles(const std::string mask, FileList& files)
00108 {
00109   string      path(get_system_path(mask));
00110   const TCHAR   *lpszT;
00111   WIN32_FIND_DATA fileinfo;
00112   HANDLE      handle;
00113   char      *stripped_path;
00114   int       i, nLen, nLen2;
00115 
00116 #ifdef UNICODE
00117   const char *name = path.c_str();
00118   nLen = strlen(name)+1;
00119   LPTSTR lpszT2 = (LPTSTR) _alloca(nLen*2);
00120   lpszT = lpszT2;
00121   MultiByteToWideChar(CP_ACP, 0, name, -1, lpszT2, nLen);
00122 #else
00123   lpszT = path.c_str();
00124 #endif
00125 
00126   handle = FindFirstFile (lpszT, &fileinfo);
00127 
00128   stripped_path = new char [path.length()+1];
00129   strcpy (stripped_path, path.c_str());
00130 
00131   for (i = strlen (stripped_path)-1; i; i--)
00132     if (stripped_path[i] == '\\' || stripped_path[i] == '/')
00133       break;
00134 
00135   if (stripped_path[i] == '\\' || stripped_path[i] == '/')
00136     stripped_path[i+1] = 0;
00137 
00138 
00139 #ifdef DEBUG
00140   std::cerr << "U7ListFiles: " << mask << " = " << path << std::endl;
00141 #endif
00142 
00143   // Now search the files
00144   if (handle != INVALID_HANDLE_VALUE)
00145   {
00146     do
00147     {
00148       nLen = std::strlen(stripped_path);
00149       nLen2 = _tcslen (fileinfo.cFileName)+1;
00150       char *filename = new char [nLen+nLen2];
00151       strcpy (filename, stripped_path);
00152 #ifdef UNICODE
00153       WideCharToMultiByte(CP_ACP, 0, fileinfo.cFileName, -1, filename+nLen, nLen2, NULL, NULL);
00154 #else
00155       std::strcat (filename, fileinfo.cFileName);
00156 #endif
00157 
00158       files.push_back(filename);
00159 #ifdef DEBUG
00160       std::cerr << filename << std::endl;
00161 #endif
00162       delete [] filename;
00163     } while (FindNextFile( handle, &fileinfo ));
00164   }
00165 
00166   if (GetLastError() != ERROR_NO_MORE_FILES) {
00167     LPTSTR lpMsgBuf;
00168     char* str;
00169     FormatMessage( 
00170       FORMAT_MESSAGE_ALLOCATE_BUFFER | 
00171       FORMAT_MESSAGE_FROM_SYSTEM | 
00172       FORMAT_MESSAGE_IGNORE_INSERTS,
00173       NULL,
00174       GetLastError(),
00175       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
00176       (LPTSTR) &lpMsgBuf,
00177       0,
00178       NULL 
00179     );
00180 #ifdef UNICODE
00181     nLen2 = _tcslen (lpMsgBuf) + 1;
00182     str = (char*) _alloca(nLen);
00183     WideCharToMultiByte(CP_ACP, 0, lpMsgBuf, -1, str, nLen2, NULL, NULL);
00184 #else
00185     str = lpMsgBuf;
00186 #endif
00187     std::cerr << "Error while listing files: " << str << std::endl;
00188     LocalFree( lpMsgBuf );
00189   }
00190 
00191 #ifdef DEBUG
00192   std::cerr << files.size() << " filenames" << std::endl;
00193 #endif
00194 
00195   delete [] stripped_path;
00196   FindClose (handle);
00197   return 0;
00198 }
00199 
00200 #elif defined(MACOS)
00201 
00202 #include <Files.h>
00203 #include <TextUtils.h>
00204 
00205 
00206 OSErr GetCatInfoNoName(short vRefNum, long dirID, std::string name, CInfoPBPtr pb);
00207 OSErr GetCatInfoNoName(short vRefNum, long dirID, std::string name, CInfoPBPtr pb)
00208 {
00209   Str255 tempName;
00210   OSErr err;
00211   
00212   CopyCStringToPascal(name.c_str(), tempName);
00213 
00214   if (tempName[0] == 0)
00215     pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */
00216   else
00217     pb->dirInfo.ioFDirIndex = 0;  /* use ioNamePtr and ioDirID */
00218 
00219   pb->dirInfo.ioNamePtr = tempName;
00220   pb->dirInfo.ioVRefNum = vRefNum;
00221   pb->dirInfo.ioDrDirID = dirID;
00222   err = PBGetCatInfoSync(pb);
00223   pb->dirInfo.ioNamePtr = NULL;
00224   return err;
00225 }
00226 
00227 
00228 int U7ListFiles(const std::string pathMask, FileList& files)
00229 {
00230   CInfoPBRec    cPB;      // the parameter block used for PBGetCatInfo calls
00231   Str63     itemName;   // the name of the current item
00232   OSErr     err;      // temporary holder of results - saves 2 bytes of stack each level
00233   short     index = 0;
00234   short     vRefNum;
00235   long      dirID;
00236   char      filename[256];
00237   string      path(get_system_path(pathMask));
00238   string      mask;
00239   string::size_type pos;
00240   
00241   pos = path.rfind(':');
00242   if(pos == string::npos)
00243   {
00244     mask = path;
00245     path.clear();
00246   }
00247   else
00248   {
00249     mask = path.substr(pos+1);
00250     path = path.substr(0,pos);
00251   }
00252   
00253   err = HGetVol( NULL, &vRefNum, &dirID );
00254   if (err != noErr)
00255     return err;
00256 
00257   err = GetCatInfoNoName(vRefNum,dirID,path,&cPB);
00258   if (err != noErr)
00259     return err;
00260   dirID = cPB.dirInfo.ioDrDirID;
00261 
00262   itemName[0] = 0;
00263   cPB.hFileInfo.ioNamePtr = (StringPtr)&itemName;
00264 
00265   do
00266   {
00267     // Get next source item at the current directory level
00268     
00269     ++index;
00270     cPB.dirInfo.ioFDirIndex = index;
00271     cPB.dirInfo.ioDrDirID = dirID;
00272     err = PBGetCatInfoSync(&cPB);   
00273 
00274     if (err == noErr)
00275     {
00276       // Is it a file (i.e. not a directory)?
00277       if ( (cPB.hFileInfo.ioFlAttrib & kioFlAttribDirMask) == 0 )
00278       {
00279         CopyPascalStringToC(itemName, filename);
00280         if (MatchString(filename, mask))
00281         {
00282           cout << "File name: " << filename << endl;
00283           files.push_back(filename);
00284         }
00285       }
00286     }
00287 
00288   } while (err == noErr );
00289 
00290   if ( (err == fnfErr) || // fnfErr is OK - it only means we hit the end of this level
00291      (err == afpAccessDenied) ) // afpAccessDenied is OK, too - it only means we cannot see inside a directory
00292   {
00293     err = noErr;
00294   }
00295   
00296   return err;
00297 }
00298 
00299 #elif defined(BEOS)
00300 
00301 #include <be/storage/Directory.h>
00302 #include <be/storage/Entry.h>
00303 
00304 int U7ListFiles(const std::string pathMask, FileList& files)
00305 {
00306   char filename[255];
00307   string path(get_system_path(pathMask));
00308   string mask;
00309   string::size_type pos;
00310   
00311   pos = path.rfind('/');
00312   if(pos == string::npos)
00313   {
00314     mask = path;
00315     path = "";
00316   }
00317   else
00318   {
00319     mask = path.substr(pos+1);
00320     path = path.substr(0,pos);
00321   }
00322 
00323   BDirectory dir(path.c_str());
00324 
00325   if (dir.InitCheck() != B_OK)
00326     return -1;
00327 
00328   do {
00329     BEntry entry;
00330     if (dir.GetNextEntry(&entry, true) == B_ENTRY_NOT_FOUND)
00331       break; // done
00332       
00333     // is it a regular file? (symlinks have already been traversed)
00334     if (!entry.IsFile())
00335       continue;
00336 
00337     entry.GetName(filename);
00338     if (MatchString(filename, mask)) {
00339       cout << "Filename: " << filename << endl;
00340       files.push_back(filename);        
00341     }
00342   } while (true);
00343   
00344   return 0;
00345 }
00346 
00347 #elif defined(__MORPHOS__) || defined(AMIGA)
00348 
00349 #define NO_PPCINLINE_VARARGS
00350 #define NO_PPCINLINE_STDARG
00351 #include <proto/dos.h>
00352 
00353 static struct AnchorPath ap __attribute__((aligned(4)));
00354 
00355 int U7ListFiles(const std::string mask, FileList& files)
00356 {
00357   string path(get_system_path(mask));
00358   char   buffer[ 256 ];
00359   size_t pos;
00360 
00361   // convert MS-DOS jokers to AmigaDOS wildcards
00362   while( (pos = path.find( '*' )) != string::npos )
00363     path.replace( pos, 1, "#?" );
00364 
00365   if( ParsePattern( path.c_str(), buffer, sizeof( buffer ) ) != -1 )
00366   {
00367     LONG error = MatchFirst( buffer, &ap );
00368 
00369     while( error == DOSFALSE )
00370     {
00371       char *filename = (char *)malloc( strlen( ap.ap_Info.fib_FileName )+1 );
00372       strcpy( filename, ap.ap_Info.fib_FileName );
00373       files.push_back( filename );
00374       error = MatchNext( &ap );
00375     }
00376 
00377     MatchEnd( &ap );
00378   }
00379   else
00380     cout << "ParsePattern() failed." << endl;
00381 
00382   return 0;
00383 }
00384 
00385 
00386 #else // This system has glob.h
00387 
00388 #include <glob.h>
00389 
00390 int U7ListFiles(const std::string mask, FileList& files)
00391 
00392 {
00393         glob_t globres;
00394     string path(get_system_path(mask));
00395         int err = glob(path.c_str(), GLOB_NOSORT, 0, &globres);
00396 
00397 
00398         switch (err) {
00399         case 0:   //OK
00400         for (int i=0; i<globres.gl_pathc; i++)
00401         {
00402           files.push_back(globres.gl_pathv[i]);
00403         }
00404         globfree(&globres);
00405                 return 0;               
00406         case 3:   //no matches
00407                 return 0;
00408         default:  //error
00409                 cerr << "Glob error " << err << endl;
00410                 return err;
00411         }
00412 }
00413 
00414 #endif

Generated on Mon Jul 9 14:42:45 2007 for ExultEngine by  doxygen 1.5.1