00001
00002
00003
00004 #include "7zFile.h"
00005
00006 #ifndef USE_WINDOWS_FILE
00007
00008 #ifndef UNDER_CE
00009 #include <errno.h>
00010 #endif
00011
00012 #else
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #define kChunkSizeMax (1 << 22)
00025
00026 #endif
00027
00028 void File_Construct(CSzFile *p)
00029 {
00030 #ifdef USE_WINDOWS_FILE
00031 p->handle = INVALID_HANDLE_VALUE;
00032 #else
00033 p->file = NULL;
00034 #endif
00035 }
00036
00037 #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
00038 static WRes File_Open(CSzFile *p, const char *name, int writeMode)
00039 {
00040 #ifdef USE_WINDOWS_FILE
00041 p->handle = CreateFileA(name,
00042 writeMode ? GENERIC_WRITE : GENERIC_READ,
00043 FILE_SHARE_READ, NULL,
00044 writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
00045 FILE_ATTRIBUTE_NORMAL, NULL);
00046 return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
00047 #else
00048 p->file = fopen(name, writeMode ? "wb+" : "rb");
00049 return (p->file != 0) ? 0 :
00050 #ifdef UNDER_CE
00051 2;
00052 #else
00053 errno;
00054 #endif
00055 #endif
00056 }
00057
00058 WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
00059 WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
00060 #endif
00061
00062 #ifdef USE_WINDOWS_FILE
00063 static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
00064 {
00065 p->handle = CreateFileW(name,
00066 writeMode ? GENERIC_WRITE : GENERIC_READ,
00067 FILE_SHARE_READ, NULL,
00068 writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
00069 FILE_ATTRIBUTE_NORMAL, NULL);
00070 return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
00071 }
00072 WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
00073 WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
00074 #endif
00075
00076 WRes File_Close(CSzFile *p)
00077 {
00078 #ifdef USE_WINDOWS_FILE
00079 if (p->handle != INVALID_HANDLE_VALUE)
00080 {
00081 if (!CloseHandle(p->handle))
00082 return GetLastError();
00083 p->handle = INVALID_HANDLE_VALUE;
00084 }
00085 #else
00086 if (p->file != NULL)
00087 {
00088 int res = fclose(p->file);
00089 if (res != 0)
00090 return res;
00091 p->file = NULL;
00092 }
00093 #endif
00094 return 0;
00095 }
00096
00097 WRes File_Read(CSzFile *p, void *data, size_t *size)
00098 {
00099 size_t originalSize = *size;
00100 if (originalSize == 0)
00101 return 0;
00102
00103 #ifdef USE_WINDOWS_FILE
00104
00105 *size = 0;
00106 do
00107 {
00108 DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
00109 DWORD processed = 0;
00110 BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
00111 data = (void *)((Byte *)data + processed);
00112 originalSize -= processed;
00113 *size += processed;
00114 if (!res)
00115 return GetLastError();
00116 if (processed == 0)
00117 break;
00118 }
00119 while (originalSize > 0);
00120 return 0;
00121
00122 #else
00123
00124 *size = fread(data, 1, originalSize, p->file);
00125 if (*size == originalSize)
00126 return 0;
00127 return ferror(p->file);
00128
00129 #endif
00130 }
00131
00132 WRes File_Write(CSzFile *p, const void *data, size_t *size)
00133 {
00134 size_t originalSize = *size;
00135 if (originalSize == 0)
00136 return 0;
00137
00138 #ifdef USE_WINDOWS_FILE
00139
00140 *size = 0;
00141 do
00142 {
00143 DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
00144 DWORD processed = 0;
00145 BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
00146 data = (void *)((Byte *)data + processed);
00147 originalSize -= processed;
00148 *size += processed;
00149 if (!res)
00150 return GetLastError();
00151 if (processed == 0)
00152 break;
00153 }
00154 while (originalSize > 0);
00155 return 0;
00156
00157 #else
00158
00159 *size = fwrite(data, 1, originalSize, p->file);
00160 if (*size == originalSize)
00161 return 0;
00162 return ferror(p->file);
00163
00164 #endif
00165 }
00166
00167 WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
00168 {
00169 #ifdef USE_WINDOWS_FILE
00170
00171 LARGE_INTEGER value;
00172 DWORD moveMethod;
00173 value.LowPart = (DWORD)*pos;
00174 value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16);
00175 switch (origin)
00176 {
00177 case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
00178 case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
00179 case SZ_SEEK_END: moveMethod = FILE_END; break;
00180 default: return ERROR_INVALID_PARAMETER;
00181 }
00182 value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
00183 if (value.LowPart == 0xFFFFFFFF)
00184 {
00185 WRes res = GetLastError();
00186 if (res != NO_ERROR)
00187 return res;
00188 }
00189 *pos = ((Int64)value.HighPart << 32) | value.LowPart;
00190 return 0;
00191
00192 #else
00193
00194 int moveMethod;
00195 int res;
00196 switch (origin)
00197 {
00198 case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
00199 case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
00200 case SZ_SEEK_END: moveMethod = SEEK_END; break;
00201 default: return 1;
00202 }
00203 res = fseek(p->file, (long)*pos, moveMethod);
00204 *pos = ftell(p->file);
00205 return res;
00206
00207 #endif
00208 }
00209
00210 WRes File_GetLength(CSzFile *p, UInt64 *length)
00211 {
00212 #ifdef USE_WINDOWS_FILE
00213
00214 DWORD sizeHigh;
00215 DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
00216 if (sizeLow == 0xFFFFFFFF)
00217 {
00218 DWORD res = GetLastError();
00219 if (res != NO_ERROR)
00220 return res;
00221 }
00222 *length = (((UInt64)sizeHigh) << 32) + sizeLow;
00223 return 0;
00224
00225 #else
00226
00227 long pos = ftell(p->file);
00228 int res = fseek(p->file, 0, SEEK_END);
00229 *length = ftell(p->file);
00230 fseek(p->file, pos, SEEK_SET);
00231 return res;
00232
00233 #endif
00234 }
00235
00236
00237
00238
00239 static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
00240 {
00241 CFileSeqInStream *p = (CFileSeqInStream *)pp;
00242 return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
00243 }
00244
00245 void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
00246 {
00247 p->s.Read = FileSeqInStream_Read;
00248 }
00249
00250
00251
00252
00253 static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
00254 {
00255 CFileInStream *p = (CFileInStream *)pp;
00256 return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
00257 }
00258
00259 static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)
00260 {
00261 CFileInStream *p = (CFileInStream *)pp;
00262 return File_Seek(&p->file, pos, origin);
00263 }
00264
00265 void FileInStream_CreateVTable(CFileInStream *p)
00266 {
00267 p->s.Read = FileInStream_Read;
00268 p->s.Seek = FileInStream_Seek;
00269 }
00270
00271
00272
00273
00274 static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
00275 {
00276 CFileOutStream *p = (CFileOutStream *)pp;
00277 File_Write(&p->file, data, &size);
00278 return size;
00279 }
00280
00281 void FileOutStream_CreateVTable(CFileOutStream *p)
00282 {
00283 p->s.Write = FileOutStream_Write;
00284 }