3 // BE WARNED THIS FILE IS HEAVILY MODIFIED TO BE USED WITH XBMC
5 #include "filesystem/Directory.h"
6 #include "filesystem/File.h"
8 #include "utils/URIUtils.h"
10 //static File *CreatedFiles[32];
11 static int RemoveCreatedActive=0;
14 : m_File(*(new XFILE::CFile()))
22 HandleType=FILE_HANDLENORMAL;
24 IgnoreReadErrors=false;
25 ErrorType=FILE_SUCCESS;
35 /*if (hFile!=BAD_HANDLE && !SkipClose)
45 void File::operator = (File &SrcFile)
47 //hFile=SrcFile.hFile;
48 m_File = SrcFile.m_File;
49 strcpy(FileName,SrcFile.FileName);
50 NewFile=SrcFile.NewFile;
51 LastWrite=SrcFile.LastWrite;
52 HandleType=SrcFile.HandleType;
53 SrcFile.SkipClose=true;
57 bool File::Open(const char *Name,const wchar *NameW,bool OpenShared,bool Update)
59 // Below commented code was left behind on spiffs request for possible later usage
61 /*ErrorType=FILE_SUCCESS;
66 uint Access=GENERIC_READ;
68 Access|=GENERIC_WRITE;
69 uint ShareMode=FILE_SHARE_READ;
71 ShareMode|=FILE_SHARE_WRITE;
73 if (WinNT() && NameW!=NULL && *NameW!=0)
74 hNewFile=CreateFileW(NameW,Access,ShareMode,NULL,OPEN_EXISTING,
75 FILE_FLAG_SEQUENTIAL_SCAN,NULL);
78 hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,
79 FILE_FLAG_SEQUENTIAL_SCAN,NULL);
81 if (hNewFile==BAD_HANDLE && GetLastError()==ERROR_FILE_NOT_FOUND)
82 ErrorType=FILE_NOTFOUND;
84 int flags=Update ? O_RDWR:O_RDONLY;
87 #if defined(_AIX) && defined(_LARGE_FILE_API)
91 #if defined(_EMX) && !defined(_DJGPP)
92 int sflags=OpenShared ? SH_DENYNO:SH_DENYWR;
93 int handle=sopen(Name,flags,sflags);
95 int handle=open(Name,flags);
97 if (!OpenShared && Update && handle>=0 && flock(handle,LOCK_EX|LOCK_NB)==-1)
104 hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,Update ? UPDATEBINARY:READBINARY);
105 if (hNewFile==BAD_HANDLE && errno==ENOENT)
106 ErrorType=FILE_NOTFOUND;
109 HandleType=FILE_HANDLENORMAL;
111 bool success=hNewFile!=BAD_HANDLE;*/
114 WideToUtf(NameW, _name, sizeof(_name));
119 success = m_File.OpenForWrite(_name);
121 success = m_File.Open(_name);
126 strcpyw(FileNameW,NameW);
130 strcpy(FileName,Name);
132 WideToChar(NameW,FileName);
133 //AddFileToList(hFile);
140 #if !defined(SHELL_EXT) && !defined(SFX_MODULE)
141 void File::TOpen(const char *Name,const wchar *NameW)
143 if (!WOpen(Name,NameW))
144 ErrHandler.Exit(OPEN_ERROR);
149 bool File::WOpen(const char *Name,const wchar *NameW)
151 if (Open(Name,NameW))
153 ErrHandler.OpenErrorMsg(Name);
158 bool File::Create(const char *Name,const wchar *NameW)
160 // Below commented code was left behind on spiffs request for possible later usage
163 if (WinNT() && NameW!=NULL && *NameW!=0)
164 hFile=CreateFileW(NameW,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
165 CREATE_ALWAYS,0,NULL);
168 hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,
169 CREATE_ALWAYS,0,NULL);
171 hFile=fopen(Name,CREATEBINARY);
175 WideToUtf(NameW, _name, sizeof(_name));
178 CStdString strPath = URIUtils::GetDirectory(_name);
179 CUtil::CreateDirectoryEx(strPath);
180 m_File.OpenForWrite(_name,true);
182 HandleType=FILE_HANDLENORMAL;
185 strcpyw(FileNameW,NameW);
189 strcpy(FileName,Name);
191 WideToChar(NameW,FileName);
192 //AddFileToList(hFile);
194 //return(hFile!=BAD_HANDLE);
199 //void File::AddFileToList(FileHandle hFile)
200 void File::AddFileToList()
202 //if (hFile!=BAD_HANDLE)
203 //for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
204 /*for (int I=0;I<32;I++)
205 if (CreatedFiles[I]==NULL)
207 CreatedFiles[I]=this;
213 #if !defined(SHELL_EXT) && !defined(SFX_MODULE)
214 void File::TCreate(const char *Name,const wchar *NameW)
216 if (!WCreate(Name,NameW))
217 ErrHandler.Exit(FATAL_ERROR);
222 bool File::WCreate(const char *Name,const wchar *NameW)
224 if (Create(Name,NameW))
226 ErrHandler.SetErrorCode(CREATE_ERROR);
227 ErrHandler.CreateErrorMsg(Name);
235 /*if (HandleType!=FILE_HANDLENORMAL)
236 HandleType=FILE_HANDLENORMAL;
238 if (hFile!=BAD_HANDLE)
242 #if defined(_WIN_32) || defined(TARGET_POSIX)
243 //success=CloseHandle(hFile) != FALSE;
246 success=fclose(hFile)!=EOF;
248 /* if (success || !RemoveCreatedActive)
249 //for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
250 for (int I=0;I<32;I++)
251 if (CreatedFiles[I]==this)
253 CreatedFiles[I]=NULL;
258 if (!success && AllowExceptions)
259 ErrHandler.CloseError(FileName);
271 FlushFileBuffers(hFile);
280 /*if (HandleType!=FILE_HANDLENORMAL || !AllowDelete)
282 if (hFile!=BAD_HANDLE)
284 return(DelFile(FileName,FileNameW));*/
285 return m_File.Delete(FileName);
289 bool File::Rename(const char *NewName)
291 bool success=strcmp(FileName,NewName)==0;
293 success=rename(FileName,NewName)==0;
296 strcpy(FileName,NewName);
303 void File::Write(const void *Data,int Size)
305 // Below commented code was left behind on spiffs request for possible later usage
309 #if !defined(_WIN_CE) && !defined(_XBOX)
310 if (HandleType!=FILE_HANDLENORMAL)
315 hFile=GetStdHandle(STD_OUTPUT_HANDLE);
322 hFile=GetStdHandle(STD_ERROR_HANDLE);
332 #if defined(_WIN_32) || defined(TARGET_POSIX)
334 if (HandleType!=FILE_HANDLENORMAL)
336 const int MaxSize=0x4000;
337 for (int I=0;I<Size;I+=MaxSize)
338 //if (!(success=WriteFile(hFile,(byte *)Data+I,Min(Size-I,MaxSize),&Written,NULL) != FALSE))
339 m_File.Write((byte*)Data+I,Min(Size-I,MaxSize));
344 //success=WriteFile(hFile,Data,Size,&Written,NULL) != FALSE;
345 m_File.Write(Data,Size);
348 success=fwrite(Data,1,Size,hFile)==Size && !ferror(hFile);
350 if (!success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
352 #if defined(_WIN_32) && !defined(SFX_MODULE) && !defined(RARDLL)
353 int ErrCode=GetLastError();
354 Int64 FilePos=Tell();
355 Int64 FreeSize=GetFreeDisk(FileName);
356 SetLastError(ErrCode);
357 if (FreeSize>Size && FilePos-Size<=0xffffffff && FilePos+Size>0xffffffff)
358 ErrHandler.WriteErrorFAT(FileName);
360 if (ErrHandler.AskRepeatWrite(FileName))
362 #if !defined(_WIN_32) && !defined(TARGET_POSIX)
365 if (Written<(unsigned int)Size && Written>0)
366 Seek(Tell()-Written,SEEK_SET);
369 ErrHandler.WriteError(NULL,FileName);
377 int File::Read(void *Data,int Size)
380 if (IgnoreReadErrors)
385 ReadSize=DirectRead(Data,Size);
388 ErrorType=FILE_READERROR;
391 if (IgnoreReadErrors)
394 for (int I=0;I<Size;I+=512)
396 Seek(FilePos+I,SEEK_SET);
397 int SizeToRead=Min(Size-I,512);
398 int ReadCode=DirectRead(Data,SizeToRead);
399 ReadSize+=(ReadCode==-1) ? 512:ReadCode;
404 if (HandleType==FILE_HANDLENORMAL && ErrHandler.AskRepeatRead(FileName))
406 ErrHandler.ReadError(FileName);
417 int File::DirectRead(void *Data,int Size)
422 int nRead = m_File.Read(Data,Size);
426 Data = (void*)(((char*)Data)+nRead);
435 const int MaxDeviceRead=20000;
437 // Below commented code was left behind on spiffs request for possible later usage
440 /*#if !defined(_WIN_CE) && !defined(_XBOX)
441 if (HandleType==FILE_HANDLESTD)
444 if (Size>MaxDeviceRead)
446 hFile=GetStdHandle(STD_INPUT_HANDLE);
454 //if (!ReadFile(hFile,Data,Size,&Read,NULL))
455 Read = m_File.Read(Data,Size);
456 if ((Read != Size) && (m_File.GetPosition() != m_File.GetLength()))
458 if (IsDevice() && Size>MaxDeviceRead)
459 return(DirectRead(Data,MaxDeviceRead));
460 if (HandleType==FILE_HANDLESTD && GetLastError()==ERROR_BROKEN_PIPE)
472 int ReadSize=fread(Data,1,Size,hFile);
481 void File::Seek(Int64 Offset,int Method)
483 if (!RawSeek(Offset,Method) && AllowExceptions)
484 ErrHandler.SeekError(FileName);
488 bool File::RawSeek(Int64 Offset,int Method)
490 /*if (hFile==BAD_HANDLE)
492 /*if (!is64plus(Offset) && Method!=SEEK_SET)
494 Offset=(Method==SEEK_CUR ? Tell():FileLength())+Offset;
497 #if defined(_WIN_32) || defined(TARGET_POSIX)
498 //LONG HighDist=int64to32(Offset>>32);
499 //if (SetFilePointer(hFile,int64to32(Offset),&HighDist,Method)==0xffffffff &&
500 if (Offset > FileLength())
503 if (m_File.Seek(Offset,Method) < 0)
509 #ifdef _LARGEFILE_SOURCE
510 if (fseeko(hFile,Offset,Method)!=0)
512 if (fseek(hFile,int64to32(Offset),Method)!=0)
522 #if defined(_WIN_32) || defined(TARGET_POSIX)
524 //uint LowDist=SetFilePointer(hFile,0,&HighDist,FILE_CURRENT);
525 //Int64 pos = m_File.GetPosition();
526 return m_File.GetPosition();
527 /*if (LowDist==0xffffffff && GetLastError()!=NO_ERROR)
529 ErrHandler.SeekError(FileName);
532 return(int32to64(HighDist,LowDist));*/
534 #ifdef _LARGEFILE_SOURCE
535 return(ftello(hFile));
537 return(ftell(hFile));
543 void File::Prealloc(Int64 Size)
546 if (RawSeek(Size,SEEK_SET))
563 void File::PutByte(byte Byte)
569 bool File::Truncate()
572 //return(SetEndOfFile(hFile) != FALSE);
580 void File::SetOpenFileTime(RarTime *ftm,RarTime *ftc,RarTime *fta)
583 // Below commented code was left behind on spiffs request for possible later usage
585 /*bool sm=ftm!=NULL && ftm->IsSet();
586 bool sc=ftc!=NULL && ftc->IsSet();
587 bool sa=fta!=NULL && fta->IsSet();
595 //SetFileTime(hFile,sc ? &fc:NULL,sa ? &fa:NULL,sm ? &fm:NULL);*/
600 void File::SetCloseFileTime(RarTime *ftm,RarTime *fta)
602 #if defined(_UNIX) || defined(_EMX)
603 SetCloseFileTimeByName(FileName,ftm,fta);
608 void File::SetCloseFileTimeByName(const char *Name,RarTime *ftm,RarTime *fta)
610 #if defined(_UNIX) || defined(_EMX)
611 bool setm=ftm!=NULL && ftm->IsSet();
612 bool seta=fta!=NULL && fta->IsSet();
617 ut.modtime=ftm->GetUnix();
619 ut.modtime=fta->GetUnix();
621 ut.actime=fta->GetUnix();
623 ut.actime=ut.modtime;
630 void File::GetOpenFileTime(RarTime *ft)
632 #if defined(_WIN_32) || defined(TARGET_POSIX)
633 /* FILETIME FileTime;
634 GetFileTime(hFile,NULL,NULL,&FileTime);
638 #if defined(_UNIX) || defined(_EMX)
640 fstat(fileno(hFile),&st);
647 void File::SetOpenFileStat(RarTime *ftm,RarTime *ftc,RarTime *fta)
650 //SetOpenFileTime(ftm,ftc,fta);
655 void File::SetCloseFileStat(RarTime *ftm,RarTime *fta,uint FileAttr)
658 //SetFileAttr(FileName,FileNameW,FileAttr);
661 SetCloseFileTime(ftm,fta);
662 SetFileAttr(FileName,FileNameW,FileAttr);
665 SetCloseFileTime(ftm,fta);
666 chmod(FileName,(mode_t)FileAttr);
671 Int64 File::FileLength()
673 return (m_File.GetLength());
677 void File::SetHandleType(FILE_HANDLETYPE Type)
683 bool File::IsDevice()
685 /*if (hFile==BAD_HANDLE)
687 #if defined(_XBOX) || defined(TARGET_POSIX) || defined(_XBMC)
690 #elif defined(_WIN_32)
691 uint Type=GetFileType(hFile);
692 return(Type==FILE_TYPE_CHAR || Type==FILE_TYPE_PIPE);
694 return(isatty(fileno(hFile)));
700 void File::fprintf(const char *fmt,...)
703 va_start(argptr,fmt);
704 safebuf char Msg[2*NM+1024],OutMsg[2*NM+1024];
705 vsprintf(Msg,fmt,argptr);
707 for (int Src=0,Dest=0;;Src++)
709 char CurChar=Msg[Src];
712 OutMsg[Dest++]=CurChar;
719 Write(OutMsg,strlen(OutMsg));
725 bool File::RemoveCreated()
727 RemoveCreatedActive++;
729 //for (int I=0;I<sizeof(CreatedFiles)/sizeof(CreatedFiles[0]);I++)
730 /*for (int I=0;I<32;I++)
731 if (CreatedFiles[I]!=NULL)
733 CreatedFiles[I]->SetExceptions(false);
735 if (CreatedFiles[I]->NewFile)
736 success=CreatedFiles[I]->Delete();
738 success=CreatedFiles[I]->Close();
740 CreatedFiles[I]=NULL;
744 RemoveCreatedActive--;*/
750 long File::Copy(File &Dest,Int64 Length)
752 Array<char> Buffer(0x10000);
754 bool CopyAll=(Length==INT64ERR);
756 while (CopyAll || Length>0)
759 int SizeToRead=(!CopyAll && Length<Buffer.Size()) ? int64to32(Length):Buffer.Size();
760 int ReadSize=Read(&Buffer[0],SizeToRead);
763 Dest.Write(&Buffer[0],ReadSize);