home *** CD-ROM | disk | FTP | other *** search
- /*
- * dir.c --
- *
- * Routines used to acquire file names and traverse the
- * directory tree.
- *
- * Copyright 1989 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- * Author: Gary Shea, UC Berkeley, Dept. of Chemistry
- */
-
- static char rcsid[] = "$Header: dir.c,v 1.3 89/07/18 00:04:01 garys Exp $";
-
- #include <ctype.h>
- #include "xf.h"
-
- /* #define DEBUG */
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DecomposePath --
- *
- * Accept a path, return a list of pointers to char
- * with the various parts of the path in it. This should
- * work for both relative and absolute pathnames.
- *
- * Results:
- * A pointer to an array of pointers to char is returned.
- * The array is null-terminated.
- *
- * Side effects:
- * Space is allocated for the array.
- *
- * Arguments:
- * path - The path to take apart.
- * kind - By-reference parameter flags relative or absolute paths.
- * parts - Number of components in the path ('/' is a component).
- *
- *----------------------------------------------------------------------
- */
-
- #define VECTOR_INC 50
- #define START 0
- #define IN_DIR 1
- #define SEP 2
-
- char **
- DecomposePath( char *path, PathKind *kind, int *parts )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DecomposePath()" ;
-
- char pTempString[ MAXPATHLEN + 1 ] ;
- char *pCurString = pTempString ;
- int state ;
-
- char **pVector ;
- int vecLen ;
-
- #ifdef DEBUG
- fprintf( pErrFp, "\n%s:\n", pLocName );
- fprintf( pErrFp, "\tpath=<%s>\n", path ) ;
- #endif
-
- /* Skip leading white space. */
-
- while ( *path != '\0' && isspace( *path ) ) ++path ;
-
- #ifdef DEBUG
- fprintf( pErrFp, "\tPost-compression:\n" );
- fprintf( pErrFp, "\tpath=<%s>\n", path ) ;
- #endif
-
- /* Take it apart, mon...
- * The only important things to look for are "/" and '\0' .
- *
- * This thing will be a state-machine.
- * START : Nothing seen yet.
- * IN_DIR : Reading the name of a dir.
- * SEP : Just saw a separator.
- */
-
- *parts = 0 ;
- state = START ;
- pVector = (char **)0 ;
- vecLen = 0 ;
-
- for ( ; ; )
- {
-
- #ifdef DEBUG
- fprintf( pErrFp,
- "\tTop: strlen=%d, state=%d\n",
- pCurString - pTempString, state ) ;
- fprintf( pErrFp,
- "\tparts=%d, vecLen=%d\n",
- *parts, vecLen ) ;
- #endif
-
- switch( state )
- {
- case START :
- if ( *path == '/' )
- {
- char *sp ;
-
- /* It's an absolute path. */
-
- *kind = AbsPath ;
-
- /* Create the vector of string pointers. */
-
- vecLen = VECTOR_INC ;
- TestAndGrow( pVector, (*parts), vecLen, VECTOR_INC, char * ) ;
- sp = malloc( 2 ) ; sp[0] = '/' ; sp[1] = '\0' ;
- pVector[ (*parts)++ ] = sp ;
- pVector[ *parts ] = (char *) 0 ;
-
- #ifdef DEBUG
- fprintf( pErrFp,
- "\t\tabsPath: Fake string <%s>\n",
- pVector[ *parts - 1 ] ) ;
- #endif
- state = SEP ;
- ++path ;
- }
- else if ( *path == '\0' )
- {
- /* A null path. */
-
- UserError( "No path specified" );
- *kind = NoPath ;
- return ( NULL ) ;
- }
- else
- {
- /* A relative path. */
-
- *kind = RelPath ;
- state = IN_DIR ;
-
- /* Save this char. */
-
- pCurString = pTempString ;
- *(pCurString++) = *(path++) ;
- *pCurString = '\0' ;
-
- #ifdef DEBUG
- fprintf( pErrFp, "\t\tSTART: Initialized temp string ptr.\n" );
- #endif
-
- }
- break ;
-
- case IN_DIR :
- if ( *path == '/' || *path == '\0' )
- {
- char *sp ;
-
- /* We just completed a dir name. Allocate
- * a string for the currently completing dir
- * name, attach it to the list of names.
- */
-
- TestAndGrow( pVector, (*parts), vecLen, VECTOR_INC, char * ) ;
- pVector[ *parts ] =
- malloc( (unsigned)(pCurString - pTempString + 1) ) ;
- strcpy( pVector[ (*parts)++ ], pTempString ) ;
- TestAndGrow( pVector, (*parts), vecLen, VECTOR_INC, char * ) ;
- pVector[ *parts ] = (char *) 0 ;
-
- #ifdef DEBUG
- fprintf( pErrFp,
- "\t\tstrLen=%d, tempStr:<%s>, newStr:<%s>\n",
- pCurString - pTempString,
- pTempString,
- pVector[ *parts - 1 ] ) ;
- #endif
-
- if ( *path == '/' )
- {
- state = SEP ;
- ++path ;
- }
- else if ( *path == '\0' )
- return( pVector ) ;
- }
- else
- {
- /* More characters for this dir name. */
-
- if ( pCurString - pTempString + 2 >= MAXPATHLEN )
- {
- sprintf( errLine, "String too long (> %d)\n",
- MAXPATHLEN ) ;
- FatalError( pLocName, errLine );
- }
-
- *(pCurString++) = *(path++) ;
- *pCurString = '\0' ;
-
- #ifdef DEBUG
- /* I wanna look at the string, mon. */
-
- fprintf( pErrFp,
- "\t\tcurStr:<%s>, strLen:%d\n",
- pTempString, pCurString - pTempString + 1 ) ;
- #endif
- }
- break ;
-
- case SEP :
- if ( *path == '/' )
- {
- /* Just ignore this... */
-
- #ifdef DEBUG
- fprintf( pErrFp, "\t\tSEP: Ignoring a '/'.\n" );
- #endif
-
- ++path ;
-
- }
- else if ( *path == '\0' )
- {
- /* Now either the pathname is just '/',
- * or we're ending on a '/'. Ending on a '/'
- * is no big deal - just ignore it.
- * If the pathname is /, then let the calling
- * program figure out that nothing's coming.
- */
-
- #ifdef DEBUG
- fprintf( pErrFp, "\t\tSEP: End of string.\n" );
- #endif
-
- return( pVector ) ;
- }
- else
- {
- /* Starting a new dir name. */
-
- pCurString = pTempString ;
- *(pCurString++) = *(path++) ;
- *pCurString = '\0' ;
- state = IN_DIR ;
-
- #ifdef DEBUG
- fprintf( pErrFp, "\t\tSEP: Initialized temp string ptr.\n" );
- #endif
- }
- break ;
-
- }
- }
-
- #ifdef DEBUG
- fprintf( pErrFp, "\tEND: Shouldn't be here...\n" ) ;
- #endif
-
- FatalError ( pLocName, "Fell through loop" );
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_AddBranch --
- *
- * Given a valid subdirectory name and a DirTree,
- * add the subdirectory to the DirTree and fill out
- * all its stuff, and make the DirTree its root.
- * If the subdir exists, return a pointer to it.
- * In this sense, both '.' and '..' are subdir's.
- *
- * Results:
- * A pointer to the new DirTree is returned, or NULL
- * if it doesn't make sense.
- *
- * Side effects:
- * A new DirTree may be allocated and filled out,
- * also the branch list in the original DirTree may be
- * extended if necessary.
- *
- * Arguments:
- * trvPtr - DirTree struct to add name below.
- * index - Index to the name in the files[] array.
- *
- *----------------------------------------------------------------------
- */
-
- DirTree *
- DirTree_AddBranch( DirTree *trvPtr, int index )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_AddBranch()" ;
-
- int branchIdx ;
-
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\n%s:\n", pLocName ) ;
- #endif
-
- /*
- * Is it really a subdirectory?
- */
-
- if ( ( trvPtr->files[ index ].statMode & S_GFMT) != S_GFDIR )
- {
- int err = 0 ;
- char *errString ;
-
- if ( (trvPtr->files[ index ].statMode & S_GFMT) == S_GFLNK )
- {
- char path[ MAXPATHLEN + 1 ] ;
- struct stat statBuf ;
-
- strcpy ( path, trvPtr->fullName ) ;
- strcat ( path, trvPtr->files[index].file ) ;
- if ( stat ( path, &statBuf ) != 0 )
- OSFatalError ( pLocName, "stat() failed" ) ;
-
- if ( (statBuf.st_mode & S_GFMT) != S_GFDIR )
- {
- errString = "Link to non-directory" ;
- ++err ;
- }
- }
- else
- {
- errString = "Not a directory" ;
- ++err ;
- }
-
- if ( err )
- {
- sprintf ( errLine,
- "%s%s: %s",
- trvPtr->relName != NULL ? trvPtr->relName : trvPtr->fullName,
- trvPtr->files[index].file,
- errString ) ;
- UserError ( errLine ) ;
- return ( NULL ) ;
- }
- }
-
- /*
- * Is it one of . or .. ?
- */
-
- if ( (trvPtr->files[ index ].file)[0] == '.' )
- {
- if ( (trvPtr->files[ index ].file)[1] == '\0' )
- return ( trvPtr ) ;
- else if ( (trvPtr->files[ index ].file)[1] == '.'
- && (trvPtr->files[ index ].file)[2] == '\0' )
- return ( trvPtr->rootPtr ) ;
- }
-
- /*
- * Has it ever been opened before?
- */
-
- for ( branchIdx = 0 ; branchIdx < trvPtr->branchCnt ; ++branchIdx )
- if ( trvPtr->branches[ branchIdx ].index == index )
- break ;
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\tbranchIdx=%d\n", branchIdx ) ;
- #endif
-
- if ( branchIdx >= trvPtr->branchCnt )
- {
- DirTree *newDirPtr ;
- char path[ MAXPATHLEN + 1 ] ;
-
- /*
- * It hasn't been opened yet.
- * Make a DirTree struct for this subdir and
- * try to get it filled out.
- */
-
- strcpy ( path, trvPtr->fullName ) ;
- strcat ( path, trvPtr->files[index].file ) ;
- strcat ( path, "/" ) ;
- newDirPtr = DirTree_PresetNew ( StrSave( trvPtr->files[index].file ),
- StrSave( path ), TRUE, trvPtr->dirLevel + 1 ) ;
- FillFilesList ( newDirPtr ) ;
-
- if ( newDirPtr->fileCnt <= 0 )
- {
- sprintf ( errLine,
- "%s%s: Directory is empty",
- trvPtr->relName != NULL ? trvPtr->relName : trvPtr->fullName,
- trvPtr->files[index].file ) ;
- UserError ( errLine ) ;
- return ( NULL ) ;
- }
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\tnewDirPtr:\n" ) ;
- DirTree_Dump( newDirPtr ) ;
- #endif
-
- /* Now add the new branch to the list. */
-
- TestAndGrow( trvPtr->branches, trvPtr->branchCnt,
- trvPtr->branchSlots, BRANCH_SLOT_INCREMENT, BranchData ) ;
- trvPtr->branches[ trvPtr->branchCnt ].index = index ;
- trvPtr->branches[ trvPtr->branchCnt ].branchPtr = newDirPtr ;
- newDirPtr->rootPtr = trvPtr ;
-
- #ifdef DEBUG1
- fprintf ( pErrFp, "\tdirRootPtr:\n" ) ;
- DirTree_TreeDump( dirRootPtr ) ;
- #endif
-
- branchIdx = trvPtr->branchCnt++ ;
- }
-
- return ( trvPtr->branches[ branchIdx ].branchPtr ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_Alloc --
- *
- * Allocate and return a pointer to a DirTree struct.
- *
- * Results:
- * A pointer to freshly-allocated memory is returned.
- *
- * Side effects:
- * The contents of the structure are initialized.
- * See DirTree_Init().
- *
- * Arguments:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- DirTree *
- DirTree_Alloc( void )
- {
- DirTree *dp ;
-
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_Alloc()" ;
-
-
- #ifdef DEBUG
- fprintf( pErrFp, "\n%s:\n", pLocName );
- #endif
-
-
- if ( ( dp = (DirTree *) malloc( sizeof( DirTree ) ) ) == (DirTree *)0 )
- FatalError( pLocName, "Out of Memory" ) ;
- DirTree_Init( dp ) ;
- return( dp ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_CWD --
- *
- * Build a DirTree that is the current working directory.
- *
- * Results:
- * A pointer to the new DirTree is returned.
- *
- * Side effects:
- * Lots.
- *
- *----------------------------------------------------------------------
- */
-
- void
- DirTree_CWD( void )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_CWD()" ;
-
- char *getwd() ;
- char path[ MAXPATHLEN + 1 ] ;
-
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\n%s:\n", pLocName ) ;
- #endif
-
- /* Get the current direcory. */
-
- if ( getwd( path ) == NULL )
- {
- perror ( "getwd" ) ;
- exit ( 1 ) ;
- }
-
- /* Now build the tree... and set the global cwdPtr in the process. */
-
- if ( ( cwdPtr = DirTree_Find ( path )) == NULL )
- exit ( 1 ) ;
-
- /* Set up the initial relative path stuff. */
-
- cwdPtr->relName = StrSave( "" ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_ClientDump --
- *
- * DirTree-tree node-dump routine for use as a callup by
- * DirTree_TreeTrav().
- *
- * Results:
- * None.
- *
- * Side effects:
- * Some i/o is done.
- *
- * Arguments:
- * dirTreePtr - DirTree struct to dump.
- * clientData - Anonymous pointer to data that will be ignored.
- *
- *----------------------------------------------------------------------
- */
-
- void
- DirTree_ClientDump( DirTree *dirTreePtr, void *clientData )
- {
- DirTree_Dump( dirTreePtr ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_Dump --
- *
- * Dump the contents of a DirTree struct to the err file.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The err file fills with garbage.
- *
- * Arguments:
- * dirTreePtr - Pointer to a DirTree struct.
- *
- *----------------------------------------------------------------------
- */
-
- void
- DirTree_Dump( DirTree *dirTreePtr )
- {
- int i, j ;
-
-
- if ( dirTreePtr == (DirTree *)0 )
- {
- fprintf( pErrFp, "\nDirTree_Dump: null dirTreePtr\n" ) ;
- return ;
- }
-
- fprintf( pErrFp, "\nDirTree_Dump: <%s> at 0x%x\n",
- dirTreePtr->name, dirTreePtr ) ;
- fprintf( pErrFp, "\tnormal=%s, fullName=<%s>\n",
- dirTreePtr ? "true" : "false",
- dirTreePtr->fullName ) ;
-
- fprintf( pErrFp, "\tfiles list: fileCnt=%d, fileSlots=%d\n",
- dirTreePtr->fileCnt, dirTreePtr->fileSlots ) ;
- for ( i = 0 ; i < dirTreePtr->fileCnt ; ++i )
- fprintf( pErrFp, "\t\t<%s>\n", dirTreePtr->files[ i ].file ) ;
-
- fprintf( pErrFp, "\trootPtr=0x%x, branchCnt=%d, branches=0x%x\n",
- dirTreePtr->rootPtr, dirTreePtr->branchCnt, dirTreePtr->branches ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_Find --
- *
- * Given a (possibly invalid) directory name,
- * attempt to find it in the tree. If it doesn't exist,
- * nodes are constructed as needed.
- *
- * Results:
- * A pointer to the DirTree which matches the path is returned.
- *
- * Side effects:
- * Lots.
- *
- * Arguments:
- * path - The argument should be a path.
- *
- *----------------------------------------------------------------------
- */
-
- DirTree *
- DirTree_Find( char *path )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_Find()" ;
-
- PathKind kind = NoPath ;
- char **strVec ;
- int isRoot = FALSE ;
-
- int parts ;
- int curPart ;
-
- DirTree *trvPtr = NULL ;
-
-
- #ifdef DEBUG
- fprintf( pErrFp, "\n%s:\n", pLocName );
- #endif
-
- if ( ( strVec = DecomposePath ( path, &kind, &parts ) ) == (char **) 0 )
- return ( NULL ) ;
-
- #ifdef DEBUG
- fprintf( pErrFp, "\t%s:\n",
- kind == AbsPath
- ? "Absolute"
- : kind == RelPath ? "Relative" : "NoPath" ) ;
- #endif
-
- /* If it's an absolute path, make sure the tree exists,
- * set the first part as the next one after the '/',
- * and set the traversal to begin from the DirTree root.
- * If a relative path, set the traversal to begin from
- * the cwd.
- */
-
- if ( kind == AbsPath )
- {
- /* First make sure the tree exists. */
-
- if ( dirRootPtr == NULL )
- {
- dirRootPtr = DirTree_PresetNew ( "/", "/", TRUE, 0 ) ;
- FillFilesList ( dirRootPtr ) ;
- }
-
- /* Now step through the remaining fields, if any. */
-
- trvPtr = dirRootPtr ;
- curPart = 1 ;
- }
- else
- {
- if ( cwdPtr == NULL )
- InternalError ( pLocName, "cwdPtr not initialized" ) ;
- else
- {
- trvPtr = cwdPtr ;
- curPart = 0 ;
- }
- }
-
- for ( ; curPart < parts ; ++curPart )
- {
- DirTree *newDirPtr ;
- int fileIdx ;
- int branchIdx ;
-
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\tTop of loop: curPart=%d\n", curPart ) ;
- if ( trvPtr != NULL )
- {
- fprintf ( pErrFp, "\ttrvPtr:\n" ) ;
- DirTree_Dump( trvPtr ) ;
- }
- else
- fprintf ( pErrFp, "\ttrvPtr is NULL\n" ) ;
- #endif
-
- /* Do we have the files for this dir yet? */
-
- if ( trvPtr->fileCnt <= 0 )
- InternalError ( pLocName, "No files" ) ;
-
- /* Is the sub-dir we're looking for in here?
- * I agree that this is tacky, but it's how
- * i'm doing it anyway.
- */
-
- if ( strcmp ( strVec[curPart], "." ) == 0 )
- newDirPtr = trvPtr ;
- else if ( strcmp ( strVec[curPart], ".." ) == 0 )
- newDirPtr = trvPtr->rootPtr ;
- else
- {
- for ( fileIdx = 0 ; fileIdx < trvPtr->fileCnt ; ++fileIdx )
- {
- if ( strcmp ( strVec[curPart],
- trvPtr->files[fileIdx].file ) == 0 )
- break ;
- }
-
- if ( fileIdx >= trvPtr->fileCnt )
- {
- sprintf ( errLine, "%s: No such file or directory", path ) ;
- UserError ( errLine ) ;
- return ( NULL ) ;
- }
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\tfileIdx=%d\n", fileIdx ) ;
- #endif
-
- if ( ( newDirPtr = DirTree_AddBranch( trvPtr, fileIdx )) == NULL )
- return ( NULL ) ;
- }
-
- /* If a relative path was specified, then propagate
- * the relative path into the new directory. This
- * may well be duplicated effort, but the check for
- * length means you can't really mess things up
- * (i hope).
- */
-
- if ( kind == RelPath )
- {
- char path[ MAXPATHLEN + 1 ] ;
-
-
- if ( trvPtr->relName == NULL )
- InternalError ( pLocName, "relName NULL" ) ;
-
- strcpy ( path, trvPtr->relName ) ;
- strcat ( path, strVec[curPart] ) ;
- strcat ( path, "/" ) ;
- if ( newDirPtr->relName == NULL
- || ( newDirPtr->relName != NULL
- && strlen ( path ) < strlen ( newDirPtr->relName ) ) )
- newDirPtr->relName = StrSave( path ) ;
- }
-
- trvPtr = newDirPtr ;
- }
-
- return ( trvPtr ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_FindWidget --
- *
- * Search a tree of widgets for a particular one. Any
- * of the command widgets may be searched for by Widget id,
- * by specifying the appropriate member of WidgetToFind.
- *
- * Results:
- * A pointer to the DirTree struct holding the widget is
- * returned if the search succeeds, otherwise NULL.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- DirTree *
- DirTree_FindWidget( DirTree *dirTreePtr, WidgetToFind kind, Widget w )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_FindWidget()" ;
-
- int i ;
-
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\n%s:\n", pLocName ) ;
- #endif
-
- if ( dirTreePtr == (DirTree *)0 ) return ( NULL ) ;
-
- if ( dirTreePtr->isDisplayed )
- {
- Widget tw ;
-
- switch ( kind )
- {
- case SetW : tw = dirTreePtr->setW ; break ;
- case UpW : tw = dirTreePtr->upComW ; break ;
- case QuitW : tw = dirTreePtr->quitComW ; break ;
- case DoneW : tw = dirTreePtr->doneComW ; break ;
- }
-
- if ( tw == w )
- return ( dirTreePtr ) ;
- }
-
- /* Recursively search each of the sub-trees. */
-
- for ( i = 0 ; i < dirTreePtr->branchCnt ; ++i )
- {
- if ( dirTreePtr->branches[ i ].branchPtr != NULL )
- {
- DirTree *dtPtr ;
-
- if ( ( dtPtr =
- DirTree_FindWidget( dirTreePtr->branches[ i ].branchPtr,
- kind, w )) != NULL )
- return ( dtPtr ) ;
- }
- }
-
- return ( NULL ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_Init --
- *
- * Initialize a DirTree struct.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The contents of the struct are modified.
- *
- * Arguments:
- * dp - Pointer to a DirTree struct.
- *
- *----------------------------------------------------------------------
- */
-
- void
- DirTree_Init( DirTree *dp )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_Init()" ;
-
-
- #ifdef DEBUG
- fprintf( pErrFp, "\n%s:\n", pLocName );
- #endif
-
- dp->name = NULL ;
- dp->fullName = NULL ;
- dp->relName = NULL ;
- dp->normal = FALSE ;
-
- dp->fileCnt = 0 ;
- dp->fileSlots = 0 ;
- dp->files = NULL ;
-
- dp->rootPtr = NULL ;
- dp->isDisplayed = FALSE ;
-
- dp->branchCnt = 0 ;
- dp->branchSlots = 0 ;
- dp->branches = NULL ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_PresetNew --
- *
- * A convenience routine to create, initialize and fill in
- * some of the more commonly used fields of a DirTree.
- *
- * Results:
- * Pointer to the newly allocated DirTree is returned.
- *
- * Side effects:
- * An DirTree is allocated, DirTree_Init is called on it, some of
- * its fields are modified based on the input parameters.
- *
- * Arguments:
- * namePtr - The name of the dirTree.
- * addr - Address in memory which the dirTree refers to.
- * status - Has the address been determined yet?
- *
- *----------------------------------------------------------------------
- */
-
- DirTree *
- DirTree_PresetNew( char *name, char *fullName, int normal, int dirLevel )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_PresetNew()" ;
-
- DirTree *dp ;
-
- #ifdef DEBUG
- fprintf( pErrFp, "\n%s:\n", pLocName );
- fprintf( pErrFp, "\tname=<%s>, fullName=<%s>, normal=%d\n",
- name, fullName, normal ) ;
-
- /* Test to see if the conditions on fullName are met. */
- { int len = strlen ( fullName ) ;
- if ( fullName [ len - 1 ] != '/' )
- InternalError ( pLocName, "fullName not '/'-terminated" ) ;
- }
- #endif
-
- dp = DirTree_Alloc() ;
- dp->name = name ;
- dp->fullName = fullName ;
- dp->normal = normal ;
- dp->dirLevel = dirLevel ;
-
- return( dp ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_TreeDump --
- *
- * Dump the contents of the DirTree tree with the
- * given root.
- *
- * Results:
- * None.
- *
- * Side effects:
- * More garbage in the err file.
- *
- * Arguments:
- * rootPtr - Root of a DirTree tree.
- *
- *----------------------------------------------------------------------
- */
-
- void
- DirTree_TreeDump( DirTree *rootPtr )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_TreeDump()" ;
-
-
- fprintf( pErrFp, "\n%s:\n", pLocName );
- DirTree_TreeTrav( rootPtr, PreOrder, DirTree_ClientDump, (void *)0 ) ;
- fprintf( pErrFp, "END DirTree_TreeDump()\n" ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DirTree_TreeTrav --
- *
- * Traverse the DirTree_Tree,
- * calling the passed in function on each node as it is
- * visited. This is a structure-hiding routine - i hope
- * it's useful!!!.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The passed in fcn gets called on every node of the tree.
- *
- * Arguments:
- * dirTreePtr - Pointer to the root of the tree.
- * travMode - Whether the traversal is InOrder, PreOrder, or PostOrder.
- * NodeOp - Function that will operate on the nodes.
- * clientData - Anonymous pointer to data used by NodeOp.
- *
- *----------------------------------------------------------------------
- */
-
- void
- DirTree_TreeTrav( DirTree *dirTreePtr, TreeOrder travOrder,
- void NodeOp( DirTree *nodePtr, void *clientData ),
- void *clientData )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "DirTree_TreeTrav()" ;
-
- int i ;
-
-
- #ifdef DEBUG
- fprintf( pErrFp, "\n%s:\n", pLocName );
- #endif
-
-
- if ( dirTreePtr == (DirTree *)0 ) return ;
-
- if ( travOrder == PreOrder )
- NodeOp( dirTreePtr, clientData ) ;
-
- for ( i = 0 ; i < dirTreePtr->branchCnt ; ++i )
- if ( dirTreePtr->branches[ i ].branchPtr != (DirTree *)0 )
- DirTree_TreeTrav( dirTreePtr->branches[ i ].branchPtr,
- travOrder, NodeOp, clientData ) ;
-
- if ( travOrder == PostOrder )
- NodeOp( dirTreePtr, clientData ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * FileData_Compare --
- *
- * Compare two FileData structs by strcmp()-ing the file
- * fields. This is a qsort()-callable routine and is used
- * to sort the list of files.
- *
- * Results:
- * An integer less than zero is returned if leftPtr < rightPtr,
- * 0 if they are equal,
- * an integer greater than zero is returned if leftPtr > rightPtr.
- *
- * Side effects:
- * None.
- *
- * Arguments:
- * leftPtr - Pointer to a pointer to a FileData struct.
- * rightPtr - Pointer to a pointer to a FileData struct.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- FileData_Compare( FileData *leftPtr, FileData *rightPtr )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "FileData_Compare()" ;
-
- # ifdef DEBUG
- fprintf ( pErrFp, "\n%s:\n", pLocName ) ;
- # endif
-
- return ( strcmp ( leftPtr->file, rightPtr->file ) ) ;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * FillFilesList --
- *
- * Given a DirTree with its fullName filled in,
- * fill in its files[] list.
- *
- * Results:
- * Currently returns True, or dies if there's an error.
- *
- * Side effects:
- * Mucho space is allocated for the filenames.
- *
- * Arguments:
- * trvPtr - The DirTree to fill in.
- *
- *----------------------------------------------------------------------
- */
-
- int
- FillFilesList ( DirTree *trvPtr )
- {
- char errLine[ ERRLINE_LEN ] ;
- char *pLocName = "FillFilesList()" ;
-
- DIR *dirFp ;
- DirEnt *entPtr ;
- char *sp ;
-
- char path[ MAXPATHLEN ] ;
- int pathLen ;
-
- struct stat statBuf ;
-
- static int FileData_Compare( FileData **leftPtr, FileData **rightPtr ) ;
-
-
- #ifdef DEBUG
- fprintf( pErrFp, "\n%s:\n", pLocName );
- #endif
-
- /* First try to open the directory in which we are sitting. */
-
- if ( ( dirFp = opendir ( trvPtr->fullName ) ) == NULL )
- InternalError ( pLocName, "opendir() failed" ) ;
-
- /* Get ready for calling lsat by making a string to tack
- * file names onto the end of.
- */
-
- strcpy ( path, trvPtr->fullName ) ;
- pathLen = strlen ( path ) ;
-
- /* Now traverse the directory getting the files. */
-
- for ( entPtr = readdir( dirFp )
- ; entPtr != (DirEnt *)0
- ; entPtr = readdir( dirFp ) )
- {
- if ( !ls_mode_a && entPtr->d_name[ 0 ] == '.' ) continue ;
-
- /* Construct a path so that lstat() may be called. */
-
- path[ pathLen ] = '\0' ;
- strcat ( &path[pathLen], entPtr->d_name ) ;
- if ( lstat ( path, &statBuf ) != 0 )
- OSFatalError ( pLocName, "lstat() failed" ) ;
-
- /* Make sure there's someplace to put the (local) name. */
-
- TestAndGrow ( trvPtr->files, trvPtr->fileCnt,
- trvPtr->fileSlots, FILE_SLOT_INCREMENT, FileData ) ;
-
- trvPtr->files[ trvPtr->fileCnt ].file = StrSave ( entPtr->d_name ) ;
- trvPtr->files[ trvPtr->fileCnt ].statMode = statBuf.st_mode ;
-
- #ifdef DEBUG1
- fprintf ( pErrFp, "\t\t%d: <%s>, statMode=0%o\n",
- trvPtr->fileCnt,
- trvPtr->files[ trvPtr->fileCnt ].file,
- trvPtr->files[ trvPtr->fileCnt ].statMode ) ;
- #endif
-
- trvPtr->fileCnt++ ;
- }
-
- #ifdef DEBUG
- fprintf ( pErrFp, "\t%s: DONE\n", pLocName ) ;
- #endif
-
- /* Sort the files, if there are any... */
-
- if ( trvPtr->fileCnt > 0 )
- qsort ( (char *) trvPtr->files, trvPtr->fileCnt,
- sizeof(FileData), FileData_Compare ) ;
-
- return( TRUE ) ;
- }
-
-