home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-03-03 | 45.5 KB | 1,005 lines |
- /* > c.GetDirs - (c) Paul Witheridge - Version 2.04 - 03 Mar 1993 */
-
- /*===================================================================*/
- /* */
- /* Getdirentrys */
- /* ------------ */
- /* */
- /* Getdirentrys is a function which reads entries from a directory */
- /* and then invokes a caller-supplied function to process each */
- /* file-object, passing the directory entry details in a 'direntry' */
- /* structure defined in 'getdirs.h'. */
- /* */
- /* The caller supplies the name of the directory to be read (plus */
- /* optionally, a wildcarded or non-wildcarded object name to be */
- /* matched against objects in the directory), an indicator as to */
- /* whether any subdirectories found should be read (recursively) */
- /* and a pointer to the caller's function to process the entries. */
- /* */
- /* The global integer variable "getdirentrys_counter" counts the */
- /* the number of objects passed to the caller's function. */
- /* */
- /* The caller's function should return a value of 'TRUE' if it has */
- /* not encountered any fatal errors, or 'FALSE' if it wants to */
- /* stop processing of any further directory entries. */
- /* */
- /*-------------------------------------------------------------------*/
- /* */
- /* This file includes the following functions: */
- /* */
- /* getdirentrys - read and process directory entries */
- /* buildtree - internal (static) recursive function */
- /* processtree - internal (static) recursive function */
- /* extendpath - internal (static) function */
- /* freetree - internal (static) recursive function */
- /* */
- /*-------------------------------------------------------------------*/
- /* */
- /* COPYRIGHT NOTICE */
- /* */
- /* GetDirs is subject to Copyright. */
- /* */
- /* Permission is granted by the author to any recipient of this */
- /* material to use and make/disseminate copies of the application */
- /* provided that no charges are made for doing so (other than to */
- /* cover any cost of media or postage) and that this notice is */
- /* included with all copies. */
- /* */
- /*===================================================================*/
-
- #include "kernel.h" /* ARC specifics */
- #include <ctype.h> /* Character handling */
- #include <limits.h> /* Implementation limits */
- #include <stddef.h> /* Standard defintions */
- #include <stdio.h> /* Input/output */
- #include <stdlib.h> /* General utilities */
- #include <string.h> /* String handling */
-
- #include "beep.h" /* Beep header */
- #include "getdirs.h" /* GetDirs header */
- #include "useful.h" /* Useful defns */
-
- /*-------------------------------------------------------------------*/
- /* Global data declarations and definitions. */
- /*-------------------------------------------------------------------*/
-
- #define maxpathlen 255 /* Max path length */
- #define maxobjectlen 20 /* Max object length */
- #define maxdirlistlen 850 /* Max directory list length */
-
- struct dirblock /* Directory list structure */
- {
- struct dirblock *subdirq ; /* Ptr to subdirectory tree */
- struct dirblock *nextptr ; /* Ptr to next list */
- struct dirblock *contptr ; /* Ptr to continuation list */
- int nobjects ; /* No. of objects in this list */
- int handle ; /* Handle (id) for this list */
- char dirlist[maxdirlistlen] ; /* List of nul-term'd objects */
- } ;
-
- int getdirentrys_counter ; /* Count of files processed */
-
- static enum boolean (*funcptr)( /* Ptr to function */
- const char *path,
- direntry *ptr) ;
-
- static const char toolong[] = /* Common error message */
- "'%s' too long" ;
-
- static const char outofmemory[] = /* Common error message */
- "out of memory" ;
-
- static const char invalidentry[] = /* Common error message */
- "Invalid directory entry '%s'\n" ;
-
- /*-------------------------------------------------------------------*/
- /* Declare functions local in scope to this file. */
- /*-------------------------------------------------------------------*/
-
- static enum boolean buildtree( /* Build directory list tree */
- char *path,
- const char *object,
- const enum recursive recursion,
- const int handle,
- struct dirblock **subdirq) ;
-
- static enum boolean processtree( /* Process directory list tree */
- char *path,
- struct dirblock *dirblkptr) ;
-
- static enum boolean extendpath( /* Add leafname to path */
- char *path,
- int pathlen,
- const char *leafname) ;
-
- static void freetree( /* Free directory list tree */
- struct dirblock **subdirq) ;
-
- /*===================================================================*/
- /* */
- /* getdirentrys - read directory entries */
- /* ------------ */
- /* */
- /* This function is called to read entries from a caller-specified */
- /* directory and pass details of any entries for file objects to a */
- /* caller-supplied function. It is intended for use with a non */
- /* multitasking utility, since it may write error messages to the */
- /* standard output stream. */
- /* */
- /* The caller provides three arguments: */
- /* */
- /* (1) Directory name and optional object name. This may be a fully */
- /* qualified name (e.g. 'adfs::IDEDisc4.$.Clib.h') or it may be */
- /* relative to the currently selected directory (e.g. just 'h' */
- /* if the CSD is 'adfs::IDEDisc4.$.Clib' or '^.h' if the CSD is */
- /* 'adfs::IDEDisc4.$.Clib.o'). It may end with a wild-carded or */
- /* non-wildcarded object name which will be used to select */
- /* objects from the director (e.g. 'h.a*' meaning all file */
- /* objects beginning with 'a' in directory 'h' which is a sub- */
- /* directory of the CSD). */
- /* */
- /* (2) A switch indicating whether any subdirectories found in the */
- /* specified directory are to be processed or not. This can take */
- /* one of three values 'RECURSE_NEVER', 'RECURSE_ONCE' or */
- /* 'RECURSE_ALWAYS'. These are defined in 'getdirs.h'. They have */
- /* the following effect: */
- /* */
- /* RECURSE_NEVER implies that the caller knows that the first */
- /* argument is in the form 'directory.object', and that object */
- /* is a (possibly wildcarded) file leafname. Only file objects */
- /* in 'directory' are to be processed; any subdirectories are */
- /* to be ignored. So if 'object' turned out to be a directory */
- /* name it would be ignored. This value would only be used under */
- /* special circumstances. */
- /* */
- /* RECURSE_ONCE implies that the caller is unsure whether the */
- /* first argument is in the form 'directory.object' or just */
- /* 'directory'. If it turns out to be a directory, then all the */
- /* file objects in that directory are to be processed, but any */
- /* subdirectories are to be ignored. This would be the normal */
- /* value to use if subdirectories were not to be processed. */
- /* */
- /* RECURSE_ALWAYS implies full recursion. All files matching */
- /* 'object' found in directory will be processed. All sub- */
- /* directories matching 'object' will be read; all files in them */
- /* will be processed and all subdirectories found will be read */
- /* recursively. */
- /* */
- /* (3) A pointer to a function which will process the file-objects. */
- /* It will be called once for each file-object found in the */
- /* specified directory (and all subdirectories if argument 2 */
- /* specifies recursive processing of subdirectories). It is */
- /* passed the name of the directory and a pointer to the details */
- /* from the directory in a 'direntry' structure. These details */
- /* include the object-name, its load and exec addresses (which */
- /* may be in the form of file-type and time-stamp), its length, */
- /* and its attributes. The file-type is extracted from the load */
- /* address and supplied separately (or as 0xFFFFFFFF if the file */
- /* has no file-type and time-stamp). This function should return */
- /* a value of 'FALSE' to halt further processing, or 'TRUE' to */
- /* continue processing of the directory entries. */
- /* */
- /* Getdirentrys returns a value of TRUE if it encountered no errors */
- /* in reading the directory entries and if the caller-supplied */
- /* function always returns 'TRUE'. Getdirentrys returns a value of */
- /* 'FALSE' if it encountered any errors reading the directory, or if */
- /* the caller-supplied function returned a value of FALSE. The */
- /* values 'TRUE' and 'FALSE' are defined in 'useful.h'. */
- /* */
- /* Two passes are made through the directory (and subdirectories if */
- /* recursive processing required). The first pass is performed by */
- /* calling the internal function 'buildtree' which creates a tree */
- /* of 'dirlist' structures listing the current contents of the */
- /* directories. The second pass is performed by calling the internal */
- /* function 'processtree' which checks that each file-object in the */
- /* tree structure is still present, and if so invokes the caller- */
- /* supplied function. */
- /* */
- /* The two passes are made in this way so that the caller-supplied */
- /* function is only invoked for objects that already exist, and not */
- /* for any objects that the caller-supplied function may create. */
- /* Otherwise, potentially infinite loops could occur - not really */
- /* infinite because they would stop when directory of disk full */
- /* conditions occurred. */
- /* */
- /* The internal function 'freetree' is used to free up the memory */
- /* allocated to the tree structure. */
- /* */
- /* The counter 'getdirentrys_counter' is used to count the number of */
- /* times the caller-supplied function is invoked. This count is */
- /* available (as an external variable) to the original caller of */
- /* 'getdirentrys' when thus returns. */
- /* */
- /*===================================================================*/
-
- enum boolean getdirentrys(
- const char *fname, /* Ptr to initial name */
- const enum recursive recursion, /* Recursion switch */
- enum boolean (*func)( /* Ptr to function */
- const char *path,
- direntry *ptr))
- {
- /*-----------------------------------------------------------------*/
- /* Local definitions. */
- /*-----------------------------------------------------------------*/
-
- char *p ; /* Working pointer */
- int pathlen ; /* Path length */
- struct dirblock *dirblkptr ; /* Ptr to directory tree */
- enum boolean result ; /* Value to be returned */
- char path[maxpathlen+1] ; /* Path work area */
- char object[maxobjectlen+1] ; /* Object work area */
- static char asterisk[] = "*" ; /* Default object */
- static const char specials[] = /* Special directory letters */
- "@$^\\&%" ;
-
- /*-----------------------------------------------------------------*/
- /* Executable statements */
- /* */
- /* First zero counter in case of immediate exit. */
- /*-----------------------------------------------------------------*/
-
- getdirentrys_counter = 0 ;
-
- /*-----------------------------------------------------------------*/
- /* Copy argument "fname" to variable "path" where it can be worked */
- /* on. Strip leading blanks and quotes; then copy up to, but not */
- /* including, first blank or quote (or to end of string). Take */
- /* FALSE exit immediately if it is too long. */
- /*-----------------------------------------------------------------*/
-
- if ( strlen(fname) > maxpathlen - 3 )
- {
- printf(toolong,fname) ;
- beep() ;
- return FALSE ;
- }
-
- strcpy(path,fname + strspn(fname," \"")) ;
- pathlen = strcspn(path," \"") ;
- path[pathlen] = '\0' ;
-
- /*-----------------------------------------------------------------*/
- /* If argument is null then default to current directory. */
- /*-----------------------------------------------------------------*/
-
- if ( pathlen == 0 )
- {
- strcpy(path,"@") ;
- pathlen = 1 ;
- }
-
- /*-----------------------------------------------------------------*/
- /* If argument incorporates any periods, split into path and */
- /* object at last period. */
- /*-----------------------------------------------------------------*/
-
- if ( ( p = strrchr(path,'.') ) != NULL )
- {
- pathlen = p - path ;
- p++ ;
- }
-
- /*-----------------------------------------------------------------*/
- /* If no period, check for a colon which could be either end of a */
- /* filing system name or start of a disk name. */
- /* */
- /* If just name of a filing system (e.g. adfs:) then add "@" and */
- /* set object to "*". */
- /* */
- /* If filing system name plus special directory letter or disk */
- /* name (e.g. adfs:@ or adfs::IDEDisk4) then just set object to */
- /* "*". */
- /* */
- /* If filing system name plus object name (e.g. adfs:myfile) then */
- /* split into path and object just after ":" and add "@" to the */
- /* filing system name. */
- /*-----------------------------------------------------------------*/
-
- else if ( ( p = strchr(path,':') ) != NULL )
- {
- p++ ;
- if ( *p == '\0' )
- {
- path[pathlen++] = '@' ;
- p = asterisk ;
- }
- else if ( ( *(p + 1) == '\0' && strchr(specials,*p) != NULL ) ||
- ( *p == ':' ) )
- {
- p = asterisk ;
- }
- else
- {
- memmove(p + 1,p,strlen(p) + 1) ;
- *p = '@' ;
- p++ ;
- pathlen = p - path ;
- }
- }
-
- /*-----------------------------------------------------------------*/
- /* No period or colon found. */
- /* */
- /* If argument is just a directory letter (e.g. @ or $) then just */
- /* set object to "*". */
- /* */
- /* Otherwise treat entire argument as the object name and set the */
- /* path to "@". */
- /*-----------------------------------------------------------------*/
-
- else
- {
- if ( pathlen == 1 && strchr(specials,path[0]) != NULL )
- {
- p = asterisk ;
- }
- else
- {
- p = path + 1 ;
- memmove(p,path,strlen(path) + 1) ;
- *p = '@' ;
- pathlen = 1 ;
- }
- }
-
- /*-----------------------------------------------------------------*/
- /* Copy the object to variable "object" and store terminating nul */
- /* at end of the path. Take FALSE exit if the object name is too */
- /* long. */
- /*-----------------------------------------------------------------*/
-
- if ( strlen(p) > maxobjectlen )
- {
- printf(toolong,p) ;
- beep() ;
- return FALSE ;
- }
- strcpy(object,p) ;
-
- path[pathlen] = '\0' ;
-
- /*-----------------------------------------------------------------*/
- /* Copy function pointer to global variable (to avoid need to pass */
- /* same value on when recursing). Set anchor word for directory */
- /* list tree to NULL. Then invoke buildtree to create directory */
- /* list tree and processtree to process the entries in the tree. */
- /*-----------------------------------------------------------------*/
-
- funcptr = func ;
- dirblkptr = NULL ;
-
- if ( ( result = buildtree(path,object,recursion,0,&dirblkptr) ) == TRUE )
- {
- if ( dirblkptr != NULL )
- {
- result = processtree(path,dirblkptr) ;
- freetree(&dirblkptr) ;
- }
- }
-
- /*-----------------------------------------------------------------*/
- /* Return to caller. */
- /*-----------------------------------------------------------------*/
-
- return result ;
- }
-
- /*===================================================================*/
- /* */
- /* buildtree - build tree of directory entry lists */
- /* --------- */
- /* */
- /* This function is called to create a list of entries in the */
- /* target directory that match a (possibly wildcarded) object name. */
- /* This function will also invoke itself recursively, if required, */
- /* to process subdirectories. */
- /* */
- /* The caller provides as arguments: */
- /* */
- /* path - the name of the directory to be searched, must */
- /* include the path (if any) and leafname */
- /* */
- /* object - wildcarded object name used in selecting directory */
- /* entries */
- /* */
- /* recursion - switch indicating if matching files only are to be */
- /* processed (RECURSE_NEVER), or first dirctory if no */
- /* matching files found (RECURSE_ONCE), or all */
- /* matching files and directives are to be processed */
- /* recursively (RECURSE_ALWAYS) */
- /* */
- /* handle - identifier used later to identify this entry */
- /* */
- /* subdirq - pointer to anchor word on which to queue the */
- /* directory list if it is successfully built. */
- /* */
- /* If the function completes successfully, it returns a value of */
- /* TRUE (and if any matching directory entries were found, it queues */
- /* the directory list it has built off the anchor word provided by */
- /* the caller). */
- /* */
- /* If an error is encountered, it returns FALSE. In this case no */
- /* directory list is built. */
- /* */
- /*===================================================================*/
-
- static enum boolean buildtree(
- char *path, /* Directory path */
- const char *object, /* Object (wildcarded) */
- const enum recursive recursion, /* Recursion switch */
- int handle, /* Id provided by caller */
- struct dirblock **subdirq) /* Ptr to subdir queue anchor */
- {
- /*-----------------------------------------------------------------*/
- /* Local definitions */
- /*-----------------------------------------------------------------*/
-
- int pathlen ; /* Length of path string */
- int found ; /* Found switch */
- int result ; /* OSGBPB result */
- int i ; /* Working integer */
- char *dataptr ; /* Working pointer */
- struct dirblock *dirblkptr ; /* Ptr to directory list block */
- struct dirblock *firstblkptr ; /* Ptr to 1st block in cont q */
- struct dirblock *prevblkptr ; /* Ptr to prev block in cont q */
- _kernel_osgbpb_block gbpbblk ; /* OS_GBPG parameter block */
- _kernel_osfile_block fileblk ; /* OS_File parameter block */
-
- /*-----------------------------------------------------------------*/
- /* Executable statements */
- /* */
- /* First save length of path on entry so that path can be */
- /* truncated again to this length on exit. Also set found flag to */
- /* value of FALSE (it will be set to TRUE later if any files found */
- /* to process. */
- /*-----------------------------------------------------------------*/
-
- pathlen = strlen(path) ;
- found = FALSE ;
-
- /*-----------------------------------------------------------------*/
- /* Next allocate memory for first block of directory names */
- /* (continuation blocks may be added later). Take FALSE exit if */
- /* unable to do so. Otherwise initialise control fields at head of */
- /* block: number of names in block set to zero; anchor field for */
- /* subdirectory queue, chain pointer for queueing block off parent */
- /* directory block and chain pointer used to queue continuation */
- /* blocks are set to null, and handle provided by caller is stored */
- /* in header. */
- /*-----------------------------------------------------------------*/
-
- if ( ( dirblkptr = malloc(sizeof(struct dirblock)) ) == NULL )
- {
- puts(outofmemory) ;
- beep() ;
- goto badbuild3 ;
- }
- dirblkptr->nobjects = 0 ;
- dirblkptr->subdirq = dirblkptr->nextptr = dirblkptr->contptr = NULL ;
- dirblkptr->handle = handle ;
-
- firstblkptr = dirblkptr ;
- prevblkptr = NULL ;
-
- /*-----------------------------------------------------------------*/
- /* Use OS_GBPB to read list of names in directory that match the */
- /* (possibly wildcarded) object name provided by the caller. This */
- /* is done as a repetitive process until an OS_GBPB indicates that */
- /* no more entries remain (probably only ever go through loop once */
- /* but the RICS-OS PRM states that not all filing systems may be */
- /* able to do it in one go). If zero entries are obtained but the */
- /* returned values indicate that the end of the directory has not */
- /* been reached, then the buffer is full. In this case get a */
- /* continuation block and keep going. */
- /*-----------------------------------------------------------------*/
-
- gbpbblk.dataptr = dirblkptr->dirlist ;
- gbpbblk.buf_len = sizeof(dirblkptr->dirlist) ;
- gbpbblk.fileptr = 0 ;
- gbpbblk.wild_fld = (char *)object ;
-
- do
- {
- gbpbblk.nbytes = INT_MAX ;
- if ( ( result = _kernel_osgbpb(9,(unsigned)path,&gbpbblk) )
- == _kernel_ERROR )
- {
- printf("%s\n",_kernel_last_oserror()->errmess) ;
- goto badbuild1 ;
- }
- for ( i = 0 ; i < gbpbblk.nbytes ; i++ )
- {
- gbpbblk.dataptr = (char *)gbpbblk.dataptr +
- strlen((char *)gbpbblk.dataptr) + 1 ;
- }
- dirblkptr->nobjects += gbpbblk.nbytes ;
- if ( gbpbblk.fileptr == -1 )
- {
- break ;
- }
- gbpbblk.buf_len = dirblkptr->dirlist + sizeof(dirblkptr->dirlist)
- - (char *)gbpbblk.dataptr ;
- if ( gbpbblk.nbytes == 0 || gbpbblk.buf_len < maxobjectlen + 1 )
- {
- if ( ( dirblkptr->contptr = malloc(sizeof(struct dirblock)) ) == NULL )
- {
- puts(outofmemory) ;
- goto badbuild1 ;
- }
- prevblkptr = dirblkptr ;
- dirblkptr = dirblkptr->contptr ;
- dirblkptr->nobjects = 0 ;
- dirblkptr->subdirq = dirblkptr->nextptr = dirblkptr->contptr = NULL ;
- dirblkptr->handle = handle ;
- gbpbblk.dataptr = dirblkptr->dirlist ;
- gbpbblk.buf_len = sizeof(dirblkptr->dirlist) ;
- }
- } FOREVER ;
-
- /*-----------------------------------------------------------------*/
- /* If no matching entries found in the directory, go take TRUE */
- /* exit immediately (which will cause directory list block to be */
- /* freed instead of queued because found flag is not set). */
- /*-----------------------------------------------------------------*/
-
- if ( firstblkptr->nobjects == 0 )
- {
- goto goodbuild ;
- }
-
- /*-----------------------------------------------------------------*/
- /* Otherwise free unused space at end of the last (or only) */
- /* directory list block. Allow for possible NULL return from */
- /* realloc although it does not seem likely since we are */
- /* shortening the block. */
- /*-----------------------------------------------------------------*/
-
- dirblkptr = realloc(dirblkptr,offsetof(struct dirblock,dirlist) +
- (char *)gbpbblk.dataptr - dirblkptr->dirlist) ;
- if ( dirblkptr != NULL )
- {
- if ( prevblkptr == NULL )
- {
- firstblkptr = dirblkptr ;
- }
- else
- {
- prevblkptr->contptr = dirblkptr ;
- }
- }
-
- /*-----------------------------------------------------------------*/
- /* Loop through list of directory entries checking which ones are */
- /* files and which ones are subdirectories using OS_File type 13 */
- /* to read the catalog details for each object (note: a period */
- /* must be added to the end of the path for OS_File). */
- /*-----------------------------------------------------------------*/
-
- for ( dirblkptr = firstblkptr ;
- dirblkptr != NULL ;
- dirblkptr = dirblkptr->contptr )
- {
- for ( i = 0 , dataptr = dirblkptr->dirlist ;
- i < dirblkptr->nobjects ;
- i++ , dataptr += strlen(dataptr) + 1 )
- {
- strcpy(path + pathlen,".") ;
- fileblk.start = (int)path ;
- switch ( _kernel_osfile(13,dataptr,&fileblk) )
- {
- /*-----------------------------------------------------------*/
- /* Returned value = 1 (file found). Set file found flag. */
- /*-----------------------------------------------------------*/
-
- case 1 :
-
- found = TRUE ;
- break ;
-
- /*-----------------------------------------------------------*/
- /* Returned value = 2 (directory found). If recursion always */
- /* required, call ouselves recursively to build directory */
- /* list block for the subdirectory. If not just skip the */
- /* directory. */
- /* */
- /* Also accept value of 3 since this is returned for a */
- /* SparkFS archive using the latest version of SparkFS. */
- /*-----------------------------------------------------------*/
-
- case 2 :
- case 3 :
-
- if ( recursion == RECURSE_ALWAYS )
- {
- if ( !extendpath(path,pathlen,dataptr) )
- {
- goto badbuild2 ;
- }
- if ( !buildtree(path,"*",RECURSE_ALWAYS,
- (int)dataptr,&firstblkptr->subdirq) )
- {
- goto badbuild2 ;
- }
- }
- break ;
-
- /*-----------------------------------------------------------*/
- /* Returned value = -2 (error occurred). Display error */
- /* message and go take FALSE exit. */
- /*-----------------------------------------------------------*/
-
- case _kernel_ERROR :
-
- printf("%s\n",_kernel_last_oserror()->errmess) ;
- goto badbuild1 ;
-
- /*-----------------------------------------------------------*/
- /* Other value should not occur. Being paranoid, if they do */
- /* just display a message and go take FALSE exit. */
- /*-----------------------------------------------------------*/
-
- default :
-
- printf(invalidentry,dataptr) ;
- goto badbuild1 ;
- }
-
- /*-------------------------------------------------------------*/
- /* Truncate path to original length. */
- /*-------------------------------------------------------------*/
-
- path[pathlen] = '\0' ;
- }
- }
-
- /*-----------------------------------------------------------------*/
- /* If no files were found then all the entries must have been for */
- /* subdirectories. If blanket recursion (RECURSE_ALWAYS) was not */
- /* required, none of them were processed. If RECURSE_ONCE was */
- /* specified, process the first entry only by invoking ourselves */
- /* recursively (but prevent any deeper recursion by specifying */
- /* RECURSE_NEVER). */
- /*-----------------------------------------------------------------*/
-
- if ( !found && recursion == RECURSE_ONCE )
- {
- freetree(&firstblkptr->contptr) ;
- firstblkptr->nobjects = 1 ;
- dirblkptr = realloc(firstblkptr,offsetof(struct dirblock,dirlist) +
- strlen(firstblkptr->dirlist) + 1) ;
- if ( dirblkptr != NULL )
- {
- firstblkptr = dirblkptr ;
- }
- if ( !extendpath(path,pathlen,firstblkptr->dirlist) )
- {
- goto badbuild2 ;
- }
- if ( !buildtree(path,"*",RECURSE_NEVER,(int)firstblkptr->dirlist,
- &firstblkptr->subdirq) )
- {
- goto badbuild2 ;
- }
- path[pathlen] = '\0' ;
- }
-
- /*-----------------------------------------------------------------*/
- /* Arrive here to take TRUE exit to caller indicating that no */
- /* error occurred. If no files were found and no subdirectory */
- /* lists queued, just free the directory list block. Otherwise */
- /* queue it off the caller's subdirectory queue. */
- /*-----------------------------------------------------------------*/
-
- goodbuild:
-
- if ( !found && firstblkptr->subdirq == NULL )
- {
- freetree(&firstblkptr) ;
- }
- else
- {
- firstblkptr->nextptr = *subdirq ;
- *subdirq = firstblkptr ;
- }
- return TRUE ;
-
- /*-----------------------------------------------------------------*/
- /* Arrive here when error occurs to take FALSE exit to caller. */
- /*-----------------------------------------------------------------*/
-
- badbuild1:
-
- beep() ;
-
- badbuild2:
-
- freetree(&firstblkptr) ;
-
- badbuild3:
-
- path[pathlen] = '\0' ;
- return FALSE ;
- }
-
- /*===================================================================*/
- /* */
- /* processtree - process files in directory list */
- /* ----------- */
- /* */
- /* This function processes all the files listed in the tree of */
- /* directory lists created by buildtree, by caller a processing */
- /* function pointed to by global variable "funcptr" for each file in */
- /* turn. It calls itself recursively to handle subdirectories. */
- /* */
- /* The caller provides two arguments: */
- /* */
- /* path - name of the directory including path (if any) */
- /* and leaf-name. */
- /* */
- /* firstblkptr - pointer to first (or only) block of directory */
- /* entries (there may be continuation blocks) */
- /* */
- /*===================================================================*/
-
- static enum boolean processtree(
- char *path, /* Ptr to path */
- struct dirblock *firstblkptr) /* Ptr to 1st directory block */
- {
- /*-----------------------------------------------------------------*/
- /* Local definitions. */
- /*-----------------------------------------------------------------*/
-
- int pathlen ; /* Length of path string */
- int i ; /* Working integer */
- char *dataptr ; /* Working pointer */
- struct dirblock *dirblkptr ; /* Ptr to directory block */
- struct dirblock *subblkptr ; /* Working dir list block ptr */
- _kernel_osfile_block fileblk ; /* OS_File parameter block */
- direntry direntryblk ; /* Directory entry data */
-
- /*-----------------------------------------------------------------*/
- /* Executable statements */
- /* */
- /* First save current path length so that path can be truncated */
- /* to original length after being extending for recursion. */
- /*-----------------------------------------------------------------*/
-
- pathlen = strlen(path) ;
-
- /*-----------------------------------------------------------------*/
- /* Perform outer loop starting with first block and proceeding */
- /* through any continuation blocks. Each block contains list of */
- /* directory entries. */
- /*-----------------------------------------------------------------*/
-
- for ( dirblkptr = firstblkptr ;
- dirblkptr != NULL ;
- dirblkptr = dirblkptr->contptr )
- {
- /*---------------------------------------------------------------*/
- /* Loop through entries in the directory list invoking OS_File */
- /* to read catalog information for the object. */
- /*---------------------------------------------------------------*/
-
- for ( i = 0 , dataptr = dirblkptr->dirlist ;
- i < dirblkptr->nobjects ;
- i++ , dataptr += strlen(dataptr) + 1 )
- {
- strcpy(path + pathlen,".") ;
- fileblk.start = (int)path ;
- switch ( _kernel_osfile(13,dataptr,&fileblk) )
- {
- /*-----------------------------------------------------------*/
- /* Returned value = 0 (not found). This is unlikely, but */
- /* could occur if the processing function provided by the */
- /* caller gets up to very funny tricks. Issue message and */
- /* ignore. */
- /*-----------------------------------------------------------*/
-
- case 0 :
-
- printf("'%s.%s' not found\n",path,dataptr) ;
-
- break ;
-
- /*-----------------------------------------------------------*/
- /* Returned value = 1 (file). Bump number of files found and */
- /* copy catalog information into a direntry structure */
- /* (defined in "getdirs.h"). Extract file-type as */
- /* convenience for the processing function (or use -1 if not */
- /* file-typed). Then call the processing function. Abort */
- /* further processing if this returns FALSE. */
- /*-----------------------------------------------------------*/
-
- case 1 :
-
- getdirentrys_counter++ ;
-
- direntryblk.load = fileblk.load ;
- direntryblk.exec = fileblk.exec ;
- direntryblk.length = fileblk.start ;
- direntryblk.attr = fileblk.end ;
- direntryblk.name = dataptr ;
-
- if ( ( fileblk.load & 0xfff00000 ) == 0xfff00000 )
- {
- direntryblk.type = ( fileblk.load & 0x000fff00 ) >> 8 ;
- }
- else
- {
- direntryblk.type = -1 ;
- }
-
- if ( !funcptr(path,&direntryblk) )
- {
- goto badprocess ;
- }
-
- break ;
-
- /*-----------------------------------------------------------*/
- /* Returned value = 2 (directory). Search the queue of */
- /* subdirectory lists using pointer to directory name as */
- /* handle. If found then invoke ourselves recursively to */
- /* process. As before, a value of 3 is also accepted since */
- /* it indicates a SparkFS archive. */
- /*-----------------------------------------------------------*/
-
- case 2 :
- case 3 :
-
- for ( subblkptr = firstblkptr->subdirq ;
- subblkptr != NULL ;
- subblkptr = subblkptr->nextptr )
- {
- if ( subblkptr->handle == (int)dataptr )
- {
- if ( !extendpath(path,pathlen,dataptr) )
- {
- goto badprocess ;
- }
- if ( !processtree(path,subblkptr) )
- {
- goto badprocess ;
- }
- break ;
- }
- }
-
- break ;
-
- /*-----------------------------------------------------------*/
- /* Returned value = -2 (error). Issue error message and */
- /* abort any further processing. */
- /*-----------------------------------------------------------*/
-
- case _kernel_ERROR :
-
- printf("%s\n",_kernel_last_oserror()->errmess) ;
- beep() ;
- goto badprocess ;
-
- /*-----------------------------------------------------------*/
- /* Other values should not occur. Again, being paranoid, if */
- /* they do, issue warning message and abort any further */
- /* processing. */
- /*-----------------------------------------------------------*/
-
- default :
-
- printf(invalidentry,dataptr) ;
- beep() ;
- goto badprocess ;
- }
-
- /*-------------------------------------------------------------*/
- /* Truncate path to original length. */
- /*-------------------------------------------------------------*/
-
- path[pathlen] = '\0' ;
- }
- }
-
- /*-----------------------------------------------------------------*/
- /* After all files processed without error, return TRUE. */
- /*-----------------------------------------------------------------*/
-
- return TRUE ;
-
- /*-----------------------------------------------------------------*/
- /* Arrive here on error to return FALSE. */
- /*-----------------------------------------------------------------*/
-
- badprocess:
-
- path[pathlen] = '\0' ;
- return FALSE ;
- }
-
- /*===================================================================*/
- /* */
- /* extendpath - add leafname to path */
- /* ---------- */
- /* */
- /* This function provides common support to both "buildtree" and */
- /* "processtree" for extending the current path name with a further */
- /* leafname when recursion is required to process a subdirectory. */
- /* */
- /* It returns TRUE if the path could be extended or FALSE if there */
- /* was not enough room. */
- /* */
- /*===================================================================*/
-
- static enum boolean extendpath(
- char *path, /* Ptr to current path */
- int pathlen, /* Length of current path */
- const char *leafname) /* Ptr to leafname to add */
- {
- /*-----------------------------------------------------------------*/
- /* Executable statements */
- /* */
- /* If path would become too long issue error message and take */
- /* FALSE exit (maxpathlen is defined in "getdirs.h"). */
- /* */
- /* Otherwise add period plus leafname to end of path and take */
- /* TRUE exit. */
- /*-----------------------------------------------------------------*/
-
- if ( pathlen + 1 + strlen(leafname) > maxpathlen )
- {
- printf(toolong,path) ;
- beep() ;
- return FALSE ;
- }
-
- path[pathlen] = '.' ;
- strcpy(path + pathlen + 1,leafname) ;
-
- return TRUE ;
- }
-
- /*===================================================================*/
- /* */
- /* freetree - free tree of subdirectory lists */
- /* -------- */
- /* */
- /* This function provides common support to "getdirentrys" and to */
- /* "buildtree". It frees the tree of directory lists queued off */
- /* the anchor word provided by the caller. It calls itself */
- /* recursively to process lists for subdirectories. */
- /* */
- /*===================================================================*/
-
- static void freetree(
- struct dirblock **subdirq) /* Ptr to sub directory queue */
- {
- /*-----------------------------------------------------------------*/
- /* Local definitions. */
- /*-----------------------------------------------------------------*/
-
- struct dirblock *dirblkptr ; /* Directory list block ptr */
- struct dirblock *contptr ; /* Ptr to continuation block */
-
- /*-----------------------------------------------------------------*/
- /* Executable statements */
- /* */
- /* Run queue of directory lists queued off the anchor word */
- /* provided by caller, freeing the storage allocated to the lists. */
- /* Invoke ourselves recursively to process subdirectory lists. */
- /*-----------------------------------------------------------------*/
-
- while ( ( dirblkptr = *subdirq ) != NULL )
- {
- *subdirq = dirblkptr->nextptr ;
- freetree(&dirblkptr->subdirq) ;
- do
- {
- contptr = dirblkptr->contptr ;
- free(dirblkptr) ;
- } while ( ( dirblkptr = contptr ) != NULL ) ;
- }
- }
-
- /*===================================================================*/
-