219 lines
5.0 KiB
C++
219 lines
5.0 KiB
C++
|
#include "rar.hpp"
|
||
|
|
||
|
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
|
||
|
|