]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/file.cpp
Save the alpha values if the image has an alpha channel
[wxWidgets.git] / src / common / file.cpp
... / ...
CommitLineData
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>
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13/*
14 TODO: remove all the WinCE ugliness from here, implement the wxOpen(),
15 wxSeek(), ... functions in a separate file for WinCE instead!!!
16 */
17
18// ----------------------------------------------------------------------------
19// headers
20// ----------------------------------------------------------------------------
21
22#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
23 #pragma implementation "file.h"
24#endif
25
26// For compilers that support precompilation, includes "wx.h".
27#include "wx/wxprec.h"
28
29#ifdef __BORLANDC__
30 #pragma hdrstop
31#endif
32
33#if wxUSE_FILE
34
35// standard
36#if defined(__WXMSW__) && !defined(__GNUWIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
37 #include <io.h>
38
39#ifndef __SALFORDC__
40 #define WIN32_LEAN_AND_MEAN
41 #define NOSERVICE
42 #define NOIME
43 #define NOATOM
44 #define NOGDI
45 #define NOGDICAPMASKS
46 #define NOMETAFILE
47 #define NOMINMAX
48 #define NOMSG
49 #define NOOPENFILE
50 #define NORASTEROPS
51 #define NOSCROLL
52 #define NOSOUND
53 #define NOSYSMETRICS
54 #define NOTEXTMETRIC
55 #define NOWH
56 #define NOCOMM
57 #define NOKANJI
58 #define NOCRYPT
59 #define NOMCX
60#endif
61
62#elif defined(__WXMSW__) && defined(__WXWINCE__)
63 // TODO: what to include?
64#elif (defined(__OS2__))
65 #include <io.h>
66#elif (defined(__UNIX__) || defined(__GNUWIN32__))
67 #include <unistd.h>
68 #include <time.h>
69 #include <sys/stat.h>
70 #ifdef __GNUWIN32__
71 #include "wx/msw/wrapwin.h"
72 #endif
73#elif defined(__DOS__)
74 #if defined(__WATCOMC__)
75 #include <io.h>
76 #elif defined(__DJGPP__)
77 #include <io.h>
78 #include <unistd.h>
79 #include <stdio.h>
80 #else
81 #error "Please specify the header with file functions declarations."
82 #endif
83#elif (defined(__WXSTUBS__))
84 // Have to ifdef this for different environments
85 #include <io.h>
86#elif (defined(__WXMAC__))
87#if __MSL__ < 0x6000
88 int access( const char *path, int mode ) { return 0 ; }
89#else
90 int _access( const char *path, int mode ) { return 0 ; }
91#endif
92 char* mktemp( char * path ) { return path ;}
93 #include <stat.h>
94 #include <unistd.h>
95#else
96 #error "Please specify the header with file functions declarations."
97#endif //Win/UNIX
98
99#include <stdio.h> // SEEK_xxx constants
100
101#ifndef __WXWINCE__
102#include <fcntl.h> // O_RDONLY &c
103#endif
104
105#ifdef __WXWINCE__
106// Nothing
107#elif !defined(__MWERKS__)
108 #include <sys/types.h> // needed for stat
109 #include <sys/stat.h> // stat
110#elif defined(__MWERKS__) && ( defined(__WXMSW__) || defined(__MACH__) )
111 #include <sys/types.h> // needed for stat
112 #include <sys/stat.h> // stat
113#endif
114
115// Windows compilers don't have these constants
116#ifndef W_OK
117 enum
118 {
119 F_OK = 0, // test for existence
120 X_OK = 1, // execute permission
121 W_OK = 2, // write
122 R_OK = 4 // read
123 };
124#endif // W_OK
125
126// there is no distinction between text and binary files under Unix, so define
127// O_BINARY as 0 if the system headers don't do it already
128#if defined(__UNIX__) && !defined(O_BINARY)
129 #define O_BINARY (0)
130#endif //__UNIX__
131
132#ifdef __SALFORDC__
133 #include <unix.h>
134#endif
135
136#ifndef MAX_PATH
137 #define MAX_PATH 512
138#endif
139
140// some broken compilers don't have 3rd argument in open() and creat()
141#ifdef __SALFORDC__
142 #define ACCESS(access)
143 #define stat _stat
144#else // normal compiler
145 #define ACCESS(access) , (access)
146#endif // Salford C
147
148// wxWidgets
149#ifndef WX_PRECOMP
150 #include "wx/string.h"
151 #include "wx/intl.h"
152 #include "wx/log.h"
153#endif // !WX_PRECOMP
154
155#include "wx/filename.h"
156#include "wx/file.h"
157#include "wx/filefn.h"
158
159#ifdef __WXMSW__
160 #include "wx/msw/mslu.h"
161#endif
162
163#ifdef __WXWINCE__
164 #include "wx/msw/private.h"
165#endif
166
167// ============================================================================
168// implementation of wxFile
169// ============================================================================
170
171// ----------------------------------------------------------------------------
172// static functions
173// ----------------------------------------------------------------------------
174
175bool wxFile::Exists(const wxChar *name)
176{
177 return wxFileExists(name);
178}
179
180bool wxFile::Access(const wxChar *name, OpenMode mode)
181{
182 int how;
183
184 switch ( mode )
185 {
186 default:
187 wxFAIL_MSG(wxT("bad wxFile::Access mode parameter."));
188 // fall through
189
190 case read:
191 how = R_OK;
192 break;
193
194 case write:
195 how = W_OK;
196 break;
197
198 case read_write:
199 how = R_OK | W_OK;
200 break;
201 }
202
203#ifdef __WXWINCE__
204 // FIXME: use CreateFile with 0 access to query the file
205 return TRUE;
206#else
207 return wxAccess(name, how) == 0;
208#endif
209}
210
211// ----------------------------------------------------------------------------
212// opening/closing
213// ----------------------------------------------------------------------------
214
215// ctors
216wxFile::wxFile(const wxChar *szFileName, OpenMode mode)
217{
218 m_fd = fd_invalid;
219 m_error = FALSE;
220
221 Open(szFileName, mode);
222}
223
224// create the file, fail if it already exists and bOverwrite
225bool wxFile::Create(const wxChar *szFileName, bool bOverwrite, int accessMode)
226{
227 // if bOverwrite we create a new file or truncate the existing one,
228 // otherwise we only create the new file and fail if it already exists
229#if defined(__WXMAC__) && !defined(__UNIX__) && !wxUSE_UNICODE
230 // Dominic Mazzoni [dmazzoni+@cs.cmu.edu] reports that open is still broken on the mac, so we replace
231 // int fd = open(wxUnix2MacFilename( szFileName ), O_CREAT | (bOverwrite ? O_TRUNC : O_EXCL), access);
232 int fd = creat( szFileName , accessMode);
233#else
234#ifdef __WXWINCE__
235 HANDLE fileHandle = ::CreateFile(szFileName, GENERIC_WRITE, 0, NULL,
236 bOverwrite ? CREATE_ALWAYS : CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
237 0);
238 int fd = 0;
239 if (fileHandle == INVALID_HANDLE_VALUE)
240 fd = (int) fileHandle;
241 else
242 fd = -1;
243#else
244 int fd = wxOpen( szFileName,
245 O_BINARY | O_WRONLY | O_CREAT |
246 (bOverwrite ? O_TRUNC : O_EXCL)
247 ACCESS(accessMode) );
248#endif
249#endif
250 if ( fd == -1 )
251 {
252 wxLogSysError(_("can't create file '%s'"), szFileName);
253 return FALSE;
254 }
255 else
256 {
257 Attach(fd);
258 return TRUE;
259 }
260}
261
262// open the file
263bool wxFile::Open(const wxChar *szFileName, OpenMode mode, int accessMode)
264{
265#ifdef __WXWINCE__
266 DWORD access = 0;
267 DWORD shareMode = 0;
268 DWORD disposition = 0;
269
270 int flags = O_BINARY;
271
272 switch ( mode )
273 {
274 case read:
275 access = GENERIC_READ;
276 shareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
277 disposition = OPEN_EXISTING;
278 break;
279
280 case write_append:
281 if ( wxFile::Exists(szFileName) )
282 {
283 access = GENERIC_READ|GENERIC_WRITE;
284 shareMode = FILE_SHARE_READ;
285 disposition = 0;
286 break;
287 }
288 //else: fall through as write_append is the same as write if the
289 // file doesn't exist
290
291 case write:
292 access = GENERIC_WRITE;
293 shareMode = 0;
294 disposition = TRUNCATE_EXISTING;
295 break;
296
297 case write_excl:
298 access = GENERIC_WRITE;
299 shareMode = 0;
300 disposition = TRUNCATE_EXISTING;
301 break;
302
303 case read_write:
304 access = GENERIC_READ|GENERIC_WRITE;
305 shareMode = 0;
306 disposition = 0;
307 break;
308 }
309
310 int fd = 0;
311 HANDLE fileHandle = ::CreateFile(szFileName, access, shareMode, NULL,
312 disposition, FILE_ATTRIBUTE_NORMAL, 0);
313 if (fileHandle == INVALID_HANDLE_VALUE)
314 fd = -1;
315 else
316 fd = (int) fileHandle;
317#else
318 int flags = O_BINARY;
319
320 switch ( mode )
321 {
322 case read:
323 flags |= O_RDONLY;
324 break;
325
326 case write_append:
327 if ( wxFile::Exists(szFileName) )
328 {
329 flags |= O_WRONLY | O_APPEND;
330 break;
331 }
332 //else: fall through as write_append is the same as write if the
333 // file doesn't exist
334
335 case write:
336 flags |= O_WRONLY | O_CREAT | O_TRUNC;
337 break;
338
339 case write_excl:
340 flags |= O_WRONLY | O_CREAT | O_EXCL;
341 break;
342
343 case read_write:
344 flags |= O_RDWR;
345 break;
346 }
347
348 int fd = wxOpen( szFileName, flags ACCESS(accessMode));
349#endif
350 if ( fd == -1 )
351 {
352 wxLogSysError(_("can't open file '%s'"), szFileName);
353 return FALSE;
354 }
355 else {
356 Attach(fd);
357 return TRUE;
358 }
359}
360
361// close
362bool wxFile::Close()
363{
364 if ( IsOpened() ) {
365#ifdef __WXWINCE__
366 if (!CloseHandle((HANDLE) m_fd))
367#else
368 if ( close(m_fd) == -1 )
369#endif
370 {
371 wxLogSysError(_("can't close file descriptor %d"), m_fd);
372 m_fd = fd_invalid;
373 return FALSE;
374 }
375 else
376 m_fd = fd_invalid;
377 }
378
379 return TRUE;
380}
381
382// ----------------------------------------------------------------------------
383// read/write
384// ----------------------------------------------------------------------------
385
386// read
387off_t wxFile::Read(void *pBuf, off_t nCount)
388{
389 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
390
391#ifdef __WXWINCE__
392 DWORD bytesRead = 0;
393 int iRc = 0;
394 if (ReadFile((HANDLE) m_fd, pBuf, (DWORD) nCount, & bytesRead, NULL))
395 iRc = bytesRead;
396 else
397 iRc = -1;
398#elif defined(__MWERKS__)
399 int iRc = ::read(m_fd, (char*) pBuf, nCount);
400#else
401 int iRc = ::read(m_fd, pBuf, nCount);
402#endif
403 if ( iRc == -1 ) {
404 wxLogSysError(_("can't read from file descriptor %d"), m_fd);
405 return wxInvalidOffset;
406 }
407 else
408 return (size_t)iRc;
409}
410
411// write
412size_t wxFile::Write(const void *pBuf, size_t nCount)
413{
414 wxCHECK( (pBuf != NULL) && IsOpened(), 0 );
415
416#ifdef __WXWINCE__
417 DWORD bytesRead = 0;
418 int iRc = 0;
419 if (WriteFile((HANDLE) m_fd, pBuf, (DWORD) nCount, & bytesRead, NULL))
420 iRc = bytesRead;
421 else
422 iRc = -1;
423#elif defined(__MWERKS__)
424#if __MSL__ >= 0x6000
425 int iRc = ::write(m_fd, (void*) pBuf, nCount);
426#else
427 int iRc = ::write(m_fd, (const char*) pBuf, nCount);
428#endif
429#else
430 int iRc = ::write(m_fd, pBuf, nCount);
431#endif
432 if ( iRc == -1 ) {
433 wxLogSysError(_("can't write to file descriptor %d"), m_fd);
434 m_error = TRUE;
435 return 0;
436 }
437 else
438 return iRc;
439}
440
441// flush
442bool wxFile::Flush()
443{
444 if ( IsOpened() ) {
445#ifdef __WXWINCE__
446 // Do nothing
447#elif defined(__VISUALC__) || wxHAVE_FSYNC
448 if ( wxFsync(m_fd) == -1 )
449 {
450 wxLogSysError(_("can't flush file descriptor %d"), m_fd);
451 return FALSE;
452 }
453#else // no fsync
454 // just do nothing
455#endif // fsync
456 }
457
458 return TRUE;
459}
460
461// ----------------------------------------------------------------------------
462// seek
463// ----------------------------------------------------------------------------
464
465// seek
466off_t wxFile::Seek(off_t ofs, wxSeekMode mode)
467{
468 wxASSERT( IsOpened() );
469
470#ifdef __WXWINCE__
471 int origin;
472 switch ( mode ) {
473 default:
474 wxFAIL_MSG(_("unknown seek origin"));
475
476 case wxFromStart:
477 origin = FILE_BEGIN;
478 break;
479
480 case wxFromCurrent:
481 origin = FILE_CURRENT;
482 break;
483
484 case wxFromEnd:
485 origin = FILE_END;
486 break;
487 }
488
489 DWORD res = SetFilePointer((HANDLE) m_fd, ofs, 0, origin) ;
490 if (res == 0xFFFFFFFF && GetLastError() != NO_ERROR)
491 {
492 wxLogSysError(_("can't seek on file descriptor %d"), m_fd);
493 return wxInvalidOffset;
494 }
495 else
496 return (off_t)res;
497#else
498 int origin;
499 switch ( mode ) {
500 default:
501 wxFAIL_MSG(_("unknown seek origin"));
502
503 case wxFromStart:
504 origin = SEEK_SET;
505 break;
506
507 case wxFromCurrent:
508 origin = SEEK_CUR;
509 break;
510
511 case wxFromEnd:
512 origin = SEEK_END;
513 break;
514 }
515
516 int iRc = lseek(m_fd, ofs, origin);
517 if ( iRc == -1 ) {
518 wxLogSysError(_("can't seek on file descriptor %d"), m_fd);
519 return wxInvalidOffset;
520 }
521 else
522 return (off_t)iRc;
523#endif
524}
525
526// get current off_t
527off_t wxFile::Tell() const
528{
529 wxASSERT( IsOpened() );
530
531#ifdef __WXWINCE__
532 DWORD res = SetFilePointer((HANDLE) m_fd, 0, 0, FILE_CURRENT) ;
533 if (res == 0xFFFFFFFF && GetLastError() != NO_ERROR)
534 {
535 wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd);
536 return wxInvalidOffset;
537 }
538 else
539 return (off_t)res;
540#else
541 int iRc = wxTell(m_fd);
542 if ( iRc == -1 ) {
543 wxLogSysError(_("can't get seek position on file descriptor %d"), m_fd);
544 return wxInvalidOffset;
545 }
546 else
547 return (off_t)iRc;
548#endif
549}
550
551// get current file length
552off_t wxFile::Length() const
553{
554 wxASSERT( IsOpened() );
555
556#ifdef __WXWINCE__
557 DWORD off0 = SetFilePointer((HANDLE) m_fd, 0, 0, FILE_CURRENT);
558 DWORD off1 = SetFilePointer((HANDLE) m_fd, 0, 0, FILE_END);
559 off_t len = off1;
560
561 // Restore position
562 SetFilePointer((HANDLE) m_fd, off0, 0, FILE_BEGIN);
563 return len;
564#else
565#ifdef __VISUALC__
566 int iRc = _filelength(m_fd);
567#else // !VC++
568 int iRc = wxTell(m_fd);
569 if ( iRc != -1 ) {
570 // @ have to use const_cast :-(
571 int iLen = ((wxFile *)this)->SeekEnd();
572 if ( iLen != -1 ) {
573 // restore old position
574 if ( ((wxFile *)this)->Seek(iRc) == -1 ) {
575 // error
576 iLen = -1;
577 }
578 }
579
580 iRc = iLen;
581 }
582#endif // VC++
583
584 if ( iRc == -1 ) {
585 wxLogSysError(_("can't find length of file on file descriptor %d"), m_fd);
586 return wxInvalidOffset;
587 }
588 else
589 return (off_t)iRc;
590#endif
591}
592
593// is end of file reached?
594bool wxFile::Eof() const
595{
596 wxASSERT( IsOpened() );
597
598#ifdef __WXWINCE__
599 DWORD off0 = SetFilePointer((HANDLE) m_fd, 0, 0, FILE_CURRENT);
600 DWORD off1 = SetFilePointer((HANDLE) m_fd, 0, 0, FILE_END);
601 if (off0 == off1)
602 return TRUE;
603 else
604 {
605 SetFilePointer((HANDLE) m_fd, off0, 0, FILE_BEGIN);
606 return FALSE;
607 }
608#else
609 int iRc;
610
611#if defined(__DOS__) || defined(__UNIX__) || defined(__GNUWIN32__) || defined( __MWERKS__ ) || defined(__SALFORDC__)
612 // @@ this doesn't work, of course, on unseekable file descriptors
613 off_t ofsCur = Tell(),
614 ofsMax = Length();
615 if ( ofsCur == wxInvalidOffset || ofsMax == wxInvalidOffset )
616 iRc = -1;
617 else
618 iRc = ofsCur == ofsMax;
619#else // Windows and "native" compiler
620 iRc = eof(m_fd);
621#endif // Windows/Unix
622
623 switch ( iRc ) {
624 case 1:
625 break;
626
627 case 0:
628 return FALSE;
629
630 case -1:
631 wxLogSysError(_("can't determine if the end of file is reached on descriptor %d"), m_fd);
632 break;
633
634 default:
635 wxFAIL_MSG(_("invalid eof() return value."));
636 }
637
638 return TRUE;
639#endif
640}
641
642// ============================================================================
643// implementation of wxTempFile
644// ============================================================================
645
646// ----------------------------------------------------------------------------
647// construction
648// ----------------------------------------------------------------------------
649
650wxTempFile::wxTempFile(const wxString& strName)
651{
652 Open(strName);
653}
654
655bool wxTempFile::Open(const wxString& strName)
656{
657 // we must have an absolute filename because otherwise CreateTempFileName()
658 // would create the temp file in $TMP (i.e. the system standard location
659 // for the temp files) which might be on another volume/drive/mount and
660 // wxRename()ing it later to m_strName from Commit() would then fail
661 //
662 // with the absolute filename, the temp file is created in the same
663 // directory as this one which ensures that wxRename() may work later
664 wxFileName fn(strName);
665 if ( !fn.IsAbsolute() )
666 {
667 fn.Normalize(wxPATH_NORM_ABSOLUTE);
668 }
669
670 m_strName = fn.GetFullPath();
671
672 m_strTemp = wxFileName::CreateTempFileName(m_strName, &m_file);
673
674 if ( m_strTemp.empty() )
675 {
676 // CreateTempFileName() failed
677 return FALSE;
678 }
679
680#ifdef __UNIX__
681 // the temp file should have the same permissions as the original one
682 mode_t mode;
683
684 wxStructStat st;
685 if ( stat( (const char*) m_strName.fn_str(), &st) == 0 )
686 {
687 mode = st.st_mode;
688 }
689 else
690 {
691 // file probably didn't exist, just give it the default mode _using_
692 // user's umask (new files creation should respect umask)
693 mode_t mask = umask(0777);
694 mode = 0666 & ~mask;
695 umask(mask);
696 }
697
698 if ( chmod( (const char*) m_strTemp.fn_str(), mode) == -1 )
699 {
700#ifndef __OS2__
701 wxLogSysError(_("Failed to set temporary file permissions"));
702#endif
703 }
704#endif // Unix
705
706 return TRUE;
707}
708
709// ----------------------------------------------------------------------------
710// destruction
711// ----------------------------------------------------------------------------
712
713wxTempFile::~wxTempFile()
714{
715 if ( IsOpened() )
716 Discard();
717}
718
719bool wxTempFile::Commit()
720{
721 m_file.Close();
722
723 if ( wxFile::Exists(m_strName) && wxRemove(m_strName) != 0 ) {
724 wxLogSysError(_("can't remove file '%s'"), m_strName.c_str());
725 return FALSE;
726 }
727
728 if ( !wxRenameFile(m_strTemp, m_strName) ) {
729 wxLogSysError(_("can't commit changes to file '%s'"), m_strName.c_str());
730 return FALSE;
731 }
732
733 return TRUE;
734}
735
736void wxTempFile::Discard()
737{
738 m_file.Close();
739 if ( wxRemove(m_strTemp) != 0 )
740 wxLogSysError(_("can't remove temporary file '%s'"), m_strTemp.c_str());
741}
742
743#endif // wxUSE_FILE
744