ListFiles.h

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

Generated on Fri Jul 27 22:27:22 2007 for pentagram by  doxygen 1.4.7