Пример #1
0
int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType)
{
  if (strlen(NewLhd.FileName)>=NM || wcslen(NewLhd.FileNameW)>=NM)
    return(0);
  bool Dir=(NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
  if (ExclCheck(NewLhd.FileName,Dir,false,true))
    return(0);
#ifndef SFX_MODULE
  if (TimeCheck(NewLhd.mtime))
    return(0);
  if ((NewLhd.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (NewLhd.FileAttr & InclFileAttr)==0)
    return(0);
  if (!Dir && SizeCheck(NewLhd.FullUnpSize))
    return(0);
#endif
  char *ArgName;
  wchar *ArgNameW;
  FileArgs->Rewind();
  for (int StringCount=1;FileArgs->GetString(&ArgName,&ArgNameW);StringCount++)
  {
#ifndef SFX_MODULE
    bool Unicode=(NewLhd.Flags & LHD_UNICODE) || ArgNameW!=NULL && *ArgNameW!=0;
    if (Unicode)
    {
      wchar NameW[NM],ArgW[NM],*NamePtr=NewLhd.FileNameW;
      bool CorrectUnicode=true;
      if (ArgNameW==NULL || *ArgNameW==0)
      {
        if (!CharToWide(ArgName,ArgW) || *ArgW==0)
          CorrectUnicode=false;
        ArgNameW=ArgW;
      }
      if ((NewLhd.Flags & LHD_UNICODE)==0)
      {
        if (!CharToWide(NewLhd.FileName,NameW) || *NameW==0)
          CorrectUnicode=false;
        NamePtr=NameW;
      }
      if (CmpName(ArgNameW,NamePtr,MatchType))
      {
        if (ExactMatch!=NULL)
          *ExactMatch=wcsicompc(ArgNameW,NamePtr)==0;
        return(StringCount);
      }
      if (CorrectUnicode)
        continue;
    }
#endif
    if (CmpName(ArgName,NewLhd.FileName,MatchType))
    {
      if (ExactMatch!=NULL)
        *ExactMatch=stricompc(ArgName,NewLhd.FileName)==0;
      return(StringCount);
    }
  }
  return(0);
}
Пример #2
0
int CommandData::IsProcessFile(FileHeader &NewLhd,bool *ExactMatch,int MatchType)
{
  if (strlen(NewLhd.FileName)>=NM || strlenw(NewLhd.FileNameW)>=NM)
    return(0);
  if (ExclCheck(NewLhd.FileName,false))
    return(0);
#ifndef SFX_MODULE
  if (TimeCheck(NewLhd.mtime))
    return(0);
#endif
  char *ArgName;
  wchar *ArgNameW;
  FileArgs->Rewind();
  for (int StringCount=1;FileArgs->GetString(&ArgName,&ArgNameW);StringCount++)
  {
#ifndef SFX_MODULE
    bool Unicode=(NewLhd.Flags & LHD_UNICODE) || ArgNameW!=NULL;
    if (Unicode)
    {
      wchar NameW[NM],ArgW[NM],*NamePtr=NewLhd.FileNameW;
      if (ArgNameW==NULL)
      {
        CharToWide(ArgName,ArgW);
        ArgNameW=ArgW;
      }
      if ((NewLhd.Flags & LHD_UNICODE)==0)
      {
        CharToWide(NewLhd.FileName,NameW);
        NamePtr=NameW;
      }
      if (CmpName(ArgNameW,NamePtr,MatchType))
      {
        if (ExactMatch!=NULL)
          *ExactMatch=stricompcw(ArgNameW,NamePtr)==0;
        return(StringCount);
      }
      continue;
    }
#endif
    if (CmpName(ArgName,NewLhd.FileName,MatchType))
    {
      if (ExactMatch!=NULL)
        *ExactMatch=stricompc(ArgName,NewLhd.FileName)==0;
      return(StringCount);
    }
  }
  return(0);
}
Пример #3
0
/* сравнить имя файла со списком масок
   Возвращает TRUE в случае успеха.
   Путь к файлу в FileName НЕ игнорируется */
bool FileMasksProcessor::Compare(const wchar_t *FileName)
{
	if (bRE)
	{
		int i = n;
		int len = StrLength(FileName);
		bool ret = re->Search(FileName,FileName+len,m,i) ? TRUE : FALSE;

		//Освободим память если большая строка, чтоб не накапливалось.
		if (len > 1024)
			re->CleanStack();

		return ret;
	}

	Masks.Reset();

	while (nullptr!=(MaskPtr=Masks.GetNext()))
	{
		// SkipPath=FALSE, т.к. в CFileMask вызывается PointToName
		if (CmpName(MaskPtr,FileName, false))
			return true;
	}

	return false;
}
Пример #4
0
int CommandData::IsProcessFile(FileHeader &FileHead,bool *ExactMatch,int MatchType,
                               wchar *MatchedArg,uint MatchedArgSize)
{
  if (MatchedArg!=NULL && MatchedArgSize>0)
    *MatchedArg=0;
//  if (wcslen(FileHead.FileName)>=NM)
//    return 0;
  bool Dir=FileHead.Dir;
  if (ExclCheck(FileHead.FileName,Dir,false,true))
    return 0;
#ifndef SFX_MODULE
  if (TimeCheck(FileHead.mtime))
    return 0;
  if ((FileHead.FileAttr & ExclFileAttr)!=0 || InclAttrSet && (FileHead.FileAttr & InclFileAttr)==0)
    return 0;
  if (!Dir && SizeCheck(FileHead.UnpSize))
    return 0;
#endif
  wchar *ArgName;
  FileArgs.Rewind();
  for (int StringCount=1;(ArgName=FileArgs.GetString())!=NULL;StringCount++)
    if (CmpName(ArgName,FileHead.FileName,MatchType))
    {
      if (ExactMatch!=NULL)
        *ExactMatch=wcsicompc(ArgName,FileHead.FileName)==0;
      if (MatchedArg!=NULL)
        wcsncpyz(MatchedArg,ArgName,MatchedArgSize);
      return StringCount;
    }
  return 0;
}
Пример #5
0
bool CommandData::ExclCheckArgs(StringList *Args,char *CheckName,bool CheckFullPath)
{
  char *Name=ConvertPath(CheckName,NULL);
  char FullName[NM],*CurName;
  *FullName=0;
  Args->Rewind();
  while ((CurName=Args->GetString())!=NULL)
#ifndef SFX_MODULE
    if (CheckFullPath && IsFullPath(CurName))
    {
      if (*FullName==0)
        ConvertNameToFull(CheckName,FullName);
      if (CmpName(CurName,FullName,MATCH_WILDSUBPATH))
        return(true);
    }
    else
#endif
      if (CmpName(ConvertPath(CurName,NULL),Name,MATCH_WILDSUBPATH))
        return(true);
  return(false);
}
Пример #6
0
    // VISITORS
    virtual void visit(AstNetlist* nodep, AstNUser*) {
	// Collect list of scopes
	nodep->iterateChildren(*this);
	varsExpand();

	// Sort by names, so line/process order matters less
	stable_sort(m_scopes.begin(), m_scopes.end(), CmpName());
	stable_sort(m_dpis.begin(), m_dpis.end(), CmpDpi());

	// Output
	emitSymHdr();
	emitSymImp();
	if (v3Global.dpi()) {
	    emitDpiHdr();
	    emitDpiImp();
	}
    }
Пример #7
0
bool NativePluginModel::IsPlugin(const string& filename)
{
	if (!CmpName(L"*.dll", filename.data(), false))
		return false;

	bool Result = false;
	if (const auto ModuleFile = os::handle(os::CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING)))
	{
		if (const auto ModuleMapping = os::handle(CreateFileMapping(ModuleFile.native_handle(), nullptr, PAGE_READONLY, 0, 0, nullptr)))
		{
			if (const auto Data = MapViewOfFile(ModuleMapping.native_handle(), FILE_MAP_READ, 0, 0, 0))
			{
				Result = IsPlugin2(Data);
				UnmapViewOfFile(Data);
			}
		}
	}
	return Result;
}
Пример #8
0
// Return 'true' if we need to exclude the directory from archiving as result
// of -x switch. We do not want -x*. switch to exclude all directories,
// so when archiving we process exclusion arguments for directories specially.
bool CommandData::ExclCheckDir(char *CheckName)
{
  // If exclusion mask and directory name match exactly, return true.
  if (ExclCheckArgs(ExclArgs,CheckName,true,MATCH_EXACT))
    return(true);

  // Now we want to allow wildcards in exclusion mask only if it has
  // '\' at the end. So 'dir*\' will exclude all dir* directories.
  // We append '\' to directory name, so it will match only masks having
  // '\' at the end.
  char DirName[NM+1];
  ConvertPath(CheckName,DirName);
  AddEndSlash(DirName);

  char *CurMask;
  ExclArgs->Rewind();
  while ((CurMask=ExclArgs->GetString())!=NULL)
    if (IsPathDiv(*PointToLastChar(CurMask)))
      if (CmpName(CurMask,DirName,MATCH_SUBPATH))
        return(true);
  
  return(false);
}
Пример #9
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);

    // 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,FD,GetLinks);

    // Link check is important for NTFS, where links can have "Directory"
    // attribute, but we do not want to recurse to them in "get links" mode.
    bool IsDir=FindCode && FD->IsDir && (!GetLinks || !FD->IsLink);

    // 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. We always comrpess the entire directory
    // if folder wildcard is specified.
    bool SearchAll=!IsDir && (Depth>0 || Recurse==RECURSE_ALWAYS ||
                   FolderWildcards && Recurse!=RECURSE_DISABLE || 
                   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]=new FindFile;

      wchar SearchMask[NM];
      wcsncpyz(SearchMask,CurMask,ASIZE(SearchMask));
      if (SearchAll)
        SetName(SearchMask,MASKALL,ASIZE(SearchMask));
      FindStack[Depth]->SetMask(SearchMask);
    }
    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 || !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,CurMask);
            // User asked to return RARX_NOFILES and not RARX_OPEN here.
            ErrHandler.SetErrorCode(RARX_NOFILES);
          }
        }

        // 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;

        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;
    if (Error)
      ScanError(Error);

    wchar DirName[NM];
    *DirName=0;

    // Going to at least one directory level higher.
    delete FindStack[Depth];
    FindStack[Depth--]=NULL;
    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;
    }

    wchar *Slash=wcsrchr(CurMask,CPATHDIVIDER);
    if (Slash!=NULL)
    {
      wchar Mask[NM];
      wcsncpyz(Mask,Slash,ASIZE(Mask));
      if (Depth<SetAllMaskDepth)
        wcsncpyz(Mask+1,PointToName(OrigCurMask),ASIZE(Mask)-1);
      *Slash=0;
      wcsncpyz(DirName,CurMask,ASIZE(DirName));
      wchar *PrevSlash=wcsrchr(CurMask,CPATHDIVIDER);
      if (PrevSlash==NULL)
        wcsncpyz(CurMask,Mask+1,ASIZE(CurMask));
      else
      {
        *(PrevSlash+1)=0;
        wcsncatz(CurMask,Mask,ASIZE(CurMask));
      }
    }
    if (GetDirs==SCAN_GETDIRSTWICE &&
        FindFile::FastFind(DirName,FD,GetLinks) && FD->IsDir)
    {
      FD->Flags|=FDDF_SECONDDIR;
      return Error ? SCAN_ERROR:SCAN_SUCCESS;
    }
    return Error ? SCAN_ERROR:SCAN_NEXT;
  }

  // Link check is required for NTFS links, not for Unix.
  if (FD->IsDir && (!GetLinks || !FD->IsLink))
  {
    // 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;
    }
    
    wchar Mask[NM];

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

    if (wcslen(CurMask)+wcslen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1)
    {
      uiMsg(UIERROR_PATHTOOLONG,CurMask,SPATHDIVIDER,Mask);
      return SCAN_ERROR;
    }

    AddEndSlash(CurMask,ASIZE(CurMask));
    wcsncatz(CurMask,Mask,ASIZE(CurMask));

    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;
}
Пример #10
0
bool FindFile::Next(struct FindData *fd,bool GetSymLink)
{
  fd->Error=false;
  if (*FindMask==0)
    return(false);
#ifdef _WIN_32
  if (FirstCall)
  {
    if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,FindMaskW,fd))==INVALID_HANDLE_VALUE)
      return(false);
  }
  else
    if (Win32Find(hFind,FindMask,FindMaskW,fd)==INVALID_HANDLE_VALUE)
      return(false);
#else
  if (FirstCall)
  {
    char DirName[NM];
    strcpy(DirName,FindMask);
    RemoveNameFromPath(DirName);
    if (*DirName==0)
      strcpy(DirName,".");
/*
    else
    {
      int Length=strlen(DirName);
      if (Length>1 && DirName[Length-1]==CPATHDIVIDER && (Length!=3 || !IsDriveDiv(DirName[1])))
        DirName[Length-1]=0;
    }
*/
    if ((dirp=opendir(DirName))==NULL)
    {
      fd->Error=(errno!=ENOENT);
      return(false);
    }
  }
  while (1)
  {
    struct dirent *ent=readdir(dirp);
    if (ent==NULL)
      return(false);
    if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
      continue;
    if (CmpName(FindMask,ent->d_name,MATCH_NAMES))
    {
      char FullName[NM];
      strcpy(FullName,FindMask);
      *PointToName(FullName)=0;
      if (strlen(FullName)+strlen(ent->d_name)>=ASIZE(FullName)-1)
      {
#ifndef SILENT
        Log(NULL,"\n%s%s",FullName,ent->d_name);
        Log(NULL,St(MPathTooLong));
#endif
        return(false);
      }
      strcat(FullName,ent->d_name);
      if (!FastFind(FullName,NULL,fd,GetSymLink))
      {
        ErrHandler.OpenErrorMsg(FullName);
        continue;
      }
      strcpy(fd->Name,FullName);
      break;
    }
  }
  *fd->NameW=0;
#ifdef _APPLE
  if (!LowAscii(fd->Name))
    UtfToWide(fd->Name,fd->NameW,sizeof(fd->NameW));
#elif defined(UNICODE_SUPPORTED)
  if (!LowAscii(fd->Name) && UnicodeEnabled())
    CharToWide(fd->Name,fd->NameW);
#endif
#endif
  fd->Flags=0;
  fd->IsDir=IsDir(fd->FileAttr);
  FirstCall=false;
  char *Name=PointToName(fd->Name);
  if (strcmp(Name,".")==0 || strcmp(Name,"..")==0)
    return(Next(fd));
  return(true);
}
Пример #11
0
bool CommandData::ExclCheckArgs(StringList *Args,bool Dir,char *CheckName,bool CheckFullPath,int MatchMode)
{
  char *Name=ConvertPath(CheckName,NULL);
  char FullName[NM];
  char CurMask[NM+1]; // We reserve the space to append "*" to mask.
  *FullName=0;
  Args->Rewind();
  while (Args->GetString(CurMask,ASIZE(CurMask)-1))
  {
    char *LastMaskChar=PointToLastChar(CurMask);
    bool DirMask=IsPathDiv(*LastMaskChar); // Mask for directories only.

    if (Dir)
    {
      // CheckName is a directory.
      if (DirMask)
      {
        // We process the directory and have the directory exclusion mask.
        // So let's convert "mask\" to "mask" and process it normally.
        
        *LastMaskChar=0;
      }
      else
      {
        // If mask has wildcards in name part and does not have the trailing
        // '\' character, we cannot use it for directories.
      
        if (IsWildcard(PointToName(CurMask)))
          continue;
      }
    }
    else
    {
      // If we process a file inside of directory excluded by "dirmask\".
      // we want to exclude such file too. So we convert "dirmask\" to
      // "dirmask\*". It is important for operations other than archiving.
      // When archiving, directory matched by "dirmask\" is excluded
      // from further scanning.

      if (DirMask)
        strcat(CurMask,"*");
    }

#ifndef SFX_MODULE
    if (CheckFullPath && IsFullPath(CurMask))
    {
      // We do not need to do the special "*\" processing here, because
      // onlike the "else" part of this "if", now we convert names to full
      // format, so they all include the path, which is matched by "*\"
      // correctly. Moreover, removing "*\" from mask would break
      // the comparison, because now all names have the path.

      if (*FullName==0)
        ConvertNameToFull(CheckName,FullName);
      if (CmpName(CurMask,FullName,MatchMode))
        return(true);
    }
    else
#endif
    {
      char NewName[NM+2],*CurName=Name;
      if (CurMask[0]=='*' && IsPathDiv(CurMask[1]))
      {
        // We want "*\name" to match 'name' not only in subdirectories,
        // but also in the current directory. We convert the name
        // from 'name' to '.\name' to be matched by "*\" part even if it is
        // in current directory.
        NewName[0]='.';
        NewName[1]=CPATHDIVIDER;
        strncpyz(NewName+2,Name,ASIZE(NewName)-2);
        CurName=NewName;
      }

      if (CmpName(ConvertPath(CurMask,NULL),CurName,MatchMode))
        return(true);
    }
  }
  return(false);
}
Пример #12
0
// IS: это реальное тело функции сравнения с маской, но использовать
// IS: "снаружи" нужно не эту функцию, а CmpName (ее тело расположено
// IS: после CmpName_Body)
static int CmpName_Body(const wchar_t *pattern,const wchar_t *str, bool CmpNameSearchMode)
{
	for (;; ++str)
	{
		/* $ 01.05.2001 DJ
		   используем инлайновые версии
		*/
		wchar_t stringc=ToUpper(*str);
		wchar_t patternc=ToUpper(*pattern++);

		switch (patternc)
		{
			case 0:
				return !stringc;
			case L'?':

				if (!stringc)
					return FALSE;

				break;
			case L'*':

				if (!*pattern)
					return TRUE;

				/* $ 01.05.2001 DJ
				   оптимизированная ветка работает и для имен с несколькими
				   точками
				*/
				if (*pattern==L'.')
				{
					if (pattern[1]==L'*' && !pattern[2])
						return TRUE;

					if (!wcspbrk(pattern, L"*?["))
					{
						const wchar_t *dot = wcsrchr(str, L'.');

						if (!pattern[1])
							return !dot || !dot[1];

						const wchar_t *patdot = wcschr(pattern+1, L'.');

						if (patdot  && !dot)
							return FALSE;

						if (!patdot && dot )
							return !StrCmpI(pattern+1,dot+1);
					}
				}

				do
				{
					if(CmpName(pattern,str,false,CmpNameSearchMode))
						return TRUE;
				}
				while (*str++);

				return FALSE;
			case L'[':
			{
				if (!wcschr(pattern,L']'))
				{
					if (patternc != stringc)
						return FALSE;

					break;
				}

				if (*pattern && *(pattern+1)==L']')
				{
					if (*pattern!=*str)
						return FALSE;

					pattern+=2;
					break;
				}

				int match = 0;
				wchar_t rangec;
				while ((rangec = ToUpper(*pattern++)) != 0)
				{
					if (rangec == L']')
					{
						if (match)
							break;
						else
							return FALSE;
					}

					if (match)
						continue;

					if (rangec == L'-' && *(pattern - 2) != L'[' && *pattern != L']')
					{
						match = (stringc <= ToUpper(*pattern) &&
						         ToUpper(*(pattern - 2)) <= stringc);
						pattern++;
					}
					else
						match = (stringc == rangec);
				}

				if (!rangec)
					return FALSE;
			}
				break;
			default:

				if (patternc != stringc)
				{
					if (patternc==L'.' && !stringc && !CmpNameSearchMode)
						return *pattern != L'.' && CmpName(pattern, str, true, CmpNameSearchMode);
					else
						return FALSE;
				}

				break;
		}
	}
}
Пример #13
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);
}
Пример #14
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);
}
Пример #15
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);
}
Пример #16
0
bool FindFile::Next(FindData *fd,bool GetSymLink)
{
  fd->Error=false;
  if (*FindMask==0)
    return false;
#ifdef _WIN_ALL
  if (FirstCall)
  {
    if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
      return false;
  }
  else
    if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
      return false;
#else
  if (FirstCall)
  {
    wchar DirName[NM];
    wcsncpyz(DirName,FindMask,ASIZE(DirName));
    RemoveNameFromPath(DirName);
    if (*DirName==0)
      wcscpy(DirName,L".");
    char DirNameA[NM];
    WideToChar(DirName,DirNameA,ASIZE(DirNameA));
    if ((dirp=opendir(DirNameA))==NULL)
    {
      fd->Error=(errno!=ENOENT);
      return false;
    }
  }
  while (1)
  {
    struct dirent *ent=readdir(dirp);
    if (ent==NULL)
      return false;
    if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
      continue;
    wchar Name[NM];
    if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
      Log(NULL,St(MInvalidName),Name);

    if (CmpName(FindMask,Name,MATCH_NAMES))
    {
      wchar FullName[NM];
      wcscpy(FullName,FindMask);
      *PointToName(FullName)=0;
      if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
      {
#ifndef SILENT
        Log(NULL,L"\n%ls%ls",FullName,Name);
        Log(NULL,St(MPathTooLong));
#endif
        return false;
      }
      wcscat(FullName,Name);
      if (!FastFind(FullName,fd,GetSymLink))
      {
        ErrHandler.OpenErrorMsg(NULL,FullName);
        continue;
      }
      wcscpy(fd->Name,FullName);
      break;
    }
  }
#endif
  fd->Flags=0;
  fd->IsDir=IsDir(fd->FileAttr);
  fd->IsLink=IsLink(fd->FileAttr);

  FirstCall=false;
  wchar *NameOnly=PointToName(fd->Name);
  if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
    return Next(fd);
  return true;
}