"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