Exemplo n.º 1
0
int ParseVersionFileName(char *Name,wchar *NameW,bool Truncate)
{
  int Version=0;
  char *VerText=strrchrd(Name,';');
  if (VerText!=NULL)
  {
    Version=atoi(VerText+1);
    if (Truncate)
      *VerText=0;
  }
  if (NameW!=NULL)
  {
    wchar *VerTextW=strrchrw(NameW,';');
    if (VerTextW!=NULL)
    {
      if (Version==0)
        Version=atoiw(VerTextW+1);
      if (Truncate)
        *VerTextW=0;
    }
  }
  return(Version);
}
Exemplo n.º 2
0
char *GetExt(const char *Name)
{
  return(strrchrd(PointToName(Name),'.'));
}
Exemplo n.º 3
0
int ScanTree::FindProc(FindData *FindData)
{
  if (*CurMask==0)
    return(SCAN_NEXT);
  FastFindFile=false;
  if (FindStack[Depth]==NULL)
  {
    bool Wildcards=IsWildcard(CurMask,CurMaskW);
    bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
    bool IsDir=FindCode && FindData->IsDir;
    bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
                   Wildcards && Recurse==RECURSE_WILDCARDS);
    if (Depth==0)
      SearchAllInRoot=SearchAll;
    if (SearchAll || Wildcards)
    {
      FindStack[Depth]=new FindFile;
      char SearchMask[NM];
      strcpy(SearchMask,CurMask);
      if (SearchAll)
        strcpy(PointToName(SearchMask),MASKALL);
      FindStack[Depth]->SetMask(SearchMask);
      if (*CurMaskW)
      {
        wchar SearchMaskW[NM];
        strcpyw(SearchMaskW,CurMaskW);
        if (SearchAll)
          strcpyw(PointToName(SearchMaskW),MASKALLW);
        FindStack[Depth]->SetMaskW(SearchMaskW);
      }
    }
    else
    {
      FastFindFile=true;
      if (!FindCode)
      {
        ErrHandler.OpenErrorMsg(CurMask);
        return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
      }
    }
  }

  if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
  {
    bool Error=FindData->Error;

#ifdef _WIN_32
    if (Error && strstr(CurMask,"System Volume Information\\")!=NULL)
      Error=false;
#endif

#ifndef SILENT
    if (Error)
    {
      Log(NULL,St(MScanError),CurMask);
    }
#endif

    char DirName[NM];
    wchar DirNameW[NM];
    *DirName=0;
    *DirNameW=0;

    delete FindStack[Depth];
    FindStack[Depth--]=NULL;
    while (Depth>=0 && FindStack[Depth]==NULL)
      Depth--;
    if (Depth < 0)
      return(SCAN_DONE);
    char *Slash=strrchrd(CurMask,CPATHDIVIDER);
    if (Slash!=NULL)
    {
      char Mask[NM];
      strcpy(Mask,Slash);
      *Slash=0;
      strcpy(DirName,CurMask);
      char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
      if (PrevSlash==NULL)
        strcpy(CurMask,Mask+1);
      else
        strcpy(PrevSlash,Mask);
    }

    if (*CurMaskW!=0)
    {
      wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER);
      if (Slash!=NULL)
      {
        wchar Mask[NM];
        strcpyw(Mask,Slash);
        *Slash=0;
        strcpyw(DirNameW,CurMaskW);
        wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER);
        if (PrevSlash==NULL)
          strcpyw(CurMaskW,Mask+1);
        else
          strcpyw(PrevSlash,Mask);
      }
      if (LowAscii(CurMaskW))
        *CurMaskW=0;
    }
    if (GetDirs==SCAN_GETDIRSTWICE &&
        FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir)
      return(Error ? SCAN_ERROR:SCAN_SUCCESS);
    return(Error ? SCAN_ERROR:SCAN_NEXT);
  }

  if (FindData->IsDir)
  {
    if (!FastFindFile && Depth==0 && !SearchAllInRoot)
      return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);

    char Mask[NM];
    strcpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask));
    strcpy(CurMask,FindData->Name);

    if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
    {
#ifndef SILENT
      Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
      Log(NULL,St(MPathTooLong));
#endif
      return(SCAN_ERROR);
    }

    AddEndSlash(CurMask);
    strcat(CurMask,Mask);

    if (*CurMaskW && *FindData->NameW==0)
      CharToWide(FindData->Name,FindData->NameW);
    if (*FindData->NameW!=0)
    {
      wchar Mask[NM];
      if (FastFindFile)
        strcpyw(Mask,MASKALLW);
      else
        if (*CurMaskW)
          strcpyw(Mask,PointToName(CurMaskW));
        else
          CharToWide(PointToName(CurMask),Mask);
      strcpyw(CurMaskW,FindData->NameW);
      AddEndSlash(CurMaskW);
      strcatw(CurMaskW,Mask);
    }
    Depth++;
  }
  if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
    return(SCAN_NEXT);
  return(SCAN_SUCCESS);
}
Exemplo n.º 4
0
int ScanTree::FindProc(FindData *FindData)
{
  if (*CurMask==0)
    return(SCAN_NEXT);
  FastFindFile=false;
  if (FindStack[Depth]==NULL)
  {
    bool Wildcards=IsWildcard(CurMask,CurMaskW);
    bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FindData,GetLinks);
    bool IsDir=FindCode && FindData->IsDir;
    bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
                   Wildcards && Recurse==RECURSE_WILDCARDS);
    if (Depth==0)
      SearchAllInRoot=SearchAll;
    if (SearchAll || Wildcards)
    {
      FindStack[Depth]=new FindFile;
      char SearchMask[NM];
      strcpy(SearchMask,CurMask);
      if (SearchAll)
        strcpy(PointToName(SearchMask),MASKALL);
      FindStack[Depth]->SetMask(SearchMask);
      if (*CurMaskW)
      {
        wchar SearchMaskW[NM];
        strcpyw(SearchMaskW,CurMaskW);
        if (SearchAll)
          strcpyw(PointToName(SearchMaskW),MASKALLW);
        FindStack[Depth]->SetMaskW(SearchMaskW);
      }
    }
    else
    {
      FastFindFile=true;
      if (!FindCode)
      {
        if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
          return(SCAN_NEXT);
        ErrHandler.OpenErrorMsg(ErrArcName,CurMask);
        return(FindData->Error ? SCAN_ERROR:SCAN_NEXT);
      }
    }
  }

  if (!FastFindFile && !FindStack[Depth]->Next(FindData,GetLinks))
  {
    bool Error=FindData->Error;

#ifdef _WIN_32
    if (Error)
    {
      // Do not display an error if we cannot scan contents of reparse
      // point. Vista contains a lot of reparse (or junction) points,
      // which are not accessible.
      if ((FindData->FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
        Error=false;

      // Do not display an error if we cannot scan contents of
      // "System Volume Information" folder. Normally it is not accessible.
      if (strstr(CurMask,"System Volume Information\\")!=NULL)
        Error=false;
    }
#endif

    if (Cmd!=NULL && Cmd->ExclCheck(CurMask,true))
      Error=false;

#ifndef SILENT
    if (Error)
    {
      Log(NULL,St(MScanError),CurMask);
    }
#endif

    char DirName[NM];
    wchar DirNameW[NM];
    *DirName=0;
    *DirNameW=0;

    delete FindStack[Depth];
    FindStack[Depth--]=NULL;
    while (Depth>=0 && FindStack[Depth]==NULL)
      Depth--;
    if (Depth < 0)
    {
      if (Error)
        Errors++;
      return(SCAN_DONE);
    }
    char *Slash=strrchrd(CurMask,CPATHDIVIDER);
    if (Slash!=NULL)
    {
      char Mask[NM];
      strcpy(Mask,Slash);
      if (Depth<SetAllMaskDepth)
        strcpy(Mask+1,PointToName(OrigCurMask));
      *Slash=0;
      strcpy(DirName,CurMask);
      char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
      if (PrevSlash==NULL)
        strcpy(CurMask,Mask+1);
      else
        strcpy(PrevSlash,Mask);
    }

    if (*CurMaskW!=0)
    {
      wchar *Slash=strrchrw(CurMaskW,CPATHDIVIDER);
      if (Slash!=NULL)
      {
        wchar Mask[NM];
        strcpyw(Mask,Slash);
        if (Depth<SetAllMaskDepth)
          strcpyw(Mask+1,PointToName(OrigCurMaskW));
        *Slash=0;
        strcpyw(DirNameW,CurMaskW);
        wchar *PrevSlash=strrchrw(CurMaskW,CPATHDIVIDER);
        if (PrevSlash==NULL)
          strcpyw(CurMaskW,Mask+1);
        else
          strcpyw(PrevSlash,Mask);
      }
#ifndef _WIN_CE
      if (LowAscii(CurMaskW))
        *CurMaskW=0;
#endif
    }
    if (GetDirs==SCAN_GETDIRSTWICE &&
        FindFile::FastFind(DirName,DirNameW,FindData,GetLinks) && FindData->IsDir)
      return(Error ? SCAN_ERROR:SCAN_SUCCESS);
    return(Error ? SCAN_ERROR:SCAN_NEXT);
  }

  if (FindData->IsDir)
  {
    if (!FastFindFile && Depth==0 && !SearchAllInRoot)
      return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);

//    if (GetDirs==SCAN_GETCURDIRS && Depth==0 && !SearchAllInRoot)
//      return(SCAN_SUCCESS);

    char Mask[NM];
    bool MaskAll=FastFindFile;

//    bool MaskAll=CmpName(CurMask,FindData->Name,MATCH_NAMES);

    strcpy(Mask,MaskAll ? MASKALL:PointToName(CurMask));
    strcpy(CurMask,FindData->Name);

    if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
    {
#ifndef SILENT
      Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
      Log(NULL,St(MPathTooLong));
#endif
      return(SCAN_ERROR);
    }

    AddEndSlash(CurMask);
    strcat(CurMask,Mask);

    if (*CurMaskW && *FindData->NameW==0)
      CharToWide(FindData->Name,FindData->NameW);
    if (*FindData->NameW!=0)
    {
      wchar Mask[NM];
      if (FastFindFile)
        strcpyw(Mask,MASKALLW);
      else
        if (*CurMaskW)
          strcpyw(Mask,PointToName(CurMaskW));
        else
          CharToWide(PointToName(CurMask),Mask);
      strcpyw(CurMaskW,FindData->NameW);
      AddEndSlash(CurMaskW);
      strcatw(CurMaskW,Mask);
    }
    Depth++;
    if (MaskAll)
      SetAllMaskDepth=Depth;
  }
  if (!FastFindFile && !CmpName(CurMask,FindData->Name,MATCH_NAMES))
    return(SCAN_NEXT);
  return(SCAN_SUCCESS);
}
Exemplo n.º 5
0
SCAN_CODE ScanTree::FindProc(FindData *FD)
{
  if (*CurMask==0)
    return(SCAN_NEXT);
  bool FastFindFile=false;
  
  if (FindStack[Depth]==NULL) // No FindFile object for this depth yet.
  {
    bool Wildcards=IsWildcard(CurMask,CurMaskW);

    // If we have a file name without wildcards, we can try to use
    // FastFind to optimize speed. For example, in Unix it results in
    // stat call instead of opendir/readdir/closedir.
    bool FindCode=!Wildcards && FindFile::FastFind(CurMask,CurMaskW,FD,GetLinks);

    bool IsDir=FindCode && FD->IsDir;

    // SearchAll means that we'll use "*" mask for search, so we'll find
    // subdirectories and will be able to recurse into them.
    // We do not use "*" for directories at any level or for files
    // at top level in recursion mode.
    bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
                   Wildcards && Recurse==RECURSE_WILDCARDS || 
                   ScanEntireDisk && Recurse!=RECURSE_DISABLE);
    if (Depth==0)
      SearchAllInRoot=SearchAll;
    if (SearchAll || Wildcards)
    {
      // Create the new FindFile object for wildcard based search.
      FindStack[Depth].reset(new FindFile);
      char SearchMask[NM];
      strcpy(SearchMask,CurMask);
      if (SearchAll)
        strcpy(PointToName(SearchMask),MASKALL);
      FindStack[Depth]->SetMask(SearchMask);
      if (*CurMaskW!=0)
      {
        wchar SearchMaskW[NM];
        wcscpy(SearchMaskW,CurMaskW);
        if (SearchAll)
          wcscpy(PointToName(SearchMaskW),MASKALLW);
        FindStack[Depth]->SetMaskW(SearchMaskW);
      }
    }
    else
    {
      // Either we failed to fast find or we found a file or we found
      // a directory in RECURSE_DISABLE mode, so we do not need to scan it.
      // We can return here and do not need to process further.
      // We need to process further only if we fast found a directory.
      if (!FindCode || !FD->IsDir || Recurse==RECURSE_DISABLE)
      {
         // Return SCAN_SUCCESS if we found a file.
        SCAN_CODE RetCode=SCAN_SUCCESS;

        if (!FindCode)
        {
          // Return SCAN_ERROR if problem is more serious than just
          // "file not found".
          RetCode=FD->Error ? SCAN_ERROR:SCAN_NEXT;

          // If we failed to find an object, but our current mask is excluded,
          // we skip this object and avoid indicating an error.
          if (Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true))
            RetCode=SCAN_NEXT;
          else
            ErrHandler.OpenErrorMsg(ErrArcName,NULL,CurMask,CurMaskW);
        }

        // If we searched only for one file or directory in "fast find" 
        // (without a wildcard) mode, let's set masks to zero, 
        // so calling function will know that current mask is used 
        // and next one must be read from mask list for next call.
        // It is not necessary for directories, because even in "fast find"
        // mode, directory recursing will quit by (Depth < 0) condition,
        // which returns SCAN_DONE to calling function.
        *CurMask=0;
        *CurMaskW=0;

        return(RetCode);
      }

      // We found a directory using only FindFile::FastFind function.
      FastFindFile=true;
    }
  }

  if (!FastFindFile && !FindStack[Depth]->Next(FD,GetLinks))
  {
    // We cannot find anything more in directory either because of
    // some error or just as result of all directory entries already read.

    bool Error=FD->Error;

#ifdef _WIN_ALL
    if (Error)
    {
      // Do not display an error if we cannot scan contents of reparse
      // point. Vista contains a lot of reparse (or junction) points,
      // which are not accessible.
      if ((FD->FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)!=0)
        Error=false;

      // Do not display an error if we cannot scan contents of
      // "System Volume Information" folder. Normally it is not accessible.
      if (strstr(CurMask,"System Volume Information\\")!=NULL)
        Error=false;
    }
#endif

    if (Error && Cmd!=NULL && Cmd->ExclCheck(CurMask,false,true,true))
      Error=false;

#ifndef SILENT
    if (Error)
    {
      Log(NULL,St(MScanError),CurMask);
      ErrHandler.SysErrMsg();
    }
#endif

    char DirName[NM];
    wchar DirNameW[NM];
    *DirName=0;
    *DirNameW=0;

    // Going to at least one directory level higher.
    FindStack[Depth--].reset();
    while (Depth>=0 && FindStack[Depth]==NULL)
      Depth--;
    if (Depth < 0)
    {
      // Directories scanned both in normal and FastFindFile mode,
      // finally exit from scan here, by (Depth < 0) condition.

      if (Error)
        Errors++;
      return(SCAN_DONE);
    }
    char *Slash=strrchrd(CurMask,CPATHDIVIDER);
    if (Slash!=NULL)
    {
      char Mask[NM];
      strcpy(Mask,Slash);
      if (Depth<SetAllMaskDepth)
        strcpy(Mask+1,PointToName(OrigCurMask));
      *Slash=0;
      strcpy(DirName,CurMask);
      char *PrevSlash=strrchrd(CurMask,CPATHDIVIDER);
      if (PrevSlash==NULL)
        strcpy(CurMask,Mask+1);
      else
        strcpy(PrevSlash,Mask);
    }

    if (*CurMaskW!=0)
    {
      wchar *Slash=wcsrchr(CurMaskW,CPATHDIVIDER);
      if (Slash!=NULL)
      {
        wchar Mask[NM];
        wcscpy(Mask,Slash);
        if (Depth<SetAllMaskDepth)
          wcscpy(Mask+1,PointToName(OrigCurMaskW));
        *Slash=0;
        wcscpy(DirNameW,CurMaskW);
        wchar *PrevSlash=wcsrchr(CurMaskW,CPATHDIVIDER);
        if (PrevSlash==NULL)
          wcscpy(CurMaskW,Mask+1);
        else
          wcscpy(PrevSlash,Mask);
      }
#ifndef _WIN_CE
//      if (LowAscii(CurMaskW))
//        *CurMaskW=0;
#endif
    }
    if (GetDirs==SCAN_GETDIRSTWICE &&
        FindFile::FastFind(DirName,DirNameW,FD,GetLinks) && FD->IsDir)
    {
      FD->Flags|=FDDF_SECONDDIR;
      return(Error ? SCAN_ERROR:SCAN_SUCCESS);
    }
    return(Error ? SCAN_ERROR:SCAN_NEXT);
  }

  if (FD->IsDir)
  {
    // If we found the directory in top (Depth==0) directory
    // and if we are not in "fast find" (directory name only as argument)
    // or in recurse (SearchAll was set when opening the top directory) mode,
    // we do not recurse into this directory. We either return it by itself
    // or skip it.
    if (!FastFindFile && Depth==0 && !SearchAllInRoot)
      return(GetDirs==SCAN_GETCURDIRS ? SCAN_SUCCESS:SCAN_NEXT);

    // Let's check if directory name is excluded, so we do not waste
    // time searching in directory, which will be excluded anyway.
    if (Cmd!=NULL && (Cmd->ExclCheck(FD->Name,true,false,false) ||
        Cmd->ExclDirByAttr(FD->FileAttr)))
    {
      // If we are here in "fast find" mode, it means that entire directory
      // specified in command line is excluded. Then we need to return
      // SCAN_DONE to go to next mask and avoid the infinite loop
      // in GetNext() function. Such loop would be possible in case of
      // SCAN_NEXT code and "rar a arc dir -xdir" command.

      return(FastFindFile ? SCAN_DONE:SCAN_NEXT);
    }
    
    char Mask[NM];

    strcpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask));
    strcpy(CurMask,FD->Name);

    if (strlen(CurMask)+strlen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
    {
#ifndef SILENT
      Log(NULL,"\n%s%c%s",CurMask,CPATHDIVIDER,Mask);
      Log(NULL,St(MPathTooLong));
#endif
      return(SCAN_ERROR);
    }

    AddEndSlash(CurMask);
    strcat(CurMask,Mask);

    if (*CurMaskW && *FD->NameW==0)
      CharToWide(FD->Name,FD->NameW);
    if (*FD->NameW!=0)
    {
      wchar Mask[NM];
      if (FastFindFile)
        wcscpy(Mask,MASKALLW);
      else
        if (*CurMaskW)
          wcscpy(Mask,PointToName(CurMaskW));
        else
          CharToWide(PointToName(CurMask),Mask);
      wcscpy(CurMaskW,FD->NameW);
      AddEndSlash(CurMaskW);
      wcscat(CurMaskW,Mask);
    }
    Depth++;

    // We need to use OrigCurMask for depths less than SetAllMaskDepth
    // and "*" for depths equal or larger than SetAllMaskDepth.
    // It is important when "fast finding" directories at Depth > 0.
    // For example, if current directory is RootFolder and we compress
    // the following directories structure:
    //   RootFolder
    //     +--Folder1
    //     |  +--Folder2
    //     |  +--Folder3
    //     +--Folder4
    // with 'rar a -r arcname Folder2' command, rar could add not only
    // Folder1\Folder2 contents, but also Folder1\Folder3 if we were using
    // "*" mask at all levels. We need to use "*" mask inside of Folder2,
    // but return to "Folder2" mask when completing scanning Folder2.
    // We can rewrite SearchAll expression above to avoid fast finding
    // directories at Depth > 0, but then 'rar a -r arcname Folder2'
    // will add the empty Folder2 and do not add its contents.

    if (FastFindFile)
      SetAllMaskDepth=Depth;
  }
  if (!FastFindFile && !CmpName(CurMask,FD->Name,MATCH_NAMES))
    return(SCAN_NEXT);

  return(SCAN_SUCCESS);
}