Example #1
0
/*
 * 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 */
Example #2
0
/*
 * 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 */
Example #3
0
/* 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 );
        }
    }
}
Example #4
0
/* 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 );
}
Example #5
0
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;
}