1 #include "rar.hpp"
2
MakeDir(const char * Name,const wchar * NameW,bool SetAttr,uint Attr)3 MKDIR_CODE MakeDir(const char *Name,const wchar *NameW,bool SetAttr,uint Attr)
4 {
5 #ifdef _WIN_ALL
6 BOOL RetCode;
7 if (WinNT() && NameW!=NULL && *NameW!=0)
8 RetCode=CreateDirectoryW(NameW,NULL);
9 else
10 if (Name!=NULL)
11 RetCode=CreateDirectoryA(Name,NULL);
12 else
13 return(MKDIR_BADPATH);
14 if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
15 {
16 if (SetAttr)
17 SetFileAttr(Name,NameW,Attr);
18 return(MKDIR_SUCCESS);
19 }
20 int ErrCode=GetLastError();
21 if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
22 return(MKDIR_BADPATH);
23 return(MKDIR_ERROR);
24 #else
25
26 // No Unicode in the rest of function, so Name must be not NULL.
27 if (Name==NULL)
28 return(MKDIR_BADPATH);
29 #endif
30
31 #ifdef _EMX
32 #ifdef _DJGPP
33 if (mkdir(Name,(Attr & FA_RDONLY) ? 0:S_IWUSR)==0)
34 #else
35 if (__mkdir(Name)==0)
36 #endif
37 {
38 if (SetAttr)
39 SetFileAttr(Name,NameW,Attr);
40 return(MKDIR_SUCCESS);
41 }
42 return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
43 #endif
44
45 #ifdef _UNIX
46 mode_t uattr=SetAttr ? (mode_t)Attr:0777;
47 int ErrCode=mkdir(Name,uattr);
48 if (ErrCode==-1)
49 return(errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR);
50 return(MKDIR_SUCCESS);
51 #endif
52 }
53
54
CreatePath(const char * Path,bool SkipLastName)55 bool CreatePath(const char *Path,bool SkipLastName)
56 {
57 if (Path==NULL || *Path==0)
58 return(false);
59
60 #if defined(_WIN_ALL) || defined(_EMX)
61 uint DirAttr=0;
62 #else
63 uint DirAttr=0777;
64 #endif
65
66 bool Success=true;
67
68 for (const char *s=Path;*s!=0;s=charnext(s))
69 {
70 if (s-Path>=NM)
71 break;
72
73 if (*s==CPATHDIVIDER)
74 {
75 char DirName[NM];
76 strncpy(DirName,Path,s-Path);
77 DirName[s-Path]=0;
78
79 if (MakeDir(DirName,NULL,true,DirAttr)==MKDIR_SUCCESS)
80 {
81 #ifndef GUI
82 mprintf(St(MCreatDir),DirName);
83 mprintf(" %s",St(MOk));
84 #endif
85 }
86 else
87 Success=false;
88 }
89 }
90 if (!SkipLastName)
91 if (!IsPathDiv(*PointToLastChar(Path)))
92 if (MakeDir(Path,NULL,true,DirAttr)!=MKDIR_SUCCESS)
93 Success=false;
94 return(Success);
95 }
96
97
CreatePath(const wchar * Path,bool SkipLastName)98 bool CreatePath(const wchar *Path,bool SkipLastName)
99 {
100 if (Path==NULL || *Path==0)
101 return(false);
102
103 #if defined(_WIN_ALL) || defined(_EMX)
104 uint DirAttr=0;
105 #else
106 uint DirAttr=0777;
107 #endif
108
109 bool Success=true;
110
111 for (const wchar *s=Path;*s!=0;s++)
112 {
113 if (s-Path>=NM)
114 break;
115
116 if (*s==CPATHDIVIDER)
117 {
118 wchar DirName[NM];
119 wcsncpy(DirName,Path,s-Path);
120 DirName[s-Path]=0;
121
122 if (MakeDir(NULL,DirName,true,DirAttr)==MKDIR_SUCCESS)
123 {
124 #ifndef GUI
125 char DirNameA[NM];
126 WideToChar(DirName,DirNameA,ASIZE(DirNameA));
127 DirNameA[ASIZE(DirNameA)-1]=0;
128 mprintf(St(MCreatDir),DirNameA);
129 mprintf(" %s",St(MOk));
130 #endif
131 }
132 else
133 Success=false;
134 }
135 }
136 if (!SkipLastName)
137 if (!IsPathDiv(*PointToLastChar(Path)))
138 if (MakeDir(NULL,Path,true,DirAttr)!=MKDIR_SUCCESS)
139 Success=false;
140 return(Success);
141 }
142
143
CreatePath(const char * Path,const wchar * PathW,bool SkipLastName)144 bool CreatePath(const char *Path,const wchar *PathW,bool SkipLastName)
145 {
146 #ifdef _WIN_ALL
147 // If we are in Windows, let's try Unicode path first. In Unix we do not
148 // need it (Unix MakeDir will fails with Unicode only name).
149 if (PathW!=NULL && *PathW!=0)
150 return(CreatePath(PathW,SkipLastName));
151 #endif
152 if (Path!=NULL && *Path!=0)
153 return(CreatePath(Path,SkipLastName));
154 return(false);
155 }
156
157
SetDirTime(const char * Name,const wchar * NameW,RarTime * ftm,RarTime * ftc,RarTime * fta)158 void SetDirTime(const char *Name,const wchar *NameW,RarTime *ftm,RarTime *ftc,RarTime *fta)
159 {
160 #ifdef _WIN_ALL
161 if (!WinNT())
162 return;
163
164 bool sm=ftm!=NULL && ftm->IsSet();
165 bool sc=ftc!=NULL && ftc->IsSet();
166 bool sa=fta!=NULL && fta->IsSet();
167
168 unsigned int DirAttr=GetFileAttr(Name,NameW);
169 bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FA_RDONLY)!=0);
170 if (ResetAttr)
171 SetFileAttr(Name,NameW,0);
172
173 wchar DirNameW[NM];
174 GetWideName(Name,NameW,DirNameW,ASIZE(DirNameW));
175 HANDLE hFile=CreateFileW(DirNameW,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
176 NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
177 if (hFile==INVALID_HANDLE_VALUE)
178 return;
179 FILETIME fm,fc,fa;
180 if (sm)
181 ftm->GetWin32(&fm);
182 if (sc)
183 ftc->GetWin32(&fc);
184 if (sa)
185 fta->GetWin32(&fa);
186 SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
187 CloseHandle(hFile);
188 if (ResetAttr)
189 SetFileAttr(Name,NameW,DirAttr);
190 #endif
191 #if defined(_UNIX) || defined(_EMX)
192 File::SetCloseFileTimeByName(Name,ftm,fta);
193 #endif
194 }
195
196
IsRemovable(const char * Name)197 bool IsRemovable(const char *Name)
198 {
199 #ifdef _WIN_ALL
200 char Root[NM];
201 GetPathRoot(Name,Root);
202 int Type=GetDriveTypeA(*Root!=0 ? Root:NULL);
203 return(Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM);
204 #elif defined(_EMX)
205 char Drive=etoupper(Name[0]);
206 return((Drive=='A' || Drive=='B') && Name[1]==':');
207 #else
208 return(false);
209 #endif
210 }
211
212
213
214
215 #ifndef SFX_MODULE
GetFreeDisk(const char * Name)216 int64 GetFreeDisk(const char *Name)
217 {
218 #ifdef _WIN_ALL
219 char Root[NM];
220 GetPathRoot(Name,Root);
221
222 typedef BOOL (WINAPI *GETDISKFREESPACEEX)(
223 LPCSTR,PULARGE_INTEGER,PULARGE_INTEGER,PULARGE_INTEGER
224 );
225 static GETDISKFREESPACEEX pGetDiskFreeSpaceEx=NULL;
226
227 if (pGetDiskFreeSpaceEx==NULL)
228 {
229 HMODULE hKernel=GetModuleHandleW(L"kernel32.dll");
230 if (hKernel!=NULL)
231 pGetDiskFreeSpaceEx=(GETDISKFREESPACEEX)GetProcAddress(hKernel,"GetDiskFreeSpaceExA");
232 }
233 if (pGetDiskFreeSpaceEx!=NULL)
234 {
235 GetFilePath(Name,Root,ASIZE(Root));
236 ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
237 uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
238 if (pGetDiskFreeSpaceEx(*Root ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
239 uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
240 return(INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart));
241 }
242
243 // We are here if we failed to load GetDiskFreeSpaceExA.
244 DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters;
245 if (!GetDiskFreeSpaceA(*Root ? Root:NULL,&SectorsPerCluster,&BytesPerSector,&FreeClusters,&TotalClusters))
246 return(1457664);
247 int64 FreeSize=SectorsPerCluster*BytesPerSector;
248 FreeSize=FreeSize*FreeClusters;
249 return(FreeSize);
250 #elif defined(_BEOS)
251 char Root[NM];
252 GetFilePath(Name,Root,ASIZE(Root));
253 dev_t Dev=dev_for_path(*Root ? Root:".");
254 if (Dev<0)
255 return(1457664);
256 fs_info Info;
257 if (fs_stat_dev(Dev,&Info)!=0)
258 return(1457664);
259 int64 FreeSize=Info.block_size;
260 FreeSize=FreeSize*Info.free_blocks;
261 return(FreeSize);
262 #elif defined(_UNIX)
263 return(1457664);
264 #elif defined(_EMX)
265 int Drive=IsDiskLetter(Name) ? etoupper(Name[0])-'A'+1:0;
266 #ifndef _DJGPP
267 if (_osmode == OS2_MODE)
268 {
269 FSALLOCATE fsa;
270 if (DosQueryFSInfo(Drive,1,&fsa,sizeof(fsa))!=0)
271 return(1457664);
272 int64 FreeSize=fsa.cSectorUnit*fsa.cbSector;
273 FreeSize=FreeSize*fsa.cUnitAvail;
274 return(FreeSize);
275 }
276 else
277 #endif
278 {
279 union REGS regs,outregs;
280 memset(®s,0,sizeof(regs));
281 regs.h.ah=0x36;
282 regs.h.dl=Drive;
283 #ifdef _DJGPP
284 int86 (0x21,®s,&outregs);
285 #else
286 _int86 (0x21,®s,&outregs);
287 #endif
288 if (outregs.x.ax==0xffff)
289 return(1457664);
290 int64 FreeSize=outregs.x.ax*outregs.x.cx;
291 FreeSize=FreeSize*outregs.x.bx;
292 return(FreeSize);
293 }
294 #else
295 #define DISABLEAUTODETECT
296 return(1457664);
297 #endif
298 }
299 #endif
300
301
302
303
304
FileExist(const char * Name,const wchar * NameW)305 bool FileExist(const char *Name,const wchar *NameW)
306 {
307 #ifdef _WIN_ALL
308 if (WinNT() && NameW!=NULL && *NameW!=0)
309 return(GetFileAttributesW(NameW)!=0xffffffff);
310 else
311 return(Name!=NULL && GetFileAttributesA(Name)!=0xffffffff);
312 #elif defined(ENABLE_ACCESS)
313 return(access(Name,0)==0);
314 #else
315 FindData FD;
316 return(FindFile::FastFind(Name,NameW,&FD));
317 #endif
318 }
319
320
FileExist(const wchar * Name)321 bool FileExist(const wchar *Name)
322 {
323 return FileExist(NULL,Name);
324 }
325
326
WildFileExist(const char * Name,const wchar * NameW)327 bool WildFileExist(const char *Name,const wchar *NameW)
328 {
329 if (IsWildcard(Name,NameW))
330 {
331 FindFile Find;
332 Find.SetMask(Name);
333 Find.SetMaskW(NameW);
334 FindData fd;
335 return(Find.Next(&fd));
336 }
337 return(FileExist(Name,NameW));
338 }
339
340
IsDir(uint Attr)341 bool IsDir(uint Attr)
342 {
343 #if defined (_WIN_ALL) || defined(_EMX)
344 return(Attr!=0xffffffff && (Attr & 0x10)!=0);
345 #endif
346 #if defined(_UNIX)
347 return((Attr & 0xF000)==0x4000);
348 #endif
349 }
350
351
IsUnreadable(uint Attr)352 bool IsUnreadable(uint Attr)
353 {
354 #if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
355 return(S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr));
356 #endif
357 return(false);
358 }
359
360
IsLabel(uint Attr)361 bool IsLabel(uint Attr)
362 {
363 #if defined (_WIN_ALL) || defined(_EMX)
364 return((Attr & 8)!=0);
365 #else
366 return(false);
367 #endif
368 }
369
370
IsLink(uint Attr)371 bool IsLink(uint Attr)
372 {
373 #ifdef _UNIX
374 return((Attr & 0xF000)==0xA000);
375 #else
376 return(false);
377 #endif
378 }
379
380
381
382
383
384
IsDeleteAllowed(uint FileAttr)385 bool IsDeleteAllowed(uint FileAttr)
386 {
387 #if defined(_WIN_ALL) || defined(_EMX)
388 return((FileAttr & (FA_RDONLY|FA_SYSTEM|FA_HIDDEN))==0);
389 #else
390 return((FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR));
391 #endif
392 }
393
394
PrepareToDelete(const char * Name,const wchar * NameW)395 void PrepareToDelete(const char *Name,const wchar *NameW)
396 {
397 #if defined(_WIN_ALL) || defined(_EMX)
398 SetFileAttr(Name,NameW,0);
399 #endif
400 #ifdef _UNIX
401 if (Name!=NULL)
402 chmod(Name,S_IRUSR|S_IWUSR|S_IXUSR);
403 #endif
404 }
405
406
GetFileAttr(const char * Name,const wchar * NameW)407 uint GetFileAttr(const char *Name,const wchar *NameW)
408 {
409 #ifdef _WIN_ALL
410 if (WinNT() && NameW!=NULL && *NameW!=0)
411 return(GetFileAttributesW(NameW));
412 else
413 return(GetFileAttributesA(Name));
414 #elif defined(_DJGPP)
415 return(_chmod(Name,0));
416 #else
417 struct stat st;
418 if (stat(Name,&st)!=0)
419 return(0);
420 #ifdef _EMX
421 return(st.st_attr);
422 #else
423 return(st.st_mode);
424 #endif
425 #endif
426 }
427
428
SetFileAttr(const char * Name,const wchar * NameW,uint Attr)429 bool SetFileAttr(const char *Name,const wchar *NameW,uint Attr)
430 {
431 bool Success;
432 #ifdef _WIN_ALL
433 if (WinNT() && NameW!=NULL && *NameW!=0)
434 Success=SetFileAttributesW(NameW,Attr)!=0;
435 else
436 if (Name!=NULL)
437 Success=SetFileAttributesA(Name,Attr)!=0;
438 else
439 Success=false;
440 #elif defined(_DJGPP)
441 Success=_chmod(Name,1,Attr)!=-1;
442 #elif defined(_EMX)
443 Success=__chmod(Name,1,Attr)!=-1;
444 #elif defined(_UNIX)
445 Success=chmod(Name,(mode_t)Attr)==0;
446 #else
447 Success=false;
448 #endif
449 return(Success);
450 }
451
452
453
454
455 #ifndef SFX_MODULE
CalcFileCRC(File * SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)456 uint CalcFileCRC(File *SrcFile,int64 Size,CALCCRC_SHOWMODE ShowMode)
457 {
458 SaveFilePos SavePos(*SrcFile);
459 const size_t BufSize=0x10000;
460 Array<byte> Data(BufSize);
461 int64 BlockCount=0;
462 uint DataCRC=0xffffffff;
463
464 #if !defined(SILENT) && !defined(_WIN_CE)
465 int64 FileLength=SrcFile->FileLength();
466 if (ShowMode!=CALCCRC_SHOWNONE)
467 {
468 mprintf(St(MCalcCRC));
469 mprintf(" ");
470 }
471
472 #endif
473
474 SrcFile->Seek(0,SEEK_SET);
475 while (true)
476 {
477 size_t SizeToRead;
478 if (Size==INT64NDF) // If we process the entire file.
479 SizeToRead=BufSize; // Then always attempt to read the entire buffer.
480 else
481 SizeToRead=(size_t)Min((int64)BufSize,Size);
482 int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
483 if (ReadSize==0)
484 break;
485
486 ++BlockCount;
487 if ((BlockCount & 15)==0)
488 {
489 #if !defined(SILENT) && !defined(_WIN_CE)
490 if (ShowMode==CALCCRC_SHOWALL)
491 mprintf("\b\b\b\b%3d%%",ToPercent(BlockCount*int64(BufSize),FileLength));
492 #endif
493 Wait();
494 }
495 DataCRC=CRC(DataCRC,&Data[0],ReadSize);
496 if (Size!=INT64NDF)
497 Size-=ReadSize;
498 }
499 #if !defined(SILENT) && !defined(_WIN_CE)
500 if (ShowMode==CALCCRC_SHOWALL)
501 mprintf("\b\b\b\b ");
502 #endif
503 return(DataCRC^0xffffffff);
504 }
505 #endif
506
507
RenameFile(const char * SrcName,const wchar * SrcNameW,const char * DestName,const wchar * DestNameW)508 bool RenameFile(const char *SrcName,const wchar *SrcNameW,const char *DestName,const wchar *DestNameW)
509 {
510 return(rename(SrcName,DestName)==0);
511 }
512
513
DelFile(const char * Name)514 bool DelFile(const char *Name)
515 {
516 return(DelFile(Name,NULL));
517 }
518
519
520
521
DelFile(const char * Name,const wchar * NameW)522 bool DelFile(const char *Name,const wchar *NameW)
523 {
524 return(Name!=NULL && remove(Name)==0);
525 }
526
527
528
529
530
531
532
533
534 #if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
SetFileCompression(char * Name,wchar * NameW,bool State)535 bool SetFileCompression(char *Name,wchar *NameW,bool State)
536 {
537 wchar FileNameW[NM];
538 GetWideName(Name,NameW,FileNameW,ASIZE(FileNameW));
539 HANDLE hFile=CreateFileW(FileNameW,FILE_READ_DATA|FILE_WRITE_DATA,
540 FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
541 FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
542 if (hFile==INVALID_HANDLE_VALUE)
543 return(false);
544 SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
545 DWORD Result;
546 int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
547 sizeof(NewState),NULL,0,&Result,NULL);
548 CloseHandle(hFile);
549 return(RetCode!=0);
550 }
551 #endif
552
553
554
555
556
557
558
559
560
561