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(&regs,0,sizeof(regs));
281     regs.h.ah=0x36;
282     regs.h.dl=Drive;
283 #ifdef _DJGPP
284     int86 (0x21,&regs,&outregs);
285 #else
286     _int86 (0x21,&regs,&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