/* * Copyright (C) 2007-2008 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #include "file.h" #include #include #include #include #include #include // for mkstemp namespace Bu { subExceptionDef( FileException ) } Bu::File::File( const Bu::FString &sName, int iFlags ) : fd( -1 ) { fd = ::open( sName.getStr(), getPosixFlags( iFlags ) ); if( fd < 0 ) { throw Bu::FileException( errno, "%s: %s", strerror(errno), sName.getStr() ); } } Bu::File::File( int fd ) : fd( fd ) { } Bu::File::~File() { close(); } void Bu::File::close() { if( fd >= 0 ) { if( ::close( fd ) ) { throw Bu::FileException( errno, "%s", strerror(errno) ); } fd = -1; } } size_t Bu::File::read( void *pBuf, size_t nBytes ) { if( fd < 0 ) throw FileException("File not open."); return ::read( fd, pBuf, nBytes ); } size_t Bu::File::write( const void *pBuf, size_t nBytes ) { if( fd < 0 ) throw FileException("File not open."); return ::write( fd, pBuf, nBytes ); } long Bu::File::tell() { if( fd < 0 ) throw FileException("File not open."); return lseek( fd, 0, SEEK_CUR ); } void Bu::File::seek( long offset ) { if( fd < 0 ) throw FileException("File not open."); lseek( fd, offset, SEEK_CUR ); } void Bu::File::setPos( long pos ) { if( fd < 0 ) throw FileException("File not open."); lseek( fd, pos, SEEK_SET ); } void Bu::File::setPosEnd( long pos ) { if( fd < 0 ) throw FileException("File not open."); lseek( fd, pos, SEEK_END ); } bool Bu::File::isEOS() { return false; } bool Bu::File::canRead() { return true; } bool Bu::File::canWrite() { return true; } bool Bu::File::isReadable() { return true; } bool Bu::File::isWritable() { return true; } bool Bu::File::isSeekable() { return true; } bool Bu::File::isBlocking() { return true; } void Bu::File::setBlocking( bool bBlocking ) { #ifdef WIN32 fprintf(stderr, "STUB: Bu::File::setBlocking\n"); #else if( bBlocking ) fcntl( fd, F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK) ); else fcntl( fd, F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK ); #endif } #ifndef WIN32 Bu::File Bu::File::tempFile( Bu::FString &sName ) { int afh_d = mkstemp( sName.getStr() ); return Bu::File( afh_d ); } void Bu::File::truncate( long nSize ) { ftruncate( fd, nSize ); } void Bu::File::chmod( mode_t t ) { fchmod( fd, t ); } #endif void Bu::File::flush() { // There is no flushing with direct I/O... //fflush( fh ); } bool Bu::File::isOpen() { return (fd > -1); } int Bu::File::getPosixFlags( int iFlags ) { int iRet = 0; switch( (iFlags&ReadWrite) ) { // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so // lets be proper and use the right value in the right place. case Read: iRet = O_RDONLY; break; case Write: iRet = O_WRONLY; break; case ReadWrite: iRet = O_RDWR; break; default: throw FileException( "You must specify Read, Write, or both when opening a file."); } if( (iFlags&Create) ) iRet |= O_CREAT; if( (iFlags&Append) ) iRet |= O_APPEND; if( (iFlags&Truncate) ) iRet |= O_TRUNC; if( (iFlags&NonBlock) ) iRet |= O_NONBLOCK; if( (iFlags&Exclusive) ) iRet |= O_EXCL; return iRet; }