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 wchar Name[NM];
67 struct dirent *ent=readdir(dirp);
68 if (ent==NULL)
69 return false;
70 if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0)
71 continue;
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