|
1 /**************************************************************************** |
|
2 ** |
|
3 ** |
|
4 ** Implementation of QFileInfo class |
|
5 ** |
|
6 ** Created : 950628 |
|
7 ** |
|
8 ** Copyright (C) 1992-2000 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 for Unix/X11 or for Qt/Embedded may use this file in accordance |
|
23 ** with the Qt Commercial License 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 "qglobal.h" |
|
39 |
|
40 #include "qfile.h" |
|
41 #include "qfiledefs_p.h" |
|
42 |
|
43 #if (defined(_OS_MAC_) && (!defined(_OS_UNIX_))) || defined(_OS_MSDOS_) || defined(_OS_WIN32_) || defined(_OS_OS2_) || defined(_OS_CYGWIN_) |
|
44 # define HAS_TEXT_FILEMODE // has translate/text filemode |
|
45 #endif |
|
46 #if defined(O_NONBLOCK) |
|
47 # define HAS_ASYNC_FILEMODE |
|
48 # define OPEN_ASYNC O_NONBLOCK |
|
49 #elif defined(O_NDELAY) |
|
50 # define HAS_ASYNC_FILEMODE |
|
51 # define OPEN_ASYNC O_NDELAY |
|
52 #endif |
|
53 |
|
54 bool qt_file_access( const QString& fn, int t ) |
|
55 { |
|
56 if ( fn.isEmpty() ) |
|
57 return FALSE; |
|
58 return ACCESS( QFile::encodeName(fn), t ) == 0; |
|
59 } |
|
60 |
|
61 /*! |
|
62 Removes the file \a fileName. |
|
63 Returns TRUE if successful, otherwise FALSE. |
|
64 */ |
|
65 |
|
66 bool QFile::remove( const QString &fileName ) |
|
67 { |
|
68 if ( fileName.isEmpty() ) { |
|
69 #if defined(CHECK_NULL) |
|
70 qWarning( "QFile::remove: Empty or null file name" ); |
|
71 #endif |
|
72 return FALSE; |
|
73 } |
|
74 return unlink( QFile::encodeName(fileName) ) == 0; |
|
75 // unlink more common in UNIX |
|
76 } |
|
77 |
|
78 #if defined(O_NONBLOCK) |
|
79 # define HAS_ASYNC_FILEMODE |
|
80 # define OPEN_ASYNC O_NONBLOCK |
|
81 #elif defined(O_NDELAY) |
|
82 # define HAS_ASYNC_FILEMODE |
|
83 # define OPEN_ASYNC O_NDELAY |
|
84 #endif |
|
85 |
|
86 /*! |
|
87 Opens the file specified by the file name currently set, using the mode \e m. |
|
88 Returns TRUE if successful, otherwise FALSE. |
|
89 |
|
90 The mode parameter \e m must be a combination of the following flags: |
|
91 <ul> |
|
92 <li>\c IO_Raw specified raw (non-buffered) file access. |
|
93 <li>\c IO_ReadOnly opens the file in read-only mode. |
|
94 <li>\c IO_WriteOnly opens the file in write-only mode (and truncates). |
|
95 <li>\c IO_ReadWrite opens the file in read/write mode, equivalent to |
|
96 \c (IO_ReadOnly|IO_WriteOnly). |
|
97 <li>\c IO_Append opens the file in append mode. This mode is very useful |
|
98 when you want to write something to a log file. The file index is set to |
|
99 the end of the file. Note that the result is undefined if you position the |
|
100 file index manually using at() in append mode. |
|
101 <li>\c IO_Truncate truncates the file. |
|
102 <li>\c IO_Translate enables carriage returns and linefeed translation |
|
103 for text files under MS-DOS, Windows and OS/2. |
|
104 </ul> |
|
105 |
|
106 The raw access mode is best when I/O is block-operated using 4kB block size |
|
107 or greater. Buffered access works better when reading small portions of |
|
108 data at a time. |
|
109 |
|
110 <strong>Important:</strong> When working with buffered files, data may |
|
111 not be written to the file at once. Call \link flush() flush\endlink |
|
112 to make sure the data is really written. |
|
113 |
|
114 \warning We have experienced problems with some C libraries when a buffered |
|
115 file is opened for both reading and writing. If a read operation takes place |
|
116 immediately after a write operation, the read buffer contains garbage data. |
|
117 Worse, the same garbage is written to the file. Calling flush() before |
|
118 readBlock() solved this problem. |
|
119 |
|
120 If the file does not exist and \c IO_WriteOnly or \c IO_ReadWrite is |
|
121 specified, it is created. |
|
122 |
|
123 Example: |
|
124 \code |
|
125 QFile f1( "/tmp/data.bin" ); |
|
126 QFile f2( "readme.txt" ); |
|
127 f1.open( IO_Raw | IO_ReadWrite | IO_Append ); |
|
128 f2.open( IO_ReadOnly | IO_Translate ); |
|
129 \endcode |
|
130 |
|
131 \sa name(), close(), isOpen(), flush() |
|
132 */ |
|
133 |
|
134 bool QFile::open( int m ) |
|
135 { |
|
136 if ( isOpen() ) { // file already open |
|
137 #if defined(CHECK_STATE) |
|
138 qWarning( "QFile::open: File already open" ); |
|
139 #endif |
|
140 return FALSE; |
|
141 } |
|
142 if ( fn.isNull() ) { // no file name defined |
|
143 #if defined(CHECK_NULL) |
|
144 qWarning( "QFile::open: No file name specified" ); |
|
145 #endif |
|
146 return FALSE; |
|
147 } |
|
148 init(); // reset params |
|
149 setMode( m ); |
|
150 if ( !(isReadable() || isWritable()) ) { |
|
151 #if defined(CHECK_RANGE) |
|
152 qWarning( "QFile::open: File access not specified" ); |
|
153 #endif |
|
154 return FALSE; |
|
155 } |
|
156 bool ok = TRUE; |
|
157 STATBUF st; |
|
158 if ( isRaw() ) { // raw file I/O |
|
159 int oflags = OPEN_RDONLY; |
|
160 if ( isReadable() && isWritable() ) |
|
161 oflags = OPEN_RDWR; |
|
162 else if ( isWritable() ) |
|
163 oflags = OPEN_WRONLY; |
|
164 if ( flags() & IO_Append ) { // append to end of file? |
|
165 if ( flags() & IO_Truncate ) |
|
166 oflags |= (OPEN_CREAT | OPEN_TRUNC); |
|
167 else |
|
168 oflags |= (OPEN_APPEND | OPEN_CREAT); |
|
169 setFlags( flags() | IO_WriteOnly ); // append implies write |
|
170 } else if ( isWritable() ) { // create/trunc if writable |
|
171 if ( flags() & IO_Truncate ) |
|
172 oflags |= (OPEN_CREAT | OPEN_TRUNC); |
|
173 else |
|
174 oflags |= OPEN_CREAT; |
|
175 } |
|
176 #if defined(HAS_TEXT_FILEMODE) |
|
177 if ( isTranslated() ) |
|
178 #ifdef __CYGWIN__ |
|
179 /* Do nothing, allowing the Cygwin mount mode to take effect. */; |
|
180 #else |
|
181 oflags |= OPEN_TEXT; |
|
182 #endif |
|
183 else |
|
184 oflags |= OPEN_BINARY; |
|
185 #endif |
|
186 #if defined(HAS_ASYNC_FILEMODE) |
|
187 if ( isAsynchronous() ) |
|
188 oflags |= OPEN_ASYNC; |
|
189 #endif |
|
190 fd = OPEN( QFile::encodeName(fn), oflags, 0666 ); |
|
191 |
|
192 if ( fd != -1 ) { // open successful |
|
193 FSTAT( fd, &st ); // get the stat for later usage |
|
194 } else { |
|
195 ok = FALSE; |
|
196 } |
|
197 } else { // buffered file I/O |
|
198 QCString perm; |
|
199 char perm2[4]; |
|
200 bool try_create = FALSE; |
|
201 if ( flags() & IO_Append ) { // append to end of file? |
|
202 setFlags( flags() | IO_WriteOnly ); // append implies write |
|
203 perm = isReadable() ? "a+" : "a"; |
|
204 } else { |
|
205 if ( isReadWrite() ) { |
|
206 if ( flags() & IO_Truncate ) { |
|
207 perm = "w+"; |
|
208 } else { |
|
209 perm = "r+"; |
|
210 try_create = TRUE; // try to create if not exists |
|
211 } |
|
212 } else if ( isReadable() ) { |
|
213 perm = "r"; |
|
214 } else if ( isWritable() ) { |
|
215 perm = "w"; |
|
216 } |
|
217 } |
|
218 qstrcpy( perm2, perm ); |
|
219 #if defined(HAS_TEXT_FILEMODE) |
|
220 if ( isTranslated() ) |
|
221 #ifdef __CYGWIN__ |
|
222 /* Do nothing, allowing the Cygwin mount mode to take effect. */; |
|
223 #else |
|
224 strcat( perm2, "t" ); |
|
225 #endif |
|
226 else |
|
227 strcat( perm2, "b" ); |
|
228 #endif |
|
229 while (1) { // At most twice |
|
230 |
|
231 fh = fopen( QFile::encodeName(fn), perm2 ); |
|
232 |
|
233 if ( !fh && try_create ) { |
|
234 perm2[0] = 'w'; // try "w+" instead of "r+" |
|
235 try_create = FALSE; |
|
236 } else { |
|
237 break; |
|
238 } |
|
239 } |
|
240 if ( fh ) { |
|
241 FSTAT( FILENO(fh), &st ); // get the stat for later usage |
|
242 } else { |
|
243 ok = FALSE; |
|
244 } |
|
245 } |
|
246 if ( ok ) { |
|
247 setState( IO_Open ); |
|
248 // on successful open the file stat was got; now test what type |
|
249 // of file we have |
|
250 if ( (st.st_mode & STAT_MASK) != STAT_REG ) { |
|
251 // non-seekable |
|
252 setType( IO_Sequential ); |
|
253 length = INT_MAX; |
|
254 ioIndex = (flags() & IO_Append) == 0 ? 0 : length; |
|
255 } else { |
|
256 length = (int)st.st_size; |
|
257 ioIndex = (flags() & IO_Append) == 0 ? 0 : length; |
|
258 if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) { |
|
259 // try if you can read from it (if you can, it's a sequential |
|
260 // device; e.g. a file in the /proc filesystem) |
|
261 int c = getch(); |
|
262 if ( c != -1 ) { |
|
263 ungetch(c); |
|
264 setType( IO_Sequential ); |
|
265 length = INT_MAX; |
|
266 } |
|
267 } |
|
268 } |
|
269 } else { |
|
270 init(); |
|
271 if ( errno == EMFILE ) // no more file handles/descrs |
|
272 setStatus( IO_ResourceError ); |
|
273 else |
|
274 setStatus( IO_OpenError ); |
|
275 } |
|
276 return ok; |
|
277 } |
|
278 |
|
279 /*! |
|
280 Opens a file in the mode \e m using an existing file handle \e f. |
|
281 Returns TRUE if successful, otherwise FALSE. |
|
282 |
|
283 Example: |
|
284 \code |
|
285 #include <stdio.h> |
|
286 |
|
287 void printError( const char* msg ) |
|
288 { |
|
289 QFile f; |
|
290 f.open( IO_WriteOnly, stderr ); |
|
291 f.writeBlock( msg, qstrlen(msg) ); // write to stderr |
|
292 f.close(); |
|
293 } |
|
294 \endcode |
|
295 |
|
296 When a QFile is opened using this function, close() does not actually |
|
297 close the file, only flushes it. |
|
298 |
|
299 \warning If \e f is \c stdin, \c stdout, \c stderr, you may not |
|
300 be able to seek. See QIODevice::isSequentialAccess() for more |
|
301 information. |
|
302 |
|
303 \sa close() |
|
304 */ |
|
305 |
|
306 bool QFile::open( int m, FILE *f ) |
|
307 { |
|
308 if ( isOpen() ) { |
|
309 #if defined(CHECK_RANGE) |
|
310 qWarning( "QFile::open: File already open" ); |
|
311 #endif |
|
312 return FALSE; |
|
313 } |
|
314 init(); |
|
315 setMode( m &~IO_Raw ); |
|
316 setState( IO_Open ); |
|
317 fh = f; |
|
318 ext_f = TRUE; |
|
319 STATBUF st; |
|
320 FSTAT( FILENO(fh), &st ); |
|
321 ioIndex = (int)ftell( fh ); |
|
322 if ( (st.st_mode & STAT_MASK) != STAT_REG || f == stdin ) { //stdin is non seekable |
|
323 // non-seekable |
|
324 setType( IO_Sequential ); |
|
325 length = INT_MAX; |
|
326 } else { |
|
327 length = (int)st.st_size; |
|
328 if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) { |
|
329 // try if you can read from it (if you can, it's a sequential |
|
330 // device; e.g. a file in the /proc filesystem) |
|
331 int c = getch(); |
|
332 if ( c != -1 ) { |
|
333 ungetch(c); |
|
334 setType( IO_Sequential ); |
|
335 length = INT_MAX; |
|
336 } |
|
337 } |
|
338 } |
|
339 return TRUE; |
|
340 } |
|
341 |
|
342 /*! |
|
343 Opens a file in the mode \e m using an existing file descriptor \e f. |
|
344 Returns TRUE if successful, otherwise FALSE. |
|
345 |
|
346 When a QFile is opened using this function, close() does not actually |
|
347 close the file. |
|
348 |
|
349 \warning If \e f is one of 0 (stdin), 1 (stdout) or 2 (stderr), you may not |
|
350 be able to seek. size() is set to \c INT_MAX (in limits.h). |
|
351 |
|
352 \sa close() |
|
353 */ |
|
354 |
|
355 |
|
356 bool QFile::open( int m, int f ) |
|
357 { |
|
358 if ( isOpen() ) { |
|
359 #if defined(CHECK_RANGE) |
|
360 qWarning( "QFile::open: File already open" ); |
|
361 #endif |
|
362 return FALSE; |
|
363 } |
|
364 init(); |
|
365 setMode( m |IO_Raw ); |
|
366 setState( IO_Open ); |
|
367 fd = f; |
|
368 ext_f = TRUE; |
|
369 STATBUF st; |
|
370 FSTAT( fd, &st ); |
|
371 ioIndex = (int)LSEEK(fd, 0, SEEK_CUR); |
|
372 if ( (st.st_mode & STAT_MASK) != STAT_REG || f == 0 ) { // stdin is not seekable... |
|
373 // non-seekable |
|
374 setType( IO_Sequential ); |
|
375 length = INT_MAX; |
|
376 } else { |
|
377 length = (int)st.st_size; |
|
378 if ( length == 0 && isReadable() ) { |
|
379 // try if you can read from it (if you can, it's a sequential |
|
380 // device; e.g. a file in the /proc filesystem) |
|
381 int c = getch(); |
|
382 if ( c != -1 ) { |
|
383 ungetch(c); |
|
384 setType( IO_Sequential ); |
|
385 length = INT_MAX; |
|
386 } |
|
387 resetStatus(); |
|
388 } |
|
389 } |
|
390 return TRUE; |
|
391 } |
|
392 |
|
393 /*! |
|
394 Returns the file size. |
|
395 \sa at() |
|
396 */ |
|
397 |
|
398 uint QFile::size() const |
|
399 { |
|
400 STATBUF st; |
|
401 if ( isOpen() ) { |
|
402 FSTAT( fh ? FILENO(fh) : fd, &st ); |
|
403 } else { |
|
404 STAT( QFile::encodeName(fn), &st ); |
|
405 } |
|
406 return st.st_size; |
|
407 } |
|
408 |
|
409 /*! |
|
410 \fn int QFile::at() const |
|
411 Returns the file index. |
|
412 \sa size() |
|
413 */ |
|
414 |
|
415 /*! |
|
416 Sets the file index to \e pos. Returns TRUE if successful, otherwise FALSE. |
|
417 |
|
418 Example: |
|
419 \code |
|
420 QFile f( "data.bin" ); |
|
421 f.open( IO_ReadOnly ); // index set to 0 |
|
422 f.at( 100 ); // set index to 100 |
|
423 f.at( f.at()+50 ); // set index to 150 |
|
424 f.at( f.size()-80 ); // set index to 80 before EOF |
|
425 f.close(); |
|
426 \endcode |
|
427 |
|
428 \warning The result is undefined if the file was \link open() opened\endlink |
|
429 using the \c IO_Append specifier. |
|
430 |
|
431 \sa size(), open() |
|
432 */ |
|
433 |
|
434 bool QFile::at( int pos ) |
|
435 { |
|
436 if ( !isOpen() ) { |
|
437 #if defined(CHECK_STATE) |
|
438 qWarning( "QFile::at: File is not open" ); |
|
439 #endif |
|
440 return FALSE; |
|
441 } |
|
442 bool ok; |
|
443 if ( isRaw() ) { // raw file |
|
444 pos = (int)LSEEK(fd, pos, SEEK_SET); |
|
445 ok = pos != -1; |
|
446 } else { // buffered file |
|
447 ok = fseek(fh, pos, SEEK_SET) == 0; |
|
448 } |
|
449 if ( ok ) |
|
450 ioIndex = pos; |
|
451 #if defined(CHECK_RANGE) |
|
452 else |
|
453 qWarning( "QFile::at: Cannot set file position %d", pos ); |
|
454 #endif |
|
455 return ok; |
|
456 } |
|
457 |
|
458 /*! |
|
459 Reads at most \e len bytes from the file into \e p and returns the |
|
460 number of bytes actually read. |
|
461 |
|
462 Returns -1 if a serious error occurred. |
|
463 |
|
464 \warning We have experienced problems with some C libraries when a buffered |
|
465 file is opened for both reading and writing. If a read operation takes place |
|
466 immediately after a write operation, the read buffer contains garbage data. |
|
467 Worse, the same garbage is written to the file. Calling flush() before |
|
468 readBlock() solved this problem. |
|
469 |
|
470 \sa writeBlock() |
|
471 */ |
|
472 |
|
473 int QFile::readBlock( char *p, uint len ) |
|
474 { |
|
475 #if defined(CHECK_NULL) |
|
476 if ( !p ) |
|
477 qWarning( "QFile::readBlock: Null pointer error" ); |
|
478 #endif |
|
479 #if defined(CHECK_STATE) |
|
480 if ( !isOpen() ) { // file not open |
|
481 qWarning( "QFile::readBlock: File not open" ); |
|
482 return -1; |
|
483 } |
|
484 if ( !isReadable() ) { // reading not permitted |
|
485 qWarning( "QFile::readBlock: Read operation not permitted" ); |
|
486 return -1; |
|
487 } |
|
488 #endif |
|
489 int nread = 0; // number of bytes read |
|
490 if ( !ungetchBuffer.isEmpty() ) { |
|
491 // need to add these to the returned string. |
|
492 int l = ungetchBuffer.length(); |
|
493 while( nread < l ) { |
|
494 *p = ungetchBuffer[ l - nread - 1 ]; |
|
495 p++; |
|
496 nread++; |
|
497 } |
|
498 ungetchBuffer.truncate( l - nread ); |
|
499 } |
|
500 |
|
501 if ( nread < (int)len ) { |
|
502 if ( isRaw() ) { // raw file |
|
503 nread += READ( fd, p, len-nread ); |
|
504 if ( len && nread <= 0 ) { |
|
505 nread = 0; |
|
506 setStatus(IO_ReadError); |
|
507 } |
|
508 } else { // buffered file |
|
509 nread += fread( p, 1, len-nread, fh ); |
|
510 if ( (uint)nread != len ) { |
|
511 if ( ferror( fh ) || nread==0 ) |
|
512 setStatus(IO_ReadError); |
|
513 } |
|
514 } |
|
515 } |
|
516 ioIndex += nread; |
|
517 return nread; |
|
518 } |
|
519 |
|
520 /*! \overload int writeBlock( const QByteArray& data ) |
|
521 */ |
|
522 |
|
523 /*! \reimp |
|
524 |
|
525 Writes \e len bytes from \e p to the file and returns the number of |
|
526 bytes actually written. |
|
527 |
|
528 Returns -1 if a serious error occurred. |
|
529 |
|
530 \warning When working with buffered files, data may not be written |
|
531 to the file at once. Call flush() to make sure the data is really |
|
532 written. |
|
533 |
|
534 \sa readBlock() |
|
535 */ |
|
536 |
|
537 int QFile::writeBlock( const char *p, uint len ) |
|
538 { |
|
539 #if defined(CHECK_NULL) |
|
540 if ( p == 0 && len != 0 ) |
|
541 qWarning( "QFile::writeBlock: Null pointer error" ); |
|
542 #endif |
|
543 #if defined(CHECK_STATE) |
|
544 if ( !isOpen() ) { // file not open |
|
545 qWarning( "QFile::writeBlock: File not open" ); |
|
546 return -1; |
|
547 } |
|
548 if ( !isWritable() ) { // writing not permitted |
|
549 qWarning( "QFile::writeBlock: Write operation not permitted" ); |
|
550 return -1; |
|
551 } |
|
552 #endif |
|
553 int nwritten; // number of bytes written |
|
554 if ( isRaw() ) // raw file |
|
555 nwritten = WRITE( fd, p, len ); |
|
556 else // buffered file |
|
557 nwritten = fwrite( p, 1, len, fh ); |
|
558 if ( nwritten != (int)len ) { // write error |
|
559 if ( errno == ENOSPC ) // disk is full |
|
560 setStatus( IO_ResourceError ); |
|
561 else |
|
562 setStatus( IO_WriteError ); |
|
563 if ( isRaw() ) // recalc file position |
|
564 ioIndex = (int)LSEEK( fd, 0, SEEK_CUR ); |
|
565 else |
|
566 ioIndex = fseek( fh, 0, SEEK_CUR ); |
|
567 } else { |
|
568 ioIndex += nwritten; |
|
569 } |
|
570 if ( ioIndex > length ) // update file length |
|
571 length = ioIndex; |
|
572 return nwritten; |
|
573 } |
|
574 |
|
575 /*! |
|
576 Returns the file handle of the file. |
|
577 |
|
578 This is a small positive integer, suitable for use with C library |
|
579 functions such as fdopen() and fcntl(), as well as with QSocketNotifier. |
|
580 |
|
581 If the file is not open or there is an error, handle() returns -1. |
|
582 |
|
583 \sa QSocketNotifier |
|
584 */ |
|
585 |
|
586 int QFile::handle() const |
|
587 { |
|
588 if ( !isOpen() ) |
|
589 return -1; |
|
590 else if ( fh ) |
|
591 return FILENO( fh ); |
|
592 else |
|
593 return fd; |
|
594 } |
|
595 |
|
596 /*! |
|
597 Closes an open file. |
|
598 |
|
599 The file is not closed if it was opened with an existing file handle. |
|
600 If the existing file handle is a \c FILE*, the file is flushed. |
|
601 If the existing file handle is an \c int file descriptor, nothing |
|
602 is done to the file. |
|
603 |
|
604 Some "write-behind" filesystems may report an unspecified error on |
|
605 closing the file. These errors only indicate that something may |
|
606 have gone wrong since the previous open(). In such a case status() |
|
607 reports IO_UnspecifiedError after close(), otherwise IO_Ok. |
|
608 |
|
609 \sa open(), flush() |
|
610 */ |
|
611 |
|
612 |
|
613 void QFile::close() |
|
614 { |
|
615 bool ok = FALSE; |
|
616 if ( isOpen() ) { // file is not open |
|
617 if ( fh ) { // buffered file |
|
618 if ( ext_f ) |
|
619 ok = fflush( fh ) != -1; // flush instead of closing |
|
620 else |
|
621 ok = fclose( fh ) != -1; |
|
622 } else { // raw file |
|
623 if ( ext_f ) |
|
624 ok = TRUE; // cannot close |
|
625 else |
|
626 ok = CLOSE( fd ) != -1; |
|
627 } |
|
628 init(); // restore internal state |
|
629 } |
|
630 if (!ok) |
|
631 setStatus (IO_UnspecifiedError); |
|
632 |
|
633 return; |
|
634 } |
|
635 |
|
636 int64 QFile::pos() const |
|
637 { |
|
638 if (isOpen()) |
|
639 { |
|
640 // TODO: support 64 bit size |
|
641 return ftell( fh ); |
|
642 } |
|
643 return -1; |
|
644 } |
|
645 |
|
646 int64 QFile::toEnd() |
|
647 { |
|
648 if (isOpen()) |
|
649 { |
|
650 // TODO: support 64 bit size |
|
651 if (fseek( fh, 0, SEEK_END )!=-1) |
|
652 { |
|
653 return ftell( fh ); |
|
654 } |
|
655 } |
|
656 return -1; |
|
657 } |
|
658 |
|
659 bool QFile::seek( int64 pos ) |
|
660 { |
|
661 if (isOpen()) |
|
662 { |
|
663 // TODO: support 64 bit size |
|
664 return fseek( fh, pos, SEEK_SET )!=-1; |
|
665 } |
|
666 return FALSE; |
|
667 } |
|
668 |