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(&regs,0,sizeof(regs));
234     regs.h.ah=0x36;
235     regs.h.dl=Drive;
236 #ifdef _DJGPP
237     int86 (0x21,&regs,&outregs);
238 #else
239     _int86 (0x21,&regs,&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