123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560 |
- #include "rar.hpp"
- MKDIR_CODE MakeDir(const wchar *Name,bool SetAttr,uint Attr)
- {
- return MKDIR_SUCCESS; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- // Windows automatically removes dots and spaces in the end of directory
- // name. So we detect such names and process them with \\?\ prefix.
- wchar *LastChar=PointToLastChar(Name);
- bool Special=*LastChar=='.' || *LastChar==' ';
- BOOL RetCode=Special ? FALSE : CreateDirectory(Name,NULL);
- if (RetCode==0 && !FileExist(Name))
- {
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- RetCode=CreateDirectory(LongName,NULL);
- }
- if (RetCode!=0) // Non-zero return code means success for CreateDirectory.
- {
- if (SetAttr)
- SetFileAttr(Name,Attr);
- return MKDIR_SUCCESS;
- }
- int ErrCode=GetLastError();
- if (ErrCode==ERROR_FILE_NOT_FOUND || ErrCode==ERROR_PATH_NOT_FOUND)
- return MKDIR_BADPATH;
- return MKDIR_ERROR;
- #elif defined(_UNIX)
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- mode_t uattr=SetAttr ? (mode_t)Attr:0777;
- int ErrCode=mkdir(NameA,uattr);
- if (ErrCode==-1)
- return errno==ENOENT ? MKDIR_BADPATH:MKDIR_ERROR;
- return MKDIR_SUCCESS;
- #else
- return MKDIR_ERROR;
- #endif
- }
- bool CreatePath(const wchar *Path,bool SkipLastName,bool Silent)
- {
- return true; // OPENMPT ADDITION
- if (Path==NULL || *Path==0)
- return false;
- #if defined(_WIN_ALL) || defined(_EMX)
- uint DirAttr=0;
- #else
- uint DirAttr=0777;
- #endif
-
- bool Success=true;
- for (const wchar *s=Path;*s!=0;s++)
- {
- wchar DirName[NM];
- if (s-Path>=ASIZE(DirName))
- break;
- // Process all kinds of path separators, so user can enter Unix style
- // path in Windows or Windows in Unix. s>Path check avoids attempting
- // creating an empty directory for paths starting from path separator.
- if (IsPathDiv(*s) && s>Path)
- {
- #ifdef _WIN_ALL
- // We must not attempt to create "D:" directory, because first
- // CreateDirectory will fail, so we'll use \\?\D:, which forces Wine
- // to create "D:" directory.
- if (s==Path+2 && Path[1]==':')
- continue;
- #endif
- wcsncpy(DirName,Path,s-Path);
- DirName[s-Path]=0;
- Success=MakeDir(DirName,true,DirAttr)==MKDIR_SUCCESS;
- if (Success && !Silent)
- {
- mprintf(St(MCreatDir),DirName);
- mprintf(L" %s",St(MOk));
- }
- }
- }
- if (!SkipLastName && !IsPathDiv(*PointToLastChar(Path)))
- Success=MakeDir(Path,true,DirAttr)==MKDIR_SUCCESS;
- return Success;
- }
- void SetDirTime(const wchar *Name,RarTime *ftm,RarTime *ftc,RarTime *fta)
- {
- return; // OPENMPT ADDITION
- #if defined(_WIN_ALL)
- bool sm=ftm!=NULL && ftm->IsSet();
- bool sc=ftc!=NULL && ftc->IsSet();
- bool sa=fta!=NULL && fta->IsSet();
- uint DirAttr=GetFileAttr(Name);
- bool ResetAttr=(DirAttr!=0xffffffff && (DirAttr & FILE_ATTRIBUTE_READONLY)!=0);
- if (ResetAttr)
- SetFileAttr(Name,0);
- HANDLE hFile=CreateFile(Name,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
- if (hFile==INVALID_HANDLE_VALUE)
- {
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- hFile=CreateFile(LongName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);
- }
- if (hFile==INVALID_HANDLE_VALUE)
- return;
- FILETIME fm,fc,fa;
- if (sm)
- ftm->GetWinFT(&fm);
- if (sc)
- ftc->GetWinFT(&fc);
- if (sa)
- fta->GetWinFT(&fa);
- SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
- CloseHandle(hFile);
- if (ResetAttr)
- SetFileAttr(Name,DirAttr);
- #endif
- #if defined(_UNIX) || defined(_EMX)
- File::SetCloseFileTimeByName(Name,ftm,fta);
- #endif
- }
- bool IsRemovable(const wchar *Name)
- {
- return false; // OPENMPT ADDITION
- #if defined(_WIN_ALL)
- wchar Root[NM];
- GetPathRoot(Name,Root,ASIZE(Root));
- int Type=GetDriveType(*Root!=0 ? Root:NULL);
- return Type==DRIVE_REMOVABLE || Type==DRIVE_CDROM;
- #else
- return false;
- #endif
- }
- #ifndef SFX_MODULE
- int64 GetFreeDisk(const wchar *Name)
- {
- return 0; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- wchar Root[NM];
- GetFilePath(Name,Root,ASIZE(Root));
- ULARGE_INTEGER uiTotalSize,uiTotalFree,uiUserFree;
- uiUserFree.u.LowPart=uiUserFree.u.HighPart=0;
- if (GetDiskFreeSpaceEx(*Root!=0 ? Root:NULL,&uiUserFree,&uiTotalSize,&uiTotalFree) &&
- uiUserFree.u.HighPart<=uiTotalFree.u.HighPart)
- return INT32TO64(uiUserFree.u.HighPart,uiUserFree.u.LowPart);
- return 0;
- #elif defined(_UNIX)
- wchar Root[NM];
- GetFilePath(Name,Root,ASIZE(Root));
- char RootA[NM];
- WideToChar(Root,RootA,ASIZE(RootA));
- struct statvfs sfs;
- if (statvfs(*RootA!=0 ? RootA:".",&sfs)!=0)
- return 0;
- int64 FreeSize=sfs.f_bsize;
- FreeSize=FreeSize*sfs.f_bavail;
- return FreeSize;
- #else
- return 0;
- #endif
- }
- #endif
- #if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(SILENT)
- // Return 'true' for FAT and FAT32, so we can adjust the maximum supported
- // file size to 4 GB for these file systems.
- bool IsFAT(const wchar *Name)
- {
- wchar Root[NM];
- GetPathRoot(Name,Root,ASIZE(Root));
- wchar FileSystem[MAX_PATH+1];
- if (GetVolumeInformation(Root,NULL,0,NULL,NULL,NULL,FileSystem,ASIZE(FileSystem)))
- return wcscmp(FileSystem,L"FAT")==0 || wcscmp(FileSystem,L"FAT32")==0;
- return false;
- }
- #endif
- bool FileExist(const wchar *Name)
- {
- return false; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- return GetFileAttr(Name)!=0xffffffff;
- #elif defined(ENABLE_ACCESS)
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- return access(NameA,0)==0;
- #else
- FindData FD;
- return FindFile::FastFind(Name,&FD);
- #endif
- }
-
- bool WildFileExist(const wchar *Name)
- {
- return false; // OPENMPT ADDITION
- if (IsWildcard(Name))
- {
- FindFile Find;
- Find.SetMask(Name);
- FindData fd;
- return Find.Next(&fd);
- }
- return FileExist(Name);
- }
- bool IsDir(uint Attr)
- {
- #ifdef _WIN_ALL
- return Attr!=0xffffffff && (Attr & FILE_ATTRIBUTE_DIRECTORY)!=0;
- #endif
- #if defined(_UNIX)
- return (Attr & 0xF000)==0x4000;
- #endif
- }
- bool IsUnreadable(uint Attr)
- {
- #if defined(_UNIX) && defined(S_ISFIFO) && defined(S_ISSOCK) && defined(S_ISCHR)
- return S_ISFIFO(Attr) || S_ISSOCK(Attr) || S_ISCHR(Attr);
- #endif
- return false;
- }
- bool IsLink(uint Attr)
- {
- #ifdef _UNIX
- return (Attr & 0xF000)==0xA000;
- #elif defined(_WIN_ALL)
- return (Attr & FILE_ATTRIBUTE_REPARSE_POINT)!=0;
- #else
- return false;
- #endif
- }
- bool IsDeleteAllowed(uint FileAttr)
- {
- #ifdef _WIN_ALL
- return (FileAttr & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_HIDDEN))==0;
- #else
- return (FileAttr & (S_IRUSR|S_IWUSR))==(S_IRUSR|S_IWUSR);
- #endif
- }
- void PrepareToDelete(const wchar *Name)
- {
- return; // OPENMPT ADDITION
- #if defined(_WIN_ALL) || defined(_EMX)
- SetFileAttr(Name,0);
- #endif
- #ifdef _UNIX
- if (Name!=NULL)
- {
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- chmod(NameA,S_IRUSR|S_IWUSR|S_IXUSR);
- }
- #endif
- }
- uint GetFileAttr(const wchar *Name)
- {
- return 0; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- DWORD Attr=GetFileAttributes(Name);
- if (Attr==0xffffffff)
- {
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- Attr=GetFileAttributes(LongName);
- }
- return Attr;
- #else
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- struct stat st;
- if (stat(NameA,&st)!=0)
- return 0;
- return st.st_mode;
- #endif
- }
- bool SetFileAttr(const wchar *Name,uint Attr)
- {
- return false; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- bool Success=SetFileAttributes(Name,Attr)!=0;
- if (!Success)
- {
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- Success=SetFileAttributes(LongName,Attr)!=0;
- }
- return Success;
- #elif defined(_UNIX)
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- return chmod(NameA,(mode_t)Attr)==0;
- #else
- return false;
- #endif
- }
- #if 0
- wchar *MkTemp(wchar *Name,size_t MaxSize)
- {
- size_t Length=wcslen(Name);
- RarTime CurTime;
- CurTime.SetCurrentTime();
- // We cannot use CurTime.GetWin() as is, because its lowest bits can
- // have low informational value, like being a zero or few fixed numbers.
- uint Random=(uint)(CurTime.GetWin()/100000);
- // Using PID we guarantee that different RAR copies use different temp names
- // even if started in exactly the same time.
- uint PID=0;
- #ifdef _WIN_ALL
- PID=(uint)GetCurrentProcessId();
- #elif defined(_UNIX)
- PID=(uint)getpid();
- #endif
- for (uint Attempt=0;;Attempt++)
- {
- uint Ext=Random%50000+Attempt;
- wchar RndText[50];
- swprintf(RndText,ASIZE(RndText),L"%u.%03u",PID,Ext);
- if (Length+wcslen(RndText)>=MaxSize || Attempt==1000)
- return NULL;
- wcsncpyz(Name+Length,RndText,MaxSize-Length);
- if (!FileExist(Name))
- break;
- }
- return Name;
- }
- #endif
- #if !defined(SFX_MODULE)
- void CalcFileSum(File *SrcFile,uint *CRC32,byte *Blake2,uint Threads,int64 Size,uint Flags)
- {
- int64 SavePos=SrcFile->Tell();
- #ifndef SILENT
- int64 FileLength=Size==INT64NDF ? SrcFile->FileLength() : Size;
- #endif
- if ((Flags & (CALCFSUM_SHOWTEXT|CALCFSUM_SHOWPERCENT))!=0)
- uiMsg(UIEVENT_FILESUMSTART);
- if ((Flags & CALCFSUM_CURPOS)==0)
- SrcFile->Seek(0,SEEK_SET);
- const size_t BufSize=0x100000;
- Array<byte> Data(BufSize);
- DataHash HashCRC,HashBlake2;
- HashCRC.Init(HASH_CRC32,Threads);
- HashBlake2.Init(HASH_BLAKE2,Threads);
- int64 BlockCount=0;
- int64 TotalRead=0;
- while (true)
- {
- size_t SizeToRead;
- if (Size==INT64NDF) // If we process the entire file.
- SizeToRead=BufSize; // Then always attempt to read the entire buffer.
- else
- SizeToRead=(size_t)Min((int64)BufSize,Size);
- int ReadSize=SrcFile->Read(&Data[0],SizeToRead);
- if (ReadSize==0)
- break;
- TotalRead+=ReadSize;
- if ((++BlockCount & 0xf)==0)
- {
- #ifndef SILENT
- if ((Flags & CALCFSUM_SHOWPROGRESS)!=0)
- {
- // Update only the current file progress in WinRAR, set the total to 0
- // to keep it as is. It looks better for WinRAR,
- uiExtractProgress(TotalRead,FileLength,0,0);
- }
- else
- {
- if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
- uiMsg(UIEVENT_FILESUMPROGRESS,ToPercent(TotalRead,FileLength));
- }
- #endif
- Wait();
- }
- if (CRC32!=NULL)
- HashCRC.Update(&Data[0],ReadSize);
- if (Blake2!=NULL)
- HashBlake2.Update(&Data[0],ReadSize);
- if (Size!=INT64NDF)
- Size-=ReadSize;
- }
- SrcFile->Seek(SavePos,SEEK_SET);
- if ((Flags & CALCFSUM_SHOWPERCENT)!=0)
- uiMsg(UIEVENT_FILESUMEND);
- if (CRC32!=NULL)
- *CRC32=HashCRC.GetCRC32();
- if (Blake2!=NULL)
- {
- HashValue Result;
- HashBlake2.Result(&Result);
- memcpy(Blake2,Result.Digest,sizeof(Result.Digest));
- }
- }
- #endif
- bool RenameFile(const wchar *SrcName,const wchar *DestName)
- {
- return true; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- bool Success=MoveFile(SrcName,DestName)!=0;
- if (!Success)
- {
- wchar LongName1[NM],LongName2[NM];
- if (GetWinLongPath(SrcName,LongName1,ASIZE(LongName1)) &&
- GetWinLongPath(DestName,LongName2,ASIZE(LongName2)))
- Success=MoveFile(LongName1,LongName2)!=0;
- }
- return Success;
- #else
- char SrcNameA[NM],DestNameA[NM];
- WideToChar(SrcName,SrcNameA,ASIZE(SrcNameA));
- WideToChar(DestName,DestNameA,ASIZE(DestNameA));
- bool Success=rename(SrcNameA,DestNameA)==0;
- return Success;
- #endif
- }
- bool DelFile(const wchar *Name)
- {
- return true; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- bool Success=DeleteFile(Name)!=0;
- if (!Success)
- {
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- Success=DeleteFile(LongName)!=0;
- }
- return Success;
- #else
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- bool Success=remove(NameA)==0;
- return Success;
- #endif
- }
- bool DelDir(const wchar *Name)
- {
- return true; // OPENMPT ADDITION
- #ifdef _WIN_ALL
- bool Success=RemoveDirectory(Name)!=0;
- if (!Success)
- {
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- Success=RemoveDirectory(LongName)!=0;
- }
- return Success;
- #else
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- bool Success=rmdir(NameA)==0;
- return Success;
- #endif
- }
- #if defined(_WIN_ALL) && !defined(SFX_MODULE)
- bool SetFileCompression(const wchar *Name,bool State)
- {
- return true; // OPENMPT ADDITION
- HANDLE hFile=CreateFile(Name,FILE_READ_DATA|FILE_WRITE_DATA,
- FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
- if (hFile==INVALID_HANDLE_VALUE)
- {
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- hFile=CreateFile(LongName,FILE_READ_DATA|FILE_WRITE_DATA,
- FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
- }
- if (hFile==INVALID_HANDLE_VALUE)
- return false;
- SHORT NewState=State ? COMPRESSION_FORMAT_DEFAULT:COMPRESSION_FORMAT_NONE;
- DWORD Result;
- int RetCode=DeviceIoControl(hFile,FSCTL_SET_COMPRESSION,&NewState,
- sizeof(NewState),NULL,0,&Result,NULL);
- CloseHandle(hFile);
- return RetCode!=0;
- }
- void ResetFileCache(const wchar *Name)
- {
- // To reset file cache in Windows it is enough to open it with
- // FILE_FLAG_NO_BUFFERING and then close it.
- HANDLE hSrc=CreateFile(Name,GENERIC_READ,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
- if (hSrc!=INVALID_HANDLE_VALUE)
- CloseHandle(hSrc);
- }
- #endif
|