~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/7z/7zFile.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

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