add CHD support.
[pcsx_rearmed.git] / deps / lzma-16.04 / C / 7zFile.c
1 /* 7zFile.c -- File IO\r
2 2009-11-24 : Igor Pavlov : Public domain */\r
3 \r
4 #include "Precomp.h"\r
5 \r
6 #include "7zFile.h"\r
7 \r
8 #ifndef USE_WINDOWS_FILE\r
9 \r
10 #ifndef UNDER_CE\r
11 #include <errno.h>\r
12 #endif\r
13 \r
14 #else\r
15 \r
16 /*\r
17    ReadFile and WriteFile functions in Windows have BUG:\r
18    If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)\r
19    from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES\r
20    (Insufficient system resources exist to complete the requested service).\r
21    Probably in some version of Windows there are problems with other sizes:\r
22    for 32 MB (maybe also for 16 MB).\r
23    And message can be "Network connection was lost"\r
24 */\r
25 \r
26 #define kChunkSizeMax (1 << 22)\r
27 \r
28 #endif\r
29 \r
30 void File_Construct(CSzFile *p)\r
31 {\r
32   #ifdef USE_WINDOWS_FILE\r
33   p->handle = INVALID_HANDLE_VALUE;\r
34   #else\r
35   p->file = NULL;\r
36   #endif\r
37 }\r
38 \r
39 #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)\r
40 static WRes File_Open(CSzFile *p, const char *name, int writeMode)\r
41 {\r
42   #ifdef USE_WINDOWS_FILE\r
43   p->handle = CreateFileA(name,\r
44       writeMode ? GENERIC_WRITE : GENERIC_READ,\r
45       FILE_SHARE_READ, NULL,\r
46       writeMode ? CREATE_ALWAYS : OPEN_EXISTING,\r
47       FILE_ATTRIBUTE_NORMAL, NULL);\r
48   return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();\r
49   #else\r
50   p->file = fopen(name, writeMode ? "wb+" : "rb");\r
51   return (p->file != 0) ? 0 :\r
52     #ifdef UNDER_CE\r
53     2; /* ENOENT */\r
54     #else\r
55     errno;\r
56     #endif\r
57   #endif\r
58 }\r
59 \r
60 WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }\r
61 WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }\r
62 #endif\r
63 \r
64 #ifdef USE_WINDOWS_FILE\r
65 static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)\r
66 {\r
67   p->handle = CreateFileW(name,\r
68       writeMode ? GENERIC_WRITE : GENERIC_READ,\r
69       FILE_SHARE_READ, NULL,\r
70       writeMode ? CREATE_ALWAYS : OPEN_EXISTING,\r
71       FILE_ATTRIBUTE_NORMAL, NULL);\r
72   return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();\r
73 }\r
74 WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }\r
75 WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }\r
76 #endif\r
77 \r
78 WRes File_Close(CSzFile *p)\r
79 {\r
80   #ifdef USE_WINDOWS_FILE\r
81   if (p->handle != INVALID_HANDLE_VALUE)\r
82   {\r
83     if (!CloseHandle(p->handle))\r
84       return GetLastError();\r
85     p->handle = INVALID_HANDLE_VALUE;\r
86   }\r
87   #else\r
88   if (p->file != NULL)\r
89   {\r
90     int res = fclose(p->file);\r
91     if (res != 0)\r
92       return res;\r
93     p->file = NULL;\r
94   }\r
95   #endif\r
96   return 0;\r
97 }\r
98 \r
99 WRes File_Read(CSzFile *p, void *data, size_t *size)\r
100 {\r
101   size_t originalSize = *size;\r
102   if (originalSize == 0)\r
103     return 0;\r
104 \r
105   #ifdef USE_WINDOWS_FILE\r
106 \r
107   *size = 0;\r
108   do\r
109   {\r
110     DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;\r
111     DWORD processed = 0;\r
112     BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);\r
113     data = (void *)((Byte *)data + processed);\r
114     originalSize -= processed;\r
115     *size += processed;\r
116     if (!res)\r
117       return GetLastError();\r
118     if (processed == 0)\r
119       break;\r
120   }\r
121   while (originalSize > 0);\r
122   return 0;\r
123 \r
124   #else\r
125   \r
126   *size = fread(data, 1, originalSize, p->file);\r
127   if (*size == originalSize)\r
128     return 0;\r
129   return ferror(p->file);\r
130   \r
131   #endif\r
132 }\r
133 \r
134 WRes File_Write(CSzFile *p, const void *data, size_t *size)\r
135 {\r
136   size_t originalSize = *size;\r
137   if (originalSize == 0)\r
138     return 0;\r
139   \r
140   #ifdef USE_WINDOWS_FILE\r
141 \r
142   *size = 0;\r
143   do\r
144   {\r
145     DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;\r
146     DWORD processed = 0;\r
147     BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);\r
148     data = (void *)((Byte *)data + processed);\r
149     originalSize -= processed;\r
150     *size += processed;\r
151     if (!res)\r
152       return GetLastError();\r
153     if (processed == 0)\r
154       break;\r
155   }\r
156   while (originalSize > 0);\r
157   return 0;\r
158 \r
159   #else\r
160 \r
161   *size = fwrite(data, 1, originalSize, p->file);\r
162   if (*size == originalSize)\r
163     return 0;\r
164   return ferror(p->file);\r
165   \r
166   #endif\r
167 }\r
168 \r
169 WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)\r
170 {\r
171   #ifdef USE_WINDOWS_FILE\r
172 \r
173   LARGE_INTEGER value;\r
174   DWORD moveMethod;\r
175   value.LowPart = (DWORD)*pos;\r
176   value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */\r
177   switch (origin)\r
178   {\r
179     case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;\r
180     case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;\r
181     case SZ_SEEK_END: moveMethod = FILE_END; break;\r
182     default: return ERROR_INVALID_PARAMETER;\r
183   }\r
184   value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);\r
185   if (value.LowPart == 0xFFFFFFFF)\r
186   {\r
187     WRes res = GetLastError();\r
188     if (res != NO_ERROR)\r
189       return res;\r
190   }\r
191   *pos = ((Int64)value.HighPart << 32) | value.LowPart;\r
192   return 0;\r
193 \r
194   #else\r
195   \r
196   int moveMethod;\r
197   int res;\r
198   switch (origin)\r
199   {\r
200     case SZ_SEEK_SET: moveMethod = SEEK_SET; break;\r
201     case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;\r
202     case SZ_SEEK_END: moveMethod = SEEK_END; break;\r
203     default: return 1;\r
204   }\r
205   res = fseek(p->file, (long)*pos, moveMethod);\r
206   *pos = ftell(p->file);\r
207   return res;\r
208   \r
209   #endif\r
210 }\r
211 \r
212 WRes File_GetLength(CSzFile *p, UInt64 *length)\r
213 {\r
214   #ifdef USE_WINDOWS_FILE\r
215   \r
216   DWORD sizeHigh;\r
217   DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);\r
218   if (sizeLow == 0xFFFFFFFF)\r
219   {\r
220     DWORD res = GetLastError();\r
221     if (res != NO_ERROR)\r
222       return res;\r
223   }\r
224   *length = (((UInt64)sizeHigh) << 32) + sizeLow;\r
225   return 0;\r
226   \r
227   #else\r
228   \r
229   long pos = ftell(p->file);\r
230   int res = fseek(p->file, 0, SEEK_END);\r
231   *length = ftell(p->file);\r
232   fseek(p->file, pos, SEEK_SET);\r
233   return res;\r
234   \r
235   #endif\r
236 }\r
237 \r
238 \r
239 /* ---------- FileSeqInStream ---------- */\r
240 \r
241 static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)\r
242 {\r
243   CFileSeqInStream *p = (CFileSeqInStream *)pp;\r
244   return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;\r
245 }\r
246 \r
247 void FileSeqInStream_CreateVTable(CFileSeqInStream *p)\r
248 {\r
249   p->s.Read = FileSeqInStream_Read;\r
250 }\r
251 \r
252 \r
253 /* ---------- FileInStream ---------- */\r
254 \r
255 static SRes FileInStream_Read(void *pp, void *buf, size_t *size)\r
256 {\r
257   CFileInStream *p = (CFileInStream *)pp;\r
258   return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;\r
259 }\r
260 \r
261 static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin)\r
262 {\r
263   CFileInStream *p = (CFileInStream *)pp;\r
264   return File_Seek(&p->file, pos, origin);\r
265 }\r
266 \r
267 void FileInStream_CreateVTable(CFileInStream *p)\r
268 {\r
269   p->s.Read = FileInStream_Read;\r
270   p->s.Seek = FileInStream_Seek;\r
271 }\r
272 \r
273 \r
274 /* ---------- FileOutStream ---------- */\r
275 \r
276 static size_t FileOutStream_Write(void *pp, const void *data, size_t size)\r
277 {\r
278   CFileOutStream *p = (CFileOutStream *)pp;\r
279   File_Write(&p->file, data, &size);\r
280   return size;\r
281 }\r
282 \r
283 void FileOutStream_CreateVTable(CFileOutStream *p)\r
284 {\r
285   p->s.Write = FileOutStream_Write;\r
286 }\r