]> git.saurik.com Git - wxWidgets.git/blame - src/common/file.cpp
Updated the Remstar ODBC files, got the db sample compiling; added Freq and SubString
[wxWidgets.git] / src / common / file.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: file.cpp
3// Purpose: wxFile - encapsulates low-level "file descriptor"
4// wxTempFile
5// Author: Vadim Zeitlin
6// Modified by:
7// Created: 29/01/98
8// RCS-ID: $Id$
9// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
246037e2 10// Licence: wxWindows license
c801d85f
KB
11/////////////////////////////////////////////////////////////////////////////
12
13// ----------------------------------------------------------------------------
14// headers
15// ----------------------------------------------------------------------------
16
17#ifdef __GNUG__
18#pragma implementation "file.h"
19#endif
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23#include "wx/defs.h"
24
25#ifdef __BORLANDC__
26#pragma hdrstop
27#endif
28
29// standard
246037e2 30#if defined(__WXMSW__) && !defined(__GNUWIN32__)
c801d85f 31 #include <io.h>
30a5be97
VZ
32
33 #define WIN32_LEAN_AND_MEAN
34 #define NOSERVICE
35 #define NOIME
36 #define NOATOM
37 #define NOGDI
38 #define NOGDICAPMASKS
39 #define NOMETAFILE
40 #define NOMINMAX
41 #define NOMSG
42 #define NOOPENFILE
43 #define NORASTEROPS
44 #define NOSCROLL
45 #define NOSOUND
46 #define NOSYSMETRICS
47 #define NOTEXTMETRIC
48 #define NOWH
49 #define NOCOMM
50 #define NOKANJI
51 #define NOCRYPT
52 #define NOMCX
53 #include <windows.h> // for GetTempFileName
c801d85f
KB
54#elif (defined(__UNIX__) || defined(__GNUWIN32__))
55 #include <unistd.h>
34138703
JS
56#elif (defined(__WXSTUBS__))
57 // Have to ifdef this for different environments
58 #include <io.h>
c801d85f 59#else
246037e2 60 #error "Please specify the header with file functions declarations."
c801d85f
KB
61#endif //Win/UNIX
62
63#include <stdio.h> // SEEK_xxx constants
64#include <fcntl.h> // O_RDONLY &c
469e1e5c 65#ifndef __MWERKS__
c801d85f
KB
66#include <sys/types.h> // needed for stat
67#include <sys/stat.h> // stat
469e1e5c 68#endif
c801d85f
KB
69
70// Microsoft compiler loves underscores, feed them to it
71#ifdef _MSC_VER
469e1e5c
SC
72
73 #ifndef __MWERKS__
74
c801d85f
KB
75 // functions
76 #define open _open
77 #define close _close
78 #define read _read
79 #define write _write
80 #define lseek _lseek
81 #define fsync _commit
82 #define access _access
83 #define eof _eof
84
85 // types
86 #define stat _stat
87
88 // constants
469e1e5c 89
c801d85f
KB
90 #define O_RDONLY _O_RDONLY
91 #define O_WRONLY _O_WRONLY
92 #define O_RDWR _O_RDWR
93 #define O_EXCL _O_EXCL
94 #define O_CREAT _O_CREAT
95 #define O_BINARY _O_BINARY
96
97 #define S_IFDIR _S_IFDIR
98 #define S_IFREG _S_IFREG
469e1e5c
SC
99
100 #endif
d1427b70
VZ
101
102 #define W_OK 2
103 #define R_OK 4
c801d85f
KB
104#else
105 #define tell(fd) lseek(fd, 0, SEEK_CUR)
106#endif //_MSC_VER
107
34138703
JS
108#ifdef __BORLANDC__
109 #define W_OK 2
110 #define R_OK 4
111#endif
112
c801d85f 113// there is no distinction between text and binary files under Unix
246037e2
VZ
114#ifdef __UNIX__
115 #define O_BINARY (0)
116#endif //__UNIX__
c801d85f
KB
117
118// wxWindows
119#include <wx/string.h>
120#include <wx/intl.h>
121#include <wx/file.h>
122#include <wx/log.h>
123
81d66cf3
JS
124#ifndef MAX_PATH
125#define MAX_PATH 512
126#endif
c801d85f
KB
127
128// ============================================================================
129// implementation of wxFile
130// ============================================================================
131
132// ----------------------------------------------------------------------------
133// static functions
134// ----------------------------------------------------------------------------
d1427b70 135bool wxFile::Exists(const char *name)
246037e2
VZ
136{
137 struct stat st;
d1427b70
VZ
138 return !access(name, 0) && !stat(name, &st) && (st.st_mode & S_IFREG);
139}
140
141bool wxFile::Access(const char *name, OpenMode mode)
142{
8fdca65c 143 int how = 0;
d1427b70
VZ
144
145 switch ( mode ) {
146 case read:
147 how = R_OK;
148 break;
149
150 case write:
151 how = W_OK;
152 break;
153
154 default:
155 wxFAIL_MSG("bad wxFile::Access mode parameter.");
156 }
157
158 return access(name, how) == 0;
c801d85f
KB
159}
160
161// ----------------------------------------------------------------------------
162// opening/closing
163// ----------------------------------------------------------------------------
164
165// ctors
166wxFile::wxFile(const char *szFileName, OpenMode mode)
167{
168 m_fd = fd_invalid;
79c3e0e1 169 m_error = FALSE;
c801d85f
KB
170
171 Open(szFileName, mode);
172}
173
174// dtor
175wxFile::~wxFile()
176{
177 Close();
178}
179
180// create the file, fail if it already exists and bOverwrite
246037e2 181bool wxFile::Create(const char *szFileName, bool bOverwrite, int access)
c801d85f
KB
182{
183 // if bOverwrite we create a new file or truncate the existing one,
184 // otherwise we only create the new file and fail if it already exists
5fc5e442
VZ
185 int fd = open(szFileName, O_WRONLY | O_CREAT |
186 (bOverwrite ? O_TRUNC : O_EXCL), access);
c801d85f
KB
187
188 if ( fd == -1 ) {
1a5a8367 189 wxLogSysError(_("can't create file '%s'"), szFileName);
c801d85f
KB
190 return FALSE;
191 }
192 else {
193 Attach(fd);
194 return TRUE;
195 }
196}
197
198// open the file
246037e2 199bool wxFile::Open(const char *szFileName, OpenMode mode, int access)
c801d85f
KB
200{
201 int flags = O_BINARY;
202
203 switch ( mode ) {
246037e2
VZ
204 case read:
205 flags |= O_RDONLY;
c801d85f
KB
206 break;
207
246037e2
VZ
208 case write:
209 flags |= O_WRONLY | O_CREAT | O_TRUNC;
61b02744
VZ
210 break;
211
212 case write_append:
213 flags |= O_WRONLY | O_APPEND;
c801d85f
KB
214 break;
215
246037e2 216 case read_write:
c801d85f
KB
217 flags |= O_RDWR;
218 break;
219 }
220
246037e2 221 int fd = open(szFileName, flags, access);
c801d85f
KB
222
223 if ( fd == -1 ) {
1a5a8367 224 wxLogSysError(_("can't open file '%s'"), szFileName);
c801d85f
KB
225 return FALSE;
226 }
227 else {
228 Attach(fd);
229 return TRUE;
230 }
231}
232
233// close
61b02744 234bool wxFile::Close()
c801d85f
KB
235{
236 if ( IsOpened() ) {
61b02744 237 if ( close(m_fd) == -1 ) {
1a5a8367 238 wxLogSysError(_("can't close file descriptor %d"), m_fd);
61b02744
VZ
239 m_fd = fd_invalid;
240 return FALSE;
241 }
242 else
243 m_fd = fd_invalid;
c801d85f 244 }
61b02744
VZ
245
246 return TRUE;
c801d85f
KB
247}
248
249// ----------------------------------------------------------------------------
250// read/write
251// ----------------------------------------------------------------------------
252
253// read
254off_t wxFile::Read(void *pBuf, off_t nCount)
255{
1311c7a9 256 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
c801d85f 257
469e1e5c
SC
258#ifdef __MWERKS__
259 int iRc = ::read(m_fd, (char*) pBuf, nCount);
260#else
c801d85f 261 int iRc = ::read(m_fd, pBuf, nCount);
469e1e5c 262#endif
c801d85f 263 if ( iRc == -1 ) {
1a5a8367 264 wxLogSysError(_("can't read from file descriptor %d"), m_fd);
1678ad78 265 return wxInvalidOffset;
c801d85f
KB
266 }
267 else
c86f1403 268 return (size_t)iRc;
c801d85f
KB
269}
270
271// write
c86f1403 272size_t wxFile::Write(const void *pBuf, size_t nCount)
c801d85f 273{
1311c7a9 274 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
c801d85f 275
469e1e5c
SC
276#ifdef __MWERKS__
277 int iRc = ::write(m_fd, (const char*) pBuf, nCount);
278#else
c801d85f 279 int iRc = ::write(m_fd, pBuf, nCount);
469e1e5c 280#endif
c801d85f 281 if ( iRc == -1 ) {
1a5a8367 282 wxLogSysError(_("can't write to file descriptor %d"), m_fd);
79c3e0e1
GL
283 m_error = TRUE;
284 return 0;
c801d85f
KB
285 }
286 else
1678ad78 287 return iRc;
c801d85f
KB
288}
289
290// flush
291bool wxFile::Flush()
292{
293 if ( IsOpened() ) {
1678ad78 294 // @@@ fsync() is not ANSI (BSDish)
c801d85f 295// if ( fsync(m_fd) == -1 ) { // TODO
341287bf 296 if (wxTrue) {
1a5a8367 297 wxLogSysError(_("can't flush file descriptor %d"), m_fd);
c801d85f
KB
298 return FALSE;
299 }
300 }
301
302 return TRUE;
303}
304
305// ----------------------------------------------------------------------------
306// seek
307// ----------------------------------------------------------------------------
308
309// seek
79c3e0e1 310off_t wxFile::Seek(off_t ofs, wxSeekMode mode)
c801d85f
KB
311{
312 wxASSERT( IsOpened() );
313
314 int flag = -1;
315 switch ( mode ) {
79c3e0e1 316 case wxFromStart:
c801d85f
KB
317 flag = SEEK_SET;
318 break;
319
79c3e0e1 320 case wxFromCurrent:
c801d85f
KB
321 flag = SEEK_CUR;
322 break;
323
79c3e0e1 324 case wxFromEnd:
c801d85f
KB
325 flag = SEEK_END;
326 break;
327
328 default:
1a5a8367 329 wxFAIL_MSG(_("unknown seek origin"));
c801d85f
KB
330 }
331
332 int iRc = lseek(m_fd, ofs, flag);
333 if ( iRc == -1 ) {
1a5a8367 334 wxLogSysError(_("can't seek on file descriptor %d"), m_fd);
1678ad78 335 return wxInvalidOffset;
c801d85f
KB
336 }
337 else
338 return (off_t)iRc;
339}
340
341// get current off_t
342off_t wxFile::Tell() const
343{
344 wxASSERT( IsOpened() );
345
346 int iRc = tell(m_fd);
347 if ( iRc == -1 ) {
1a5a8367 348 wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd);
1678ad78 349 return wxInvalidOffset;
c801d85f
KB
350 }
351 else
352 return (off_t)iRc;
353}
354
355// get current file length
356off_t wxFile::Length() const
357{
358 wxASSERT( IsOpened() );
359
469e1e5c 360 #if defined( _MSC_VER ) && !defined( __MWERKS__ )
c801d85f
KB
361 int iRc = _filelength(m_fd);
362 #else
363 int iRc = tell(m_fd);
364 if ( iRc != -1 ) {
246037e2 365 // @ have to use const_cast :-(
c801d85f
KB
366 int iLen = ((wxFile *)this)->SeekEnd();
367 if ( iLen != -1 ) {
368 // restore old position
369 if ( ((wxFile *)this)->Seek(iRc) == -1 ) {
370 // error
371 iLen = -1;
372 }
373 }
374
375 iRc = iLen;
376 }
377
378 #endif //_MSC_VER
379
380 if ( iRc == -1 ) {
1a5a8367 381 wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd);
1678ad78 382 return wxInvalidOffset;
c801d85f
KB
383 }
384 else
385 return (off_t)iRc;
386}
387
388// is end of file reached?
389bool wxFile::Eof() const
390{
391 wxASSERT( IsOpened() );
392
61b02744
VZ
393 int iRc;
394
469e1e5c 395 #if defined(__UNIX__) || defined(__GNUWIN32__) || defined( __MWERKS__ )
61b02744
VZ
396 // @@ this doesn't work, of course, on unseekable file descriptors
397 off_t ofsCur = Tell(),
398 ofsMax = Length();
1678ad78 399 if ( ofsCur == wxInvalidOffset || ofsMax == wxInvalidOffset )
61b02744
VZ
400 iRc = -1;
401 else
402 iRc = ofsCur == ofsMax;
403 #else // Windows and "native" compiler
404 iRc = eof(m_fd);
405 #endif // Windows/Unix
c801d85f
KB
406
407 switch ( iRc ) {
408 case 1:
409 break;
410
411 case 0:
412 return FALSE;
413
414 case -1:
1a5a8367
DP
415 wxLogSysError(_("can't determine if the end of file is reached on \
416descriptor %d"), m_fd);
c801d85f
KB
417 break;
418
419 default:
1a5a8367 420 wxFAIL_MSG(_("invalid eof() return value."));
c801d85f
KB
421 }
422
423 return TRUE;
424}
425
426// ============================================================================
427// implementation of wxTempFile
428// ============================================================================
429
430// ----------------------------------------------------------------------------
431// construction
432// ----------------------------------------------------------------------------
433wxTempFile::wxTempFile(const wxString& strName)
434{
435 Open(strName);
436}
437
438bool wxTempFile::Open(const wxString& strName)
439{
440 m_strName = strName;
246037e2 441
b59650be
VZ
442 // we want to create the file in the same directory as strName because
443 // otherwise rename() in Commit() might not work (if the files are on
444 // different partitions for example). Unfortunately, the only standard
445 // (POSIX) temp file creation function tmpnam() can't do it.
34138703 446 #if defined(__UNIX__) || defined(__WXSTUBS__)
b59650be
VZ
447 static const char *szMktempSuffix = "XXXXXX";
448 m_strTemp << strName << szMktempSuffix;
30a5be97 449 mktemp((char *)m_strTemp.c_str()); // will do because length doesn't change
b59650be 450 #else // Windows
30a5be97
VZ
451 wxString strPath;
452 wxSplitPath(strName, &strPath, NULL, NULL);
453 if ( strPath.IsEmpty() )
454 strPath = '.'; // GetTempFileName will fail if we give it empty string
81d66cf3 455#ifdef __WIN32__
30a5be97 456 if ( !GetTempFileName(strPath, "wx_",0, m_strTemp.GetWriteBuf(MAX_PATH)) )
81d66cf3
JS
457#else
458 // Not sure why MSVC++ 1.5 header defines first param as BYTE - bug?
459 if ( !GetTempFileName((BYTE) (const char*) strPath, "wx_",0, m_strTemp.GetWriteBuf(MAX_PATH)) )
460#endif
30a5be97
VZ
461 wxLogLastError("GetTempFileName");
462 m_strTemp.UngetWriteBuf();
b59650be 463 #endif // Windows/Unix
246037e2 464
c801d85f
KB
465 return m_file.Open(m_strTemp, wxFile::write);
466}
467
468// ----------------------------------------------------------------------------
469// destruction
470// ----------------------------------------------------------------------------
471
472wxTempFile::~wxTempFile()
473{
474 if ( IsOpened() )
475 Discard();
476}
477
478bool wxTempFile::Commit()
479{
480 m_file.Close();
481
482 if ( wxFile::Exists(m_strName) && remove(m_strName) != 0 ) {
1a5a8367 483 wxLogSysError(_("can't remove file '%s'"), m_strName.c_str());
c801d85f
KB
484 return FALSE;
485 }
486
487 if ( rename(m_strTemp, m_strName) != 0 ) {
1a5a8367 488 wxLogSysError(_("can't commit changes to file '%s'"), m_strName.c_str());
c801d85f
KB
489 return FALSE;
490 }
491
492 return TRUE;
493}
494
495void wxTempFile::Discard()
496{
497 m_file.Close();
498 if ( remove(m_strTemp) != 0 )
1a5a8367 499 wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp.c_str());
c801d85f 500}