home *** CD-ROM | disk | FTP | other *** search
/ ftp.rarlab.com / 2014.05.ftp.rarlab.com.tar / ftp.rarlab.com / rar / unrar_vms_alpha-3.6.5.zip / file.cxx < prev    next >
C/C++ Source or Header  |  2006-06-27  |  14KB  |  688 lines

  1. #include "rar.hpp"
  2.  
  3. static File *CreatedFiles[256];
  4. static int RemoveCreatedActive=0;
  5.  
  6. File::File()
  7. {
  8.   hFile=BAD_HANDLE;
  9.   *FileName=0;
  10.   *FileNameW=0;
  11.   NewFile=false;
  12.   LastWrite=false;
  13.   HandleType=FILE_HANDLENORMAL;
  14.   SkipClose=false;
  15.   IgnoreReadErrors=false;
  16.   ErrorType=FILE_SUCCESS;
  17.   OpenShared=false;
  18.   AllowDelete=true;
  19.   CloseCount=0;
  20.   AllowExceptions=true;
  21. #ifdef _WIN_32
  22.   NoSequentialRead=false;
  23. #endif
  24. }
  25.  
  26.  
  27. File::~File()
  28. {
  29.   if (hFile!=BAD_HANDLE && !SkipClose)
  30.     if (NewFile)
  31.       Delete();
  32.     else
  33.       Close();
  34. }
  35.  
  36.  
  37. void File::operator = (File &SrcFile)
  38. {
  39.   hFile=SrcFile.hFile;
  40.   strcpy(FileName,SrcFile.FileName);
  41.   NewFile=SrcFile.NewFile;
  42.   LastWrite=SrcFile.LastWrite;
  43.   HandleType=SrcFile.HandleType;
  44.   SrcFile.SkipClose=true;
  45. }
  46.  
  47.  
  48. bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
  49. {
  50.   ErrorType=FILE_SUCCESS;
  51.   FileHandle hNewFile;
  52.   if (File::OpenShared)
  53.     OpenShared=true;
  54. #ifdef _WIN_32
  55.   uint Access=GENERIC_READ;
  56.   if (Update)
  57.     Access|=GENERIC_WRITE;
  58.   uint ShareMode=FILE_SHARE_READ;
  59.   if (OpenShared)
  60.     ShareMode|=FILE_SHARE_WRITE;
  61.   uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
  62.   if (WinNT() && NameW!=NULL && *NameW!=0)
  63.     hNewFile=CreateFileW(NameW,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
  64.   else
  65.     hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
  66.  
  67.   if (hNewFile==BAD_HANDLE && GetLastError()==ERROR_FILE_NOT_FOUND)
  68.     ErrorType=FILE_NOTFOUND;
  69. #else
  70.   int flags=Update ? O_RDWR:O_RDONLY;
  71. #ifdef O_BINARY
  72.   flags|=O_BINARY;
  73. #if defined(_AIX) && defined(_LARGE_FILE_API)
  74.   flags|=O_LARGEFILE;
  75. #endif
  76. #endif
  77. #if defined(_EMX) && !defined(_DJGPP)
  78.   int sflags=OpenShared ? SH_DENYNO:SH_DENYWR;
  79.   int handle=sopen(Name,flags,sflags);
  80. #else
  81.   int handle=open(Name,flags);
  82. #ifdef LOCK_EX
  83.  
  84. #ifdef _OSF_SOURCE
  85.   extern "C" int flock(int, int);
  86. #endif
  87.  
  88.   if (!OpenShared && Update && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
  89.   {
  90.     close(handle);
  91.     return(false);
  92.   }
  93. #endif
  94. #endif
  95.   hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,Update ? UPDATEBINARY:READBINARY);
  96.   if (hNewFile==BAD_HANDLE && errno==ENOENT)
  97.     ErrorType=FILE_NOTFOUND;
  98. #endif
  99.   NewFile=false;
  100.   HandleType=FILE_HANDLENORMAL;
  101.   SkipClose=false;
  102.   bool Success=hNewFile!=BAD_HANDLE;
  103.   if (Success)
  104.   {
  105.     hFile=hNewFile;
  106.     if (NameW!=NULL)
  107.       strcpyw(FileNameW,NameW);
  108.     else
  109.       *FileNameW=0;
  110.     if (Name!=NULL)
  111.       strcpy(FileName,Name);
  112.     else
  113.       WideToChar(NameW,FileName);
  114.     AddFileToList(hFile);
  115.   }
  116.   return(Success);
  117. }
  118.  
  119.  
  120. #if !defined(SHELL_EXT) && !defined(SFX_MODULE)
  121. void File::TOpen(const char *Name,const wchar *NameW)
  122. {
  123.   if (!WOpen(Name,NameW))
  124.     ErrHandler.Exit(OPEN_ERROR);
  125. }
  126. #endif
  127.  
  128.  
  129. bool File::WOpen(const char *Name,const wchar *NameW)
  130. {
  131.   if (Open(Name,NameW))
  132.     return(true);
  133.   ErrHandler.OpenErrorMsg(Name);
  134.   return(false);
  135. }
  136.  
  137.  
  138. bool File::Create(const char *Name,const wchar *NameW)
  139. {
  140. #ifdef _WIN_32
  141.   if (WinNT() && NameW!=NULL && *NameW!=0)
  142.     hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
  143.                       CREATE_ALWAYS,0,NULL);
  144.   else
  145.     hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
  146.                      CREATE_ALWAYS,0,NULL);
  147. #else
  148.   hFile=fopen(Name,CREATEBINARY);
  149. #endif
  150.   NewFile=true;
  151.   HandleType=FILE_HANDLENORMAL;
  152.   SkipClose=false;
  153.   if (NameW!=NULL)
  154.     strcpyw(FileNameW,NameW);
  155.   else
  156.     *FileNameW=0;
  157.   if (Name!=NULL)
  158.     strcpy(FileName,Name);
  159.   else
  160.     WideToChar(NameW,FileName);
  161.   AddFileToList(hFile);
  162.   return(hFile!=BAD_HANDLE);
  163. }
  164.  
  165.  
  166. void File::AddFileToList(FileHandle hFile)
  167. {
  168.   if (hFile!=BAD_HANDLE)
  169.     for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
  170.       if (CreatedFiles[I]==NULL)
  171.       {
  172.         CreatedFiles[I]=this;
  173.         break;
  174.       }
  175. }
  176.  
  177.  
  178. #if !defined(SHELL_EXT) && !defined(SFX_MODULE)
  179. void File::TCreate(const char *Name,const wchar *NameW)
  180. {
  181.   if (!WCreate(Name,NameW))
  182.     ErrHandler.Exit(FATAL_ERROR);
  183. }
  184. #endif
  185.  
  186.  
  187. bool File::WCreate(const char *Name,const wchar *NameW)
  188. {
  189.   if (Create(Name,NameW))
  190.     return(true);
  191.   ErrHandler.SetErrorCode(CREATE_ERROR);
  192.   ErrHandler.CreateErrorMsg(Name);
  193.   return(false);
  194. }
  195.  
  196.  
  197. bool File::Close()
  198. {
  199.   bool Success=true;
  200.   if (HandleType!=FILE_HANDLENORMAL)
  201.     HandleType=FILE_HANDLENORMAL;
  202.   else
  203.     if (hFile!=BAD_HANDLE)
  204.     {
  205.       if (!SkipClose)
  206.       {
  207. #ifdef _WIN_32
  208.         Success=CloseHandle(hFile);
  209. #else
  210.         Success=fclose(hFile)!=EOF;
  211. #endif
  212.         if (Success || !RemoveCreatedActive)
  213.           for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
  214.             if (CreatedFiles[I]==this)
  215.             {
  216.               CreatedFiles[I]=NULL;
  217.               break;
  218.             }
  219.       }
  220.       hFile=BAD_HANDLE;
  221.       if (!Success && AllowExceptions)
  222.         ErrHandler.CloseError(FileName);
  223.     }
  224.   CloseCount++;
  225.   return(Success);
  226. }
  227.  
  228.  
  229. void File::Flush()
  230. {
  231. #ifdef _WIN_32
  232.   FlushFileBuffers(hFile);
  233. #else
  234.   fflush(hFile);
  235. #endif
  236. }
  237.  
  238.  
  239. bool File::Delete()
  240. {
  241.   if (HandleType!=FILE_HANDLENORMAL || !AllowDelete)
  242.     return(false);
  243.   if (hFile!=BAD_HANDLE)
  244.     Close();
  245.   return(DelFile(FileName,FileNameW));
  246. }
  247.  
  248.  
  249. bool File::Rename(const char *NewName)
  250. {
  251.   bool Success=strcmp(FileName,NewName)==0;
  252.   if (!Success)
  253.     Success=rename(FileName,NewName)==0;
  254.   if (Success)
  255.   {
  256.     strcpy(FileName,NewName);
  257.     *FileNameW=0;
  258.   }
  259.   return(Success);
  260. }
  261.  
  262.  
  263. void File::Write(const void *Data,int Size)
  264. {
  265.   if (Size==0)
  266.     return;
  267. #ifndef _WIN_CE
  268.   if (HandleType!=FILE_HANDLENORMAL)
  269.     switch(HandleType)
  270.     {
  271.       case FILE_HANDLESTD:
  272. #ifdef _WIN_32
  273.         hFile=GetStdHandle(STD_OUTPUT_HANDLE);
  274. #else
  275.         hFile=stdout;
  276. #endif
  277.         break;
  278.       case FILE_HANDLEERR:
  279. #ifdef _WIN_32
  280.         hFile=GetStdHandle(STD_ERROR_HANDLE);
  281. #else
  282.         hFile=stderr;
  283. #endif
  284.         break;
  285.     }
  286. #endif
  287.   while (1)
  288.   {
  289.     bool Success;
  290. #ifdef _WIN_32
  291.     DWORD Written;
  292.     if (HandleType!=FILE_HANDLENORMAL)
  293.     {
  294.       const int MaxSize=0x4000;
  295.       for (int I=0;I<Size;I+=MaxSize)
  296.         if (!(Success=WriteFile(hFile,(byte *)Data+I,Min(Size-I,MaxSize),&Written,NULL)))
  297.           break;
  298.     }
  299.     else
  300.       Success=WriteFile(hFile,Data,Size,&Written,NULL);
  301. #else
  302.     int Written=fwrite(Data,1,Size,hFile);
  303.     Success=Written==Size && !ferror(hFile);
  304. #endif
  305.     if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
  306.     {
  307. #if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(RARDLL)
  308.       int ErrCode=GetLastError();
  309.       Int64 FilePos=Tell();
  310.       Int64 FreeSize=GetFreeDisk(FileName);
  311.       SetLastError(ErrCode);
  312.       if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
  313.         ErrHandler.WriteErrorFAT(FileName);
  314. #endif
  315.       if (ErrHandler.AskRepeatWrite(FileName))
  316.       {
  317. #ifndef _WIN_32
  318.         clearerr(hFile);
  319. #endif
  320.         if (Written<Size && Written>0)
  321.           Seek(Tell()-Written,SEEK_SET);
  322.         continue;
  323.       }
  324.       ErrHandler.WriteError(NULL,FileName);
  325.     }
  326.     break;
  327.   }
  328.   LastWrite=true;
  329. }
  330.  
  331.  
  332. int File::Read(void *Data,int Size)
  333. {
  334.   Int64 FilePos;
  335.   if (IgnoreReadErrors)
  336.     FilePos=Tell();
  337.   int ReadSize;
  338.   while (true)
  339.   {
  340.     ReadSize=DirectRead(Data,Size);
  341.     if (ReadSize==-1)
  342.     {
  343.       ErrorType=FILE_READERROR;
  344.       if (AllowExceptions)
  345.         if (IgnoreReadErrors)
  346.         {
  347.           ReadSize=0;
  348.           for (int I=0;I<Size;I+=512)
  349.           {
  350.             Seek(FilePos+I,SEEK_SET);
  351.             int SizeToRead=Min(Size-I,512);
  352.             int ReadCode=DirectRead(Data,SizeToRead);
  353.             ReadSize+=(ReadCode==-1) ? 512:ReadCode;
  354.           }
  355.         }
  356.         else
  357.         {
  358.           if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName))
  359.             continue;
  360.           ErrHandler.ReadError(FileName);
  361.         }
  362.     }
  363.     break;
  364.   }
  365.   return(ReadSize);
  366. }
  367.  
  368.  
  369. int File::DirectRead(void *Data,int Size)
  370. {
  371. #ifdef _WIN_32
  372.   const int MaxDeviceRead=20000;
  373. #endif
  374. #ifndef _WIN_CE
  375.   if (HandleType==FILE_HANDLESTD)
  376.   {
  377. #ifdef _WIN_32
  378.     if (Size>MaxDeviceRead)
  379.       Size=MaxDeviceRead;
  380.     hFile=GetStdHandle(STD_INPUT_HANDLE);
  381. #else
  382.     hFile=stdin;
  383. #endif
  384.   }
  385. #endif
  386. #ifdef _WIN_32
  387.   DWORD Read;
  388.   if (!ReadFile(hFile,Data,Size,&Read,NULL))
  389.   {
  390.     if (IsDevice() && Size>MaxDeviceRead)
  391.       return(DirectRead(Data,MaxDeviceRead));
  392.     if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE)
  393.       return(0);
  394.     return(-1);
  395.   }
  396.   return(Read);
  397. #else
  398.   if (LastWrite)
  399.   {
  400.     fflush(hFile);
  401.     LastWrite=false;
  402.   }
  403.   clearerr(hFile);
  404.   int ReadSize=fread(Data,1,Size,hFile);
  405.   if (ferror(hFile))
  406.     return(-1);
  407.   return(ReadSize);
  408. #endif
  409. }
  410.  
  411.  
  412. void File::Seek(Int64 Offset,int Method)
  413. {
  414.   if (!RawSeek(Offset,Method) && AllowExceptions)
  415.     ErrHandler.SeekError(FileName);
  416. }
  417.  
  418.  
  419. bool File::RawSeek(Int64 Offset,int Method)
  420. {
  421.   if (hFile==BAD_HANDLE)
  422.     return(true);
  423.   if (!is64plus(Offset) && Method!=SEEK_SET)
  424.   {
  425.     Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
  426.     Method=SEEK_SET;
  427.   }
  428. #ifdef _WIN_32
  429.   LONG HighDist=int64to32(Offset>>32);
  430.   if (SetFilePointer(hFile,int64to32(Offset),&HighDist,Method)==0xffffffff &&
  431.       GetLastError()!=NO_ERROR)
  432.     return(false);
  433. #else
  434.   LastWrite=false;
  435. #if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
  436.   if (fseeko(hFile,Offset,Method)!=0)
  437. #else
  438.   if (fseek(hFile,(long)int64to32(Offset),Method)!=0)
  439. #endif
  440.     return(false);
  441. #endif
  442.   return(true);
  443. }
  444.  
  445.  
  446. Int64 File::Tell()
  447. {
  448. #ifdef _WIN_32
  449.   LONG HighDist=0;
  450.   uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
  451.   if (LowDist==0xffffffff && GetLastError()!=NO_ERROR)
  452.     if (AllowExceptions)
  453.       ErrHandler.SeekError(FileName);
  454.     else
  455.       return(-1);
  456.   return(int32to64(HighDist,LowDist));
  457. #else
  458. #if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
  459.   return(ftello(hFile));
  460. #else
  461.   return(ftell(hFile));
  462. #endif
  463. #endif
  464. }
  465.  
  466.  
  467. void File::Prealloc(Int64 Size)
  468. {
  469. #ifdef _WIN_32
  470.   if (RawSeek(Size,SEEK_SET))
  471.   {
  472.     Truncate();
  473.     Seek(0,SEEK_SET);
  474.   }
  475. #endif
  476. }
  477.  
  478.  
  479. byte File::GetByte()
  480. {
  481.   byte Byte=0;
  482.   Read(&Byte,1);
  483.   return(Byte);
  484. }
  485.  
  486.  
  487. void File::PutByte(byte Byte)
  488. {
  489.   Write(&Byte,1);
  490. }
  491.  
  492.  
  493. bool File::Truncate()
  494. {
  495. #ifdef _WIN_32
  496.   return(SetEndOfFile(hFile));
  497. #else
  498.   return(false);
  499. #endif
  500. }
  501.  
  502.  
  503. void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
  504. {
  505. #ifdef _WIN_32
  506.   bool sm=ftm!=NULL && ftm->IsSet();
  507.   bool sc=ftc!=NULL && ftc->IsSet();
  508.   bool sa=fta!=NULL && fta->IsSet();
  509.   FILETIME fm,fc,fa;
  510.   if (sm)
  511.     ftm->GetWin32(&fm);
  512.   if (sc)
  513.     ftc->GetWin32(&fc);
  514.   if (sa)
  515.     fta->GetWin32(&fa);
  516.   SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);
  517. #endif
  518. }
  519.  
  520.  
  521. void File::SetCloseFileTime(RarTime *ftm,RarTime *fta)
  522. {
  523. #if defined(_UNIX) || defined(_EMX)
  524.   SetCloseFileTimeByName(FileName,ftm,fta);
  525. #endif
  526. }
  527.  
  528.  
  529. void File::SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta)
  530. {
  531. #if defined(_UNIX) || defined(_EMX)
  532.   bool setm=ftm!=NULL && ftm->IsSet();
  533.   bool seta=fta!=NULL && fta->IsSet();
  534.   if (setm || seta)
  535.   {
  536.     struct utimbuf ut;
  537.     if (setm)
  538.       ut.modtime=ftm->GetUnix();
  539.     else
  540.       ut.modtime=fta->GetUnix();
  541.     if (seta)
  542.       ut.actime=fta->GetUnix();
  543.     else
  544.       ut.actime=ut.modtime;
  545.     utime(Name,&ut);
  546.   }
  547. #endif
  548. }
  549.  
  550.  
  551. void File::GetOpenFileTime(RarTime *ft)
  552. {
  553. #ifdef _WIN_32
  554.   FILETIME FileTime;
  555.   GetFileTime(hFile,NULL,NULL,&FileTime);
  556.   *ft=FileTime;
  557. #endif
  558. #if defined(_UNIX) || defined(_EMX)
  559.   struct stat st;
  560.   fstat(fileno(hFile),&st);
  561.   *ft=st.st_mtime;
  562. #endif
  563. }
  564.  
  565.  
  566. void File::SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta)
  567. {
  568. #ifdef _WIN_32
  569.   SetOpenFileTime(ftm,ftc,fta);
  570. #endif
  571. }
  572.  
  573.  
  574. void File::SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr)
  575. {
  576. #ifdef _WIN_32
  577.   SetFileAttr(FileName,FileNameW,FileAttr);
  578. #endif
  579. #ifdef _EMX
  580.   SetCloseFileTime(ftm,fta);
  581.   SetFileAttr(FileName,FileNameW,FileAttr);
  582. #endif
  583. #ifdef _UNIX
  584.   SetCloseFileTime(ftm,fta);
  585.   chmod(FileName,(mode_t)FileAttr);
  586. #endif
  587. }
  588.  
  589.  
  590. Int64 File::FileLength()
  591. {
  592.   SaveFilePos SavePos(*this);
  593.   Seek(0,SEEK_END);
  594.   return(Tell());
  595. }
  596.  
  597.  
  598. void File::SetHandleType(FILE_HANDLETYPE Type)
  599. {
  600.   HandleType=Type;
  601. }
  602.  
  603.  
  604. bool File::IsDevice()
  605. {
  606.   if (hFile==BAD_HANDLE)
  607.     return(false);
  608. #ifdef _WIN_32
  609.   uint Type=GetFileType(hFile);
  610.   return(Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE);
  611. #else
  612.   return(isatty(fileno(hFile)));
  613. #endif
  614. }
  615.  
  616.  
  617. #ifndef SFX_MODULE
  618. void File::fprintf(const char *fmt,...)
  619. {
  620.   va_list argptr;
  621.   va_start(argptr,fmt);
  622.   safebuf char Msg[2*NM+1024],OutMsg[2*NM+1024];
  623.   vsprintf(Msg,fmt,argptr);
  624. #ifdef _WIN_32
  625.   for (int Src=0,Dest=0;;Src++)
  626.   {
  627.     char CurChar=Msg[Src];
  628.     if (CurChar=='\n')
  629.       OutMsg[Dest++]='\r';
  630.     OutMsg[Dest++]=CurChar;
  631.     if (CurChar==0)
  632.       break;
  633.   }
  634. #else
  635.   strcpy(OutMsg,Msg);
  636. #endif
  637.   Write(OutMsg,strlen(OutMsg));
  638.   va_end(argptr);
  639. }
  640. #endif
  641.  
  642.  
  643. bool File::RemoveCreated()
  644. {
  645.   RemoveCreatedActive++;
  646.   bool RetCode=true;
  647.   for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
  648.     if (CreatedFiles[I]!=NULL)
  649.     {
  650.       CreatedFiles[I]->SetExceptions(false);
  651.       bool Success;
  652.       if (CreatedFiles[I]->NewFile)
  653.         Success=CreatedFiles[I]->Delete();
  654.       else
  655.         Success=CreatedFiles[I]->Close();
  656.       if (Success)
  657.         CreatedFiles[I]=NULL;
  658.       else
  659.         RetCode=false;
  660.     }
  661.   RemoveCreatedActive--;
  662.   return(RetCode);
  663. }
  664.  
  665.  
  666. #ifndef SFX_MODULE
  667. long File::Copy(File &Dest,Int64 Length)
  668. {
  669.   Array<char> Buffer(0x10000);
  670.   long CopySize=0;
  671.   bool CopyAll=(Length==INT64ERR);
  672.  
  673.   while (CopyAll || Length>0)
  674.   {
  675.     Wait();
  676.     int SizeToRead=(!CopyAll && Length<Buffer.Size()) ? int64to32(Length):Buffer.Size();
  677.     int ReadSize=Read(&Buffer[0],SizeToRead);
  678.     if (ReadSize==0)
  679.       break;
  680.     Dest.Write(&Buffer[0],ReadSize);
  681.     CopySize+=ReadSize;
  682.     if (!CopyAll)
  683.       Length-=ReadSize;
  684.   }
  685.   return(CopySize);
  686. }
  687. #endif
  688.