Blame qtools/qfile_win32.cpp

Packit 1c1d7e
/******************************************************************************
Packit 1c1d7e
 *
Packit 1c1d7e
 * 
Packit 1c1d7e
 *
Packit 1c1d7e
 * Copyright (C) 1997-2001 by Dimitri van Heesch.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Permission to use, copy, modify, and distribute this software and its
Packit 1c1d7e
 * documentation under the terms of the GNU General Public License is hereby 
Packit 1c1d7e
 * granted. No representations are made about the suitability of this software 
Packit 1c1d7e
 * for any purpose. It is provided "as is" without express or implied warranty.
Packit 1c1d7e
 * See the GNU General Public License for more details.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Documents produced by Doxygen are derivative works derived from the
Packit 1c1d7e
 * input used in their production; they are not affected by this license.
Packit 1c1d7e
 *
Packit 1c1d7e
 * Based on qfile_unix.cpp 
Packit 1c1d7e
 *
Packit 1c1d7e
 * Copyright (C) 1992-2000 Trolltech AS.
Packit 1c1d7e
 */
Packit 1c1d7e
Packit 1c1d7e
#include "qglobal.h"
Packit 1c1d7e
Packit 1c1d7e
#include "qfile.h"
Packit 1c1d7e
#include "qfiledefs_p.h"
Packit 1c1d7e
Packit 1c1d7e
#if defined(_OS_MAC_) || defined(_OS_MSDOS_) || defined(_OS_WIN32_) || defined(_OS_OS2_)
Packit 1c1d7e
# define HAS_TEXT_FILEMODE			// has translate/text filemode
Packit 1c1d7e
#endif
Packit 1c1d7e
#if defined(O_NONBLOCK)
Packit 1c1d7e
# define HAS_ASYNC_FILEMODE
Packit 1c1d7e
# define OPEN_ASYNC O_NONBLOCK
Packit 1c1d7e
#elif defined(O_NDELAY)
Packit 1c1d7e
# define HAS_ASYNC_FILEMODE
Packit 1c1d7e
# define OPEN_ASYNC O_NDELAY
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
static void reslashify( QString& n )
Packit 1c1d7e
{
Packit 1c1d7e
  for ( int i=0; i<(int)n.length(); i++ ) 
Packit 1c1d7e
  {
Packit 1c1d7e
     if ( n[i] == '/' )
Packit 1c1d7e
          n[i] = '\\';
Packit 1c1d7e
  }
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
bool qt_file_access( const QString& fn, int t )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( fn.isEmpty() )
Packit 1c1d7e
	return FALSE;
Packit 1c1d7e
#if defined(__CYGWIN32_)
Packit 1c1d7e
    return ACCESS( QFile::encodeName(fn), t ) == 0;
Packit 1c1d7e
#else
Packit 1c1d7e
    QString str = fn;
Packit 1c1d7e
    reslashify(str);
Packit 1c1d7e
    return ( _waccess( (wchar_t*) str.ucs2(), t ) == 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Removes the file \a fileName.
Packit 1c1d7e
  Returns TRUE if successful, otherwise FALSE.
Packit 1c1d7e
*/
Packit 1c1d7e
Packit 1c1d7e
bool QFile::remove( const QString &fileName )
Packit 1c1d7e
{
Packit 1c1d7e
    if ( fileName.isEmpty() ) {
Packit 1c1d7e
#if defined(CHECK_NULL)
Packit 1c1d7e
	qWarning( "QFile::remove: Empty or null file name" );
Packit 1c1d7e
#endif
Packit 1c1d7e
	return FALSE;
Packit 1c1d7e
    }
Packit 1c1d7e
#if defined(__CYGWIN32_)
Packit 1c1d7e
    // unlink more common in UNIX
Packit 1c1d7e
    return ::remove( QFile::encodeName(fileName) ) == 0;	
Packit 1c1d7e
#else
Packit 1c1d7e
    QString str = fileName;
Packit 1c1d7e
    reslashify(str);
Packit 1c1d7e
    return ( _wunlink( (wchar_t*) str.ucs2() ) == 0 );
Packit 1c1d7e
#endif
Packit 1c1d7e
}
Packit 1c1d7e
Packit 1c1d7e
#if defined(O_NONBLOCK)
Packit 1c1d7e
# define HAS_ASYNC_FILEMODE
Packit 1c1d7e
# define OPEN_ASYNC O_NONBLOCK
Packit 1c1d7e
#elif defined(O_NDELAY)
Packit 1c1d7e
# define HAS_ASYNC_FILEMODE
Packit 1c1d7e
# define OPEN_ASYNC O_NDELAY
Packit 1c1d7e
#endif
Packit 1c1d7e
Packit 1c1d7e
/*!
Packit 1c1d7e
  Opens the file specified by the file name currently set, using the mode \e m.
Packit 1c1d7e
  Returns TRUE if successful, otherwise FALSE.
Packit 1c1d7e
Packit 1c1d7e
  The mode parameter \e m must be a combination of the following flags:
Packit 1c1d7e
  
    Packit 1c1d7e
      
  • \c IO_Raw specified raw (non-buffered) file access.
  • Packit 1c1d7e
      
  • \c IO_ReadOnly opens the file in read-only mode.
  • Packit 1c1d7e
      
  • \c IO_WriteOnly opens the file in write-only mode (and truncates).
  • Packit 1c1d7e
      
  • \c IO_ReadWrite opens the file in read/write mode, equivalent to
  • Packit 1c1d7e
      \c (IO_ReadOnly|IO_WriteOnly).
    Packit 1c1d7e
      
  • \c IO_Append opens the file in append mode. This mode is very useful
  • Packit 1c1d7e
      when you want to write something to a log file. The file index is set to
    Packit 1c1d7e
      the end of the file. Note that the result is undefined if you position the
    Packit 1c1d7e
      file index manually using at() in append mode.
    Packit 1c1d7e
      
  • \c IO_Truncate truncates the file.
  • Packit 1c1d7e
      
  • \c IO_Translate enables carriage returns and linefeed translation
  • Packit 1c1d7e
      for text files under MS-DOS, Windows and OS/2.
    Packit 1c1d7e
      
    Packit 1c1d7e
    Packit 1c1d7e
      The raw access mode is best when I/O is block-operated using 4kB block size
    Packit 1c1d7e
      or greater. Buffered access works better when reading small portions of
    Packit 1c1d7e
      data at a time.
    Packit 1c1d7e
    Packit 1c1d7e
      Important: When working with buffered files, data may
    Packit 1c1d7e
      not be written to the file at once. Call \link flush() flush\endlink
    Packit 1c1d7e
      to make sure the data is really written.
    Packit 1c1d7e
    Packit 1c1d7e
      \warning We have experienced problems with some C libraries when a buffered
    Packit 1c1d7e
      file is opened for both reading and writing. If a read operation takes place
    Packit 1c1d7e
      immediately after a write operation, the read buffer contains garbage data.
    Packit 1c1d7e
      Worse, the same garbage is written to the file. Calling flush() before
    Packit 1c1d7e
      readBlock() solved this problem.
    Packit 1c1d7e
    Packit 1c1d7e
      If the file does not exist and \c IO_WriteOnly or \c IO_ReadWrite is
    Packit 1c1d7e
      specified, it is created.
    Packit 1c1d7e
    Packit 1c1d7e
      Example:
    Packit 1c1d7e
      \code
    Packit 1c1d7e
        QFile f1( "/tmp/data.bin" );
    Packit 1c1d7e
        QFile f2( "readme.txt" );
    Packit 1c1d7e
        f1.open( IO_Raw | IO_ReadWrite | IO_Append );
    Packit 1c1d7e
        f2.open( IO_ReadOnly | IO_Translate );
    Packit 1c1d7e
      \endcode
    Packit 1c1d7e
    Packit 1c1d7e
      \sa name(), close(), isOpen(), flush()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    bool QFile::open( int m )
    Packit 1c1d7e
    {
    Packit 1c1d7e
        if ( isOpen() ) {				// file already open
    Packit 1c1d7e
    #if defined(CHECK_STATE)
    Packit 1c1d7e
    	qWarning( "QFile::open: File already open" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    	return FALSE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if ( fn.isNull() ) {			// no file name defined
    Packit 1c1d7e
    #if defined(CHECK_NULL)
    Packit 1c1d7e
    	qWarning( "QFile::open: No file name specified" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    	return FALSE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        init();					// reset params
    Packit 1c1d7e
        setMode( m );
    Packit 1c1d7e
        if ( !(isReadable() || isWritable()) ) {
    Packit 1c1d7e
    #if defined(CHECK_RANGE)
    Packit 1c1d7e
    	qWarning( "QFile::open: File access not specified" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    	return FALSE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        bool ok = TRUE;
    Packit 1c1d7e
        STATBUF st;
    Packit 1c1d7e
        if ( isRaw() ) {				// raw file I/O
    Packit 1c1d7e
    	int oflags = OPEN_RDONLY;
    Packit 1c1d7e
    	if ( isReadable() && isWritable() )
    Packit 1c1d7e
    	    oflags = OPEN_RDWR;
    Packit 1c1d7e
    	else if ( isWritable() )
    Packit 1c1d7e
    	    oflags = OPEN_WRONLY;
    Packit 1c1d7e
    	if ( flags() & IO_Append ) {		// append to end of file?
    Packit 1c1d7e
    	    if ( flags() & IO_Truncate )
    Packit 1c1d7e
    		oflags |= (OPEN_CREAT | OPEN_TRUNC);
    Packit 1c1d7e
    	    else
    Packit 1c1d7e
    		oflags |= (OPEN_APPEND | OPEN_CREAT);
    Packit 1c1d7e
    	    setFlags( flags() | IO_WriteOnly ); // append implies write
    Packit 1c1d7e
    	} else if ( isWritable() ) {		// create/trunc if writable
    Packit 1c1d7e
    	    if ( flags() & IO_Truncate )
    Packit 1c1d7e
    		oflags |= (OPEN_CREAT | OPEN_TRUNC);
    Packit 1c1d7e
    	    else
    Packit 1c1d7e
    		oflags |= OPEN_CREAT;
    Packit 1c1d7e
    	}
    Packit 1c1d7e
    #if defined(HAS_TEXT_FILEMODE)
    Packit 1c1d7e
    	if ( isTranslated() )
    Packit 1c1d7e
    	    oflags |= OPEN_TEXT;
    Packit 1c1d7e
    	else
    Packit 1c1d7e
    	    oflags |= OPEN_BINARY;
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    #if defined(HAS_ASYNC_FILEMODE)
    Packit 1c1d7e
    	if ( isAsynchronous() )
    Packit 1c1d7e
    	    oflags |= OPEN_ASYNC;
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    Packit 1c1d7e
    Packit 1c1d7e
    #if defined(__CYGWIN32_)
    Packit 1c1d7e
    	fd = OPEN( QFile::encodeName(fn), oflags, 0666 );
    Packit 1c1d7e
    #else
    Packit 1c1d7e
            QString str = fn;
    Packit 1c1d7e
            reslashify(str);
    Packit 1c1d7e
            fd = _wopen( (wchar_t*) str.ucs2(), oflags, 0666 );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    Packit 1c1d7e
    	if ( fd != -1 ) {			// open successful
    Packit 1c1d7e
    	    FSTAT( fd, &st ); // get the stat for later usage
    Packit 1c1d7e
    	} else {
    Packit 1c1d7e
    	    ok = FALSE;
    Packit 1c1d7e
    	}
    Packit 1c1d7e
        } else {					// buffered file I/O
    Packit 1c1d7e
    	QCString perm;
    Packit 1c1d7e
    	char perm2[4];
    Packit 1c1d7e
    	bool try_create = FALSE;
    Packit 1c1d7e
    	if ( flags() & IO_Append ) {		// append to end of file?
    Packit 1c1d7e
    	    setFlags( flags() | IO_WriteOnly ); // append implies write
    Packit 1c1d7e
    	    perm = isReadable() ? "a+" : "a";
    Packit 1c1d7e
    	} else {
    Packit 1c1d7e
    	    if ( isReadWrite() ) {
    Packit 1c1d7e
    		if ( flags() & IO_Truncate ) {
    Packit 1c1d7e
    		    perm = "w+";
    Packit 1c1d7e
    		} else {
    Packit 1c1d7e
    		    perm = "r+";
    Packit 1c1d7e
    		    try_create = TRUE;		// try to create if not exists
    Packit 1c1d7e
    		}
    Packit 1c1d7e
    	    } else if ( isReadable() ) {
    Packit 1c1d7e
    		perm = "r";
    Packit 1c1d7e
    	    } else if ( isWritable() ) {
    Packit 1c1d7e
    		perm = "w";
    Packit 1c1d7e
    	    }
    Packit 1c1d7e
    	}
    Packit 1c1d7e
    	qstrcpy( perm2, perm );
    Packit 1c1d7e
    	if ( isTranslated() )
    Packit 1c1d7e
    	    strcat( perm2, "t" );
    Packit 1c1d7e
    	else
    Packit 1c1d7e
    	    strcat( perm2, "b" );
    Packit 1c1d7e
    	while (1) { // At most twice
    Packit 1c1d7e
    Packit 1c1d7e
    #if defined(__CYGWIN32_)
    Packit 1c1d7e
    	    fh = fopen( QFile::encodeName(fn), perm2 );
    Packit 1c1d7e
    #else
    Packit 1c1d7e
                QString str = fn;
    Packit 1c1d7e
                QString prm( perm2 );
    Packit 1c1d7e
                reslashify(str);
    Packit 1c1d7e
                fh = _wfopen( (wchar_t*) str.ucs2(), (wchar_t*) prm.ucs2() );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    Packit 1c1d7e
    	    if ( !fh && try_create ) {
    Packit 1c1d7e
    		perm2[0] = 'w';			// try "w+" instead of "r+"
    Packit 1c1d7e
    		try_create = FALSE;
    Packit 1c1d7e
    	    } else {
    Packit 1c1d7e
    		break;
    Packit 1c1d7e
    	    }
    Packit 1c1d7e
    	}
    Packit 1c1d7e
    	if ( fh ) {
    Packit 1c1d7e
    	    FSTAT( FILENO(fh), &st ); // get the stat for later usage
    Packit 1c1d7e
    	} else {
    Packit 1c1d7e
    	    ok = FALSE;
    Packit 1c1d7e
    	}
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if ( ok ) {
    Packit 1c1d7e
    	setState( IO_Open );
    Packit 1c1d7e
    	// on successful open the file stat was got; now test what type
    Packit 1c1d7e
    	// of file we have
    Packit 1c1d7e
    	if ( (st.st_mode & STAT_MASK) != STAT_REG ) {
    Packit 1c1d7e
    	    // non-seekable
    Packit 1c1d7e
    	    setType( IO_Sequential );
    Packit 1c1d7e
    	    length = INT_MAX;
    Packit 1c1d7e
    	    ioIndex  = (flags() & IO_Append) == 0 ? 0 : length;
    Packit 1c1d7e
    	} else {
    Packit 1c1d7e
    	    length = (int)st.st_size;
    Packit 1c1d7e
    	    ioIndex  = (flags() & IO_Append) == 0 ? 0 : length;
    Packit 1c1d7e
    	    if ( !(flags()&IO_Truncate) && length == 0 && isReadable() ) {
    Packit 1c1d7e
    		// try if you can read from it (if you can, it's a sequential
    Packit 1c1d7e
    		// device; e.g. a file in the /proc filesystem)
    Packit 1c1d7e
    		int c = getch();
    Packit 1c1d7e
    		if ( c != -1 ) {
    Packit 1c1d7e
    		    ungetch(c);
    Packit 1c1d7e
    		    setType( IO_Sequential );
    Packit 1c1d7e
    		    length = INT_MAX;
    Packit 1c1d7e
    		}
    Packit 1c1d7e
    	    }
    Packit 1c1d7e
    	}
    Packit 1c1d7e
        } else {
    Packit 1c1d7e
    	init();
    Packit 1c1d7e
    	if ( errno == EMFILE )			// no more file handles/descrs
    Packit 1c1d7e
    	    setStatus( IO_ResourceError );
    Packit 1c1d7e
    	else
    Packit 1c1d7e
    	    setStatus( IO_OpenError );
    Packit 1c1d7e
        }
    Packit 1c1d7e
        return ok;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      Opens a file in the mode \e m using an existing file handle \e f.
    Packit 1c1d7e
      Returns TRUE if successful, otherwise FALSE.
    Packit 1c1d7e
    Packit 1c1d7e
      Example:
    Packit 1c1d7e
      \code
    Packit 1c1d7e
        #include <stdio.h>
    Packit 1c1d7e
    Packit 1c1d7e
        void printError( const char* msg )
    Packit 1c1d7e
        {
    Packit 1c1d7e
    	QFile f;
    Packit 1c1d7e
    	f.open( IO_WriteOnly, stderr );
    Packit 1c1d7e
    	f.writeBlock( msg, qstrlen(msg) );	// write to stderr
    Packit 1c1d7e
    	f.close();
    Packit 1c1d7e
        }
    Packit 1c1d7e
      \endcode
    Packit 1c1d7e
    Packit 1c1d7e
      When a QFile is opened using this function, close() does not actually
    Packit 1c1d7e
      close the file, only flushes it.
    Packit 1c1d7e
    Packit 1c1d7e
      \warning If \e f is \c stdin, \c stdout, \c stderr, you may not
    Packit 1c1d7e
      be able to seek.  See QIODevice::isSequentialAccess() for more
    Packit 1c1d7e
      information.
    Packit 1c1d7e
    Packit 1c1d7e
      \sa close()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    bool QFile::open( int m, FILE *f )
    Packit 1c1d7e
    {
    Packit 1c1d7e
        if ( isOpen() ) {
    Packit 1c1d7e
    #if defined(CHECK_RANGE)
    Packit 1c1d7e
    	qWarning( "QFile::open: File already open" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    	return FALSE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        init();
    Packit 1c1d7e
        setMode( m &~IO_Raw );
    Packit 1c1d7e
        setState( IO_Open );
    Packit 1c1d7e
        fh = f;
    Packit 1c1d7e
        ext_f = TRUE;
    Packit 1c1d7e
        STATBUF st;
    Packit 1c1d7e
        FSTAT( FILENO(fh), &st );
    Packit 1c1d7e
        ioIndex = (int)ftell( fh );
    Packit 1c1d7e
        if ( (st.st_mode & STAT_MASK) != STAT_REG ) {
    Packit 1c1d7e
    	// non-seekable
    Packit 1c1d7e
    	setType( IO_Sequential );
    Packit 1c1d7e
    	length = INT_MAX;
    Packit 1c1d7e
        } else {
    Packit 1c1d7e
    	length = (int)st.st_size;
    Packit 1c1d7e
    	if ( (flags() & !IO_Truncate) && length == 0 && isReadable() ) {
    Packit 1c1d7e
    	    // try if you can read from it (if you can, it's a sequential
    Packit 1c1d7e
    	    // device; e.g. a file in the /proc filesystem)
    Packit 1c1d7e
    	    int c = getch();
    Packit 1c1d7e
    	    if ( c != -1 ) {
    Packit 1c1d7e
    		ungetch(c);
    Packit 1c1d7e
    		setType( IO_Sequential );
    Packit 1c1d7e
    		length = INT_MAX;
    Packit 1c1d7e
    	    }
    Packit 1c1d7e
    	}
    Packit 1c1d7e
        }
    Packit 1c1d7e
        return TRUE;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      Opens a file in the mode \e m using an existing file descriptor \e f.
    Packit 1c1d7e
      Returns TRUE if successful, otherwise FALSE.
    Packit 1c1d7e
    Packit 1c1d7e
      When a QFile is opened using this function, close() does not actually
    Packit 1c1d7e
      close the file.
    Packit 1c1d7e
    Packit 1c1d7e
      \warning If \e f is one of 0 (stdin), 1 (stdout) or 2 (stderr), you may not
    Packit 1c1d7e
      be able to seek. size() is set to \c INT_MAX (in limits.h).
    Packit 1c1d7e
    Packit 1c1d7e
      \sa close()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    Packit 1c1d7e
    bool QFile::open( int m, int f )
    Packit 1c1d7e
    {
    Packit 1c1d7e
        if ( isOpen() ) {
    Packit 1c1d7e
    #if defined(CHECK_RANGE)
    Packit 1c1d7e
    	qWarning( "QFile::open: File already open" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    	return FALSE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        init();
    Packit 1c1d7e
        setMode( m |IO_Raw );
    Packit 1c1d7e
        setState( IO_Open );
    Packit 1c1d7e
        fd = f;
    Packit 1c1d7e
        ext_f = TRUE;
    Packit 1c1d7e
        STATBUF st;
    Packit 1c1d7e
        FSTAT( fd, &st );
    Packit 1c1d7e
        ioIndex  = (int)LSEEK(fd, 0, SEEK_CUR);
    Packit 1c1d7e
        if ( (st.st_mode & STAT_MASK) != STAT_REG ) {
    Packit 1c1d7e
    	// non-seekable
    Packit 1c1d7e
    	setType( IO_Sequential );
    Packit 1c1d7e
    	length = INT_MAX;
    Packit 1c1d7e
        } else {
    Packit 1c1d7e
    	length = (int)st.st_size;
    Packit 1c1d7e
    	if ( length == 0 && isReadable() ) {
    Packit 1c1d7e
    	    // try if you can read from it (if you can, it's a sequential
    Packit 1c1d7e
    	    // device; e.g. a file in the /proc filesystem)
    Packit 1c1d7e
    	    int c = getch();
    Packit 1c1d7e
    	    if ( c != -1 ) {
    Packit 1c1d7e
    		ungetch(c);
    Packit 1c1d7e
    		setType( IO_Sequential );
    Packit 1c1d7e
    		length = INT_MAX;
    Packit 1c1d7e
    	    }
    Packit 1c1d7e
    	}
    Packit 1c1d7e
        }
    Packit 1c1d7e
        return TRUE;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      Returns the file size.
    Packit 1c1d7e
      \sa at()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    uint QFile::size() const
    Packit 1c1d7e
    {
    Packit 1c1d7e
        STATBUF st;
    Packit 1c1d7e
        if ( isOpen() ) {
    Packit 1c1d7e
    	FSTAT( fh ? FILENO(fh) : fd, &st );
    Packit 1c1d7e
            return st.st_size;
    Packit 1c1d7e
        } else {
    Packit 1c1d7e
    #if defined(__CYGWIN32_)
    Packit 1c1d7e
    	STAT( QFile::encodeName(fn), &st );
    Packit 1c1d7e
    #else
    Packit 1c1d7e
            QString str = fn;
    Packit 1c1d7e
            reslashify(str);
    Packit 1c1d7e
    #ifdef QT_LARGEFILE_SUPPORT
    Packit 1c1d7e
            if ( _wstati64( (wchar_t*) str.ucs2(), &st ) != -1 ) {
    Packit 1c1d7e
    #else
    Packit 1c1d7e
            if ( _wstat( (wchar_t*) str.ucs2(), &st ) != -1 ) {
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
                return st.st_size;
    Packit 1c1d7e
            }
    Packit 1c1d7e
        }
    Packit 1c1d7e
        return 0;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      \fn int QFile::at() const
    Packit 1c1d7e
      Returns the file index.
    Packit 1c1d7e
      \sa size()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      Sets the file index to \e pos. Returns TRUE if successful, otherwise FALSE.
    Packit 1c1d7e
    Packit 1c1d7e
      Example:
    Packit 1c1d7e
      \code
    Packit 1c1d7e
        QFile f( "data.bin" );
    Packit 1c1d7e
        f.open( IO_ReadOnly );			// index set to 0
    Packit 1c1d7e
        f.at( 100 );				// set index to 100
    Packit 1c1d7e
        f.at( f.at()+50 );				// set index to 150
    Packit 1c1d7e
        f.at( f.size()-80 );			// set index to 80 before EOF
    Packit 1c1d7e
        f.close();
    Packit 1c1d7e
      \endcode
    Packit 1c1d7e
    Packit 1c1d7e
      \warning The result is undefined if the file was \link open() opened\endlink
    Packit 1c1d7e
      using the \c IO_Append specifier.
    Packit 1c1d7e
    Packit 1c1d7e
      \sa size(), open()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    bool QFile::at( int pos )
    Packit 1c1d7e
    {
    Packit 1c1d7e
        if ( !isOpen() ) {
    Packit 1c1d7e
    #if defined(CHECK_STATE)
    Packit 1c1d7e
    	qWarning( "QFile::at: File is not open" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    	return FALSE;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        bool ok;
    Packit 1c1d7e
        if ( isRaw() ) {				// raw file
    Packit 1c1d7e
    	pos = (int)LSEEK(fd, pos, SEEK_SET);
    Packit 1c1d7e
    	ok = pos != -1;
    Packit 1c1d7e
        } else {					// buffered file
    Packit 1c1d7e
    	ok = fseek(fh, pos, SEEK_SET) == 0;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if ( ok )
    Packit 1c1d7e
    	ioIndex = pos;
    Packit 1c1d7e
    #if defined(CHECK_RANGE)
    Packit 1c1d7e
        else
    Packit 1c1d7e
    	qWarning( "QFile::at: Cannot set file position %d", pos );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
        return ok;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      Reads at most \e len bytes from the file into \e p and returns the
    Packit 1c1d7e
      number of bytes actually read.
    Packit 1c1d7e
    Packit 1c1d7e
      Returns -1 if a serious error occurred.
    Packit 1c1d7e
    Packit 1c1d7e
      \warning We have experienced problems with some C libraries when a buffered
    Packit 1c1d7e
      file is opened for both reading and writing. If a read operation takes place
    Packit 1c1d7e
      immediately after a write operation, the read buffer contains garbage data.
    Packit 1c1d7e
      Worse, the same garbage is written to the file. Calling flush() before
    Packit 1c1d7e
      readBlock() solved this problem.
    Packit 1c1d7e
    Packit 1c1d7e
      \sa writeBlock()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    int QFile::readBlock( char *p, uint len )
    Packit 1c1d7e
    {
    Packit 1c1d7e
    #if defined(CHECK_NULL)
    Packit 1c1d7e
        if ( !p )
    Packit 1c1d7e
    	qWarning( "QFile::readBlock: Null pointer error" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    #if defined(CHECK_STATE)
    Packit 1c1d7e
        if ( !isOpen() ) {				// file not open
    Packit 1c1d7e
    	qWarning( "QFile::readBlock: File not open" );
    Packit 1c1d7e
    	return -1;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if ( !isReadable() ) {			// reading not permitted
    Packit 1c1d7e
    	qWarning( "QFile::readBlock: Read operation not permitted" );
    Packit 1c1d7e
    	return -1;
    Packit 1c1d7e
        }
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
        int nread;					// number of bytes read
    Packit 1c1d7e
        if ( isRaw() ) {				// raw file
    Packit 1c1d7e
    	nread = READ( fd, p, len );
    Packit 1c1d7e
    	if ( len && nread <= 0 ) {
    Packit 1c1d7e
    	    nread = 0;
    Packit 1c1d7e
    	    setStatus(IO_ReadError);
    Packit 1c1d7e
    	}
    Packit 1c1d7e
        } else {					// buffered file
    Packit 1c1d7e
    	nread = fread( p, 1, len, fh );
    Packit 1c1d7e
    	if ( (uint)nread != len ) {
    Packit 1c1d7e
    	    if ( ferror( fh ) || nread==0 )
    Packit 1c1d7e
    		setStatus(IO_ReadError);
    Packit 1c1d7e
    	}
    Packit 1c1d7e
        }
    Packit 1c1d7e
        ioIndex += nread;
    Packit 1c1d7e
        return nread;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*! \overload int writeBlock( const QByteArray& data )
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    /*! \reimp
    Packit 1c1d7e
    Packit 1c1d7e
      Writes \e len bytes from \e p to the file and returns the number of
    Packit 1c1d7e
      bytes actually written.
    Packit 1c1d7e
    Packit 1c1d7e
      Returns -1 if a serious error occurred.
    Packit 1c1d7e
    Packit 1c1d7e
      \warning When working with buffered files, data may not be written
    Packit 1c1d7e
      to the file at once. Call flush() to make sure the data is really
    Packit 1c1d7e
      written.
    Packit 1c1d7e
    Packit 1c1d7e
      \sa readBlock()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    int QFile::writeBlock( const char *p, uint len )
    Packit 1c1d7e
    {
    Packit 1c1d7e
    #if defined(CHECK_NULL)
    Packit 1c1d7e
        if ( p == 0 && len != 0 )
    Packit 1c1d7e
    	qWarning( "QFile::writeBlock: Null pointer error" );
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
    #if defined(CHECK_STATE)
    Packit 1c1d7e
        if ( !isOpen() ) {				// file not open
    Packit 1c1d7e
    	qWarning( "QFile::writeBlock: File not open" );
    Packit 1c1d7e
    	return -1;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if ( !isWritable() ) {			// writing not permitted
    Packit 1c1d7e
    	qWarning( "QFile::writeBlock: Write operation not permitted" );
    Packit 1c1d7e
    	return -1;
    Packit 1c1d7e
        }
    Packit 1c1d7e
    #endif
    Packit 1c1d7e
        int nwritten;				// number of bytes written
    Packit 1c1d7e
        if ( isRaw() )				// raw file
    Packit 1c1d7e
    	nwritten = WRITE( fd, p, len );
    Packit 1c1d7e
        else					// buffered file
    Packit 1c1d7e
    	nwritten = fwrite( p, 1, len, fh );
    Packit 1c1d7e
        if ( nwritten != (int)len ) {		// write error
    Packit 1c1d7e
    	if ( errno == ENOSPC )			// disk is full
    Packit 1c1d7e
    	    setStatus( IO_ResourceError );
    Packit 1c1d7e
    	else
    Packit 1c1d7e
    	    setStatus( IO_WriteError );
    Packit 1c1d7e
    	if ( isRaw() )				// recalc file position
    Packit 1c1d7e
    	    ioIndex = (int)LSEEK( fd, 0, SEEK_CUR );
    Packit 1c1d7e
    	else
    Packit 1c1d7e
    	    ioIndex = fseek( fh, 0, SEEK_CUR );
    Packit 1c1d7e
        } else {
    Packit 1c1d7e
    	ioIndex += nwritten;
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if ( ioIndex > length )			// update file length
    Packit 1c1d7e
    	length = ioIndex;
    Packit 1c1d7e
        return nwritten;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      Returns the file handle of the file.
    Packit 1c1d7e
    Packit 1c1d7e
      This is a small positive integer, suitable for use with C library
    Packit 1c1d7e
      functions such as fdopen() and fcntl(), as well as with QSocketNotifier.
    Packit 1c1d7e
    Packit 1c1d7e
      If the file is not open or there is an error, handle() returns -1.
    Packit 1c1d7e
    Packit 1c1d7e
      \sa QSocketNotifier
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    int QFile::handle() const
    Packit 1c1d7e
    {
    Packit 1c1d7e
        if ( !isOpen() )
    Packit 1c1d7e
    	return -1;
    Packit 1c1d7e
        else if ( fh )
    Packit 1c1d7e
    	return FILENO( fh );
    Packit 1c1d7e
        else
    Packit 1c1d7e
    	return fd;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    /*!
    Packit 1c1d7e
      Closes an open file.
    Packit 1c1d7e
    Packit 1c1d7e
      The file is not closed if it was opened with an existing file handle.
    Packit 1c1d7e
      If the existing file handle is a \c FILE*, the file is flushed.
    Packit 1c1d7e
      If the existing file handle is an \c int file descriptor, nothing
    Packit 1c1d7e
      is done to the file.
    Packit 1c1d7e
    Packit 1c1d7e
      Some "write-behind" filesystems may report an unspecified error on
    Packit 1c1d7e
      closing the file. These errors only indicate that something may
    Packit 1c1d7e
      have gone wrong since the previous open(). In such a case status()
    Packit 1c1d7e
      reports IO_UnspecifiedError after close(), otherwise IO_Ok.
    Packit 1c1d7e
    Packit 1c1d7e
      \sa open(), flush()
    Packit 1c1d7e
    */
    Packit 1c1d7e
    Packit 1c1d7e
    Packit 1c1d7e
    void QFile::close()
    Packit 1c1d7e
    {
    Packit 1c1d7e
        bool ok = FALSE;
    Packit 1c1d7e
        if ( isOpen() ) {				// file is not open
    Packit 1c1d7e
    	if ( fh ) {				// buffered file
    Packit 1c1d7e
    	    if ( ext_f )
    Packit 1c1d7e
    		ok = fflush( fh ) != -1;	// flush instead of closing
    Packit 1c1d7e
    	    else
    Packit 1c1d7e
    		ok = fclose( fh ) != -1;
    Packit 1c1d7e
    	} else {				// raw file
    Packit 1c1d7e
    	    if ( ext_f )
    Packit 1c1d7e
    		ok = TRUE;			// cannot close
    Packit 1c1d7e
    	    else
    Packit 1c1d7e
    		ok = CLOSE( fd ) != -1;
    Packit 1c1d7e
    	}
    Packit 1c1d7e
    	init();					// restore internal state
    Packit 1c1d7e
        }
    Packit 1c1d7e
        if (!ok)
    Packit 1c1d7e
    	setStatus (IO_UnspecifiedError);
    Packit 1c1d7e
    Packit 1c1d7e
        return;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    int64 QFile::pos() const
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (isOpen())
    Packit 1c1d7e
      {
    Packit 1c1d7e
        // TODO: support 64 bit size
    Packit 1c1d7e
        return ftell( fh );
    Packit 1c1d7e
      }
    Packit 1c1d7e
      return -1;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    int64 QFile::toEnd() 
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (isOpen())
    Packit 1c1d7e
      {
    Packit 1c1d7e
         // TODO: support 64 bit size
    Packit 1c1d7e
         if (fseek( fh, 0, SEEK_END )!=-1)
    Packit 1c1d7e
         {
    Packit 1c1d7e
           return ftell( fh );
    Packit 1c1d7e
         }
    Packit 1c1d7e
      }
    Packit 1c1d7e
      return -1;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    bool QFile::seek( int64 pos )
    Packit 1c1d7e
    {
    Packit 1c1d7e
      if (isOpen())
    Packit 1c1d7e
      {
    Packit 1c1d7e
        // TODO: support 64 bit size
    Packit 1c1d7e
        return fseek( fh, pos, SEEK_SET )!=-1;
    Packit 1c1d7e
      }
    Packit 1c1d7e
      return FALSE;
    Packit 1c1d7e
    }
    Packit 1c1d7e
    Packit 1c1d7e
    Packit 1c1d7e