예제 #1
0
파일: files_lib.c 프로젝트: rcorrieri/core
bool HashDirectoryTree(const char *path,
                       const char **extensions_filter,
                       EVP_MD_CTX *crypto_context)
{
    HashDirectoryTreeState state;
    memset(state.buffer, 0, 1024);
    state.extensions_filter = extensions_filter;
    state.crypto_context = crypto_context;

    return TraverseDirectoryTree(path, HashDirectoryTreeCallback, &state);
}
예제 #2
0
int TraverseDirectoryTree (
   LPCTSTR pszPath, 
   LPCTSTR pszPattern, 
   DWORD   fdwFlags, 
   PFNTraverseDirectoryTreeCallback 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 = lstrlen(pszPath);
   int cchMax = cchPath + MAX_PATH + 2;
   LPTSTR psz = (LPTSTR)malloc(cchMax * sizeof(TCHAR));
   lstrcpy(psz, pszPath);
   LPTSTR pszNext = psz + lstrlen(psz);

   bool fMatchAll = false;
   if (pszPattern && pszPattern[0])
      {
      if (0 == lstrcmp(pszPattern, TEXT("*.*")) || 0 == lstrcmp(pszPattern, TEXT("*")))
         {
         fMatchAll = true;
         }
      pszNext = PathAddBackslash(psz);
      lstrcpy(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_DATA wfd;
   HANDLE hFind = FindFirstFile(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 = FindFirstFile(psz, &wfd);
            if (INVALID_HANDLE_VALUE == hFind) 
               {
               errT = GetLastError();
               if (errT != err)
                  ReportError(errT, "FindFirstFile ", psz);
               }
            else
               {
               err = 0;
               }
            }
         }
      if (err)
         ReportError(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)
            {
            lstrcpy(pszNext, wfd.cFileName); 
            if ( ! pfnCallback(pvUser, psz, pszNext - psz, (fdwFlags & ~(TDT_DIRLAST | TDT_DIRFIRST)) | dwFirst, nCurrentDepth, ixCurrentItem, wfd))
               break;
            dwFirst = 0;
            }

         } while (FindNextFile(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);

      lstrcpy(pszNext, TEXT("*"));
      hFind = FindFirstFile(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 (FindNextFile(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;

         lstrcpy(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 = TraverseDirectoryTree(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;
}
예제 #3
0
int DeletePath(LPCTSTR pszPathIn, 
               LPCTSTR pszPattern, 
               DWORD   fdwTraverse, 
               DWORD   fdwSecurity, 
               DWORD   fdwVerbose, 
               BPRINT_BUFFER & bp)
{
   DWORD fdwFlags = fdwTraverse & (TDT_INPUTMASK & ~TDT_USERMASK);
   if (fdwVerbose & DP_V_VERBOSE)
      fdwFlags |= TDT_USER_F_VERBOSE;
   if (fdwVerbose & DP_V_DIAGNOSTIC)
      fdwFlags |= TDT_DIAGNOSTIC;

   bool fQuiet = (fdwVerbose & DP_V_QUIET) != 0;

   DeletePathData lad;
   ZeroStruct(&lad);
   lad.pbp = &bp;

   if (fdwSecurity & DP_S_NODELETE)
      lad.fNoDelete = true;

   fdwFlags |= TDT_DIRLAST; // So we get directory callbacks after children have been deleted.

   // if the path isn't too long, convert to canonical form.  for long paths
   // they has better provide canonical form to begin with.
   //
   TCHAR szCanonPath[MAX_PATH+1];
   LPCTSTR pszPath = pszPathIn;
   if (lstrlen(pszPathIn) < MAX_PATH &&
       PathCanonicalize(szCanonPath, pszPathIn))
      {
      pszPath = szCanonPath;      
      }

   // the unicode versions of the windows file api's can handle very long
   // path names if they are canonical and if they are preceeded by \\?\.
   // if we are build unicode, take advantage of that capability.
  #ifdef UNICODE
   static const TCHAR szPre[]= TEXT("\\\\?\\");
   TCHAR szFullPath[MAX_PATH + NUMCHARS(szPre)];
   TCHAR * pszFullPath = szFullPath;
   TCHAR * pszFilePart = NULL;

   lstrcpy(szFullPath, szPre);
   UINT cchFullPath = GetFullPathName(pszPath, MAX_PATH, szFullPath + NUMCHARS(szPre)-1, &pszFilePart);
   if (cchFullPath >= NUMCHARS(szFullPath)-1)
      {
      pszFullPath = (TCHAR *)LocalAlloc(LPTR, (cchFullPath + NUMCHARS(szPre) + 2) * sizeof(TCHAR));
      if (pszFullPath)
         {
         lstrcpy(pszFullPath, szPre);
         if (GetFullPathName(pszPath, cchFullPath+2, pszFullPath + NUMCHARS(szPre)-1, &pszFilePart) <= cchFullPath+2)
            pszPath = pszFullPath;
         }
      }
   else
      pszPath = szFullPath;
  #endif

   int err = 0;
   DWORD fdwFileAttributes = GetFileAttributes(pszPath);
   if (INVALID_FILE_ATTRIBUTES == fdwFileAttributes)
      {
      fdwFileAttributes = 0;
      err = GetLastError();
      ReportError(err, "Could not get attributes for ", pszPath);
      return err;
      }
   const bool fIsDir = (fdwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;

   if (fdwFlags & TDT_DIAGNOSTIC)
      bprintfl(bp, TEXT("Delete %s 0x%04X %s\\%s"), fIsDir ? TEXT("Directory") : TEXT("File"), fdwFlags, pszPath, pszPattern);

   if (fIsDir)
      {
      if (fdwTraverse & TDT_SUBDIRS)
         {
         if ( ! pszPattern || ! pszPattern[0])
            err = TraverseDirectoryTree(pszPath, TEXT("*"), fdwFlags, DeletePathCallback, &lad, 0);
         else
            err = TraverseDirectoryTree(pszPath, pszPattern, fdwFlags, DeletePathCallback, &lad, 0);
         }

      if ( ! err || (fdwFlags & TDT_CONTINUE))
         {
         bprint_EndLine(bp);
         if ( ! (fdwTraverse & TDT_NODIRS) && (!pszPattern || !pszPattern[0]))
            {
            if ( ! fQuiet)
               {
               bprint(bp, lad.fNoDelete ? TEXT("NoRemove ") : TEXT("Removing "));
               bprint(bp, pszPath);
               }
            if ( ! lad.fNoDelete && ! RemoveDirectory(pszPath))
               {
               bprint_EndLine(bp);
               err = GetLastError();
               ReportError(err, "RemoveDirectory", pszPath);
               if ( ! (fdwFlags & TDT_CONTINUE))
                  if ( ! fQuiet) bprintl(bp, "Aborting.");
               }
            }
         }
      }
   else // initial path is a file, not a directory. 
      {
      if (fdwTraverse & TDT_SUBDIRS)
         {
         if ( ! pszPattern || ! pszPattern[0])
            {
            err = TraverseDirectoryTree(pszPath, TEXT("*"), fdwFlags, DeletePathCallback, &lad, 0);
            }
         else
            {
            //#pragma REMIND("TJ: add code to split the file from the path and recurse on the filename.")
            }
         }
      if (fdwTraverse & TDT_NOFILES)
         {
         // Nothing to do.
         }
      else if ( ! pszPattern || ! pszPattern[0])
         {
         if ( ! fQuiet)
            {
            bprint(bp, lad.fNoDelete ? TEXT("NoDelete ") : TEXT("Deleting "));
            bprint(bp, pszPath);
            }
         if ( ! lad.fNoDelete &&  ! DeleteFile(pszPath))
            {
            bprint_EndLine(bp);
            err = GetLastError();
            ReportError(err, "DeleteFile", pszPath);
            if ( ! (fdwFlags & TDT_CONTINUE))
               if ( ! fQuiet) bprintl(bp, "Aborting.");
            }
         }
      }

   bprint_EndLine(bp);
   return err;
}