00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "qplatformdefs.h"
00039
00040
00041 static inline int qt_open(const char *pathname, int flags, mode_t mode)
00042 { return ::open(pathname, flags, mode); }
00043 #if defined(open)
00044 # undef open
00045 #endif
00046
00047
00048 #if defined(truncate)
00049 # undef truncate
00050 #endif
00051
00052 #include "qfile.h"
00053 #include <errno.h>
00054 #include <limits.h>
00055
00056
00057 bool qt_file_access( const QString& fn, int t )
00058 {
00059 if ( fn.isEmpty() )
00060 return FALSE;
00061 return ::access( QFile::encodeName(fn), t ) == 0;
00062 }
00063
00070 bool QFile::remove( const QString &fileName )
00071 {
00072 if ( fileName.isEmpty() ) {
00073 #if defined(QT_CHECK_NULL)
00074 qWarning( "QFile::remove: Empty or null file name" );
00075 #endif
00076 return FALSE;
00077 }
00078 return unlink( QFile::encodeName(fileName) ) == 0;
00079 }
00080
00081 #if defined(O_NONBLOCK)
00082 # define HAS_ASYNC_FILEMODE
00083 # define OPEN_ASYNC O_NONBLOCK
00084 #elif defined(O_NDELAY)
00085 # define HAS_ASYNC_FILEMODE
00086 # define OPEN_ASYNC O_NDELAY
00087 #endif
00088
00163 bool QFile::open( int m )
00164 {
00165 if ( isOpen() ) {
00166 #if defined(QT_CHECK_STATE)
00167 qWarning( "QFile::open: File already open" );
00168 #endif
00169 return FALSE;
00170 }
00171 if ( fn.isNull() ) {
00172 #if defined(QT_CHECK_NULL)
00173 qWarning( "QFile::open: No file name specified" );
00174 #endif
00175 return FALSE;
00176 }
00177 init();
00178 setMode( m );
00179 if ( !(isReadable() || isWritable()) ) {
00180 #if defined(QT_CHECK_RANGE)
00181 qWarning( "QFile::open: File access not specified" );
00182 #endif
00183 return FALSE;
00184 }
00185 bool ok = TRUE;
00186 struct stat st;
00187 if ( isRaw() ) {
00188 int oflags = O_RDONLY;
00189 if ( isReadable() && isWritable() )
00190 oflags = O_RDWR;
00191 else if ( isWritable() )
00192 oflags = O_WRONLY;
00193 if ( flags() & IO_Append ) {
00194 if ( flags() & IO_Truncate )
00195 oflags |= (O_CREAT | O_TRUNC);
00196 else
00197 oflags |= (O_APPEND | O_CREAT);
00198 setFlags( flags() | IO_WriteOnly );
00199 } else if ( isWritable() ) {
00200 if ( flags() & IO_Truncate )
00201 oflags |= (O_CREAT | O_TRUNC);
00202 else
00203 oflags |= O_CREAT;
00204 }
00205 #if defined(HAS_TEXT_FILEMODE)
00206 if ( isTranslated() )
00207 oflags |= OPEN_TEXT;
00208 else
00209 oflags |= OPEN_BINARY;
00210 #endif
00211 #if defined(HAS_ASYNC_FILEMODE)
00212 if ( isAsynchronous() )
00213 oflags |= OPEN_ASYNC;
00214 #endif
00215 fd = qt_open( QFile::encodeName(fn), oflags, 0666 );
00216
00217 if ( fd != -1 ) {
00218 ::fstat( fd, &st );
00219 } else {
00220 ok = FALSE;
00221 }
00222 } else {
00223 QCString perm;
00224 char perm2[4];
00225 bool try_create = FALSE;
00226 if ( flags() & IO_Append ) {
00227 setFlags( flags() | IO_WriteOnly );
00228 perm = isReadable() ? "a+" : "a";
00229 } else {
00230 if ( isReadWrite() ) {
00231 if ( flags() & IO_Truncate ) {
00232 perm = "w+";
00233 } else {
00234 perm = "r+";
00235 try_create = TRUE;
00236 }
00237 } else if ( isReadable() ) {
00238 perm = "r";
00239 } else if ( isWritable() ) {
00240 perm = "w";
00241 }
00242 }
00243 qstrcpy( perm2, perm );
00244 #if defined(HAS_TEXT_FILEMODE)
00245 if ( isTranslated() )
00246 strcat( perm2, "t" );
00247 else
00248 strcat( perm2, "b" );
00249 #endif
00250 for (;;) {
00251
00252 fh = fopen( QFile::encodeName(fn), perm2 );
00253
00254 if ( !fh && try_create ) {
00255 perm2[0] = 'w';
00256 try_create = FALSE;
00257 } else {
00258 break;
00259 }
00260 }
00261 if ( fh ) {
00262 ::fstat( fileno(fh), &st );
00263 } else {
00264 ok = FALSE;
00265 }
00266 }
00267 if ( ok ) {
00268 setState( IO_Open );
00269
00270
00271 if ( (st.st_mode & S_IFMT) != S_IFREG ) {
00272
00273 setType( IO_Sequential );
00274 length = INT_MAX;
00275 ioIndex = 0;
00276 } else {
00277 length = (Offset)st.st_size;
00278 ioIndex = (flags() & IO_Append) == 0 ? 0 : length;
00279 if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) {
00280
00281
00282 int c = getch();
00283 if ( c != -1 ) {
00284 ungetch(c);
00285 setType( IO_Sequential );
00286 length = INT_MAX;
00287 ioIndex = 0;
00288 }
00289 }
00290 }
00291 } else {
00292 init();
00293 if ( errno == EMFILE )
00294 setStatus( IO_ResourceError );
00295 else
00296 setStatus( IO_OpenError );
00297 }
00298 return ok;
00299 }
00300
00329 bool QFile::open( int m, FILE *f )
00330 {
00331 if ( isOpen() ) {
00332 #if defined(QT_CHECK_RANGE)
00333 qWarning( "QFile::open: File already open" );
00334 #endif
00335 return FALSE;
00336 }
00337 init();
00338 setMode( m &~IO_Raw );
00339 setState( IO_Open );
00340 fh = f;
00341 ext_f = TRUE;
00342 struct stat st;
00343 ::fstat( fileno(fh), &st );
00344 #if defined(QT_LARGEFILE_SUPPORT)
00345 ioIndex = (Offset)ftello( fh );
00346 #else
00347 ioIndex = (Offset)ftell( fh );
00348 #endif
00349 if ( (st.st_mode & S_IFMT) != S_IFREG || f == stdin ) {
00350
00351 setType( IO_Sequential );
00352 length = INT_MAX;
00353 ioIndex = 0;
00354 } else {
00355 length = (Offset)st.st_size;
00356 if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) {
00357
00358
00359 int c = getch();
00360 if ( c != -1 ) {
00361 ungetch(c);
00362 setType( IO_Sequential );
00363 length = INT_MAX;
00364 ioIndex = 0;
00365 }
00366 }
00367 }
00368 return TRUE;
00369 }
00370
00391 bool QFile::open( int m, int f )
00392 {
00393 if ( isOpen() ) {
00394 #if defined(QT_CHECK_RANGE)
00395 qWarning( "QFile::open: File already open" );
00396 #endif
00397 return FALSE;
00398 }
00399 init();
00400 setMode( m |IO_Raw );
00401 setState( IO_Open );
00402 fd = f;
00403 ext_f = TRUE;
00404 struct stat st;
00405 ::fstat( fd, &st );
00406 ioIndex = (Offset)::lseek(fd, 0, SEEK_CUR);
00407 if ( (st.st_mode & S_IFMT) != S_IFREG || f == 0 ) {
00408
00409 setType( IO_Sequential );
00410 length = INT_MAX;
00411 ioIndex = 0;
00412 } else {
00413 length = (Offset)st.st_size;
00414 if ( length == 0 && isReadable() ) {
00415
00416
00417 int c = getch();
00418 if ( c != -1 ) {
00419 ungetch(c);
00420 setType( IO_Sequential );
00421 length = INT_MAX;
00422 ioIndex = 0;
00423 }
00424 resetStatus();
00425 }
00426 }
00427 return TRUE;
00428 }
00429
00435 QIODevice::Offset QFile::size() const
00436 {
00437 struct stat st;
00438 int ret = 0;
00439 if ( isOpen() ) {
00440 ret = ::fstat( fh ? fileno(fh) : fd, &st );
00441 } else {
00442 ret = ::stat( QFile::encodeName(fn), &st );
00443 }
00444 if ( ret == -1 )
00445 return 0;
00446 #if defined(QT_LARGEFILE_SUPPORT) && !defined(QT_ABI_64BITOFFSET)
00447 return (uint)st.st_size > UINT_MAX ? UINT_MAX : (QIODevice::Offset)st.st_size;
00448 #else
00449 return st.st_size;
00450 #endif
00451 }
00452
00453
00478 bool QFile::at( Offset pos )
00479 {
00480 if ( !isOpen() ) {
00481 #if defined(QT_CHECK_STATE)
00482 qWarning( "QFile::at: File is not open" );
00483 #endif
00484 return FALSE;
00485 }
00486 if ( isSequentialAccess() )
00487 return FALSE;
00488 bool ok;
00489 if ( isRaw() ) {
00490 off_t l = ::lseek( fd, pos, SEEK_SET );
00491 ok = ( l != -1 );
00492 pos = (Offset)l;
00493 } else {
00494 #if defined(QT_LARGEFILE_SUPPORT)
00495 ok = ( ::fseeko(fh, pos, SEEK_SET) == 0 );
00496 #else
00497 ok = ( ::fseek(fh, pos, SEEK_SET) == 0 );
00498 #endif
00499 }
00500 if ( ok )
00501 ioIndex = pos;
00502 #if defined(QT_CHECK_RANGE)
00503 else
00504 #if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET)
00505 qWarning( "QFile::at: Cannot set file position %llu", pos );
00506 #else
00507 qWarning( "QFile::at: Cannot set file position %lu", pos );
00508 #endif
00509 #endif
00510 return ok;
00511 }
00512
00523 Q_LONG QFile::readBlock( char *p, Q_ULONG len )
00524 {
00525 #if defined(QT_CHECK_NULL)
00526 if ( !p )
00527 qWarning( "QFile::readBlock: Null pointer error" );
00528 #endif
00529 #if defined(QT_CHECK_STATE)
00530 if ( !isOpen() ) {
00531 qWarning( "QFile::readBlock: File not open" );
00532 return -1;
00533 }
00534 if ( !isReadable() ) {
00535 qWarning( "QFile::readBlock: Read operation not permitted" );
00536 return -1;
00537 }
00538 #endif
00539 Q_ULONG nread = 0;
00540 if ( !ungetchBuffer.isEmpty() ) {
00541
00542 uint l = ungetchBuffer.length();
00543 while( nread < l ) {
00544 *p = ungetchBuffer.at( l - nread - 1 );
00545 p++;
00546 nread++;
00547 }
00548 ungetchBuffer.truncate( l - nread );
00549 }
00550
00551 if ( nread < len ) {
00552 if ( isRaw() ) {
00553 nread += ::read( fd, p, len-nread );
00554 if ( len && nread <= 0 ) {
00555 nread = 0;
00556 setStatus(IO_ReadError);
00557 }
00558 } else {
00559 nread += fread( p, 1, len-nread, fh );
00560 if ( (uint)nread != len ) {
00561 if ( ferror( fh ) || nread==0 )
00562 setStatus(IO_ReadError);
00563 }
00564 }
00565 }
00566 if ( !isSequentialAccess() )
00567 ioIndex += nread;
00568 return nread;
00569 }
00570
00571
00586 Q_LONG QFile::writeBlock( const char *p, Q_ULONG len )
00587 {
00588 #if defined(QT_CHECK_NULL)
00589 if ( p == 0 && len != 0 )
00590 qWarning( "QFile::writeBlock: Null pointer error" );
00591 #endif
00592 #if defined(QT_CHECK_STATE)
00593 if ( !isOpen() ) {
00594 qWarning( "QFile::writeBlock: File not open" );
00595 return -1;
00596 }
00597 if ( !isWritable() ) {
00598 qWarning( "QFile::writeBlock: Write operation not permitted" );
00599 return -1;
00600 }
00601 #endif
00602 Q_ULONG nwritten;
00603 if ( isRaw() )
00604 nwritten = ::write( fd, (void *)p, len );
00605 else
00606 nwritten = fwrite( p, 1, len, fh );
00607 if ( nwritten != len ) {
00608 if ( errno == ENOSPC )
00609 setStatus( IO_ResourceError );
00610 else
00611 setStatus( IO_WriteError );
00612 if ( !isSequentialAccess() ) {
00613 if ( isRaw() )
00614 ioIndex = (Offset)::lseek( fd, 0, SEEK_CUR );
00615 else
00616 #if defined(QT_LARGEFILE_SUPPORT)
00617 ioIndex = (Offset)::fseeko( fh, 0, SEEK_CUR );
00618 #else
00619 ioIndex = (Offset)::fseek( fh, 0, SEEK_CUR );
00620 #endif
00621 }
00622 } else {
00623 if ( !isSequentialAccess() )
00624 ioIndex += nwritten;
00625 }
00626 if ( ioIndex > length )
00627 length = ioIndex;
00628 return nwritten;
00629 }
00630
00644 int QFile::handle() const
00645 {
00646 if ( !isOpen() )
00647 return -1;
00648 else if ( fh )
00649 return fileno( fh );
00650 else
00651 return fd;
00652 }
00653
00671 void QFile::close()
00672 {
00673 bool ok = FALSE;
00674 if ( isOpen() ) {
00675 if ( fh ) {
00676 if ( ext_f )
00677 ok = fflush( fh ) != -1;
00678 else
00679 ok = fclose( fh ) != -1;
00680 } else {
00681 if ( ext_f )
00682 ok = TRUE;
00683 else
00684 ok = ::close( fd ) != -1;
00685 }
00686 init();
00687 }
00688 if (!ok)
00689 setStatus( IO_UnspecifiedError );
00690
00691 return;
00692 }