1 #include "rar.hpp"
2 
FindFile()3 FindFile::FindFile()
4 {
5   *FindMask=0;
6   FirstCall=true;
7 #ifdef _WIN_ALL
8   hFind=INVALID_HANDLE_VALUE;
9 #else
10   dirp=NULL;
11 #endif
12 }
13 
14 
~FindFile()15 FindFile::~FindFile()
16 {
17 #ifdef _WIN_ALL
18   if (hFind!=INVALID_HANDLE_VALUE)
19     FindClose(hFind);
20 #else
21   if (dirp!=NULL)
22     closedir(dirp);
23 #endif
24 }
25 
26 
SetMask(const wchar * Mask)27 void FindFile::SetMask(const wchar *Mask)
28 {
29   wcsncpyz(FindMask,Mask,ASIZE(FindMask));
30   FirstCall=true;
31 }
32 
33 
Next(FindData * fd,bool GetSymLink)34 bool FindFile::Next(FindData *fd,bool GetSymLink)
35 {
36   fd->Error=false;
37   if (*FindMask==0)
38     return false;
39 #ifdef _WIN_ALL
40   if (FirstCall)
41   {
42     if ((hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd))==INVALID_HANDLE_VALUE)
43       return false;
44   }
45   else
46     if (Win32Find(hFind,FindMask,fd)==INVALID_HANDLE_VALUE)
47       return false;
48 #else
49   if (FirstCall)
50   {
51     wchar DirName[NM];
52     wcsncpyz(DirName,FindMask,ASIZE(DirName));
53     RemoveNameFromPath(DirName);
54     if (*DirName==0)
55       wcsncpyz(DirName,L".",ASIZE(DirName));
56     char DirNameA[NM];
57     WideToChar(DirName,DirNameA,ASIZE(DirNameA));
58     if ((dirp=opendir(DirNameA))==NULL)
59     {
60       fd->Error=(errno!=ENOENT);
61       return false;
62     }
63   }
64   while (1)
65   {
66     struct dirent *ent=readdir(dirp);
67     if (ent==NULL)
68       return false;
69     if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
70       continue;
71     wchar Name[NM];
72     if (!CharToWide(ent->d_name,Name,ASIZE(Name)))
73       uiMsg(UIERROR_INVALIDNAME,UINULL,Name);
74 
75     if (CmpName(FindMask,Name,MATCH_NAMES))
76     {
77       wchar FullName[NM];
78       wcsncpyz(FullName,FindMask,ASIZE(FullName));
79       *PointToName(FullName)=0;
80       if (wcslen(FullName)+wcslen(Name)>=ASIZE(FullName)-1)
81       {
82         uiMsg(UIERROR_PATHTOOLONG,FullName,L"",Name);
83         return false;
84       }
85       wcsncatz(FullName,Name,ASIZE(FullName));
86       if (!FastFind(FullName,fd,GetSymLink))
87       {
88         ErrHandler.OpenErrorMsg(FullName);
89         continue;
90       }
91       wcsncpyz(fd->Name,FullName,ASIZE(fd->Name));
92       break;
93     }
94   }
95 #endif
96   fd->Flags=0;
97   fd->IsDir=IsDir(fd->FileAttr);
98   fd->IsLink=IsLink(fd->FileAttr);
99 
100   FirstCall=false;
101   wchar *NameOnly=PointToName(fd->Name);
102   if (wcscmp(NameOnly,L".")==0 || wcscmp(NameOnly,L"..")==0)
103     return Next(fd);
104   return true;
105 }
106 
107 
FastFind(const wchar * FindMask,FindData * fd,bool GetSymLink)108 bool FindFile::FastFind(const wchar *FindMask,FindData *fd,bool GetSymLink)
109 {
110   fd->Error=false;
111 #ifndef _UNIX
112   if (IsWildcard(FindMask))
113     return false;
114 #endif
115 #ifdef _WIN_ALL
116   HANDLE hFind=Win32Find(INVALID_HANDLE_VALUE,FindMask,fd);
117   if (hFind==INVALID_HANDLE_VALUE)
118     return false;
119   FindClose(hFind);
120 #else
121   char FindMaskA[NM];
122   WideToChar(FindMask,FindMaskA,ASIZE(FindMaskA));
123 
124   struct stat st;
125   if (GetSymLink)
126   {
127 #ifdef SAVE_LINKS
128     if (lstat(FindMaskA,&st)!=0)
129 #else
130     if (stat(FindMaskA,&st)!=0)
131 #endif
132     {
133       fd->Error=(errno!=ENOENT);
134       return false;
135     }
136   }
137   else
138     if (stat(FindMaskA,&st)!=0)
139     {
140       fd->Error=(errno!=ENOENT);
141       return false;
142     }
143   fd->FileAttr=st.st_mode;
144   fd->Size=st.st_size;
145 
146 #ifdef UNIX_TIME_NS
147   fd->mtime.SetUnixNS(st.st_mtim.tv_sec*(uint64)1000000000+st.st_mtim.tv_nsec);
148   fd->atime.SetUnixNS(st.st_atim.tv_sec*(uint64)1000000000+st.st_atim.tv_nsec);
149   fd->ctime.SetUnixNS(st.st_ctim.tv_sec*(uint64)1000000000+st.st_ctim.tv_nsec);
150 #else
151   fd->mtime.SetUnix(st.st_mtime);
152   fd->atime.SetUnix(st.st_atime);
153   fd->ctime.SetUnix(st.st_ctime);
154 #endif
155 
156   wcsncpyz(fd->Name,FindMask,ASIZE(fd->Name));
157 #endif
158   fd->Flags=0;
159   fd->IsDir=IsDir(fd->FileAttr);
160   fd->IsLink=IsLink(fd->FileAttr);
161 
162   return true;
163 }
164 
165 
166 #ifdef _WIN_ALL
Win32Find(HANDLE hFind,const wchar * Mask,FindData * fd)167 HANDLE FindFile::Win32Find(HANDLE hFind,const wchar *Mask,FindData *fd)
168 {
169   WIN32_FIND_DATA FindData;
170   if (hFind==INVALID_HANDLE_VALUE)
171   {
172     hFind=FindFirstFile(Mask,&FindData);
173     if (hFind==INVALID_HANDLE_VALUE)
174     {
175       wchar LongMask[NM];
176       if (GetWinLongPath(Mask,LongMask,ASIZE(LongMask)))
177         hFind=FindFirstFile(LongMask,&FindData);
178     }
179     if (hFind==INVALID_HANDLE_VALUE)
180     {
181       int SysErr=GetLastError();
182       // We must not issue an error for "file not found" and "path not found",
183       // because it is normal to not find anything for wildcard mask when
184       // archiving. Also searching for non-existent file is normal in some
185       // other modules, like WinRAR scanning for winrar_theme_description.txt
186       // to check if any themes are available.
187       fd->Error=SysErr!=ERROR_FILE_NOT_FOUND &&
188                 SysErr!=ERROR_PATH_NOT_FOUND &&
189                 SysErr!=ERROR_NO_MORE_FILES;
190     }
191   }
192   else
193     if (!FindNextFile(hFind,&FindData))
194     {
195       hFind=INVALID_HANDLE_VALUE;
196       fd->Error=GetLastError()!=ERROR_NO_MORE_FILES;
197     }
198 
199   if (hFind!=INVALID_HANDLE_VALUE)
200   {
201     wcsncpyz(fd->Name,Mask,ASIZE(fd->Name));
202     SetName(fd->Name,FindData.cFileName,ASIZE(fd->Name));
203     fd->Size=INT32TO64(FindData.nFileSizeHigh,FindData.nFileSizeLow);
204     fd->FileAttr=FindData.dwFileAttributes;
205     fd->ftCreationTime=FindData.ftCreationTime;
206     fd->ftLastAccessTime=FindData.ftLastAccessTime;
207     fd->ftLastWriteTime=FindData.ftLastWriteTime;
208     fd->mtime.SetWinFT(&FindData.ftLastWriteTime);
209     fd->ctime.SetWinFT(&FindData.ftCreationTime);
210     fd->atime.SetWinFT(&FindData.ftLastAccessTime);
211 
212 
213   }
214   fd->Flags=0;
215   return hFind;
216 }
217 #endif
218 
219