"Fossies" - the Fresh Open Source Software Archive 
Member "unrar/filefn.cpp" (4 May 2022, 13091 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "filefn.cpp" see the
Fossies "Dox" file reference documentation.
1 #include "rar.hpp"
2
3 MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr)
4 {
5 #ifdef _WIN_ALL
6 // Windows automatically removes dots and spaces in the end of directory
7 // name. So we detect such names and process them with \\?\ prefix.
8 wchar *LastChar=PointToLastChar(Name);
9 bool Special=*LastChar=='.' || *LastChar==' ';
10 BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL);
11 if (RetCode==0 && !FileExist(Name))
12 {
13 wchar LongName[NM];
14 if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
15 RetCode=CreateDirectory(LongName,NULL);
16 }
17 if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
18 {
19 if (SetAttr)
20 SetFileAttr(Name,Attr);
21 return MKDIR_SUCCESS;
22 }
23 int ErrCode=GetLastError();
24 if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
25 return MKDIR_BADPATH;
26 return MKDIR_ERROR;
27 #elif defined(_UNIX)
28 char NameA[NM];
29 WideToChar(Name,NameA,ASIZE(NameA));
30 mode_t uattr=SetAttr ? (mode_t)Attr:0777;
31 int ErrCode=mkdir(NameA,uattr);
32 if (ErrCode==-1)
33 return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR;
34 return MKDIR_SUCCESS;
35 #else
36 return MKDIR_ERROR;
37 #endif
38 }
39
40
41 bool CreatePath(const wchar *Path,bool SkipLastName,bool Silent)
42 {
43 if (Path==NULL || *Path==0)
44 return false;
45
46 #if defined(_WIN_ALL) || defined(_EMX)
47 uint DirAttr=0;
48 #else
49 uint DirAttr=0777;
50 #endif
51
52 bool Success=true;
53
54 for (const wchar *s=Path;*s!=0;s++)
55 {
56 wchar DirName[NM];
57 if (s-Path>=ASIZE(DirName))
58 break;
59
60 // Process all kinds of path separators, so user can enter Unix style
61 // path in Windows or Windows in Unix. s>Path check avoids attempting
62 // creating an empty directory for paths starting from path separator.
63 if (IsPathDiv(*s) && s>Path)
64 {
65 #ifdef _WIN_ALL
66 // We must not attempt to create "D:" directory, because first
67 // CreateDirectory will fail, so we'll use \\?\D:, which forces Wine
68 // to create "D:" directory.
69 if (s==Path+2 && Path[1]==':')
70 continue;
71 #endif
72 wcsncpy(DirName,Path,s-Path);
73 DirName[s-Path]=0;
74
75 Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS;
76 if (Success && !Silent)
77 {
78 mprintf(St(MCreatDir),DirName);
79 mprintf(L" %s",St(MOk));
80 }
81 }
82 }
83 if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
84 Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS;
85 return Success;
86 }
87
88
89 void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
90 {
91 #if defined(_WIN_ALL)
92 bool sm=ftm!=NULL && ftm->IsSet();
93 bool sc=ftc!=NULL && ftc->IsSet();
94 bool sa=fta!=NULL && fta->IsSet();
95
96 uint DirAttr=GetFileAttr(Name);
97 bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FILE_ATTRIBUTE_READONLY)!=0);
98 if (ResetAttr)
99 SetFileAttr(Name,0);
100
101 HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
102 NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
103 if (hFile==INVALID_HANDLE_VALUE)
104 {
105 wchar LongName[NM];
106 if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
107 hFile=CreateFile(LongName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
108 NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
109 }
110
111 if (hFile==INVALID_HANDLE_VALUE)
112 return;
113 FILETIME fm,fc,fa;
114 if (sm)
115 ftm->GetWinFT(&fm);
116 if (sc)
117 ftc->GetWinFT(&fc);
118 if (sa)
119 fta->GetWinFT(&fa);
120 SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
121 CloseHandle(hFile);
122 if (ResetAttr)
123 SetFileAttr(Name,DirAttr);
124 #endif
125 #if defined(_UNIX) || defined(_EMX)
126 File::SetCloseFileTimeByName(Name,ftm,fta);
127 #endif
128 }
129
130
131 bool IsRemovable(const wchar *Name)
132 {
133 #if defined(_WIN_ALL)
134 wchar Root[NM];
135 GetPathRoot(Name,Root,ASIZE(Root));
136 int Type=GetDriveType(*Root!=0 ? Root:NULL);
137 return Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM;
138 #else
139 return false;
140 #endif
141 }
142
143
144 #ifndef SFX_MODULE
145 int64 GetFreeDisk(const wchar *Name)
146 {
147 #ifdef _WIN_ALL
148 wchar Root[NM];
149 GetFilePath(Name,Root,ASIZE(Root));
150
151 ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
152 uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
153 if (GetDiskFreeSpaceEx(*Root!=0 ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
154 uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
155 return INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart);
156 return 0;
157 #elif defined(_UNIX)
158 wchar Root[NM];
159 GetFilePath(Name,Root,ASIZE(Root));
160 char RootA[NM];
161 WideToChar(Root,RootA,ASIZE(RootA));
162 struct statvfs sfs;
163 if (statvfs(*RootA!=0 ? RootA:".",&sfs)!=0)
164 return 0;
165 int64 FreeSize=sfs.f_bsize;
166 FreeSize=FreeSize*sfs.f_bavail;
167 return FreeSize;
168 #else
169 return 0;
170 #endif
171 }
172 #endif
173
174
175 #if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
176 // Return 'true' for FAT and FAT32, so we can adjust the maximum supported
177 // file size to 4 GB for these file systems.
178 bool IsFAT(const wchar *Name)
179 {
180 wchar Root[NM];
181 GetPathRoot(Name,Root,ASIZE(Root));
182 wchar FileSystem[MAX_PATH+1];
183 if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem)))
184 return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0;
185 return false;
186 }
187 #endif
188
189
190 bool FileExist(const wchar *Name)
191 {
192 #ifdef _WIN_ALL
193 return GetFileAttr(Name)!=0xffffffff;
194 #elif defined(ENABLE_ACCESS)
195 char NameA[NM];
196 WideToChar(Name,NameA,ASIZE(NameA));
197 return access(NameA,0)==0;
198 #else
199 FindData FD;
200 return FindFile::FastFind(Name,&FD);
201 #endif
202 }
203
204
205 bool WildFileExist(const wchar *Name)
206 {
207 if (IsWildcard(Name))
208 {
209 FindFile Find;
210 Find.SetMask(Name);
211 FindData fd;
212 return Find.Next(&fd);
213 }
214 return FileExist(Name);
215 }
216
217
218 bool IsDir(uint Attr)
219 {
220 #ifdef _WIN_ALL
221 return Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_DIRECTORY)!=0;
222 #endif
223 #if defined(_UNIX)
224 return (Attr & 0xF000)==0x4000;
225 #endif
226 }
227
228
229 bool IsUnreadable(uint Attr)
230 {
231 #if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
232 return S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr);
233 #endif
234 return false;
235 }
236
237
238 bool IsLink(uint Attr)
239 {
240 #ifdef _UNIX
241 return (Attr & 0xF000)==0xA000;
242 #elif defined(_WIN_ALL)
243 return (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0;
244 #else
245 return false;
246 #endif
247 }
248
249
250
251
252
253
254 bool IsDeleteAllowed(uint FileAttr)
255 {
256 #ifdef _WIN_ALL
257 return (FileAttr & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN))==0;
258 #else
259 return (FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR);
260 #endif
261 }
262
263
264 void PrepareToDelete(const wchar *Name)
265 {
266 #if defined(_WIN_ALL) || defined(_EMX)
267 SetFileAttr(Name,0);
268 #endif
269 #ifdef _UNIX
270 if (Name!=NULL)
271 {
272 char NameA[NM];
273 WideToChar(Name,NameA,ASIZE(NameA));
274 chmod(NameA,S_IRUSR|S_IWUSR|S_IXUSR);
275 }
276 #endif
277 }
278
279
280 uint GetFileAttr(const wchar *Name)
281 {
282 #ifdef _WIN_ALL
283 DWORD Attr=GetFileAttributes(Name);
284 if (Attr==0xffffffff)
285 {
286 wchar LongName[NM];
287 if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
288 Attr=GetFileAttributes(LongName);
289 }
290 return Attr;
291 #else
292 char NameA[NM];
293 WideToChar(Name,NameA,ASIZE(NameA));
294 struct stat st;
295 if (stat(NameA,&st)!=0)
296 return 0;
297 return st.st_mode;
298 #endif
299 }
300
301
302 bool SetFileAttr(const wchar *Name,uint Attr)
303 {
304 #ifdef _WIN_ALL
305 bool Success=SetFileAttributes(Name,Attr)!=0;
306 if (!Success)
307 {
308 wchar LongName[NM];
309 if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
310 Success=SetFileAttributes(LongName,Attr)!=0;
311 }
312 return Success;
313 #elif defined(_UNIX)
314 char NameA[NM];
315 WideToChar(Name,NameA,ASIZE(NameA));
316 return chmod(NameA,(mode_t)Attr)==0;
317 #else
318 return false;
319 #endif
320 }
321
322
323 #if 0
324 wchar *MkTemp(wchar *Name,size_t MaxSize)
325 {
326 size_t Length=wcslen(Name);
327
328 RarTime CurTime;
329 CurTime.SetCurrentTime();
330
331 // We cannot use CurTime.GetWin() as is, because its lowest bits can
332 // have low informational value, like being a zero or few fixed numbers.
333 uint Random=(uint)(CurTime.GetWin()/100000);
334
335 // Using PID we guarantee that different RAR copies use different temp names
336 // even if started in exactly the same time.
337 uint PID=0;
338 #ifdef _WIN_ALL
339 PID=(uint)GetCurrentProcessId();
340 #elif defined(_UNIX)
341 PID=(uint)getpid();
342 #endif
343
344 for (uint Attempt=0;;Attempt++)
345 {
346 uint Ext=Random%50000+Attempt;
347 wchar RndText[50];
348 swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
349 if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
350 return NULL;
351 wcsncpyz(Name+Length,RndText,MaxSize-Length);
352 if (!FileExist(Name))
353 break;
354 }
355 return Name;
356 }
357 #endif
358
359
360 #if !defined(SFX_MODULE)
361 void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
362 {
363 int64 SavePos=SrcFile->Tell();
364 #ifndef SILENT
365 int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
366 #endif
367
368 if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWPERCENT))!=0)
369 uiMsg(UIEVENT_FILESUMSTART);
370
371 if ((Flags & CALCFSUM_CURPOS)==0)
372 SrcFile->Seek(0,SEEK_SET);
373
374 const size_t BufSize=0x100000;
375 Array<byte> Data(BufSize);
376
377
378 DataHash HashCRC,HashBlake2;
379 HashCRC.Init(HASH_CRC32,Threads);
380 HashBlake2.Init(HASH_BLAKE2,Threads);
381
382 int64 BlockCount=0;
383 int64 TotalRead=0;
384 while (true)
385 {
386 size_t SizeToRead;
387 if (Size==INT64NDF) // If we process the entire file.
388 SizeToRead=BufSize; // Then always attempt to read the entire buffer.
389 else
390 SizeToRead=(size_t)Min((int64)BufSize,Size);
391 int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
392 if (ReadSize==0)
393 break;
394 TotalRead+=ReadSize;
395
396 if ((++BlockCount & 0xf)==0)
397 {
398 #ifndef SILENT
399 if ((Flags & CALCFSUM_SHOWPROGRESS)!=0)
400 {
401 // Update only the current file progress in WinRAR, set the total to 0
402 // to keep it as is. It looks better for WinRAR,
403 uiExtractProgress(TotalRead,FileLength,0,0);
404 }
405 else
406 {
407 if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
408 uiMsg(UIEVENT_FILESUMPROGRESS,ToPercent(TotalRead,FileLength));
409 }
410 #endif
411 Wait();
412 }
413
414 if (CRC32!=NULL)
415 HashCRC.Update(&Data[0],ReadSize);
416 if (Blake2!=NULL)
417 HashBlake2.Update(&Data[0],ReadSize);
418
419 if (Size!=INT64NDF)
420 Size-=ReadSize;
421 }
422 SrcFile->Seek(SavePos,SEEK_SET);
423
424 if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
425 uiMsg(UIEVENT_FILESUMEND);
426
427 if (CRC32!=NULL)
428 *CRC32=HashCRC.GetCRC32();
429 if (Blake2!=NULL)
430 {
431 HashValue Result;
432 HashBlake2.Result(&Result);
433 memcpy(Blake2,Result.Digest,sizeof(Result.Digest));
434 }
435 }
436 #endif
437
438
439 bool RenameFile(const wchar *SrcName,const wchar *DestName)
440 {
441 #ifdef _WIN_ALL
442 bool Success=MoveFile(SrcName,DestName)!=0;
443 if (!Success)
444 {
445 wchar LongName1[NM],LongName2[NM];
446 if (GetWinLongPath(SrcName,LongName1,ASIZE(LongName1)) &&
447 GetWinLongPath(DestName,LongName2,ASIZE(LongName2)))
448 Success=MoveFile(LongName1,LongName2)!=0;
449 }
450 return Success;
451 #else
452 char SrcNameA[NM],DestNameA[NM];
453 WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA));
454 WideToChar(DestName,DestNameA,ASIZE(DestNameA));
455 bool Success=rename(SrcNameA,DestNameA)==0;
456 return Success;
457 #endif
458 }
459
460
461 bool DelFile(const wchar *Name)
462 {
463 #ifdef _WIN_ALL
464 bool Success=DeleteFile(Name)!=0;
465 if (!Success)
466 {
467 wchar LongName[NM];
468 if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
469 Success=DeleteFile(LongName)!=0;
470 }
471 return Success;
472 #else
473 char NameA[NM];
474 WideToChar(Name,NameA,ASIZE(NameA));
475 bool Success=remove(NameA)==0;
476 return Success;
477 #endif
478 }
479
480
481 bool DelDir(const wchar *Name)
482 {
483 #ifdef _WIN_ALL
484 bool Success=RemoveDirectory(Name)!=0;
485 if (!Success)
486 {
487 wchar LongName[NM];
488 if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
489 Success=RemoveDirectory(LongName)!=0;
490 }
491 return Success;
492 #else
493 char NameA[NM];
494 WideToChar(Name,NameA,ASIZE(NameA));
495 bool Success=rmdir(NameA)==0;
496 return Success;
497 #endif
498 }
499
500
501 #if defined(_WIN_ALL) && !defined(SFX_MODULE)
502 bool SetFileCompression(const wchar *Name,bool State)
503 {
504 HANDLE hFile=CreateFile(Name,FILE_READ_DATA|FILE_WRITE_DATA,
505 FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
506 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
507 if (hFile==INVALID_HANDLE_VALUE)
508 {
509 wchar LongName[NM];
510 if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
511 hFile=CreateFile(LongName,FILE_READ_DATA|FILE_WRITE_DATA,
512 FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
513 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
514 }
515 if (hFile==INVALID_HANDLE_VALUE)
516 return false;
517 SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
518 DWORD Result;
519 int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
520 sizeof(NewState),NULL,0,&Result,NULL);
521 CloseHandle(hFile);
522 return RetCode!=0;
523 }
524
525
526 void ResetFileCache(const wchar *Name)
527 {
528 // To reset file cache in Windows it is enough to open it with
529 // FILE_FLAG_NO_BUFFERING and then close it.
530 HANDLE hSrc=CreateFile(Name,GENERIC_READ,
531 FILE_SHARE_READ|FILE_SHARE_WRITE,
532 NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
533 if (hSrc!=INVALID_HANDLE_VALUE)
534 CloseHandle(hSrc);
535 }
536 #endif
537
538
539
540
541
542
543
544
545
546