/* * DoLC - perform LC on a specified directory */ void DoLC( char *dir ) { int i; DIR *d; struct dirent *nd; #ifdef __QNX__ char tmpname[ _MAX_PATH ]; char drive[_MAX_DRIVE],directory[_MAX_DIR]; char name[_MAX_FNAME],ext[_MAX_EXT]; #endif /* * initialize for file scan */ filecnt = 0; strcpy(filename,dir); #ifndef __QNX__ if( !FNameCompare(dir,"..") ) { strcat(filename,"\\*.*"); } else if( dir[ strlen(dir)-1 ] == '.' ) { filename[ strlen(dir)-1 ] = 0; strcat(filename,"*.*"); } else if( dir[ strlen(dir)-1 ] == '\\' ) { strcat(filename,"*.*"); } else { strcat(filename,"\\*.*"); } #else if( filename[0] == 0 ) { filename[0] = '.'; filename[1] = 0; } _splitpath( filename, drive, directory, name, ext ); #endif d = opendir( filename ); if( d == NULL ) { printf( "Directory (%s) not found.\n",filename ); return; } /* * find all files (except for . and ..) */ while( (nd = readdir( d )) != NULL ) { #ifndef __QNX__ if( files_only && nd->d_attr & _A_SUBDIR ) { continue; } if( directories_only && !( nd->d_attr & _A_SUBDIR ) ) { continue; } if( !((nd->d_attr & _A_SUBDIR ) && IsDotOrDotDot( nd->d_name ))) { #else if( files_only && S_ISDIR( nd->d_stat.st_mode ) ) { continue; } if( directories_only && !S_ISDIR( nd->d_stat.st_mode ) ) { continue; } if( !((S_ISDIR( nd->d_stat.st_mode) && IsDotOrDotDot( nd->d_name ) ))) { #endif files = realloc( files, ( filecnt+1 )*sizeof( struct dirent * ) ); if( files == NULL ) { printf( "Out of memory!\n" ); exit( 1 ); } files[ filecnt ] = malloc( sizeof( struct dirent ) ); if( files[ filecnt ] == NULL ) { break; } #ifndef __QNX__ FNameLower( nd->d_name ); #else if( !(nd->d_stat.st_status & _FILE_USED ) ) { _splitpath( nd->d_name, NULL, NULL, name, ext ); _makepath( tmpname, drive, directory, name, ext ); stat( tmpname, &nd->d_stat ); } #endif memcpy( files[filecnt++],nd,sizeof( struct dirent ) ); } } closedir( d ); if( filecnt == 0 ) { return; } /* * sort the data. */ qsort( files, filecnt, sizeof(struct dirent *), Compare ); /* * determine if there are files and/or directories */ fileflag = dirflag = read_only_flag = false; for( i = 0; i < filecnt; i++ ) { #ifndef __QNX__ if( files[i]->d_attr & _A_SUBDIR ) { dirflag = true; } else if( separate_read_only && files[i]->d_attr & _A_RDONLY ) { read_only_flag = true; } else { fileflag = true; } #else if( S_ISDIR( files[i]->d_stat.st_mode ) ) { dirflag = true; } else { fileflag = true; } #endif if( fileflag && dirflag && (!separate_read_only || read_only_flag) ) { break; } } /* * print out results */ if( dirflag ) { printf("Directories:\n"); pass = DIR_PASS; linecnt=0; for( i = 0; i < filecnt; i++ ) { PrintFile( files[i] ); } if( linecnt != 0 ) { printf("\n"); } } if( fileflag ) { if( dirflag ) { printf("\n"); } printf("Files:\n"); pass = FILE_PASS; linecnt=0; for( i = 0; i < filecnt; i++ ) { PrintFile( files[i] ); } if( linecnt != 0 ) { printf("\n"); } } if( read_only_flag ) { if( dirflag || fileflag ) { printf("\n"); } printf( "Read-Only Files:\n" ); pass = READ_ONLY_PASS; linecnt = 0; for( i = 0; i < filecnt; i++ ) { PrintFile( files[i] ); } if( linecnt != 0 ) { printf("\n"); } } } /* DoLC */ /* * PrintFile - print a file entry */ void PrintFile( struct dirent *file ) { size_t len; size_t num_columns; #ifndef __QNX__ if( file->d_attr & _A_SUBDIR ) { #else if( S_ISDIR( file->d_stat.st_mode ) ) { #endif if( pass != DIR_PASS ) { return; } } else { #ifndef __QNX__ if( separate_read_only && file->d_attr & _A_RDONLY ) { if( pass != READ_ONLY_PASS ) { return; } } else if( pass != FILE_PASS ) { return; } #else if( pass != FILE_PASS ) { return; } #endif } /* calculate how many columns it will take to print the filename */ len = strlen( file->d_name ) + ( GUTTER_WIDTH + COLUMN_WIDTH - 1 ); num_columns = len / COLUMN_WIDTH; if( num_columns + linecnt > maxwidth ) { printf( "\n" ); linecnt = 0; } printf("%-*s", COLUMN_WIDTH * num_columns - GUTTER_WIDTH, file->d_name ); linecnt += num_columns; if( linecnt >= maxwidth ) { printf("\n"); linecnt = 0; } else { printf( "%*s", GUTTER_WIDTH, "" ); } } /* PrintFile */
/* * recursiveCp - copy a file to a directory (recursively entered) * * source_head points to a buffer of size _MAX_PATH that ends with a ':' * or a FILESEP. * source_tail points to the null terminator of source_head. * source_wild is the filename/pattern to append to source_head to get the * names of the file(s) to copy. * dest_head points to a buffer of size _MAX_PATH that ends with a ':' * or a FILESEP * dest_tail points to the null terminator of dest_head. * * Note that the buffers source_head/dest_head are passed down the * recursion to save stack space. */ static void recursiveCp( char *source_head, char *source_tail, char *source_wild, char *dest_head, char *dest_tail ) { DIR *directory; struct dirent *nextdirentry; void *crx = NULL; char *new_source_tail; char *new_dest_tail; pathCopy( source_head, source_tail, "*.*" ); directory = opendir( source_head ); if( directory == NULL ) { DropPrintALine( "file \"%s\" not found", source_head ); return; } if( rxflag ) { char *err = FileMatchInit( &crx, source_wild ); if( err != NULL ) { Die( "\"%s\": %s\n", err, source_wild ); } } /* * loop through all files */ while( ( nextdirentry = readdir( directory ) ) != NULL ) { /* * set up file name, then try to copy it */ FNameLower( nextdirentry->d_name ); if( rxflag ) { if( !FileMatch( crx, nextdirentry->d_name ) ) { continue; } } else { if( !FileMatchNoRx( nextdirentry->d_name, source_wild ) ) { continue; } } new_source_tail = pathCopy( source_head, source_tail, nextdirentry->d_name ); new_dest_tail = pathCopy( dest_head, dest_tail, nextdirentry->d_name ); if( nextdirentry->d_attr & _A_SUBDIR ) { if( !IsDotOrDotDot( nextdirentry->d_name ) && rflag ) { int rc; rc = mkdir( dest_head ); if( !rc ) { DirCnt++; } if( !sflag ) { if( rc ) { PrintALineThenDrop( "directory %s already exists", dest_head ); } else { PrintALineThenDrop( "created new directory %s", dest_head ); } } new_dest_tail = pathCopy( dest_head, new_dest_tail, FILESEPSTR ); new_source_tail = pathCopy( source_head, new_source_tail, FILESEPSTR ); recursiveCp( source_head, new_source_tail, rxflag ? "*" : "*.*", dest_head, new_dest_tail ); } } else { CopyOneFile( dest_head, source_head ); } } closedir( directory ); if( rxflag ) { FileMatchFini( crx ); } } /* DoCP */
/* DoRM - perform RM on a specified file */ void DoRM( const char *f ) { iolist *fhead = NULL; iolist *ftail = NULL; iolist *tmp; iolist *dhead = NULL; iolist *dtail = NULL; char *bo; char fpath[_MAX_PATH]; char tmppath[_MAX_PATH]; int i; int j; int k; int l; size_t len; DIR *d; struct dirent *nd; char wild[_MAX_PATH]; char *err; void *crx = NULL; /* get file path prefix */ fpath[0] = 0; for( i = ( int ) strlen( f ); i >= 0; i-- ) { if( f[i] == ':' || f[i] == '\\' || f[i] == '/' ) { fpath[i + 1] = 0; for( j = i; j >= 0; j-- ) fpath[j] = f[j]; i = -1; } } d = OpenDirAll( f, wild ); if( d == NULL ) { PrintALineThenDrop( "File (%s) not found.", f ); if( !fflag ) { error_occured = 1; } return; } if( rxflag ) { err = FileMatchInit( &crx, wild ); if( err != NULL ) Die( "\"%s\": %s\n", err, wild ); } k = ( int ) strlen( fpath ); while( ( nd = readdir( d ) ) != NULL ) { FNameLower( nd->d_name ); if( rxflag ) { if( !FileMatch( crx, nd->d_name ) ) continue; } else { if( !FileMatchNoRx( nd->d_name, wild ) ) continue; } /* set up file name, then try to delete it */ l = ( int ) strlen( nd->d_name ); bo = tmppath; for( i = 0; i < k; i++ ) *bo++ = fpath[i]; for( i = 0; i < l; i++ ) *bo++ = nd->d_name[i]; *bo = 0; if( nd->d_attr & _A_SUBDIR ) { /* process a directory */ if( !IsDotOrDotDot( nd->d_name ) ) { if( rflag ) { /* build directory list */ len = strlen( tmppath ); tmp = MemAlloc( sizeof( iolist ) + len ); if( dtail == NULL ) dhead = tmp; else dtail->next = tmp; dtail = tmp; memcpy( tmp->name, tmppath, len + 1 ); } else { PrintALineThenDrop( "%s is a directory, use -r", tmppath ); error_occured = 1; } } } else if( ( nd->d_attr & _A_RDONLY ) && !fflag ) { PrintALineThenDrop( "%s is read-only, use -f", tmppath ); error_occured = 1; } else { /* build file list */ len = strlen( tmppath ); tmp = MemAlloc( sizeof( iolist ) + len ); if( ftail == NULL ) fhead = tmp; else ftail->next = tmp; ftail = tmp; memcpy( tmp->name, tmppath, len + 1 ); tmp->attr = nd->d_attr; } } closedir( d ); if( rxflag ) FileMatchFini( crx ); /* process any files found */ tmp = fhead; if( tmp == NULL && !fflag ) { PrintALineThenDrop( "File (%s) not found.", f ); error_occured = 1; } while( tmp != NULL ) { if( tmp->attr & _A_RDONLY ) chmod( tmp->name, PMODE_RW ); if( iflag ) { PrintALine( "Delete %s (y\\n)", tmp->name ); while( ( i = tolower( getch() ) ) != 'y' && i != 'n' ) ; DropALine(); if( i == 'y' ) remove( tmp->name ); } else { if( !sflag ) PrintALine( "Deleting file %s", tmp->name ); remove( tmp->name ); } ftail = tmp; tmp = tmp->next; MemFree( ftail ); } /* process any directories found */ if( rflag && ( tmp = dhead ) != NULL ) { while( tmp != NULL ) { RecursiveRM( tmp->name ); dtail = tmp; tmp = tmp->next; MemFree( dtail ); } } }
/* DoRM - perform RM on a specified file */ static int DoRM( const char *f ) { iolist *tmp; iolist *dhead = NULL; iolist *dtail = NULL; char fpath[_MAX_PATH]; char fname[_MAX_PATH]; char *fpathend; size_t i; size_t j; size_t len; DIR *d; struct dirent *nd; int rc; int retval = 0; /* separate file name to path and file name parts */ len = strlen( f ); for( i = len; i > 0; --i ) { char ch = f[i - 1]; if( ch == '/' || ch == '\\' || ch == ':' ) { break; } } j = i; /* if no path then use current directory */ if( i == 0 ) { fpath[i++] = '.'; fpath[i++] = '/'; } else { memcpy( fpath, f, i ); } fpathend = fpath + i; *fpathend = '\0'; #ifdef __UNIX__ memcpy( fname, f + j, len - j + 1 ); #else if( strcmp( f + j, MASK_ALL_ITEMS ) == 0 ) { fname[0] = '*'; fname[1] = '\0'; } else { memcpy( fname, f + j, len - j + 1 ); } #endif d = opendir( fpath ); if( d == NULL ) { Log( false, "File (%s) not found.\n", f ); return( ENOENT ); } while( (nd = readdir( d )) != NULL ) { #ifdef __UNIX__ struct stat buf; if( fnmatch( fname, nd->d_name, FNM_PATHNAME | FNM_NOESCAPE ) == FNM_NOMATCH ) #else if( fnmatch( fname, nd->d_name, FNM_PATHNAME | FNM_NOESCAPE | FNM_IGNORECASE ) == FNM_NOMATCH ) #endif continue; /* set up file name, then try to delete it */ len = strlen( nd->d_name ); memcpy( fpathend, nd->d_name, len ); fpathend[len] = 0; len += i + 1; #ifdef __UNIX__ stat( fpath, &buf ); if( S_ISDIR( buf.st_mode ) ) { #else if( nd->d_attr & _A_SUBDIR ) { #endif /* process a directory */ if( IsDotOrDotDot( nd->d_name ) ) continue; if( rflag ) { /* build directory list */ tmp = Alloc( offsetof( iolist, name ) + len ); tmp->next = NULL; if( dtail == NULL ) { dhead = tmp; } else { dtail->next = tmp; } dtail = tmp; memcpy( tmp->name, fpath, len ); } else { Log( false, "%s is a directory, use -r\n", fpath ); retval = EACCES; } #ifdef __UNIX__ } else if( access( fpath, W_OK ) == -1 && errno == EACCES && !fflag ) { #else } else if( (nd->d_attr & _A_RDONLY) && !fflag ) { #endif Log( false, "%s is read-only, use -f\n", fpath ); retval = EACCES; } else { rc = remove_item( fpath, false ); if( rc != 0 ) { retval = rc; } } } closedir( d ); /* process any directories found */ for( tmp = dhead; tmp != NULL; tmp = dhead ) { dhead = tmp->next; rc = RecursiveRM( tmp->name ); if( rc != 0 ) { retval = rc; } free( tmp ); } return( retval ); } /* RecursiveRM - do an RM recursively on all files */ static int RecursiveRM( const char *dir ) { int rc; int rc2; char fname[_MAX_PATH]; /* purge the files */ strcpy( fname, dir ); strcat( fname, "/" MASK_ALL_ITEMS ); rc = DoRM( fname ); /* purge the directory */ rc2 = remove_item( dir, true ); if( rc == 0 ) rc = rc2; return( rc ); }
int TraverseDirectoryTreeW ( LPCWSTR pszPath, LPCWSTR pszPattern, DWORD fdwFlags, PFNTraverseDirectoryTreeCallbackW pfnCallback, LPVOID pvUser, int nCurrentDepth) { bool fSubdirs = (fdwFlags & TDT_SUBDIRS) != 0; bool fDiagnostic = (fdwFlags & TDT_DIAGNOSTIC) != 0; //bool fDirFirst = (fdwFlags & TDT_DIRFIRST) != 0; //bool fDirLast = (fdwFlags & TDT_DIRLAST) != 0; if (fDiagnostic) { if (pszPattern) bprintfl(*g_pbpDiag, "TDT[%d]: %04x path = '%s' pattern = '%s' subdirs = %d", nCurrentDepth, fdwFlags, pszPath, pszPattern, fSubdirs); else bprintfl(*g_pbpDiag, "TDT[%d]: %04x path = '%s' pattern = NULL subdirs = %d", nCurrentDepth, fdwFlags, pszPath, fSubdirs); } // build a string containing path\pattern, we will pass this // into FindFirstFile. there are some special cases. // we treat paths that end in \ as meaning path\*. // we replace *.* with * since it means the same thing and // is easier to parse. (this is a special case go back to DOS). // int cchPath = lstrlenW(pszPath); int cchMax = cchPath + MAX_PATH + 2; LPWSTR psz = (LPWSTR)malloc(cchMax * sizeof(WCHAR)); lstrcpyW(psz, pszPath); LPWSTR pszNext = psz + lstrlenW(psz); bool fMatchAll = false; if (pszPattern && pszPattern[0]) { if (0 == lstrcmpW(pszPattern, L"*.*") || 0 == lstrcmpW(pszPattern, L"*")) { fMatchAll = true; } pszNext = PathAddBackslashW(psz); lstrcpyW(pszNext, pszPattern); } else if (pszNext > psz && (pszNext[-1] == '\\' || pszNext[-1] == '/')) { fMatchAll = true; pszNext[0] = '*'; pszNext[1] = 0; } HRESULT hr = S_OK; int err = ERROR_SUCCESS; int ixCurrentItem = 0; DWORD dwFirst = TDT_FIRST; LinkedFindData * pdirs = NULL; WIN32_FIND_DATAW wfd; HANDLE hFind = FindFirstFileW(psz, &wfd); if (INVALID_HANDLE_VALUE == hFind) { err = GetLastError(); // if we can't open the directory because of an access denied error // it might be the DACLs that are causing the problem. If so, then // just remove the dacls. we are going to be deleting the directory // anway... // if (ERROR_ACCESS_DENIED == err) { int errT = RemoveFileDACLs(pszPath, fdwFlags & TDT_DIAGNOSTIC, g_pbpDiag); if (errT) err = errT; else { hFind = FindFirstFileW(psz, &wfd); if (INVALID_HANDLE_VALUE == hFind) { errT = GetLastError(); if (errT != err) ReportErrorW(errT, "FindFirstFile ", psz); } else { err = 0; } } } if (err) ReportErrorW(err, "FindFirstFile ", psz); } if (hFind && INVALID_HANDLE_VALUE != hFind) { do { // ignore . and .. if (IsDotOrDotDot(wfd.cFileName)) continue; ++ixCurrentItem; bool fSkip = false; if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // if we are recursing, and we happen to be matching all, then remember this // directory for later (so we don't need to enumerate again for dirs). // otherwise we will have to re-enumerate in this directory to get subdirs. if (fSubdirs && fMatchAll) { LinkedFindData * pdir = (LinkedFindData*)malloc(sizeof(LinkedFindData)); pdir->wfd = wfd; pdir->next = pdirs; pdirs = pdir; fSkip = true; // we will do the callback for this directory later, if at all. } else if (fdwFlags & TDT_NODIRS) fSkip = true; } else { if (fdwFlags & TDT_NOFILES) fSkip = true; } if (fDiagnostic) bprintfl (*g_pbpDiag, "TDT[%d]: 0x%08x %s %s", nCurrentDepth, wfd.dwFileAttributes, wfd.cFileName, fSkip ? "<skip>" : ""); if ( ! fSkip) { lstrcpyW(pszNext, wfd.cFileName); if ( ! pfnCallback(pvUser, psz, pszNext - psz, (fdwFlags & ~(TDT_DIRLAST | TDT_DIRFIRST)) | dwFirst, nCurrentDepth, ixCurrentItem, wfd)) break; dwFirst = 0; } } while (FindNextFileW(hFind, &wfd)); if (fDiagnostic) bprintfl (*g_pbpDiag, "TDT[%d]: Done with %s %s", nCurrentDepth, pszPath, pszPattern); } // we want to traverse subdirs, but we were unable to build a list of dirs when we // enumerated the files, so re-enumerate with * to get the directories. if (fSubdirs && ! fMatchAll) { if (hFind && INVALID_HANDLE_VALUE != hFind) FindClose(hFind); lstrcpyW(pszNext, L"*"); hFind = FindFirstFileW(psz, &wfd); if (INVALID_HANDLE_VALUE != hFind) { do { if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && ! IsDotOrDotDot(wfd.cFileName)) { LinkedFindData * pdir = (LinkedFindData*)malloc(sizeof(LinkedFindData)); pdir->wfd = wfd; pdir->next = pdirs; pdirs = pdir; } } while (FindNextFileW(hFind, &wfd)); } } err = GetLastError(); if (ERROR_NO_MORE_FILES == err) err = ERROR_SUCCESS; // now traverse and callback subdirectories. // if (fSubdirs && pdirs) { pdirs = ReverseLinkedList(pdirs); while (pdirs) { LinkedFindData * pdir = pdirs; pdirs = pdirs->next; lstrcpyW(pszNext, pdir->wfd.cFileName); if ((fdwFlags & TDT_DIRFIRST) && ! (fdwFlags & TDT_NODIRS)) { if (fDiagnostic) bprintfl (*g_pbpDiag, "TDT[%d]: DIRFIRST 0x%08x %s %s", nCurrentDepth, pszPath, pszPattern); if ( ! pfnCallback(pvUser, psz, pszNext - psz, TDT_DIRFIRST | (fdwFlags & ~TDT_DIRLAST) | dwFirst, nCurrentDepth, ixCurrentItem, pdir->wfd)) break; dwFirst = 0; } err = TraverseDirectoryTreeW(psz, pszPattern, fdwFlags, pfnCallback, pvUser, nCurrentDepth+1); if ((fdwFlags & TDT_DIRLAST) && ! (fdwFlags & TDT_NODIRS)) { if (fDiagnostic) bprintfl (*g_pbpDiag, "TDT[%d]: DIRLAST 0x%08x %s %s", nCurrentDepth, pszPath, pszPattern); if ( ! pfnCallback(pvUser, psz, pszNext - psz, TDT_DIRLAST | (fdwFlags & ~TDT_DIRFIRST) | dwFirst, nCurrentDepth, ixCurrentItem, pdir->wfd)) break; dwFirst = 0; } } } if (hFind && INVALID_HANDLE_VALUE != hFind) FindClose(hFind); return err; }