123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828 |
- #include "rar.hpp"
- File::File()
- {
- hFile=FILE_BAD_HANDLE;
- *FileName=0;
- NewFile=false;
- LastWrite=false;
- HandleType=FILE_HANDLENORMAL;
- LineInput=false;
- SkipClose=false;
- ErrorType=FILE_SUCCESS;
- OpenShared=false;
- AllowDelete=true;
- AllowExceptions=true;
- PreserveAtime=false;
- #ifdef _WIN_ALL
- CreateMode=FMF_UNDEFINED;
- #endif
- ReadErrorMode=FREM_ASK;
- TruncatedAfterReadError=false;
- CurFilePos=0;
- }
- File::~File()
- {
- if (hFile!=FILE_BAD_HANDLE && !SkipClose)
- if (NewFile)
- Delete();
- else
- Close();
- }
- void File::operator = (File &SrcFile)
- {
- hFile=SrcFile.hFile;
- NewFile=SrcFile.NewFile;
- LastWrite=SrcFile.LastWrite;
- HandleType=SrcFile.HandleType;
- TruncatedAfterReadError=SrcFile.TruncatedAfterReadError;
- wcsncpyz(FileName,SrcFile.FileName,ASIZE(FileName));
- SrcFile.SkipClose=true;
- }
- bool File::Open(const wchar *Name,uint Mode)
- {
- ErrorType=FILE_SUCCESS;
- FileHandle hNewFile;
- bool OpenShared=File::OpenShared || (Mode & FMF_OPENSHARED)!=0;
- bool UpdateMode=(Mode & FMF_UPDATE)!=0;
- bool WriteMode=(Mode & FMF_WRITE)!=0;
- #ifdef _WIN_ALL
- uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ;
- if (UpdateMode)
- Access|=GENERIC_WRITE;
- uint ShareMode=(Mode & FMF_OPENEXCLUSIVE) ? 0 : FILE_SHARE_READ;
- if (OpenShared)
- ShareMode|=FILE_SHARE_WRITE;
- uint Flags=FILE_FLAG_SEQUENTIAL_SCAN;
- FindData FD;
- if (PreserveAtime)
- Access|=FILE_WRITE_ATTRIBUTES;
- hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
- DWORD LastError;
- if (hNewFile==FILE_BAD_HANDLE)
- {
- LastError=GetLastError();
- wchar LongName[NM];
- if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
- {
- hNewFile=CreateFile(LongName,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
-
-
-
-
-
-
-
-
-
-
-
-
- if (GetLastError()==ERROR_FILE_NOT_FOUND)
- LastError=ERROR_FILE_NOT_FOUND;
- }
- }
- if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
- ErrorType=FILE_NOTFOUND;
- if (PreserveAtime && hNewFile!=FILE_BAD_HANDLE)
- {
- FILETIME ft={0xffffffff,0xffffffff};
- SetFileTime(hNewFile,NULL,&ft,NULL);
- }
- #else
- int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
- #ifdef O_BINARY
- flags|=O_BINARY;
- #if defined(_AIX) && defined(_LARGE_FILE_API)
- flags|=O_LARGEFILE;
- #endif
- #endif
-
- #if defined(O_NOATIME)
- if (PreserveAtime)
- flags|=O_NOATIME;
- #endif
- char NameA[NM];
- WideToChar(Name,NameA,ASIZE(NameA));
- int handle=open(NameA,flags);
- #ifdef LOCK_EX
- #ifdef _OSF_SOURCE
- extern "C" int flock(int, int);
- #endif
- if (!OpenShared && UpdateMode && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
- {
- close(handle);
- return false;
- }
- #endif
- if (handle==-1)
- hNewFile=FILE_BAD_HANDLE;
- else
- {
- #ifdef FILE_USE_OPEN
- hNewFile=handle;
- #else
- hNewFile=fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
- #endif
- }
- if (hNewFile==FILE_BAD_HANDLE && errno==ENOENT)
- ErrorType=FILE_NOTFOUND;
- #endif
- NewFile=false;
- HandleType=FILE_HANDLENORMAL;
- SkipClose=false;
- bool Success=hNewFile!=FILE_BAD_HANDLE;
- if (Success)
- {
- hFile=hNewFile;
- wcsncpyz(FileName,Name,ASIZE(FileName));
- TruncatedAfterReadError=false;
- }
- return Success;
- }
- #if !defined(SFX_MODULE)
- void File::TOpen(const wchar *Name)
- {
- if (!WOpen(Name))
- ErrHandler.Exit(RARX_OPEN);
- }
- #endif
- bool File::WOpen(const wchar *Name)
- {
- if (Open(Name))
- return true;
- ErrHandler.OpenErrorMsg(Name);
- return false;
- }
- bool File::Create(const wchar *Name,uint Mode)
- {
- return false;
-
- }
- #if !defined(SFX_MODULE)
- void File::TCreate(const wchar *Name,uint Mode)
- {
- if (!WCreate(Name,Mode))
- ErrHandler.Exit(RARX_FATAL);
- }
- #endif
- bool File::WCreate(const wchar *Name,uint Mode)
- {
- if (Create(Name,Mode))
- return true;
- ErrHandler.CreateErrorMsg(Name);
- return false;
- }
- bool File::Close()
- {
- bool Success=true;
- if (hFile!=FILE_BAD_HANDLE)
- {
- if (!SkipClose)
- {
- #ifdef _WIN_ALL
-
-
- if (HandleType==FILE_HANDLENORMAL)
- Success=CloseHandle(hFile)==TRUE;
- #else
- #ifdef FILE_USE_OPEN
- Success=close(hFile)!=-1;
- #else
- Success=fclose(hFile)!=EOF;
- #endif
- #endif
- }
- hFile=FILE_BAD_HANDLE;
- }
- HandleType=FILE_HANDLENORMAL;
- if (!Success && AllowExceptions)
- ErrHandler.CloseError(FileName);
- return Success;
- }
- bool File::Delete()
- {
- if (HandleType!=FILE_HANDLENORMAL)
- return false;
- if (hFile!=FILE_BAD_HANDLE)
- Close();
- if (!AllowDelete)
- return false;
- return DelFile(FileName);
- }
- bool File::Rename(const wchar *NewName)
- {
-
- bool Success=wcscmp(FileName,NewName)==0;
- if (!Success)
- Success=RenameFile(FileName,NewName);
- if (Success)
- wcsncpyz(FileName,NewName,ASIZE(FileName));
- return Success;
- }
- bool File::Write(const void *Data,size_t Size)
- {
- return true;
-
- }
- int File::Read(void *Data,size_t Size)
- {
- if (TruncatedAfterReadError)
- return 0;
- int64 FilePos=0;
- if (ReadErrorMode==FREM_IGNORE)
- FilePos=Tell();
- int TotalRead=0;
- while (true)
- {
- int ReadSize=DirectRead(Data,Size);
- if (ReadSize==-1)
- {
- ErrorType=FILE_READERROR;
- if (AllowExceptions)
- if (ReadErrorMode==FREM_IGNORE)
- {
- ReadSize=0;
- for (size_t I=0;I<Size;I+=512)
- {
- Seek(FilePos+I,SEEK_SET);
- size_t SizeToRead=Min(Size-I,512);
- int ReadCode=DirectRead(Data,SizeToRead);
- ReadSize+=(ReadCode==-1) ? 512:ReadCode;
- if (ReadSize!=-1)
- TotalRead+=ReadSize;
- }
- }
- else
- {
- bool Ignore=false,Retry=false,Quit=false;
- if (ReadErrorMode==FREM_ASK && HandleType==FILE_HANDLENORMAL)
- {
- ErrHandler.AskRepeatRead(FileName,Ignore,Retry,Quit);
- if (Retry)
- continue;
- }
- if (Ignore || ReadErrorMode==FREM_TRUNCATE)
- {
- TruncatedAfterReadError=true;
- return 0;
- }
- ErrHandler.ReadError(FileName);
- }
- }
- TotalRead+=ReadSize;
- if (HandleType==FILE_HANDLESTD && !LineInput && ReadSize>0 && (uint)ReadSize<Size)
- {
-
-
-
-
-
-
-
-
-
- Data=(byte*)Data+ReadSize;
- Size-=ReadSize;
- continue;
- }
- break;
- }
- if (TotalRead>0)
- CurFilePos+=TotalRead;
- return TotalRead;
- }
- int File::DirectRead(void *Data,size_t Size)
- {
- #ifdef _WIN_ALL
- const size_t MaxDeviceRead=20000;
- const size_t MaxLockedRead=32768;
- #endif
- if (HandleType==FILE_HANDLESTD)
- {
- #ifdef _WIN_ALL
- hFile=GetStdHandle(STD_INPUT_HANDLE);
- #else
- #ifdef FILE_USE_OPEN
- hFile=STDIN_FILENO;
- #else
- hFile=stdin;
- #endif
- #endif
- }
- #ifdef _WIN_ALL
-
-
- DWORD Read;
- if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
- {
- if (IsDevice() && Size>MaxDeviceRead)
- return DirectRead(Data,MaxDeviceRead);
- if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE)
- return 0;
-
-
-
-
-
-
- if (HandleType==FILE_HANDLENORMAL && Size>MaxLockedRead &&
- GetLastError()==ERROR_LOCK_VIOLATION)
- return DirectRead(Data,MaxLockedRead);
- return -1;
- }
- return Read;
- #else
- #ifdef FILE_USE_OPEN
- ssize_t ReadSize=read(hFile,Data,Size);
- if (ReadSize==-1)
- return -1;
- return (int)ReadSize;
- #else
- if (LastWrite)
- {
- fflush(hFile);
- LastWrite=false;
- }
- clearerr(hFile);
- size_t ReadSize=fread(Data,1,Size,hFile);
- if (ferror(hFile))
- return -1;
- return (int)ReadSize;
- #endif
- #endif
- }
- void File::Seek(int64 Offset,int Method)
- {
- if (!RawSeek(Offset,Method) && AllowExceptions)
- ErrHandler.SeekError(FileName);
- }
- bool File::RawSeek(int64 Offset,int Method)
- {
- if (hFile==FILE_BAD_HANDLE)
- return true;
- if (!IsSeekable())
- {
- if (Method==SEEK_CUR)
- {
- Offset+=CurFilePos;
- Method=SEEK_SET;
- }
- if (Method==SEEK_SET && Offset>=CurFilePos)
- {
- uint64 SkipSize=Offset-CurFilePos;
- while (SkipSize>0)
- {
- byte Buf[4096];
- int ReadSize=Read(Buf,(size_t)Min(SkipSize,ASIZE(Buf)));
- if (ReadSize<=0)
- return false;
- SkipSize-=ReadSize;
- }
- CurFilePos=Offset;
- return true;
- }
- return false;
- }
- if (Offset<0 && Method!=SEEK_SET)
- {
- Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
- Method=SEEK_SET;
- }
- #ifdef _WIN_ALL
- LONG HighDist=(LONG)(Offset>>32);
- if (SetFilePointer(hFile,(LONG)Offset,&HighDist,Method)==0xffffffff &&
- GetLastError()!=NO_ERROR)
- return false;
- #else
- LastWrite=false;
- #ifdef FILE_USE_OPEN
- if (lseek(hFile,(off_t)Offset,Method)==-1)
- return false;
- #elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
- if (fseeko(hFile,Offset,Method)!=0)
- return false;
- #else
- if (fseek(hFile,(long)Offset,Method)!=0)
- return false;
- #endif
- #endif
- return true;
- }
- int64 File::Tell()
- {
- if (hFile==FILE_BAD_HANDLE)
- if (AllowExceptions)
- ErrHandler.SeekError(FileName);
- else
- return -1;
- if (!IsSeekable())
- return CurFilePos;
- #ifdef _WIN_ALL
- LONG HighDist=0;
- uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
- if (LowDist==0xffffffff && GetLastError()!=NO_ERROR)
- if (AllowExceptions)
- ErrHandler.SeekError(FileName);
- else
- return -1;
- return INT32TO64(HighDist,LowDist);
- #else
- #ifdef FILE_USE_OPEN
- return lseek(hFile,0,SEEK_CUR);
- #elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
- return ftello(hFile);
- #else
- return ftell(hFile);
- #endif
- #endif
- }
- void File::Prealloc(int64 Size)
- {
-
-
- }
- byte File::GetByte()
- {
- byte Byte=0;
- Read(&Byte,1);
- return Byte;
- }
- void File::PutByte(byte Byte)
- {
- Write(&Byte,1);
- }
- bool File::Truncate()
- {
- return false;
-
- }
- void File::Flush()
- {
- return;
-
- }
- void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
- {
-
-
- }
- void File::SetCloseFileTime(RarTime *ftm,RarTime *fta)
- {
-
-
- }
- void File::SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta)
- {
-
-
- }
- void File::GetOpenFileTime(RarTime *ft)
- {
-
-
- }
- int64 File::FileLength()
- {
- int64 SavePos=Tell();
- Seek(0,SEEK_END);
- int64 Length=Tell();
- Seek(SavePos,SEEK_SET);
- return Length;
- }
- bool File::IsDevice()
- {
- if (hFile==FILE_BAD_HANDLE)
- return false;
- #ifdef _WIN_ALL
- uint Type=GetFileType(hFile);
- return Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE;
- #else
- return isatty(GetFD());
- #endif
- }
- #ifndef SFX_MODULE
- int64 File::Copy(File &Dest,int64 Length)
- {
- Array<byte> Buffer(File::CopyBufferSize());
- int64 CopySize=0;
- bool CopyAll=(Length==INT64NDF);
- while (CopyAll || Length>0)
- {
- Wait();
- size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
- byte *Buf=&Buffer[0];
- int ReadSize=Read(Buf,SizeToRead);
- if (ReadSize==0)
- break;
- size_t WriteSize=ReadSize;
- #ifdef _WIN_ALL
-
-
-
-
-
- if (CopySize==0 && WriteSize>=4096)
- {
- const size_t FirstWrite=1024;
- Dest.Write(Buf,FirstWrite);
- Buf+=FirstWrite;
- WriteSize-=FirstWrite;
- }
- #endif
- Dest.Write(Buf,WriteSize);
- CopySize+=ReadSize;
- if (!CopyAll)
- Length-=ReadSize;
- }
- return CopySize;
- }
- #endif
|