51
52
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ;
53
54
Access|=GENERIC_WRITE;
54
uint ShareMode=FILE_SHARE_READ;
55
uint ShareMode=(Mode & FMF_OPENEXCLUSIVE) ? 0 : FILE_SHARE_READ;
56
57
ShareMode|=FILE_SHARE_WRITE;
57
58
uint Flags=NoSequentialRead ? 0:FILE_FLAG_SEQUENTIAL_SCAN;
58
59
hNewFile=CreateFile(Name,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
61
if (hNewFile==BAD_HANDLE)
62
if (hNewFile==FILE_BAD_HANDLE)
63
// Following CreateFile("\\?\path") call can change the last error code
64
// from "not found" to "access denied" for relative paths like "..\path".
65
// But we need the correct "not found" code to create a new archive
66
// if existing one is not found. So we preserve the code here.
67
64
LastError=GetLastError();
69
66
wchar LongName[NM];
70
67
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
71
69
hNewFile=CreateFile(LongName,Access,ShareMode,NULL,OPEN_EXISTING,Flags,NULL);
71
// For archive names longer than 260 characters first CreateFile
72
// (without \\?\) fails and sets LastError to 3 (access denied).
73
// We need the correct "file not found" error code to decide
74
// if we create a new archive or quit with "cannot create" error.
75
// So we need to check the error code after \\?\ CreateFile again,
76
// otherwise we'll fail to create new archives with long names.
77
// But we cannot simply assign the new code to LastError,
78
// because it would break "..\arcname.rar" relative names processing.
79
// First CreateFile returns the correct "file not found" code for such
80
// names, but "\\?\" CreateFile returns ERROR_INVALID_NAME treating
81
// dots as a directory name. So we check only for "file not found"
82
// error here and for other errors use the first CreateFile result.
83
if (GetLastError()==ERROR_FILE_NOT_FOUND)
84
LastError=ERROR_FILE_NOT_FOUND;
74
if (hNewFile==BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
88
if (hNewFile==FILE_BAD_HANDLE && LastError==ERROR_FILE_NOT_FOUND)
75
89
ErrorType=FILE_NOTFOUND;
77
91
int flags=UpdateMode ? O_RDWR:(WriteMode ? O_WRONLY:O_RDONLY);
100
hNewFile=handle==-1 ? BAD_HANDLE:fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
101
if (hNewFile==BAD_HANDLE && errno==ENOENT)
115
hNewFile=FILE_BAD_HANDLE;
121
hNewFile=fdopen(handle,UpdateMode ? UPDATEBINARY:READBINARY);
124
if (hNewFile==FILE_BAD_HANDLE && errno==ENOENT)
102
125
ErrorType=FILE_NOTFOUND;
105
128
HandleType=FILE_HANDLENORMAL;
107
bool Success=hNewFile!=BAD_HANDLE;
130
bool Success=hNewFile!=FILE_BAD_HANDLE;
145
168
uint Access=WriteMode ? GENERIC_WRITE:GENERIC_READ|GENERIC_WRITE;
146
169
DWORD ShareMode=ShareRead ? FILE_SHARE_READ:0;
147
hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
149
if (hFile==BAD_HANDLE)
171
// Windows automatically removes dots and spaces in the end of file name,
172
// So we detect such names and process them with \\?\ prefix.
173
wchar *LastChar=PointToLastChar(Name);
174
bool Special=*LastChar=='.' || *LastChar==' ';
177
hFile=FILE_BAD_HANDLE;
179
hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL);
181
if (hFile==FILE_BAD_HANDLE)
151
183
wchar LongName[NM];
152
184
if (GetWinLongPath(Name,LongName,ASIZE(LongName)))
158
190
WideToChar(Name,NameA,ASIZE(NameA));
192
hFile=open(NameA,(O_CREAT|O_TRUNC) | (WriteMode ? O_WRONLY : O_RDWR));
194
if (hFile==FILE_BAD_HANDLE)
195
hFile=JniCreateFile(Name); // If external card is read-only for usual file API.
159
198
hFile=fopen(NameA,WriteMode ? WRITEBINARY:CREATEBINARY);
162
202
HandleType=FILE_HANDLENORMAL;
164
204
wcsncpyz(FileName,Name,ASIZE(FileName));
165
return hFile!=BAD_HANDLE;
205
return hFile!=FILE_BAD_HANDLE;
188
227
bool File::Close()
190
229
bool Success=true;
191
if (HandleType!=FILE_HANDLENORMAL)
192
HandleType=FILE_HANDLENORMAL;
194
if (hFile!=BAD_HANDLE)
231
if (hFile!=FILE_BAD_HANDLE)
236
// We use the standard system handle for stdout in Windows
237
// and it must not be closed here.
238
if (HandleType==FILE_HANDLENORMAL)
199
239
Success=CloseHandle(hFile)==TRUE;
201
Success=fclose(hFile)!=EOF;
205
if (!Success && AllowExceptions)
206
ErrHandler.CloseError(FileName);
242
Success=close(hFile)!=-1;
244
Success=fclose(hFile)!=EOF;
248
hFile=FILE_BAD_HANDLE;
250
HandleType=FILE_HANDLENORMAL;
251
if (!Success && AllowExceptions)
252
ErrHandler.CloseError(FileName);
215
FlushFileBuffers(hFile);
222
257
bool File::Delete()
224
259
if (HandleType!=FILE_HANDLENORMAL)
226
if (hFile!=BAD_HANDLE)
261
if (hFile!=FILE_BAD_HANDLE)
228
263
if (!AllowDelete)
249
void File::Write(const void *Data,size_t Size)
284
bool File::Write(const void *Data,size_t Size)
253
if (HandleType!=FILE_HANDLENORMAL)
288
if (HandleType==FILE_HANDLESTD)
291
hFile=GetStdHandle(STD_OUTPUT_HANDLE);
293
// Cannot use the standard stdout here, because it already has wide orientation.
294
if (hFile==FILE_BAD_HANDLE)
258
hFile=GetStdHandle(STD_OUTPUT_HANDLE);
265
hFile=GetStdHandle(STD_ERROR_HANDLE);
297
hFile=dup(STDOUT_FILENO); // Open new stdout stream.
299
hFile=fdopen(dup(STDOUT_FILENO),"w"); // Open new stdout stream.
276
310
if (HandleType!=FILE_HANDLENORMAL)
288
322
Success=WriteFile(hFile,Data,(DWORD)Size,&Written,NULL)==TRUE;
325
ssize_t Written=write(hFile,Data,Size);
326
Success=Written==Size;
290
328
int Written=fwrite(Data,1,Size,hFile);
291
329
Success=Written==Size && !ferror(hFile);
293
332
if (!Success && AllowExceptions && HandleType==FILE_HANDLENORMAL)
295
334
#if defined(_WIN_ALL) && !defined(SFX_MODULE) && !defined(RARDLL)
365
405
if (HandleType==FILE_HANDLESTD)
368
if (Size>MaxDeviceRead)
408
// if (Size>MaxDeviceRead)
409
// Size=MaxDeviceRead;
370
410
hFile=GetStdHandle(STD_INPUT_HANDLE);
420
// For pipes like 'type file.txt | rar -si arcname' ReadFile may return
421
// data in small ~4KB blocks. It may slightly reduce the compression ratio.
377
423
if (!ReadFile(hFile,Data,(DWORD)Size,&Read,NULL))
435
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
489
if (lseek64(hFile,Offset,Method)==-1)
491
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE) && !defined(__VMS)
436
492
if (fseeko(hFile,Offset,Method)!=0)
438
495
if (fseek(hFile,(long)Offset,Method)!=0)
446
503
int64 File::Tell()
448
if (hFile==BAD_HANDLE)
505
if (hFile==FILE_BAD_HANDLE)
449
506
if (AllowExceptions)
450
507
ErrHandler.SeekError(FileName);
461
518
return INT32TO64(HighDist,LowDist);
463
#if defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
521
return lseek64(hFile,0,SEEK_CUR);
522
#elif defined(_LARGEFILE_SOURCE) && !defined(_OSF_SOURCE)
464
523
return ftello(hFile);
466
525
return ftell(hFile);
482
541
#if defined(_UNIX) && defined(USE_FALLOCATE)
483
542
// fallocate is rather new call. Only latest kernels support it.
484
543
// So we are not using it by default yet.
485
int fd = fileno(hFile);
544
int fd = GetFD(hFile);
487
546
fallocate(fd, 0, 0, Size);
618
677
size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size();
619
int ReadSize=Read(&Buffer[0],SizeToRead);
678
char *Buf=&Buffer[0];
679
int ReadSize=Read(Buf,SizeToRead);
622
Dest.Write(&Buffer[0],ReadSize);
682
size_t WriteSize=ReadSize;
684
// For FAT32 USB flash drives in Windows if first write is 4 KB or more,
685
// write caching is disabled and "write through" is enabled, resulting
686
// in bad performance, especially for many small files. It happens when
687
// we create SFX archive on USB drive, because SFX module is written first.
688
// So we split the first write to small 1 KB followed by rest of data.
689
if (CopySize==0 && WriteSize>=4096)
691
const size_t FirstWrite=1024;
692
Dest.Write(Buf,FirstWrite);
694
WriteSize-=FirstWrite;
697
Dest.Write(Buf,WriteSize);
623
698
CopySize+=ReadSize;
625
700
Length-=ReadSize;