| #include "rar.hpp" |
| |
| namespace third_party_unrar { |
| |
| FindFile::FindFile() |
| { |
| *FindMask=0; |
| FirstCall=true; |
| #ifdef _WIN_ALL |
| hFind=INVALID_HANDLE_VALUE; |
| #else |
| dirp=NULL; |
| #endif |
| } |
| |
| |
| FindFile::~FindFile() |
| { |
| #ifdef _WIN_ALL |
| if (hFind!=INVALID_HANDLE_VALUE) |
| FindClose(hFind); |
| #else |
| if (dirp!=NULL) |
| closedir(dirp); |
| #endif |
| } |
| |
| |
| void FindFile::SetMask(const wchar *Mask) |
| { |
| wcscpy(FindMask,Mask); |
| FirstCall=true; |
| } |
| |
| |
| 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))) |
| uiMsg(UIERROR_INVALIDNAME,UINULL,Name); |
| |
| if (CmpName(FindMask,Name,MATCH_NAMES)) |
| { |
| wchar FullName[NM]; |
| wcscpy(FullName,FindMask); |
| *PointToName(FullName)=0; |
| if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1) |
| { |
| uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name); |
| return false; |
| } |
| wcscat(FullName,Name); |
| if (!FastFind(FullName,fd,GetSymLink)) |
| { |
| ErrHandler.OpenErrorMsg(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; |
| } |
| |
| |
| bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink) |
| { |
| fd->Error=false; |
| #ifndef _UNIX |
| if (IsWildcard(FindMask)) |
| return false; |
| #endif |
| #ifdef _WIN_ALL |
| HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd); |
| if (hFind==INVALID_HANDLE_VALUE) |
| return false; |
| FindClose(hFind); |
| #else |
| char FindMaskA[NM]; |
| WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA)); |
| |
| struct stat st; |
| if (GetSymLink) |
| { |
| #ifdef SAVE_LINKS |
| if (lstat(FindMaskA,&st)!=0) |
| #else |
| if (stat(FindMaskA,&st)!=0) |
| #endif |
| { |
| fd->Error=(errno!=ENOENT); |
| return false; |
| } |
| } |
| else |
| if (stat(FindMaskA,&st)!=0) |
| { |
| fd->Error=(errno!=ENOENT); |
| return false; |
| } |
| fd->FileAttr=st.st_mode; |
| fd->Size=st.st_size; |
| |
| #ifdef UNIX_TIME_NS |
| fd->mtime.SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec); |
| fd->atime.SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec); |
| fd->ctime.SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec); |
| #else |
| fd->mtime.SetUnix(st.st_mtime); |
| fd->atime.SetUnix(st.st_atime); |
| fd->ctime.SetUnix(st.st_ctime); |
| #endif |
| |
| wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name)); |
| #endif |
| fd->Flags=0; |
| fd->IsDir=IsDir(fd->FileAttr); |
| fd->IsLink=IsLink(fd->FileAttr); |
| |
| return true; |
| } |
| |
| |
| #ifdef _WIN_ALL |
| HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd) |
| { |
| WIN32_FIND_DATA FindData; |
| if (hFind==INVALID_HANDLE_VALUE) |
| { |
| hFind=FindFirstFile(Mask,&FindData); |
| if (hFind==INVALID_HANDLE_VALUE) |
| { |
| wchar LongMask[NM]; |
| if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask))) |
| hFind=FindFirstFile(LongMask,&FindData); |
| } |
| if (hFind==INVALID_HANDLE_VALUE) |
| { |
| int SysErr=GetLastError(); |
| // We must not issue an error for "file not found" and "path not found", |
| // because it is normal to not find anything for wildcard mask when |
| // archiving. Also searching for non-existent file is normal in some |
| // other modules, like WinRAR scanning for winrar_theme_description.txt |
| // to check if any themes are available. |
| fd->Error=SysErr!=ERROR_FILE_NOT_FOUND && |
| SysErr!=ERROR_PATH_NOT_FOUND && |
| SysErr!=ERROR_NO_MORE_FILES; |
| } |
| } |
| else |
| if (!FindNextFile(hFind,&FindData)) |
| { |
| hFind=INVALID_HANDLE_VALUE; |
| fd->Error=GetLastError()!=ERROR_NO_MORE_FILES; |
| } |
| |
| if (hFind!=INVALID_HANDLE_VALUE) |
| { |
| wcsncpyz(fd->Name,Mask,ASIZE(fd->Name)); |
| SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name)); |
| fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow); |
| fd->FileAttr=FindData.dwFileAttributes; |
| fd->ftCreationTime=FindData.ftCreationTime; |
| fd->ftLastAccessTime=FindData.ftLastAccessTime; |
| fd->ftLastWriteTime=FindData.ftLastWriteTime; |
| fd->mtime.SetWinFT(&FindData.ftLastWriteTime); |
| fd->ctime.SetWinFT(&FindData.ftCreationTime); |
| fd->atime.SetWinFT(&FindData.ftLastAccessTime); |
| |
| |
| } |
| fd->Flags=0; |
| return hFind; |
| } |
| #endif |
| |
| } // namespace third_party_unrar |