123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- /*
- These functions are based on Jim Luther's IterateDirectory() found in MoreFiles
- However, it's heavily modified by Dirk Haase
- */
- /*
- ** IterateDirectory: File Manager directory iterator routines.
- **
- ** by Jim Luther
- **
- ** File: IterateDirectory.c
- **
- ** Copyright (c) 1995-1998 Jim Luther and Apple Computer, Inc.
- ** All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours.
- **
- ** IterateDirectory is designed to drop into the MoreFiles sample code
- ** library I wrote while in Apple Developer Technical Support
- */
- /*****************************************************************************/
- /* Includes */
- /*****************************************************************************/
- #include <Types.h>
- #include <Errors.h>
- #include <Files.h>
- #include <stdio.h>
- #include <string.h>
- #include "zip.h"
- #include "macstuff.h"
- #include "helpers.h"
- #include "recurse.h"
- #include "macglob.h"
- #include "pathname.h"
- /*****************************************************************************/
- /* Macros, typedefs */
- /*****************************************************************************/
- /* The RecurseGlobals structure is used to minimize the amount of
- ** stack space used when recursively calling RecurseDirectoryLevel
- ** and to hold global information that might be needed at any time.
- */
- struct RecurseGlobals
- {
- short vRefNum;
- CInfoPBRec cPB; /* the parameter block used for
- PBGetCatInfo calls */
- unsigned char *itemName; /* the name of the current item */
- char *FullPath;
- short FullPathLen;
- OSErr result; /* temporary holder of results -
- saves 2 bytes of stack each level */
- Boolean quitFlag; /* set to true if filter wants to
- kill interation */
- unsigned short maxLevels; /* Maximum levels to
- iterate through */
- unsigned short currentLevel; /* The current level
- IterateLevel is on */
- };
- typedef struct RecurseGlobals RecurseGlobals;
- typedef RecurseGlobals *RecurseGlobalsPtr;
- /*****************************************************************************/
- /* Global Vars */
- /*****************************************************************************/
- extern MacZipGlobals MacZip;
- extern const char ResourceMark[13]; /* "XtraStuf.mac:" var is initialized in file pathname.c */
- extern int extra_fields; /* do not create extra fields if false */
- static RecurseGlobals theGlobals;
- static unsigned long DirLevels = 0;
- static char *buffer;
- extern int verbose; /* 1=report oddities in zip file structure */
- /*****************************************************************************/
- /* Prototypes */
- /*****************************************************************************/
- int procname(char *filename, int caseflag);
- int MatchWild( char *pPat, char *pStr, int case_sens);
- Boolean IsZipFile(char *name);
- static void RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals);
- static Boolean isRegularItem( RecurseGlobals *Globals);
- static void ProcessFiles(RecurseGlobals *Globals,
- Boolean hasDataFork, Boolean hasResourceFork);
- static void ProcessDirectory(RecurseGlobals *Globals,
- Boolean IncludeItem, long DirID);
- static void ProcessItem(RecurseGlobals *Globals, long DirID);
- /*****************************************************************************/
- /* Functions */
- /*****************************************************************************/
- static void RecurseDirectoryLevel(long DirID, RecurseGlobals *Globals)
- {
- char buffer2[23];
- /* if maxLevels is zero, we aren't checking levels */
- if ( (Globals->maxLevels == 0) ||
- /* if currentLevel < maxLevels, look at this level */
- (Globals->currentLevel < Globals->maxLevels) )
- {
- short index = 1;
- ++Globals->currentLevel; /* go to next level */
- if (DirLevels < Globals->currentLevel) DirLevels = Globals->currentLevel;
- sprintf(buffer2,"Globals->currentLevel: %d",Globals->currentLevel);
- do
- { /* Isn't C great... What I'd give for a "WITH
- theGlobals DO" about now... */
- /* Get next source item at the current directory level */
- Globals->cPB.dirInfo.ioFDirIndex = index;
- Globals->cPB.dirInfo.ioDrDirID = DirID;
- Globals->result = PBGetCatInfoSync((CInfoPBPtr)&Globals->cPB);
- ShowCounter(false);
- if ( Globals->result == noErr )
- {
- ProcessItem(Globals, DirID);
- } /* if ( Globals->result == noErr ) */
- ++index; /* prepare to get next item */
- /* time to fall back a level? */
- } while ( (Globals->result == noErr) && (!Globals->quitFlag) );
- if ( (Globals->result == fnfErr) || /* fnfErr is OK -
- it only means we hit
- the end of this level */
- (Globals->result == afpAccessDenied) ) /* afpAccessDenied is OK,
- too - it only means we cannot see inside a directory */
- {
- Globals->result = noErr;
- }
- --Globals->currentLevel; /* return to previous level as we leave */
- }
- }
- /*****************************************************************************/
- pascal OSErr RecurseDirectory(short vRefNum,
- long thedirID,
- ConstStr255Param name,
- unsigned short maxLevels)
- {
- OSErr result;
- short theVRefNum;
- Boolean isDirectory;
- long DirID;
- /* Get the real directory ID and make sure it is a directory */
- result = GetDirectoryID(vRefNum, thedirID, name, &DirID, &isDirectory);
- if ( result == noErr )
- {
- if ( isDirectory == true )
- {
- /* Get the real vRefNum */
- result = DetermineVRefNum(name, vRefNum, &theVRefNum);
- if ( result == noErr )
- {
- /* Set up the globals we need to access from
- the recursive routine. */
- theGlobals.cPB.hFileInfo.ioNamePtr = theGlobals.itemName;
- theGlobals.cPB.hFileInfo.ioVRefNum = theVRefNum;
- theGlobals.itemName[0] = 0;
- theGlobals.result = noErr;
- theGlobals.quitFlag = false;
- theGlobals.maxLevels = maxLevels;
- theGlobals.currentLevel = 0; /* start at level 0 */
- /* Here we go into recursion land... */
- RecurseDirectoryLevel(DirID, &theGlobals);
- result = theGlobals.result; /* set the result */
- }
- }
- else
- {
- result = dirNFErr; /* a file was passed instead
- of a directory */
- }
- }
- return ( result );
- }
- /*****************************************************************************/
- pascal OSErr FSpRecurseDirectory(const FSSpec *spec,
- unsigned short maxLevels)
- {
- OSErr rc;
- theGlobals.vRefNum = spec->vRefNum;
- /* make room for pathnames */
- theGlobals.itemName = (unsigned char *) StrCalloc(NAME_MAX);
- theGlobals.FullPath = StrCalloc(NAME_MAX);
- buffer = StrCalloc(NAME_MAX);
- if ((noisy) && (MacZip.DataForkOnly))
- printf("\n Warning: Datafork only \n");
- /* reset the count to zero */
- ShowCounter(true);
- if (noisy) leftStatusString("Build File List; Items done:");
- if (noisy) printf("\n Collecting Filenames ...");
- rc = RecurseDirectory(spec->vRefNum, spec->parID, spec->name,maxLevels);
- printerr("RecurseDirectory:",rc,rc,__LINE__,__FILE__,"");
- if (noisy) printf("\n... done \n\n %6d matched files found \n",
- MacZip.FoundFiles);
- if (noisy) printf(" %6d folders found in %d Levels \n",
- MacZip.FoundDirectories,DirLevels);
- if (MacZip.BytesOfData > (1024*1024))
- if (noisy) printf(" %4.3f MBytes unzipped size\n\n",
- (float) MacZip.BytesOfData/(1024*1024));
- else
- if (noisy) printf(" %4.3f KBytes unzipped size\n\n",
- (float) MacZip.BytesOfData/1024);
- /* free all memory of pathnames */
- theGlobals.itemName = (unsigned char *) StrFree((char *)theGlobals.itemName);
- theGlobals.FullPath = StrFree(theGlobals.FullPath);
- buffer = StrFree(buffer);
- return rc;
- }
- /*
- * Return true if filename == zipfile
- * After the first match no further check will be done !
- *
- */
- Boolean IsZipFile(char *filen)
- {
- static firstMatch = false;
- if (filen == NULL)
- firstMatch = false;
- if (!firstMatch)
- {
- if (stricmp(filen, MacZip.ZipFullPath) == 0)
- {
- firstMatch = true;
- return true;
- }
- }
- return false;
- }
- static Boolean isRegularItem( RecurseGlobals *Globals)
- {
- Boolean isInvisible = false,
- isAlias = false,
- isSystem = false;
- isSystem = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
- (1 << 12)) == 0 );
- isInvisible = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
- (1 << 14)) == 0 );
- isAlias = !((Globals->cPB.hFileInfo.ioFlFndrInfo.fdFlags &
- (1 << 15)) == 0);
- if (isAlias == true)
- {
- return false;
- }
- if (MacZip.IncludeInvisible == true)
- {
- return true;
- }
- if ((isSystem == true) ||
- (isInvisible == true))
- {
- return false;
- }
- return true;
- }
- static void ProcessFiles(RecurseGlobals *Globals,
- Boolean hasDataFork, Boolean hasResourceFork)
- {
- /* some file statistics */
- MacZip.FoundFiles++;
- if (hasDataFork == true)
- {
- MacZip.BytesOfData =
- Globals->cPB.hFileInfo.ioFlLgLen +
- MacZip.BytesOfData;
- MacZip.CurrentFork = DataFork;
- MacZip.RawCountOfItems++;
- if (MacZip.DataForkOnly == true)
- {
- procname(Globals->FullPath, false);
- hasResourceFork = false;
- }
- else
- {
- procname(Real2RfDfFilen(buffer,Globals->FullPath,
- DataFork, MacZip.MacZipMode,
- MacZip.DataForkOnly), false);
- }
- }
- if (hasResourceFork == true)
- {
- MacZip.BytesOfData =
- Globals->cPB.hFileInfo.ioFlRLgLen +
- MacZip.BytesOfData;
- MacZip.CurrentFork = ResourceFork;
- MacZip.RawCountOfItems++;
- procname(Real2RfDfFilen(buffer, Globals->FullPath,
- ResourceFork, MacZip.MacZipMode,
- MacZip.DataForkOnly), false);
- }
- }
- static void ProcessDirectory(RecurseGlobals *Globals,
- Boolean IncludeItem, long DirID)
- {
- OSErr rc;
- MacZip.isDirectory = true;
- GetFullPathFromID(Globals->FullPath,Globals->vRefNum, DirID,
- Globals->itemName, &rc);
- MacZip.RawCountOfItems++;
- MacZip.FoundDirectories++;
- if (MacZip.StoreFoldersAlso)
- {
- procname(Globals->FullPath, false);
- }
- /* We have a directory */
- if ( !Globals->quitFlag && IncludeItem)
- {
- /* Dive again if the IterateFilterProc didn't say "quit" and dir is
- not an alias */
- RecurseDirectoryLevel(Globals->cPB.dirInfo.ioDrDirID,
- Globals);
- }
- }
- static void ProcessItem(RecurseGlobals *Globals, long DirID)
- {
- OSErr rc;
- Boolean IncludeItem = false, hasDataFork = false;
- Boolean hasResourceFork = false;
- IncludeItem = isRegularItem(Globals);
- /* Is it a File? */
- if ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) == 0 )
- {
- PToCCpy(Globals->itemName,MacZip.FileName);
- MacZip.isDirectory = false;
- hasDataFork = (Globals->cPB.hFileInfo.ioFlLgLen != 0);
- hasResourceFork = (Globals->cPB.hFileInfo.ioFlRLgLen != 0);
- /* include also files with zero recource- and data-fork */
- if ((hasDataFork == 0) && (hasResourceFork == 0))
- hasDataFork = true;
- if ((hasDataFork == 0) &&
- (hasResourceFork != 0) &&
- (extra_fields == false))
- {
- IncludeItem = false;
- }
- GetFullPathFromID(Globals->FullPath,Globals->vRefNum,
- DirID, Globals->itemName, &rc);
- printerr("GetFullPathFromID:",rc,rc,__LINE__,
- __FILE__,MacZip.FileName);
- if (IncludeItem && /* don't include the zipfile itself */
- (!IsZipFile(Globals->FullPath)) )
- {
- if (MATCH(MacZip.Pattern, MacZip.FileName, false) == true)
- {
- ProcessFiles(Globals, hasDataFork, hasResourceFork);
- } /* if (MatchWild( MacZip.FileName,MacZip.Pattern ) ==
- true) */
- } /* if (!IsZipFile(Globals->FullPath)) */
- } /* Is it a File? */
- /* Is it a directory? */
- if ( (Globals->cPB.hFileInfo.ioFlAttrib & ioDirMask) != 0 )
- {
- ProcessDirectory(Globals,IncludeItem, DirID);
- } /* Is it a directory? */
- }
|