1 | /**********************************************************************
|
---|
2 | *
|
---|
3 | * FileSystem.cpp
|
---|
4 | * Copyright (C) 2003 UNESCO
|
---|
5 | *
|
---|
6 | * A component of the Greenstone digital library software
|
---|
7 | * from the New Zealand Digital Library Project at the
|
---|
8 | * University of Waikato, New Zealand.
|
---|
9 | *
|
---|
10 | * This program is free software; you can redistribute it and/or modify
|
---|
11 | * it under the terms of the GNU General Public License as published by
|
---|
12 | * the Free Software Foundation; either version 2 of the License, or
|
---|
13 | * (at your option) any later version.
|
---|
14 | *
|
---|
15 | * This program is distributed in the hope that it will be useful,
|
---|
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
18 | * GNU General Public License for more details.
|
---|
19 | *
|
---|
20 | * You should have received a copy of the GNU General Public License
|
---|
21 | * along with this program; if not, write to the Free Software
|
---|
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
23 | *
|
---|
24 | *********************************************************************/
|
---|
25 |
|
---|
26 | ////////////////////////////////////////////////////////////////////////////////////
|
---|
27 | //
|
---|
28 | // FileSystem -- The generic file pointer routines are a collection of member
|
---|
29 | // functions used to wrap the underlying file system.
|
---|
30 |
|
---|
31 |
|
---|
32 | #include "errno.h"
|
---|
33 | #include "stdafx.h"
|
---|
34 | #include "FileSystem.h"
|
---|
35 |
|
---|
36 |
|
---|
37 | using namespace FileSystem;
|
---|
38 | //---------------------------------------------------------------------
|
---|
39 | // FileSystem::FPTR *Create(const _TCHAR *fname)
|
---|
40 | //
|
---|
41 | // Create a new file and truncate existing files.
|
---|
42 | // Returns a null value if the file cannot be
|
---|
43 | // created.
|
---|
44 | //---------------------------------------------------------------------
|
---|
45 | DLL_CODE_API FileSystem::FPTR *FileSystem::Create(const char *fname)
|
---|
46 | {
|
---|
47 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
48 | return FS64Create(fname);
|
---|
49 |
|
---|
50 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
51 | FPTR *stream = new FPTR;
|
---|
52 | if (!stream)
|
---|
53 | return 0;
|
---|
54 | stream->fptr = CreateFile(fname,
|
---|
55 | GENERIC_READ | GENERIC_WRITE,
|
---|
56 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
---|
57 | NULL, // No security
|
---|
58 | CREATE_ALWAYS,
|
---|
59 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
---|
60 | NULL // No attr. template
|
---|
61 | );
|
---|
62 |
|
---|
63 | if (stream->fptr == INVALID_HANDLE_VALUE)
|
---|
64 | {
|
---|
65 | delete stream;
|
---|
66 | return 0;
|
---|
67 | }
|
---|
68 | return stream;
|
---|
69 |
|
---|
70 | #else // Use the 32-bit stdio version by default
|
---|
71 | FPTR *stream = new FPTR;
|
---|
72 | if (!stream)
|
---|
73 | return 0;
|
---|
74 | stream->fptr = fopen(fname, "w+b");
|
---|
75 | if (stream->fptr == 0)
|
---|
76 | {
|
---|
77 | delete stream; // 01/30/2002: Prevent memory leak
|
---|
78 | return 0;
|
---|
79 | }
|
---|
80 | return stream;
|
---|
81 | #endif
|
---|
82 | }
|
---|
83 |
|
---|
84 | //---------------------------------------------------------------------
|
---|
85 | // FileSystem::FPTR *Open(const _TCHAR *fname, FileSystemAccessMode mode)
|
---|
86 | //
|
---|
87 | // Open an existing file. The "mode" variable determines if the file
|
---|
88 | // is opened for read only or read/write access. Returns a null value
|
---|
89 | // if the specified file cannot be opened. NOTE: This version of the
|
---|
90 | // open functions will only accept: FILE_READONLY and FILE_READWRITE
|
---|
91 | // access modes.
|
---|
92 | //---------------------------------------------------------------------
|
---|
93 | DLL_CODE_API FileSystem::FPTR *FileSystem::Open(const char *fname, FileSystem::AccessMode mode)
|
---|
94 | {
|
---|
95 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
96 | return FSOpen(fname, mode);
|
---|
97 |
|
---|
98 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
99 | FPTR *stream = new FPTR;
|
---|
100 | if (!stream)
|
---|
101 | return 0;
|
---|
102 | if (mode == FILE_READONLY)
|
---|
103 | {
|
---|
104 | // Open for read only access
|
---|
105 | stream->fptr = CreateFile(fname,
|
---|
106 | GENERIC_READ,
|
---|
107 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
---|
108 | NULL, // No security
|
---|
109 | OPEN_EXISTING,
|
---|
110 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
---|
111 | NULL // No attr. template
|
---|
112 | );
|
---|
113 | if (stream->fptr == INVALID_HANDLE_VALUE)
|
---|
114 | {
|
---|
115 | delete stream;
|
---|
116 | return 0;
|
---|
117 | }
|
---|
118 | }
|
---|
119 | else
|
---|
120 | { // Open for read/write access
|
---|
121 | stream->fptr = CreateFile(fname,
|
---|
122 | GENERIC_READ | GENERIC_WRITE,
|
---|
123 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
---|
124 | NULL, // No security
|
---|
125 | OPEN_EXISTING,
|
---|
126 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
---|
127 | NULL // No attr. template
|
---|
128 | );
|
---|
129 |
|
---|
130 | if (stream->fptr == INVALID_HANDLE_VALUE)
|
---|
131 | {
|
---|
132 | delete stream;
|
---|
133 | return 0;
|
---|
134 | }
|
---|
135 | }
|
---|
136 | return stream;
|
---|
137 |
|
---|
138 | #else // Use the 32-bit stdio version by default
|
---|
139 | FPTR *stream = new FPTR;
|
---|
140 | if (!stream)
|
---|
141 | return 0;
|
---|
142 |
|
---|
143 | if (mode == FILE_READONLY)
|
---|
144 | {
|
---|
145 | // Open for read only access
|
---|
146 | stream->fptr = fopen(fname, "rb");
|
---|
147 | if (stream->fptr == 0)
|
---|
148 | {
|
---|
149 | delete stream; // 01/30/2002: Prevent memory leak
|
---|
150 | return 0;
|
---|
151 | }
|
---|
152 | }
|
---|
153 | else
|
---|
154 | { // Open for read/write access
|
---|
155 | stream->fptr = fopen(fname, "r+b");
|
---|
156 | if (stream->fptr == 0)
|
---|
157 | {
|
---|
158 | delete stream; // 01/30/2002: Prevent memory leak
|
---|
159 | return 0;
|
---|
160 | }
|
---|
161 | }
|
---|
162 | return stream;
|
---|
163 | #endif
|
---|
164 | }
|
---|
165 |
|
---|
166 | //---------------------------------------------------------------------
|
---|
167 | // int Close(FileSystem::FPTR *stream)
|
---|
168 | //
|
---|
169 | // Close an open file. Returns a non-zero value to indicate an error
|
---|
170 | // condition or zero if successful.
|
---|
171 | //---------------------------------------------------------------------
|
---|
172 | DLL_CODE_API int FileSystem::Close(FPTR *stream)
|
---|
173 | {
|
---|
174 | if (!stream)
|
---|
175 | return 0; // The file stream is not open
|
---|
176 |
|
---|
177 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
178 | return FS64Close(stream);
|
---|
179 |
|
---|
180 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
181 | if (!CloseHandle(stream->fptr))
|
---|
182 | return 1;
|
---|
183 | delete stream;
|
---|
184 | stream = 0;
|
---|
185 | return 0;
|
---|
186 |
|
---|
187 | #else // Use the 32-bit stdio version by default
|
---|
188 | if (fclose(stream->fptr) != 0)
|
---|
189 | return 1;
|
---|
190 | delete stream;
|
---|
191 | stream = 0; // 02/02/2002: Set pointer to zero after releasing it
|
---|
192 | return 0;
|
---|
193 | #endif
|
---|
194 | }
|
---|
195 |
|
---|
196 | //-----------------------------------------------------------------------------
|
---|
197 | // int Flush(FileSystem::FPTR *stream)
|
---|
198 | //
|
---|
199 | // Flush the any open disk buffers. Returns a non-zero value to indicate
|
---|
200 | // an error // condition or zero if successful.
|
---|
201 | //
|
---|
202 | // ATTENTION: ****MS VC++*** YOU SHOULD LINK YOUR APPLICATION WITH COMMODE.OBJ
|
---|
203 | // file. COMMODE.OBJ changes the global commit flag such that
|
---|
204 | // calling fflush() or _flushall() commits the file buffer to disk.
|
---|
205 | // The Windows NT operating system provides the WIN32 API FlushFileBuffers().
|
---|
206 | // The _commit() function included with the Visual C++ 32-bit Edition
|
---|
207 | // CRT calls FlushFileBuffers to write buffered data to disk.
|
---|
208 | //-----------------------------------------------------------------------------
|
---|
209 | DLL_CODE_API int FileSystem::Flush(FPTR *stream)
|
---|
210 | {
|
---|
211 | if (!stream)
|
---|
212 | return 0; // The file stream is not open
|
---|
213 |
|
---|
214 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
215 | return FS64Flush(stream);
|
---|
216 |
|
---|
217 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
218 | if (!FlushFileBuffers(stream->fptr))
|
---|
219 | return 1;
|
---|
220 | return 0;
|
---|
221 |
|
---|
222 | #else // Use the 32-bit stdio version by default
|
---|
223 | int ret = fflush(stream->fptr);
|
---|
224 | if (ret != 0)
|
---|
225 | {
|
---|
226 | TRACE("\nerrno=%d\n\n\n", errno);
|
---|
227 | return 1; // Error
|
---|
228 | }
|
---|
229 | else
|
---|
230 | return 0;
|
---|
231 | #endif
|
---|
232 | }
|
---|
233 |
|
---|
234 | //---------------------------------------------------------------------
|
---|
235 | // int Read(FileSystem::FPTR *stream, void *buf, isis::uint32_t bytes)
|
---|
236 | //
|
---|
237 | // Read a specified number of bytes from the current file position
|
---|
238 | // into a memory buffer. Returns the total number if bytes read from the
|
---|
239 | // file.
|
---|
240 | //---------------------------------------------------------------------
|
---|
241 | DLL_CODE_API isis::ulong32_t FileSystem::Read(FPTR *stream, void *buf,
|
---|
242 | isis::ulong32_t bytes)
|
---|
243 | {
|
---|
244 | if (!stream)
|
---|
245 | return (isis::ulong32_t)0; // The file stream is not open
|
---|
246 |
|
---|
247 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
248 | return FS64Read(stream, buf, bytes);
|
---|
249 |
|
---|
250 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
251 | DWORD bytes_read;
|
---|
252 | if (!ReadFile(stream->fptr, (LPVOID)buf, (DWORD)bytes, &bytes_read, NULL))
|
---|
253 | {
|
---|
254 | return (isis::ulong32_t)0;
|
---|
255 | }
|
---|
256 | return (isis::ulong32_t)bytes_read;
|
---|
257 |
|
---|
258 | #else // Use the 32-bit stdio version by default
|
---|
259 | return (isis::ulong32_t)fread((unsigned char *)buf, 1, bytes, stream->fptr);
|
---|
260 | #endif
|
---|
261 | }
|
---|
262 | //---------------------------------------------------------------------
|
---|
263 | // int Write(FileSystem::FPTR *stream, const void *buf, isis::uint32_t bytes)
|
---|
264 | //
|
---|
265 | // Write a specific number of bytes from a memory buffer to the
|
---|
266 | // current file position. Returns the total number if bytes written
|
---|
267 | // to the file.
|
---|
268 | //---------------------------------------------------------------------
|
---|
269 | DLL_CODE_API isis::ulong32_t FileSystem::Write(FPTR *stream, const void *buf,
|
---|
270 | isis::ulong32_t bytes)
|
---|
271 | {
|
---|
272 | if (!stream)
|
---|
273 | return (isis::ulong32_t)0; // The file stream is not open
|
---|
274 |
|
---|
275 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
276 | return FS64Write(stream, buf, bytes);
|
---|
277 |
|
---|
278 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
279 | DWORD bytes_moved;
|
---|
280 | if (!WriteFile(stream->fptr, (LPVOID)buf, (DWORD)bytes, &bytes_moved, NULL))
|
---|
281 | {
|
---|
282 | return (isis::ulong32_t)0;
|
---|
283 | }
|
---|
284 | return (isis::ulong32_t)bytes_moved;
|
---|
285 |
|
---|
286 | #else // Use the 32-bit stdio version by default
|
---|
287 | return (isis::ulong32_t)fwrite((const unsigned char *)buf, 1, bytes, stream->fptr);
|
---|
288 | #endif
|
---|
289 | }
|
---|
290 | //---------------------------------------------------------------------------
|
---|
291 | // isis::int32_t Seek(FileSystem::FPTR *stream, isis::int32_t offset, FileSystemSeekMode mode)
|
---|
292 | //
|
---|
293 | // Seek to the specified offset starting at the beginning (SEEK_SET),
|
---|
294 | // end (SEEK_END) or current offset (SEEK_CUR). Returns a negative 1
|
---|
295 | // to indicate an error condition or the current stream position if
|
---|
296 | // successful.
|
---|
297 | //----------------------------------------------------------------------------
|
---|
298 | DLL_CODE_API FAU_t FileSystem::Seek(FPTR *stream, FAU_t offset, FileSystem::SeekMode mode)
|
---|
299 | {
|
---|
300 | if (!stream)
|
---|
301 | return (FAU_t) - 1; // The file stream is not open
|
---|
302 |
|
---|
303 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
304 | return FS64Seek(stream, offset, mode);
|
---|
305 |
|
---|
306 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
307 | if (mode == FILE_SEEK_BEG)
|
---|
308 | {
|
---|
309 | return (FAU_t)SetFilePointer(stream->fptr, offset, NULL, FILE_BEGIN);
|
---|
310 | }
|
---|
311 | else if (mode == FILE_SEEK_CUR)
|
---|
312 | {
|
---|
313 | return (FAU_t)SetFilePointer(stream->fptr, offset, NULL, FILE_CURRENT);
|
---|
314 | }
|
---|
315 | else if (mode == FILE_SEEK_END)
|
---|
316 | {
|
---|
317 | return (FAU_t)SetFilePointer(stream->fptr, offset, NULL, FILE_END);
|
---|
318 | }
|
---|
319 | else
|
---|
320 | { // An invalid seek mode was specified
|
---|
321 | return (FAU_t) - 1;
|
---|
322 | }
|
---|
323 |
|
---|
324 | #else // Use the 32-bit stdio version by default
|
---|
325 | if (mode == FILE_SEEK_BEG)
|
---|
326 | {
|
---|
327 | return fseek(stream->fptr, offset, SEEK_SET);
|
---|
328 | }
|
---|
329 | else if (mode == FILE_SEEK_CUR)
|
---|
330 | {
|
---|
331 | return fseek(stream->fptr, offset, SEEK_CUR);
|
---|
332 | }
|
---|
333 | else if (mode == FILE_SEEK_END)
|
---|
334 | {
|
---|
335 | return fseek(stream->fptr, offset, SEEK_CUR);
|
---|
336 | }
|
---|
337 | else
|
---|
338 | { // An invalid seek mode was specified
|
---|
339 | return (FAU_t) - 1;
|
---|
340 | }
|
---|
341 | #endif
|
---|
342 | }
|
---|
343 | //----------------------------------------------------------------------------
|
---|
344 | // isis::int32_t Tell(FileSystem::FPTR *stream)
|
---|
345 | //
|
---|
346 | //----------------------------------------------------------------------------
|
---|
347 | DLL_CODE_API FAU_t FileSystem::Tell(FPTR *stream)
|
---|
348 | {
|
---|
349 | if (!stream)
|
---|
350 | return (FAU_t) - 1; // The file stream is not open
|
---|
351 |
|
---|
352 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
353 | return FS64Tell(stream);
|
---|
354 |
|
---|
355 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
356 | return (__LWORD__)SetFilePointer(stream->fptr, 0, NULL, FILE_CURRENT);
|
---|
357 |
|
---|
358 | #else // Use the 32-bit stdio version by default
|
---|
359 | return ftell(stream->fptr);
|
---|
360 | #endif
|
---|
361 | }
|
---|
362 |
|
---|
363 | //----------------------------------------------------------------------------
|
---|
364 | // int Exists(const char *fname)
|
---|
365 | //
|
---|
366 | // Returns true if the specified file exists.
|
---|
367 | //----------------------------------------------------------------------------
|
---|
368 | DLL_CODE_API int FileSystem::Exists(const char *fname)
|
---|
369 | // Returns true if the specified file exists.
|
---|
370 | {
|
---|
371 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
372 | return FS64Exists(fname);
|
---|
373 |
|
---|
374 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
375 | HANDLE hFile = CreateFile(fname,
|
---|
376 | GENERIC_READ,
|
---|
377 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
---|
378 | NULL, // No security
|
---|
379 | OPEN_EXISTING,
|
---|
380 | FILE_ATTRIBUTE_NORMAL,
|
---|
381 | NULL // No attr. template
|
---|
382 | );
|
---|
383 |
|
---|
384 | if (hFile == INVALID_HANDLE_VALUE)
|
---|
385 | {
|
---|
386 | return 0;
|
---|
387 | }
|
---|
388 |
|
---|
389 | CloseHandle(hFile);
|
---|
390 | return 1;
|
---|
391 |
|
---|
392 | #else // Use the 32-bit stdio version by default
|
---|
393 | struct stat buf;
|
---|
394 | return stat(fname, &buf) ==(FAU_t)0;
|
---|
395 | #endif
|
---|
396 | }
|
---|
397 |
|
---|
398 |
|
---|
399 |
|
---|
400 | //----------------------------------------------------------------------------
|
---|
401 | // FAU_t FileSize(const _TCHAR *fname)
|
---|
402 | //
|
---|
403 | // Returns the length of the specified file or negative 1 to indicate an
|
---|
404 | // error condition.
|
---|
405 | //----------------------------------------------------------------------------
|
---|
406 | DLL_CODE_API FAU_t FileSystem::FileSize(const char *fname)
|
---|
407 | {
|
---|
408 | #if defined(__64_BIT_FILE_SYSTEM__)
|
---|
409 | return FS64FileSize(fname);
|
---|
410 |
|
---|
411 | #elif defined(__WIN32__) && defined(__NTFS__)
|
---|
412 | HANDLE hFile = CreateFile(fname,
|
---|
413 | GENERIC_READ,
|
---|
414 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
---|
415 | NULL, // No security
|
---|
416 | OPEN_EXISTING,
|
---|
417 | FILE_ATTRIBUTE_NORMAL,
|
---|
418 | NULL // No attr. template
|
---|
419 | );
|
---|
420 |
|
---|
421 | // Could not open the specified file
|
---|
422 | if (hFile == INVALID_HANDLE_VALUE)
|
---|
423 | {
|
---|
424 | return (FAU_t) - 1;
|
---|
425 | }
|
---|
426 |
|
---|
427 | BY_HANDLE_FILE_INFORMATION info;
|
---|
428 |
|
---|
429 | if (GetFileInformationByHandle(hFile, &info) == 0)
|
---|
430 | {
|
---|
431 | return (FAU_t) - 1;
|
---|
432 | }
|
---|
433 | CloseHandle(hFile);
|
---|
434 | return (FAU_t)info.nFileSizeLow;;
|
---|
435 |
|
---|
436 | #else // Use the 32-bit stdio version by default
|
---|
437 | struct stat buf;
|
---|
438 | int result = stat(fname, &buf);
|
---|
439 | if (result != 0)
|
---|
440 | return -1;
|
---|
441 | return buf.st_size;
|
---|
442 | #endif
|
---|
443 | }
|
---|
444 |
|
---|
445 | // #include <io.h>
|
---|
446 | // #include <share.h>
|
---|
447 |
|
---|
448 |
|
---|
449 | // int FileSystem::CanOpenForWriting(const _TCHAR *fname)
|
---|
450 | // {
|
---|
451 | // // Try to open for writing
|
---|
452 | // int fd = _tsopen(fname, _O_WRONLY | O_BINARY, _SH_DENYWR);
|
---|
453 | // if (fd == -1)
|
---|
454 | // return 0;
|
---|
455 | // _close(fd);
|
---|
456 | // return 1;
|
---|
457 | // }
|
---|
458 |
|
---|
459 | // int FileSystem::CanOpenReadOnly(const _TCHAR *fname)
|
---|
460 | // {
|
---|
461 | // // Try to open for read only
|
---|
462 | // int fd = _tsopen(fname, _O_RDONLY | O_BINARY, _SH_DENYNO);
|
---|
463 | // if (fd == -1)
|
---|
464 | // return 0;
|
---|
465 | // _close(fd);
|
---|
466 | // return 1;
|
---|
467 | // }
|
---|
468 |
|
---|
469 | //----------------------------------------------------------------------------
|
---|
470 | // int IsReadOnly(const _TCHAR* fname)
|
---|
471 | //
|
---|
472 | // Returns true if the specified file is read only.
|
---|
473 | //----------------------------------------------------------------------------
|
---|
474 | // int FileSystem::IsReadOnly(const _TCHAR *fname)
|
---|
475 | // {
|
---|
476 | // struct _stat buf;
|
---|
477 | // _tstat(fname, &buf);
|
---|
478 | // if (buf.st_mode & S_IWRITE)
|
---|
479 | // return 0;
|
---|
480 | // return 1;
|
---|
481 | // }
|
---|
482 |
|
---|