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