📄 recurse.c
字号:
/*These functions are based on Jim Luther's IterateDirectory() found in MoreFilesHowever, 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? */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -