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