source: vendor/trolltech/current/src/tools/qfile.cpp

Last change on this file was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 18.1 KB
Line 
1/****************************************************************************
2** $Id: qfile.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QFile class
5**
6** Created : 930812
7**
8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qplatformdefs.h"
39
40// POSIX Large File Support redefines open -> open64
41#if defined(open)
42# undef open
43#endif
44
45// POSIX Large File Support redefines truncate -> truncate64
46#if defined(truncate)
47# undef truncate
48#endif
49
50#include "qfile.h"
51#ifndef NO_ERRNO_H
52#include <errno.h>
53#endif
54
55
56// Duplicated from qobject.h, but we cannot include qobject.h here since
57// it causes qmake to not build on irix g++
58#define QT_TRANSLATE_NOOP(scope,x) (x)
59
60const char* qt_fileerr_unknown = QT_TRANSLATE_NOOP( "QFile", "Unknown error" );
61const char* qt_fileerr_read = QT_TRANSLATE_NOOP( "QFile", "Could not read from the file" );
62const char* qt_fileerr_write = QT_TRANSLATE_NOOP( "QFile", "Could not write to the file" );
63
64#define QFILEERR_EACCES QT_TRANSLATE_NOOP( "QFile", "Permission denied" )
65#define QFILEERR_EMFILE QT_TRANSLATE_NOOP( "QFile", "Too many open files" )
66#define QFILEERR_ENOENT QT_TRANSLATE_NOOP( "QFile", "No such file or directory" )
67#define QFILEERR_ENOSPC QT_TRANSLATE_NOOP( "QFile", "No space left on device" )
68
69class QFilePrivate
70{
71public:
72 QString errorString;
73};
74
75extern bool qt_file_access( const QString& fn, int t );
76
77/*!
78 \class QFile qfile.h
79 \reentrant
80 \brief The QFile class is an I/O device that operates on files.
81
82 \ingroup io
83 \mainclass
84
85 QFile is an I/O device for reading and writing binary and text
86 files. A QFile may be used by itself or more conveniently with a
87 QDataStream or QTextStream.
88
89 The file name is usually passed in the constructor but can be
90 changed with setName(). You can check for a file's existence with
91 exists() and remove a file with remove().
92
93 The file is opened with open(), closed with close() and flushed
94 with flush(). Data is usually read and written using QDataStream
95 or QTextStream, but you can read with readBlock() and readLine()
96 and write with writeBlock(). QFile also supports getch(),
97 ungetch() and putch().
98
99 The size of the file is returned by size(). You can get the
100 current file position or move to a new file position using the
101 at() functions. If you've reached the end of the file, atEnd()
102 returns TRUE. The file handle is returned by handle().
103
104 Here is a code fragment that uses QTextStream to read a text file
105 line by line. It prints each line with a line number.
106 \code
107 QStringList lines;
108 QFile file( "file.txt" );
109 if ( file.open( IO_ReadOnly ) ) {
110 QTextStream stream( &file );
111 QString line;
112 int i = 1;
113 while ( !stream.atEnd() ) {
114 line = stream.readLine(); // line of text excluding '\n'
115 printf( "%3d: %s\n", i++, line.latin1() );
116 lines += line;
117 }
118 file.close();
119 }
120 \endcode
121
122 Writing text is just as easy. The following example shows how to
123 write the data we read into the string list from the previous
124 example:
125 \code
126 QFile file( "file.txt" );
127 if ( file.open( IO_WriteOnly ) ) {
128 QTextStream stream( &file );
129 for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
130 stream << *it << "\n";
131 file.close();
132 }
133 \endcode
134
135 The QFileInfo class holds detailed information about a file, such
136 as access permissions, file dates and file types.
137
138 The QDir class manages directories and lists of file names.
139
140 Qt uses Unicode file names. If you want to do your own I/O on Unix
141 systems you may want to use encodeName() (and decodeName()) to
142 convert the file name into the local encoding.
143
144 \important readAll() at()
145
146 \sa QDataStream, QTextStream
147*/
148
149/*!
150 \fn Q_LONG QFile::writeBlock( const QByteArray& data )
151
152 \overload
153*/
154
155
156/*!
157 Constructs a QFile with no name.
158*/
159
160QFile::QFile()
161: d(0)
162{
163 init();
164}
165
166/*!
167 Constructs a QFile with a file name \a name.
168
169 \sa setName()
170*/
171
172QFile::QFile( const QString &name )
173 : fn(name), d(0)
174{
175 init();
176}
177
178
179/*!
180 Destroys a QFile. Calls close().
181*/
182
183QFile::~QFile()
184{
185 close();
186 delete d;
187}
188
189
190/*!
191 \internal
192 Initialize internal data.
193*/
194
195void QFile::init()
196{
197 delete d;
198 d = new QFilePrivate;
199 setFlags( IO_Direct );
200 setStatus( IO_Ok );
201 setErrorString( qt_fileerr_unknown );
202 fh = 0;
203 fd = 0;
204 length = 0;
205 ioIndex = 0;
206 ext_f = FALSE; // not an external file handle
207}
208
209
210/*!
211 \fn QString QFile::name() const
212
213 Returns the name set by setName().
214
215 \sa setName(), QFileInfo::fileName()
216*/
217
218/*!
219 Sets the name of the file to \a name. The name can have no path, a
220 relative path or an absolute absolute path.
221
222 Do not call this function if the file has already been opened.
223
224 If the file name has no path or a relative path, the path used
225 will be whatever the application's current directory path is
226 \e{at the time of the open()} call.
227
228 Example:
229 \code
230 QFile file;
231 QDir::setCurrent( "/tmp" );
232 file.setName( "readme.txt" );
233 QDir::setCurrent( "/home" );
234 file.open( IO_ReadOnly ); // opens "/home/readme.txt" under Unix
235 \endcode
236
237 Note that the directory separator "/" works for all operating
238 systems supported by Qt.
239
240 \sa name(), QFileInfo, QDir
241*/
242
243void QFile::setName( const QString &name )
244{
245 if ( isOpen() ) {
246#if defined(QT_CHECK_STATE)
247 qWarning( "QFile::setName: File is open" );
248#endif
249 close();
250 }
251 fn = name;
252}
253
254/*!
255 \overload
256
257 Returns TRUE if this file exists; otherwise returns FALSE.
258
259 \sa name()
260*/
261
262bool QFile::exists() const
263{
264 return qt_file_access( fn, F_OK );
265}
266
267/*!
268 Returns TRUE if the file given by \a fileName exists; otherwise
269 returns FALSE.
270*/
271
272bool QFile::exists( const QString &fileName )
273{
274 return qt_file_access( fileName, F_OK );
275}
276
277
278/*!
279 Removes the file specified by the file name currently set. Returns
280 TRUE if successful; otherwise returns FALSE.
281
282 The file is closed before it is removed.
283*/
284
285bool QFile::remove()
286{
287 close();
288 return remove( fn );
289}
290
291#if defined(Q_OS_MAC) || defined(Q_OS_MSDOS) || defined(Q_OS_WIN32) || defined(Q_OS_OS2)
292# define HAS_TEXT_FILEMODE // has translate/text filemode
293#endif
294#if defined(O_NONBLOCK)
295# define HAS_ASYNC_FILEMODE
296# define OPEN_ASYNC O_NONBLOCK
297#elif defined(O_NDELAY)
298# define HAS_ASYNC_FILEMODE
299# define OPEN_ASYNC O_NDELAY
300#endif
301
302/*!
303 Flushes the file buffer to the disk.
304
305 close() also flushes the file buffer.
306*/
307
308void QFile::flush()
309{
310 if ( isOpen() && fh ) // can only flush open/buffered
311 fflush( fh ); // file
312}
313
314/*! \reimp
315 \fn QIODevice::Offset QFile::at() const
316*/
317
318/*!
319 Returns TRUE if the end of file has been reached; otherwise returns FALSE.
320 If QFile has not been open()'d, then the behavior is undefined.
321
322 \sa size()
323*/
324
325bool QFile::atEnd() const
326{
327 if ( !isOpen() ) {
328#if defined(QT_CHECK_STATE)
329 qWarning( "QFile::atEnd: File is not open" );
330#endif
331 return FALSE;
332 }
333 if ( isDirectAccess() && !isTranslated() ) {
334 if ( at() < length )
335 return FALSE;
336 }
337 return QIODevice::atEnd();
338}
339
340/*!
341 Reads a line of text.
342
343 Reads bytes from the file into the char* \a p, until end-of-line
344 or \a maxlen bytes have been read, whichever occurs first. Returns
345 the number of bytes read, or -1 if there was an error. Any
346 terminating newline is not stripped.
347
348 This function is only efficient for buffered files. Avoid
349 readLine() for files that have been opened with the \c IO_Raw
350 flag.
351
352 \sa readBlock(), QTextStream::readLine()
353*/
354
355Q_LONG QFile::readLine( char *p, Q_ULONG maxlen )
356{
357 if ( maxlen == 0 ) // application bug?
358 return 0;
359#if defined(QT_CHECK_STATE)
360 Q_CHECK_PTR( p );
361 if ( !isOpen() ) { // file not open
362 qWarning( "QFile::readLine: File not open" );
363 return -1;
364 }
365 if ( !isReadable() ) { // reading not permitted
366 qWarning( "QFile::readLine: Read operation not permitted" );
367 return -1;
368 }
369#endif
370 Q_LONG nread; // number of bytes read
371 if ( isRaw() ) { // raw file
372 nread = QIODevice::readLine( p, maxlen );
373 } else { // buffered file
374 p = fgets( p, maxlen, fh );
375 if ( p ) {
376 nread = qstrlen( p );
377 if ( !isSequentialAccess() )
378 ioIndex += nread;
379 } else {
380 nread = -1;
381 setStatus(IO_ReadError);
382 setErrorString( qt_fileerr_read );
383 }
384 }
385 return nread;
386}
387
388
389/*!
390 \overload
391
392 Reads a line of text.
393
394 Reads bytes from the file into string \a s, until end-of-line or
395 \a maxlen bytes have been read, whichever occurs first. Returns
396 the number of bytes read, or -1 if there was an error, e.g. end of
397 file. Any terminating newline is not stripped.
398
399 This function is only efficient for buffered files. Avoid using
400 readLine() for files that have been opened with the \c IO_Raw
401 flag.
402
403 Note that the string is read as plain Latin1 bytes, not Unicode.
404
405 \sa readBlock(), QTextStream::readLine()
406*/
407
408Q_LONG QFile::readLine( QString& s, Q_ULONG maxlen )
409{
410 QByteArray ba(maxlen);
411 Q_LONG l = readLine(ba.data(),maxlen);
412 if ( l >= 0 ) {
413 ba.truncate(l);
414 s = QString(ba);
415 }
416 return l;
417}
418
419
420/*!
421 Reads a single byte/character from the file.
422
423 Returns the byte/character read, or -1 if the end of the file has
424 been reached.
425
426 \sa putch(), ungetch()
427*/
428
429int QFile::getch()
430{
431#if defined(QT_CHECK_STATE)
432 if ( !isOpen() ) { // file not open
433 qWarning( "QFile::getch: File not open" );
434 return EOF;
435 }
436 if ( !isReadable() ) { // reading not permitted
437 qWarning( "QFile::getch: Read operation not permitted" );
438 return EOF;
439 }
440#endif
441
442 int ch;
443
444 if ( !ungetchBuffer.isEmpty() ) {
445 int len = ungetchBuffer.length();
446 ch = ungetchBuffer[ len-1 ];
447 ungetchBuffer.truncate( len - 1 );
448 return ch;
449 }
450
451 if ( isRaw() ) { // raw file (inefficient)
452 char buf[1];
453 ch = readBlock( buf, 1 ) == 1 ? buf[0] : EOF;
454 } else { // buffered file
455 if ( (ch = getc( fh )) != EOF ) {
456 if ( !isSequentialAccess() )
457 ioIndex++;
458 } else {
459 setStatus(IO_ReadError);
460 setErrorString( qt_fileerr_read );
461 }
462 }
463 return ch;
464}
465
466/*!
467 Writes the character \a ch to the file.
468
469 Returns \a ch, or -1 if some error occurred.
470
471 \sa getch(), ungetch()
472*/
473
474int QFile::putch( int ch )
475{
476#if defined(QT_CHECK_STATE)
477 if ( !isOpen() ) { // file not open
478 qWarning( "QFile::putch: File not open" );
479 return EOF;
480 }
481 if ( !isWritable() ) { // writing not permitted
482 qWarning( "QFile::putch: Write operation not permitted" );
483 return EOF;
484 }
485#endif
486 if ( isRaw() ) { // raw file (inefficient)
487 char buf[1];
488 buf[0] = ch;
489 ch = writeBlock( buf, 1 ) == 1 ? ch : EOF;
490 } else { // buffered file
491 if ( (ch = putc( ch, fh )) != EOF ) {
492 if ( !isSequentialAccess() )
493 ioIndex++;
494 if ( ioIndex > length ) // update file length
495 length = ioIndex;
496 } else {
497 setStatus(IO_WriteError);
498 setErrorString( qt_fileerr_write );
499 }
500 }
501 return ch;
502}
503
504/*!
505 Puts the character \a ch back into the file and decrements the
506 index if it is not zero.
507
508 This function is normally called to "undo" a getch() operation.
509
510 Returns \a ch, or -1 if an error occurred.
511
512 \sa getch(), putch()
513*/
514
515int QFile::ungetch( int ch )
516{
517#if defined(QT_CHECK_STATE)
518 if ( !isOpen() ) { // file not open
519 qWarning( "QFile::ungetch: File not open" );
520 return EOF;
521 }
522 if ( !isReadable() ) { // reading not permitted
523 qWarning( "QFile::ungetch: Read operation not permitted" );
524 return EOF;
525 }
526#endif
527 if ( ch == EOF ) // cannot unget EOF
528 return ch;
529
530 if ( isSequentialAccess() && !fh) {
531 // pipe or similar => we cannot ungetch, so do it manually
532 ungetchBuffer += QChar(ch);
533 return ch;
534 }
535
536 if ( isRaw() ) { // raw file (very inefficient)
537 char buf[1];
538 at( ioIndex-1 );
539 buf[0] = ch;
540 if ( writeBlock(buf, 1) == 1 )
541 at ( ioIndex-1 );
542 else
543 ch = EOF;
544 } else { // buffered file
545 if ( (ch = ungetc(ch, fh)) != EOF ) {
546 if ( !isSequentialAccess() )
547 ioIndex--;
548 } else {
549 setStatus( IO_ReadError );
550 setErrorString( qt_fileerr_read );
551 }
552 }
553 return ch;
554}
555
556
557static QCString locale_encoder( const QString &fileName )
558{
559 return fileName.local8Bit();
560}
561
562
563static QFile::EncoderFn encoder = locale_encoder;
564
565/*!
566 When you use QFile, QFileInfo, and QDir to access the file system
567 with Qt, you can use Unicode file names. On Unix, these file names
568 are converted to an 8-bit encoding. If you want to do your own
569 file I/O on Unix, you should convert the file name using this
570 function. On Windows NT/2000, Unicode file names are supported
571 directly in the file system and this function should be avoided.
572 On Windows 95, non-Latin1 locales are not supported.
573
574 By default, this function converts \a fileName to the local 8-bit
575 encoding determined by the user's locale. This is sufficient for
576 file names that the user chooses. File names hard-coded into the
577 application should only use 7-bit ASCII filename characters.
578
579 The conversion scheme can be changed using setEncodingFunction().
580 This might be useful if you wish to give the user an option to
581 store file names in UTF-8, etc., but be aware that such file names
582 would probably then be unrecognizable when seen by other programs.
583
584 \sa decodeName()
585*/
586
587QCString QFile::encodeName( const QString &fileName )
588{
589 return (*encoder)(fileName);
590}
591
592/*!
593 \enum QFile::EncoderFn
594
595 This is used by QFile::setEncodingFunction().
596*/
597
598/*!
599 \nonreentrant
600
601 Sets the function for encoding Unicode file names to \a f. The
602 default encodes in the locale-specific 8-bit encoding.
603
604 \sa encodeName()
605*/
606void QFile::setEncodingFunction( EncoderFn f )
607{
608 encoder = f;
609}
610
611static
612QString locale_decoder( const QCString &localFileName )
613{
614 return QString::fromLocal8Bit(localFileName);
615}
616
617static QFile::DecoderFn decoder = locale_decoder;
618
619/*!
620 This does the reverse of QFile::encodeName() using \a localFileName.
621
622 \sa setDecodingFunction()
623*/
624QString QFile::decodeName( const QCString &localFileName )
625{
626 return (*decoder)(localFileName);
627}
628
629/*!
630 \enum QFile::DecoderFn
631
632 This is used by QFile::setDecodingFunction().
633*/
634
635/*!
636 \nonreentrant
637
638 Sets the function for decoding 8-bit file names to \a f. The
639 default uses the locale-specific 8-bit encoding.
640
641 \sa encodeName(), decodeName()
642*/
643
644void QFile::setDecodingFunction( DecoderFn f )
645{
646 decoder = f;
647}
648
649/*!
650 Returns a human-readable description of the reason of an error that occurred
651 on the device. The error described by the string corresponds to changes of
652 QIODevice::status(). If the status is reset, the error string is also reset.
653
654 The returned strings are not translated with the QObject::tr() or
655 QApplication::translate() functions. They are marked as translatable
656 strings in the "QFile" context. Before you show the string to the user you
657 should translate it first, for example:
658
659 \code
660 QFile f( "address.dat" );
661 if ( !f.open( IO_ReadOnly ) {
662 QMessageBox::critical(
663 this,
664 tr("Open failed"),
665 tr("Could not open file for reading: %1").arg( qApp->translate("QFile",f.errorString()) )
666 );
667 return;
668 }
669 \endcode
670
671 \sa QIODevice::status(), QIODevice::resetStatus(), setErrorString()
672*/
673
674QString QFile::errorString() const
675{
676 if ( status() == IO_Ok )
677 return qt_fileerr_unknown;
678 return d->errorString;
679}
680
681/*!
682 \nonreentrant
683
684 Sets the error string returned by the errorString() function to \a str.
685
686 \sa errorString(), QIODevice::status()
687*/
688
689void QFile::setErrorString( const QString& str )
690{
691 d->errorString = str;
692}
693
694void QFile::setErrorStringErrno( int errnum )
695{
696 switch ( errnum ) {
697 case EACCES:
698 d->errorString = QFILEERR_EACCES;
699 break;
700 case EMFILE:
701 d->errorString = QFILEERR_EMFILE;
702 break;
703 case ENOENT:
704 d->errorString = QFILEERR_ENOENT;
705 break;
706 case ENOSPC:
707 d->errorString = QFILEERR_ENOSPC;
708 break;
709 default:
710#ifndef Q_OS_TEMP
711 d->errorString = QString::fromLocal8Bit( strerror( errnum ) );
712#else
713 {
714 unsigned short *string;
715 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
716 NULL,
717 errnum,
718 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
719 (LPTSTR)&string,
720 0,
721 NULL );
722 d->errorString = QString::fromUcs2( string );
723 LocalFree( (HLOCAL)string );
724 }
725#endif
726 break;
727 }
728}
Note: See TracBrowser for help on using the repository browser.