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