Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

filemanager.cpp

00001 /*
00002     Copyright (C) 2001, 2002 Stephane Magnenat, Luc-Olivier de Charrière and
00003       Julien Pilet
00004     for any question or comment contact us at nct@ysagoon.com or nuage@ysagoon.com
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 */
00020 /* \file
00021  * \brief File system abstraction
00022  *
00023  * When openging a file, look for it in a pool of directories.
00024  */
00025 
00026 #include "filemanager.h"
00027 #include <assert.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 
00032 FileManager *fileManagerPtr=0;
00033 
00034 // here we handle compile time options
00035 #ifdef HAVE_CONFIG_H
00036 #  include <config.h>
00037 #else
00038 #       ifdef WIN32
00039 #               define PACKAGE_DATA_DIR ".."
00040 #               define PACKAGE_SOURCE_DIR "../.."
00041 #       else
00042 #               define PACKAGE_DATA_DIR ".."
00043 #               define PACKAGE_SOURCE_DIR SRC_PATH
00044 #       endif
00045 #endif
00046 
00047 // include for directory listing
00048 #ifdef WIN32
00049 #       include <windows.h>
00050 #       include <io.h>
00051 #else
00052 #       include <sys/types.h>
00053 #ifdef WITH_DIRECTORY_LISTING
00054 #       include <dirent.h>
00055 #endif
00056 #       include <sys/stat.h>
00057 #endif
00058 
00059 FileManager::FileManager()
00060 {
00061     addDir(".");
00062     addDir(PACKAGE_DATA_DIR);
00063     addDir(PACKAGE_SOURCE_DIR);
00064 #ifdef WITH_DIRECTORY_LISTING
00065         fileListIndex=-1;
00066 #endif
00067         dirListIndexCache=-1;
00068         /*totTest=0;
00069         cMiss=0;
00070         cHit=0;*/
00071 }
00072 
00073 FileManager::~FileManager()
00074 {
00075         clearDirList();
00076 #ifdef WITH_DIRECTORY_LISTING
00077         clearFileList();
00078 #endif
00079 }
00080 
00081 void FileManager::clearDirList(void)
00082 {
00083         for (std::vector<const char *>::iterator dirListIterator=dirList.begin(); dirListIterator!=dirList.end(); ++dirListIterator)
00084         {
00085                 delete[] const_cast<char*>(*dirListIterator);
00086         }
00087         dirList.clear();
00088 }
00089 
00090 #ifdef WITH_DIRECTORY_LISTING
00091 void FileManager::clearFileList(void)
00092 {
00093         for (std::vector<const char *>::iterator fileListIterator=fileList.begin(); fileListIterator!=fileList.end(); ++fileListIterator)
00094         {
00095                 delete[] const_cast<char*>(*fileListIterator);
00096         }
00097         fileList.clear();
00098         fileListIndex=-1;
00099 }
00100 #endif
00101 
00102 void FileManager::addDir(const char *dir)
00103 {
00104         int len=strlen(dir);
00105         char *newDir=new char[len+1];
00106         strncpy(newDir, dir, len+1);
00107         dirList.push_back(newDir);
00108         dirListIndexCache=0;
00109 }
00110 
00111 FILE *FileManager::openWithbackupFP(const char *filename, const char *mode)
00112 {
00113         if (strchr(mode, 'w'))
00114         {
00115                 char backupText[512];
00116                 snprintf(backupText, sizeof(backupText), "%s~", filename);
00117                 rename(filename, backupText);
00118         }
00119         return fopen(filename, mode);
00120 }
00121 
00122 FILE *FileManager::openFP(const char *filename, const char *mode, bool verboseIfNotFound)
00123 {
00124         std::vector<const char *>::iterator dirListIterator;
00125 
00126         if (filename && (filename[0] == '/'))
00127                 return fopen(filename, mode);
00128 
00129         // try cache
00130         if ((strchr(mode, 'w')==NULL) && (dirListIndexCache>=0))
00131         {
00132                 int allocatedLength=strlen(filename) + strlen(dirList[dirListIndexCache]) + 2;
00133                 char *fn = new char[allocatedLength];
00134                 snprintf(fn, allocatedLength, "%s%c%s", dirList[dirListIndexCache], DIR_SEPARATOR ,filename);
00135                 FILE *fp =  openWithbackupFP(fn, mode);
00136                 delete[] fn;
00137                 if (fp)
00138                         return fp;
00139         }
00140 
00141         // otherwise search
00142         int index=0;
00143         for (dirListIterator=dirList.begin(); dirListIterator!=dirList.end(); ++dirListIterator)
00144         {
00145                 int allocatedLength=strlen(filename) + strlen(dirList[index]) + 2;
00146                 char *fn = new char[allocatedLength];
00147                 snprintf(fn, allocatedLength, "%s%c%s", *dirListIterator, DIR_SEPARATOR ,filename);
00148 
00149                 FILE *fp =  openWithbackupFP(fn, mode);
00150                 //totTest++;
00151                 delete[] fn;
00152                 if (fp)
00153                 {
00154                         dirListIndexCache=index;
00155                         return fp;
00156                 }
00157                 index++;
00158         }
00159 
00160         if (verboseIfNotFound)
00161         {
00162                 fprintf(stderr, "FILE %s not found in mode %s.\n", filename, mode);
00163                 fprintf(stderr, "Searched path :\n");
00164                 for (dirListIterator=dirList.begin(); dirListIterator!=dirList.end(); ++dirListIterator)
00165                 {
00166                         printf("%s\n", *dirListIterator);
00167                 }
00168         }
00169 
00170         return NULL;
00171 }
00172 
00173 void FileManager::remove(const char *filename)
00174 {
00175         std::vector<const char *>::iterator dirListIterator;
00176 
00177         // other wise search
00178         for (dirListIterator=dirList.begin(); dirListIterator!=dirList.end(); ++dirListIterator)
00179         {
00180                 int allocatedLength=strlen(filename) + strlen(*dirListIterator) + 2;
00181                 char *fn = new char[allocatedLength];
00182                 snprintf(fn, allocatedLength, "%s%c%s", *dirListIterator, DIR_SEPARATOR ,filename);
00183                 remove(fn);
00184         }
00185 }
00186 
00187 #ifdef WITH_DIRECTORY_LISTING
00188 bool FileManager::addListingForDir(const char *realDir, const char *extension)
00189 {
00190 #ifdef WIN32 
00191         WIN32_FIND_DATA wfd;
00192         HANDLE hFind = NULL;
00193         BOOL b = TRUE;
00194         // temp for the paths
00195         char temp[MAX_PATH];
00196         char real[MAX_PATH];
00197         memset(real, 0, MAX_PATH);
00198 
00199         if (!realDir)
00200                 return false;
00201 
00202         if (!strncmp(realDir, "../", 3))
00203                 return true;
00204 
00205         if (!strcmp(realDir, "./.") || !strcmp(realDir, "./"))
00206                 memcpy(real, ".", 1);
00207         else
00208                 memcpy(real, realDir, strlen(realDir) + 1);
00209 
00210         // search for the subdirectories
00211         memset(temp, 0, MAX_PATH);
00212         sprintf(temp, "%s%c*", real, DIR_SEPARATOR);
00213         hFind = FindFirstFile(temp, &wfd);
00214         while (b) {
00215                 if (!strncmp(wfd.cFileName, "..", 2))
00216                 {
00217                         b = FindNextFile(hFind, &wfd);
00218                         continue;
00219                 }
00220                 if (!strncmp(wfd.cFileName, ".", 1))
00221                 {
00222                         b = FindNextFile(hFind, &wfd);
00223                         continue;
00224                 }
00225                 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00226                 {
00227                         memset(temp, 0, MAX_PATH);
00228                         sprintf(temp, "%s%c%s", real, DIR_SEPARATOR, wfd.cFileName);
00229                         addListingForDir(temp, extension);
00230                 }
00231                 b = FindNextFile(hFind, &wfd);
00232         }
00233 
00234         b = TRUE;
00235         // search for the files...
00236         memset(temp, 0, MAX_PATH);
00237         if (extension)
00238                 sprintf(temp, "%s%c*.%s", real,DIR_SEPARATOR, extension);
00239         else
00240                 sprintf(temp, "%s%c*", real, DIR_SEPARATOR);
00241         hFind = FindFirstFile(temp, &wfd);
00242         if (hFind == INVALID_HANDLE_VALUE) return true;
00243         while (b) {
00244                 if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
00245                 {
00246                         // test if name already exists in vector
00247                         bool alreadyIn=false;
00248                         for (std::vector<const char *>::iterator fileListIterator=fileList.begin(); (fileListIterator!=fileList.end())&&(alreadyIn==false); ++fileListIterator)
00249                         {
00250                                 memset(temp, 0, MAX_PATH);
00251                                 sprintf(temp, "%s%c%s", real, DIR_SEPARATOR, wfd.cFileName);
00252                                 if (strcmp(temp, *fileListIterator)==0)
00253                                         alreadyIn=true;
00254                         }
00255                         if (!alreadyIn)
00256                         {
00257                                 int len=strlen(wfd.cFileName) + strlen(real) + 2;
00258                                 char *fileName=new char[len];
00259                                 memset(fileName, 0, len);
00260                                 sprintf(fileName, "%s%c%s", real, DIR_SEPARATOR, wfd.cFileName);
00261                                 fileList.push_back(fileName);
00262                         }
00263                 }
00264                 b = FindNextFile(hFind, &wfd);
00265         }
00266         
00267 #else // angel > plus Win32 (system primate)
00268         DIR *dir=opendir(realDir);
00269         struct dirent *dirEntry;
00270 
00271         if (!dir)
00272         {
00273 #ifdef DBG_VPATH_LIST
00274                 fprintf(stderr, "Open dir failed for dir %s\n", realDir);
00275 #endif
00276                 return false;
00277         }
00278 
00279         while ((dirEntry=readdir(dir))!=NULL)
00280         {
00281 #ifdef DBG_VPATH_LIST
00282                 fprintf(stderr, "%s\n", dirEntry->d_name);
00283 #endif
00284                 int l, nl;
00285                 l=strlen(extension);
00286                 nl=strlen(dirEntry->d_name);
00287                 if ((nl>l) &&
00288                         (dirEntry->d_name[nl-l-1]=='.') &&
00289                         (strcmp(extension,dirEntry->d_name+(nl-l))==0))
00290                 {
00291                         // test if name already exists in vector
00292                         bool alreadyIn=false;
00293                         for (std::vector<const char *>::iterator fileListIterator=fileList.begin(); (fileListIterator!=fileList.end())&&(alreadyIn==false); ++fileListIterator)
00294                         {
00295                                 if (strcmp(dirEntry->d_name, *fileListIterator)==0)
00296                                         alreadyIn=true;
00297                         }
00298                         if (!alreadyIn)
00299                         {
00300                                 int len=strlen(dirEntry->d_name)+1;
00301                                 char *fileName=new char[len];
00302                                 strncpy(fileName, dirEntry->d_name, len);
00303                                 fileList.push_back(fileName);
00304                         }
00305                 }
00306         }
00307 
00308         closedir(dir);
00309 #endif // angel > end of comentaire primate
00310         return true;
00311 }
00312 
00313 bool FileManager::initDirectoryListing(const char *virtualDir, const char *extension)
00314 {
00315         bool result=false;
00316         clearFileList();
00317         for (std::vector<const char *>::iterator dirListIterator=dirList.begin(); dirListIterator!=dirList.end(); ++dirListIterator)
00318         {
00319                 int allocatedLength=strlen(virtualDir) + strlen(*dirListIterator) + 2;
00320                 char *dn = new char[allocatedLength];
00321                 snprintf(dn, allocatedLength,  "%s%c%s", *dirListIterator, DIR_SEPARATOR ,virtualDir);
00322 #ifdef DBG_VPATH_LIST
00323                 fprintf(stderr, "Listing from dir %s :\n", dn);
00324 #endif
00325                 result=addListingForDir(dn, extension) || result;
00326                 delete[] dn;
00327         }
00328         if (result)
00329                 fileListIndex=0;
00330         else
00331                 fileListIndex=-1;
00332         return result;
00333 }
00334 
00335 const char *FileManager::getNextDirectoryEntry(void)
00336 {
00337         if ((fileListIndex>=0) && (fileListIndex<(signed)fileList.size()))
00338         {
00339                 return fileList[fileListIndex++];
00340         }
00341         return NULL;
00342 }
00343 #endif
00344 

Generated on Fri May 16 13:01:45 2003 for Jelie by doxygen1.2.15