xref: /aosp_15_r20/external/lzma/C/7zFile.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker /* 7zFile.c -- File IO
2*f6dc9357SAndroid Build Coastguard Worker 2023-04-02 : Igor Pavlov : Public domain */
3*f6dc9357SAndroid Build Coastguard Worker 
4*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker #include "7zFile.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #ifndef USE_WINDOWS_FILE
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker   #include <errno.h>
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker   #ifndef USE_FOPEN
13*f6dc9357SAndroid Build Coastguard Worker     #include <stdio.h>
14*f6dc9357SAndroid Build Coastguard Worker     #include <fcntl.h>
15*f6dc9357SAndroid Build Coastguard Worker     #ifdef _WIN32
16*f6dc9357SAndroid Build Coastguard Worker       #include <io.h>
17*f6dc9357SAndroid Build Coastguard Worker       typedef int ssize_t;
18*f6dc9357SAndroid Build Coastguard Worker       typedef int off_t;
19*f6dc9357SAndroid Build Coastguard Worker     #else
20*f6dc9357SAndroid Build Coastguard Worker       #include <unistd.h>
21*f6dc9357SAndroid Build Coastguard Worker     #endif
22*f6dc9357SAndroid Build Coastguard Worker   #endif
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker #else
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker /*
27*f6dc9357SAndroid Build Coastguard Worker    ReadFile and WriteFile functions in Windows have BUG:
28*f6dc9357SAndroid Build Coastguard Worker    If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
29*f6dc9357SAndroid Build Coastguard Worker    from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
30*f6dc9357SAndroid Build Coastguard Worker    (Insufficient system resources exist to complete the requested service).
31*f6dc9357SAndroid Build Coastguard Worker    Probably in some version of Windows there are problems with other sizes:
32*f6dc9357SAndroid Build Coastguard Worker    for 32 MB (maybe also for 16 MB).
33*f6dc9357SAndroid Build Coastguard Worker    And message can be "Network connection was lost"
34*f6dc9357SAndroid Build Coastguard Worker */
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker #endif
37*f6dc9357SAndroid Build Coastguard Worker 
38*f6dc9357SAndroid Build Coastguard Worker #define kChunkSizeMax (1 << 22)
39*f6dc9357SAndroid Build Coastguard Worker 
File_Construct(CSzFile * p)40*f6dc9357SAndroid Build Coastguard Worker void File_Construct(CSzFile *p)
41*f6dc9357SAndroid Build Coastguard Worker {
42*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_WINDOWS_FILE
43*f6dc9357SAndroid Build Coastguard Worker   p->handle = INVALID_HANDLE_VALUE;
44*f6dc9357SAndroid Build Coastguard Worker   #elif defined(USE_FOPEN)
45*f6dc9357SAndroid Build Coastguard Worker   p->file = NULL;
46*f6dc9357SAndroid Build Coastguard Worker   #else
47*f6dc9357SAndroid Build Coastguard Worker   p->fd = -1;
48*f6dc9357SAndroid Build Coastguard Worker   #endif
49*f6dc9357SAndroid Build Coastguard Worker }
50*f6dc9357SAndroid Build Coastguard Worker 
51*f6dc9357SAndroid Build Coastguard Worker #if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
52*f6dc9357SAndroid Build Coastguard Worker 
File_Open(CSzFile * p,const char * name,int writeMode)53*f6dc9357SAndroid Build Coastguard Worker static WRes File_Open(CSzFile *p, const char *name, int writeMode)
54*f6dc9357SAndroid Build Coastguard Worker {
55*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_WINDOWS_FILE
56*f6dc9357SAndroid Build Coastguard Worker 
57*f6dc9357SAndroid Build Coastguard Worker   p->handle = CreateFileA(name,
58*f6dc9357SAndroid Build Coastguard Worker       writeMode ? GENERIC_WRITE : GENERIC_READ,
59*f6dc9357SAndroid Build Coastguard Worker       FILE_SHARE_READ, NULL,
60*f6dc9357SAndroid Build Coastguard Worker       writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
61*f6dc9357SAndroid Build Coastguard Worker       FILE_ATTRIBUTE_NORMAL, NULL);
62*f6dc9357SAndroid Build Coastguard Worker   return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
63*f6dc9357SAndroid Build Coastguard Worker 
64*f6dc9357SAndroid Build Coastguard Worker   #elif defined(USE_FOPEN)
65*f6dc9357SAndroid Build Coastguard Worker 
66*f6dc9357SAndroid Build Coastguard Worker   p->file = fopen(name, writeMode ? "wb+" : "rb");
67*f6dc9357SAndroid Build Coastguard Worker   return (p->file != 0) ? 0 :
68*f6dc9357SAndroid Build Coastguard Worker     #ifdef UNDER_CE
69*f6dc9357SAndroid Build Coastguard Worker     2; /* ENOENT */
70*f6dc9357SAndroid Build Coastguard Worker     #else
71*f6dc9357SAndroid Build Coastguard Worker     errno;
72*f6dc9357SAndroid Build Coastguard Worker     #endif
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker   #else
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker   int flags = (writeMode ? (O_CREAT | O_EXCL | O_WRONLY) : O_RDONLY);
77*f6dc9357SAndroid Build Coastguard Worker   #ifdef O_BINARY
78*f6dc9357SAndroid Build Coastguard Worker   flags |= O_BINARY;
79*f6dc9357SAndroid Build Coastguard Worker   #endif
80*f6dc9357SAndroid Build Coastguard Worker   p->fd = open(name, flags, 0666);
81*f6dc9357SAndroid Build Coastguard Worker   return (p->fd != -1) ? 0 : errno;
82*f6dc9357SAndroid Build Coastguard Worker 
83*f6dc9357SAndroid Build Coastguard Worker   #endif
84*f6dc9357SAndroid Build Coastguard Worker }
85*f6dc9357SAndroid Build Coastguard Worker 
InFile_Open(CSzFile * p,const char * name)86*f6dc9357SAndroid Build Coastguard Worker WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
87*f6dc9357SAndroid Build Coastguard Worker 
OutFile_Open(CSzFile * p,const char * name)88*f6dc9357SAndroid Build Coastguard Worker WRes OutFile_Open(CSzFile *p, const char *name)
89*f6dc9357SAndroid Build Coastguard Worker {
90*f6dc9357SAndroid Build Coastguard Worker   #if defined(USE_WINDOWS_FILE) || defined(USE_FOPEN)
91*f6dc9357SAndroid Build Coastguard Worker   return File_Open(p, name, 1);
92*f6dc9357SAndroid Build Coastguard Worker   #else
93*f6dc9357SAndroid Build Coastguard Worker   p->fd = creat(name, 0666);
94*f6dc9357SAndroid Build Coastguard Worker   return (p->fd != -1) ? 0 : errno;
95*f6dc9357SAndroid Build Coastguard Worker   #endif
96*f6dc9357SAndroid Build Coastguard Worker }
97*f6dc9357SAndroid Build Coastguard Worker 
98*f6dc9357SAndroid Build Coastguard Worker #endif
99*f6dc9357SAndroid Build Coastguard Worker 
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker #ifdef USE_WINDOWS_FILE
File_OpenW(CSzFile * p,const WCHAR * name,int writeMode)102*f6dc9357SAndroid Build Coastguard Worker static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
103*f6dc9357SAndroid Build Coastguard Worker {
104*f6dc9357SAndroid Build Coastguard Worker   p->handle = CreateFileW(name,
105*f6dc9357SAndroid Build Coastguard Worker       writeMode ? GENERIC_WRITE : GENERIC_READ,
106*f6dc9357SAndroid Build Coastguard Worker       FILE_SHARE_READ, NULL,
107*f6dc9357SAndroid Build Coastguard Worker       writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
108*f6dc9357SAndroid Build Coastguard Worker       FILE_ATTRIBUTE_NORMAL, NULL);
109*f6dc9357SAndroid Build Coastguard Worker   return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
110*f6dc9357SAndroid Build Coastguard Worker }
InFile_OpenW(CSzFile * p,const WCHAR * name)111*f6dc9357SAndroid Build Coastguard Worker WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
OutFile_OpenW(CSzFile * p,const WCHAR * name)112*f6dc9357SAndroid Build Coastguard Worker WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
113*f6dc9357SAndroid Build Coastguard Worker #endif
114*f6dc9357SAndroid Build Coastguard Worker 
File_Close(CSzFile * p)115*f6dc9357SAndroid Build Coastguard Worker WRes File_Close(CSzFile *p)
116*f6dc9357SAndroid Build Coastguard Worker {
117*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_WINDOWS_FILE
118*f6dc9357SAndroid Build Coastguard Worker 
119*f6dc9357SAndroid Build Coastguard Worker   if (p->handle != INVALID_HANDLE_VALUE)
120*f6dc9357SAndroid Build Coastguard Worker   {
121*f6dc9357SAndroid Build Coastguard Worker     if (!CloseHandle(p->handle))
122*f6dc9357SAndroid Build Coastguard Worker       return GetLastError();
123*f6dc9357SAndroid Build Coastguard Worker     p->handle = INVALID_HANDLE_VALUE;
124*f6dc9357SAndroid Build Coastguard Worker   }
125*f6dc9357SAndroid Build Coastguard Worker 
126*f6dc9357SAndroid Build Coastguard Worker   #elif defined(USE_FOPEN)
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker   if (p->file != NULL)
129*f6dc9357SAndroid Build Coastguard Worker   {
130*f6dc9357SAndroid Build Coastguard Worker     int res = fclose(p->file);
131*f6dc9357SAndroid Build Coastguard Worker     if (res != 0)
132*f6dc9357SAndroid Build Coastguard Worker     {
133*f6dc9357SAndroid Build Coastguard Worker       if (res == EOF)
134*f6dc9357SAndroid Build Coastguard Worker         return errno;
135*f6dc9357SAndroid Build Coastguard Worker       return res;
136*f6dc9357SAndroid Build Coastguard Worker     }
137*f6dc9357SAndroid Build Coastguard Worker     p->file = NULL;
138*f6dc9357SAndroid Build Coastguard Worker   }
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker   #else
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker   if (p->fd != -1)
143*f6dc9357SAndroid Build Coastguard Worker   {
144*f6dc9357SAndroid Build Coastguard Worker     if (close(p->fd) != 0)
145*f6dc9357SAndroid Build Coastguard Worker       return errno;
146*f6dc9357SAndroid Build Coastguard Worker     p->fd = -1;
147*f6dc9357SAndroid Build Coastguard Worker   }
148*f6dc9357SAndroid Build Coastguard Worker 
149*f6dc9357SAndroid Build Coastguard Worker   #endif
150*f6dc9357SAndroid Build Coastguard Worker 
151*f6dc9357SAndroid Build Coastguard Worker   return 0;
152*f6dc9357SAndroid Build Coastguard Worker }
153*f6dc9357SAndroid Build Coastguard Worker 
154*f6dc9357SAndroid Build Coastguard Worker 
File_Read(CSzFile * p,void * data,size_t * size)155*f6dc9357SAndroid Build Coastguard Worker WRes File_Read(CSzFile *p, void *data, size_t *size)
156*f6dc9357SAndroid Build Coastguard Worker {
157*f6dc9357SAndroid Build Coastguard Worker   size_t originalSize = *size;
158*f6dc9357SAndroid Build Coastguard Worker   *size = 0;
159*f6dc9357SAndroid Build Coastguard Worker   if (originalSize == 0)
160*f6dc9357SAndroid Build Coastguard Worker     return 0;
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_WINDOWS_FILE
163*f6dc9357SAndroid Build Coastguard Worker 
164*f6dc9357SAndroid Build Coastguard Worker   do
165*f6dc9357SAndroid Build Coastguard Worker   {
166*f6dc9357SAndroid Build Coastguard Worker     const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
167*f6dc9357SAndroid Build Coastguard Worker     DWORD processed = 0;
168*f6dc9357SAndroid Build Coastguard Worker     const BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
169*f6dc9357SAndroid Build Coastguard Worker     data = (void *)((Byte *)data + processed);
170*f6dc9357SAndroid Build Coastguard Worker     originalSize -= processed;
171*f6dc9357SAndroid Build Coastguard Worker     *size += processed;
172*f6dc9357SAndroid Build Coastguard Worker     if (!res)
173*f6dc9357SAndroid Build Coastguard Worker       return GetLastError();
174*f6dc9357SAndroid Build Coastguard Worker     // debug : we can break here for partial reading mode
175*f6dc9357SAndroid Build Coastguard Worker     if (processed == 0)
176*f6dc9357SAndroid Build Coastguard Worker       break;
177*f6dc9357SAndroid Build Coastguard Worker   }
178*f6dc9357SAndroid Build Coastguard Worker   while (originalSize > 0);
179*f6dc9357SAndroid Build Coastguard Worker 
180*f6dc9357SAndroid Build Coastguard Worker   #elif defined(USE_FOPEN)
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker   do
183*f6dc9357SAndroid Build Coastguard Worker   {
184*f6dc9357SAndroid Build Coastguard Worker     const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize;
185*f6dc9357SAndroid Build Coastguard Worker     const size_t processed = fread(data, 1, curSize, p->file);
186*f6dc9357SAndroid Build Coastguard Worker     data = (void *)((Byte *)data + (size_t)processed);
187*f6dc9357SAndroid Build Coastguard Worker     originalSize -= processed;
188*f6dc9357SAndroid Build Coastguard Worker     *size += processed;
189*f6dc9357SAndroid Build Coastguard Worker     if (processed != curSize)
190*f6dc9357SAndroid Build Coastguard Worker       return ferror(p->file);
191*f6dc9357SAndroid Build Coastguard Worker     // debug : we can break here for partial reading mode
192*f6dc9357SAndroid Build Coastguard Worker     if (processed == 0)
193*f6dc9357SAndroid Build Coastguard Worker       break;
194*f6dc9357SAndroid Build Coastguard Worker   }
195*f6dc9357SAndroid Build Coastguard Worker   while (originalSize > 0);
196*f6dc9357SAndroid Build Coastguard Worker 
197*f6dc9357SAndroid Build Coastguard Worker   #else
198*f6dc9357SAndroid Build Coastguard Worker 
199*f6dc9357SAndroid Build Coastguard Worker   do
200*f6dc9357SAndroid Build Coastguard Worker   {
201*f6dc9357SAndroid Build Coastguard Worker     const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize;
202*f6dc9357SAndroid Build Coastguard Worker     const ssize_t processed = read(p->fd, data, curSize);
203*f6dc9357SAndroid Build Coastguard Worker     if (processed == -1)
204*f6dc9357SAndroid Build Coastguard Worker       return errno;
205*f6dc9357SAndroid Build Coastguard Worker     if (processed == 0)
206*f6dc9357SAndroid Build Coastguard Worker       break;
207*f6dc9357SAndroid Build Coastguard Worker     data = (void *)((Byte *)data + (size_t)processed);
208*f6dc9357SAndroid Build Coastguard Worker     originalSize -= (size_t)processed;
209*f6dc9357SAndroid Build Coastguard Worker     *size += (size_t)processed;
210*f6dc9357SAndroid Build Coastguard Worker     // debug : we can break here for partial reading mode
211*f6dc9357SAndroid Build Coastguard Worker     // break;
212*f6dc9357SAndroid Build Coastguard Worker   }
213*f6dc9357SAndroid Build Coastguard Worker   while (originalSize > 0);
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker   #endif
216*f6dc9357SAndroid Build Coastguard Worker 
217*f6dc9357SAndroid Build Coastguard Worker   return 0;
218*f6dc9357SAndroid Build Coastguard Worker }
219*f6dc9357SAndroid Build Coastguard Worker 
220*f6dc9357SAndroid Build Coastguard Worker 
File_Write(CSzFile * p,const void * data,size_t * size)221*f6dc9357SAndroid Build Coastguard Worker WRes File_Write(CSzFile *p, const void *data, size_t *size)
222*f6dc9357SAndroid Build Coastguard Worker {
223*f6dc9357SAndroid Build Coastguard Worker   size_t originalSize = *size;
224*f6dc9357SAndroid Build Coastguard Worker   *size = 0;
225*f6dc9357SAndroid Build Coastguard Worker   if (originalSize == 0)
226*f6dc9357SAndroid Build Coastguard Worker     return 0;
227*f6dc9357SAndroid Build Coastguard Worker 
228*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_WINDOWS_FILE
229*f6dc9357SAndroid Build Coastguard Worker 
230*f6dc9357SAndroid Build Coastguard Worker   do
231*f6dc9357SAndroid Build Coastguard Worker   {
232*f6dc9357SAndroid Build Coastguard Worker     const DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
233*f6dc9357SAndroid Build Coastguard Worker     DWORD processed = 0;
234*f6dc9357SAndroid Build Coastguard Worker     const BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
235*f6dc9357SAndroid Build Coastguard Worker     data = (const void *)((const Byte *)data + processed);
236*f6dc9357SAndroid Build Coastguard Worker     originalSize -= processed;
237*f6dc9357SAndroid Build Coastguard Worker     *size += processed;
238*f6dc9357SAndroid Build Coastguard Worker     if (!res)
239*f6dc9357SAndroid Build Coastguard Worker       return GetLastError();
240*f6dc9357SAndroid Build Coastguard Worker     if (processed == 0)
241*f6dc9357SAndroid Build Coastguard Worker       break;
242*f6dc9357SAndroid Build Coastguard Worker   }
243*f6dc9357SAndroid Build Coastguard Worker   while (originalSize > 0);
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker   #elif defined(USE_FOPEN)
246*f6dc9357SAndroid Build Coastguard Worker 
247*f6dc9357SAndroid Build Coastguard Worker   do
248*f6dc9357SAndroid Build Coastguard Worker   {
249*f6dc9357SAndroid Build Coastguard Worker     const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize;
250*f6dc9357SAndroid Build Coastguard Worker     const size_t processed = fwrite(data, 1, curSize, p->file);
251*f6dc9357SAndroid Build Coastguard Worker     data = (void *)((Byte *)data + (size_t)processed);
252*f6dc9357SAndroid Build Coastguard Worker     originalSize -= processed;
253*f6dc9357SAndroid Build Coastguard Worker     *size += processed;
254*f6dc9357SAndroid Build Coastguard Worker     if (processed != curSize)
255*f6dc9357SAndroid Build Coastguard Worker       return ferror(p->file);
256*f6dc9357SAndroid Build Coastguard Worker     if (processed == 0)
257*f6dc9357SAndroid Build Coastguard Worker       break;
258*f6dc9357SAndroid Build Coastguard Worker   }
259*f6dc9357SAndroid Build Coastguard Worker   while (originalSize > 0);
260*f6dc9357SAndroid Build Coastguard Worker 
261*f6dc9357SAndroid Build Coastguard Worker   #else
262*f6dc9357SAndroid Build Coastguard Worker 
263*f6dc9357SAndroid Build Coastguard Worker   do
264*f6dc9357SAndroid Build Coastguard Worker   {
265*f6dc9357SAndroid Build Coastguard Worker     const size_t curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : originalSize;
266*f6dc9357SAndroid Build Coastguard Worker     const ssize_t processed = write(p->fd, data, curSize);
267*f6dc9357SAndroid Build Coastguard Worker     if (processed == -1)
268*f6dc9357SAndroid Build Coastguard Worker       return errno;
269*f6dc9357SAndroid Build Coastguard Worker     if (processed == 0)
270*f6dc9357SAndroid Build Coastguard Worker       break;
271*f6dc9357SAndroid Build Coastguard Worker     data = (const void *)((const Byte *)data + (size_t)processed);
272*f6dc9357SAndroid Build Coastguard Worker     originalSize -= (size_t)processed;
273*f6dc9357SAndroid Build Coastguard Worker     *size += (size_t)processed;
274*f6dc9357SAndroid Build Coastguard Worker   }
275*f6dc9357SAndroid Build Coastguard Worker   while (originalSize > 0);
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker   #endif
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker   return 0;
280*f6dc9357SAndroid Build Coastguard Worker }
281*f6dc9357SAndroid Build Coastguard Worker 
282*f6dc9357SAndroid Build Coastguard Worker 
File_Seek(CSzFile * p,Int64 * pos,ESzSeek origin)283*f6dc9357SAndroid Build Coastguard Worker WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
284*f6dc9357SAndroid Build Coastguard Worker {
285*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_WINDOWS_FILE
286*f6dc9357SAndroid Build Coastguard Worker 
287*f6dc9357SAndroid Build Coastguard Worker   DWORD moveMethod;
288*f6dc9357SAndroid Build Coastguard Worker   UInt32 low = (UInt32)*pos;
289*f6dc9357SAndroid Build Coastguard Worker   LONG high = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */
290*f6dc9357SAndroid Build Coastguard Worker   // (int) to eliminate clang warning
291*f6dc9357SAndroid Build Coastguard Worker   switch ((int)origin)
292*f6dc9357SAndroid Build Coastguard Worker   {
293*f6dc9357SAndroid Build Coastguard Worker     case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
294*f6dc9357SAndroid Build Coastguard Worker     case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
295*f6dc9357SAndroid Build Coastguard Worker     case SZ_SEEK_END: moveMethod = FILE_END; break;
296*f6dc9357SAndroid Build Coastguard Worker     default: return ERROR_INVALID_PARAMETER;
297*f6dc9357SAndroid Build Coastguard Worker   }
298*f6dc9357SAndroid Build Coastguard Worker   low = SetFilePointer(p->handle, (LONG)low, &high, moveMethod);
299*f6dc9357SAndroid Build Coastguard Worker   if (low == (UInt32)0xFFFFFFFF)
300*f6dc9357SAndroid Build Coastguard Worker   {
301*f6dc9357SAndroid Build Coastguard Worker     WRes res = GetLastError();
302*f6dc9357SAndroid Build Coastguard Worker     if (res != NO_ERROR)
303*f6dc9357SAndroid Build Coastguard Worker       return res;
304*f6dc9357SAndroid Build Coastguard Worker   }
305*f6dc9357SAndroid Build Coastguard Worker   *pos = ((Int64)high << 32) | low;
306*f6dc9357SAndroid Build Coastguard Worker   return 0;
307*f6dc9357SAndroid Build Coastguard Worker 
308*f6dc9357SAndroid Build Coastguard Worker   #else
309*f6dc9357SAndroid Build Coastguard Worker 
310*f6dc9357SAndroid Build Coastguard Worker   int moveMethod; // = origin;
311*f6dc9357SAndroid Build Coastguard Worker 
312*f6dc9357SAndroid Build Coastguard Worker   switch ((int)origin)
313*f6dc9357SAndroid Build Coastguard Worker   {
314*f6dc9357SAndroid Build Coastguard Worker     case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
315*f6dc9357SAndroid Build Coastguard Worker     case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
316*f6dc9357SAndroid Build Coastguard Worker     case SZ_SEEK_END: moveMethod = SEEK_END; break;
317*f6dc9357SAndroid Build Coastguard Worker     default: return EINVAL;
318*f6dc9357SAndroid Build Coastguard Worker   }
319*f6dc9357SAndroid Build Coastguard Worker 
320*f6dc9357SAndroid Build Coastguard Worker   #if defined(USE_FOPEN)
321*f6dc9357SAndroid Build Coastguard Worker   {
322*f6dc9357SAndroid Build Coastguard Worker     int res = fseek(p->file, (long)*pos, moveMethod);
323*f6dc9357SAndroid Build Coastguard Worker     if (res == -1)
324*f6dc9357SAndroid Build Coastguard Worker       return errno;
325*f6dc9357SAndroid Build Coastguard Worker     *pos = ftell(p->file);
326*f6dc9357SAndroid Build Coastguard Worker     if (*pos == -1)
327*f6dc9357SAndroid Build Coastguard Worker       return errno;
328*f6dc9357SAndroid Build Coastguard Worker     return 0;
329*f6dc9357SAndroid Build Coastguard Worker   }
330*f6dc9357SAndroid Build Coastguard Worker   #else
331*f6dc9357SAndroid Build Coastguard Worker   {
332*f6dc9357SAndroid Build Coastguard Worker     off_t res = lseek(p->fd, (off_t)*pos, moveMethod);
333*f6dc9357SAndroid Build Coastguard Worker     if (res == -1)
334*f6dc9357SAndroid Build Coastguard Worker       return errno;
335*f6dc9357SAndroid Build Coastguard Worker     *pos = res;
336*f6dc9357SAndroid Build Coastguard Worker     return 0;
337*f6dc9357SAndroid Build Coastguard Worker   }
338*f6dc9357SAndroid Build Coastguard Worker 
339*f6dc9357SAndroid Build Coastguard Worker   #endif // USE_FOPEN
340*f6dc9357SAndroid Build Coastguard Worker   #endif // USE_WINDOWS_FILE
341*f6dc9357SAndroid Build Coastguard Worker }
342*f6dc9357SAndroid Build Coastguard Worker 
343*f6dc9357SAndroid Build Coastguard Worker 
File_GetLength(CSzFile * p,UInt64 * length)344*f6dc9357SAndroid Build Coastguard Worker WRes File_GetLength(CSzFile *p, UInt64 *length)
345*f6dc9357SAndroid Build Coastguard Worker {
346*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_WINDOWS_FILE
347*f6dc9357SAndroid Build Coastguard Worker 
348*f6dc9357SAndroid Build Coastguard Worker   DWORD sizeHigh;
349*f6dc9357SAndroid Build Coastguard Worker   DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
350*f6dc9357SAndroid Build Coastguard Worker   if (sizeLow == 0xFFFFFFFF)
351*f6dc9357SAndroid Build Coastguard Worker   {
352*f6dc9357SAndroid Build Coastguard Worker     DWORD res = GetLastError();
353*f6dc9357SAndroid Build Coastguard Worker     if (res != NO_ERROR)
354*f6dc9357SAndroid Build Coastguard Worker       return res;
355*f6dc9357SAndroid Build Coastguard Worker   }
356*f6dc9357SAndroid Build Coastguard Worker   *length = (((UInt64)sizeHigh) << 32) + sizeLow;
357*f6dc9357SAndroid Build Coastguard Worker   return 0;
358*f6dc9357SAndroid Build Coastguard Worker 
359*f6dc9357SAndroid Build Coastguard Worker   #elif defined(USE_FOPEN)
360*f6dc9357SAndroid Build Coastguard Worker 
361*f6dc9357SAndroid Build Coastguard Worker   long pos = ftell(p->file);
362*f6dc9357SAndroid Build Coastguard Worker   int res = fseek(p->file, 0, SEEK_END);
363*f6dc9357SAndroid Build Coastguard Worker   *length = ftell(p->file);
364*f6dc9357SAndroid Build Coastguard Worker   fseek(p->file, pos, SEEK_SET);
365*f6dc9357SAndroid Build Coastguard Worker   return res;
366*f6dc9357SAndroid Build Coastguard Worker 
367*f6dc9357SAndroid Build Coastguard Worker   #else
368*f6dc9357SAndroid Build Coastguard Worker 
369*f6dc9357SAndroid Build Coastguard Worker   off_t pos;
370*f6dc9357SAndroid Build Coastguard Worker   *length = 0;
371*f6dc9357SAndroid Build Coastguard Worker   pos = lseek(p->fd, 0, SEEK_CUR);
372*f6dc9357SAndroid Build Coastguard Worker   if (pos != -1)
373*f6dc9357SAndroid Build Coastguard Worker   {
374*f6dc9357SAndroid Build Coastguard Worker     const off_t len2 = lseek(p->fd, 0, SEEK_END);
375*f6dc9357SAndroid Build Coastguard Worker     const off_t res2 = lseek(p->fd, pos, SEEK_SET);
376*f6dc9357SAndroid Build Coastguard Worker     if (len2 != -1)
377*f6dc9357SAndroid Build Coastguard Worker     {
378*f6dc9357SAndroid Build Coastguard Worker       *length = (UInt64)len2;
379*f6dc9357SAndroid Build Coastguard Worker       if (res2 != -1)
380*f6dc9357SAndroid Build Coastguard Worker         return 0;
381*f6dc9357SAndroid Build Coastguard Worker     }
382*f6dc9357SAndroid Build Coastguard Worker   }
383*f6dc9357SAndroid Build Coastguard Worker   return errno;
384*f6dc9357SAndroid Build Coastguard Worker 
385*f6dc9357SAndroid Build Coastguard Worker   #endif
386*f6dc9357SAndroid Build Coastguard Worker }
387*f6dc9357SAndroid Build Coastguard Worker 
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker /* ---------- FileSeqInStream ---------- */
390*f6dc9357SAndroid Build Coastguard Worker 
FileSeqInStream_Read(ISeqInStreamPtr pp,void * buf,size_t * size)391*f6dc9357SAndroid Build Coastguard Worker static SRes FileSeqInStream_Read(ISeqInStreamPtr pp, void *buf, size_t *size)
392*f6dc9357SAndroid Build Coastguard Worker {
393*f6dc9357SAndroid Build Coastguard Worker   Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileSeqInStream)
394*f6dc9357SAndroid Build Coastguard Worker   const WRes wres = File_Read(&p->file, buf, size);
395*f6dc9357SAndroid Build Coastguard Worker   p->wres = wres;
396*f6dc9357SAndroid Build Coastguard Worker   return (wres == 0) ? SZ_OK : SZ_ERROR_READ;
397*f6dc9357SAndroid Build Coastguard Worker }
398*f6dc9357SAndroid Build Coastguard Worker 
FileSeqInStream_CreateVTable(CFileSeqInStream * p)399*f6dc9357SAndroid Build Coastguard Worker void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
400*f6dc9357SAndroid Build Coastguard Worker {
401*f6dc9357SAndroid Build Coastguard Worker   p->vt.Read = FileSeqInStream_Read;
402*f6dc9357SAndroid Build Coastguard Worker }
403*f6dc9357SAndroid Build Coastguard Worker 
404*f6dc9357SAndroid Build Coastguard Worker 
405*f6dc9357SAndroid Build Coastguard Worker /* ---------- FileInStream ---------- */
406*f6dc9357SAndroid Build Coastguard Worker 
FileInStream_Read(ISeekInStreamPtr pp,void * buf,size_t * size)407*f6dc9357SAndroid Build Coastguard Worker static SRes FileInStream_Read(ISeekInStreamPtr pp, void *buf, size_t *size)
408*f6dc9357SAndroid Build Coastguard Worker {
409*f6dc9357SAndroid Build Coastguard Worker   Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileInStream)
410*f6dc9357SAndroid Build Coastguard Worker   const WRes wres = File_Read(&p->file, buf, size);
411*f6dc9357SAndroid Build Coastguard Worker   p->wres = wres;
412*f6dc9357SAndroid Build Coastguard Worker   return (wres == 0) ? SZ_OK : SZ_ERROR_READ;
413*f6dc9357SAndroid Build Coastguard Worker }
414*f6dc9357SAndroid Build Coastguard Worker 
FileInStream_Seek(ISeekInStreamPtr pp,Int64 * pos,ESzSeek origin)415*f6dc9357SAndroid Build Coastguard Worker static SRes FileInStream_Seek(ISeekInStreamPtr pp, Int64 *pos, ESzSeek origin)
416*f6dc9357SAndroid Build Coastguard Worker {
417*f6dc9357SAndroid Build Coastguard Worker   Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileInStream)
418*f6dc9357SAndroid Build Coastguard Worker   const WRes wres = File_Seek(&p->file, pos, origin);
419*f6dc9357SAndroid Build Coastguard Worker   p->wres = wres;
420*f6dc9357SAndroid Build Coastguard Worker   return (wres == 0) ? SZ_OK : SZ_ERROR_READ;
421*f6dc9357SAndroid Build Coastguard Worker }
422*f6dc9357SAndroid Build Coastguard Worker 
FileInStream_CreateVTable(CFileInStream * p)423*f6dc9357SAndroid Build Coastguard Worker void FileInStream_CreateVTable(CFileInStream *p)
424*f6dc9357SAndroid Build Coastguard Worker {
425*f6dc9357SAndroid Build Coastguard Worker   p->vt.Read = FileInStream_Read;
426*f6dc9357SAndroid Build Coastguard Worker   p->vt.Seek = FileInStream_Seek;
427*f6dc9357SAndroid Build Coastguard Worker }
428*f6dc9357SAndroid Build Coastguard Worker 
429*f6dc9357SAndroid Build Coastguard Worker 
430*f6dc9357SAndroid Build Coastguard Worker /* ---------- FileOutStream ---------- */
431*f6dc9357SAndroid Build Coastguard Worker 
FileOutStream_Write(ISeqOutStreamPtr pp,const void * data,size_t size)432*f6dc9357SAndroid Build Coastguard Worker static size_t FileOutStream_Write(ISeqOutStreamPtr pp, const void *data, size_t size)
433*f6dc9357SAndroid Build Coastguard Worker {
434*f6dc9357SAndroid Build Coastguard Worker   Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CFileOutStream)
435*f6dc9357SAndroid Build Coastguard Worker   const WRes wres = File_Write(&p->file, data, &size);
436*f6dc9357SAndroid Build Coastguard Worker   p->wres = wres;
437*f6dc9357SAndroid Build Coastguard Worker   return size;
438*f6dc9357SAndroid Build Coastguard Worker }
439*f6dc9357SAndroid Build Coastguard Worker 
FileOutStream_CreateVTable(CFileOutStream * p)440*f6dc9357SAndroid Build Coastguard Worker void FileOutStream_CreateVTable(CFileOutStream *p)
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker   p->vt.Write = FileOutStream_Write;
443*f6dc9357SAndroid Build Coastguard Worker }
444