//------------------------------------------------------------------------------ // Desc: This file contains the F_64BitFile class // // Tabs: 3 // // Copyright (c) 2001,2003-2006 Novell, Inc. All Rights Reserved. // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the GNU General Public // License as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, contact Novell, Inc. // // To contact Novell about this file by physical or electronic mail, // you may find current contact information at www.novell.com // // $Id: f64bitfh.cpp 3111 2006-01-19 13:10:50 -0700 (Thu, 19 Jan 2006) dsanders $ //------------------------------------------------------------------------------ #include "ftksys.h" #define F_MULTI_FHDL_LIST_SIZE 8 #define F_MULTI_FHDL_DEFAULT_MAX_FILE_SIZE ((FLMUINT)0xFFFFFFFF) /**************************************************************************** Desc: ****************************************************************************/ typedef struct { IF_FileHdl * pFileHdl; FLMUINT uiFileNum; FLMBOOL bDirty; } FH_INFO; /**************************************************************************** Desc: ****************************************************************************/ class F_MultiFileHdl : public IF_MultiFileHdl { public: F_MultiFileHdl( FLMUINT uiMaxFileSize = F_MULTI_FHDL_DEFAULT_MAX_FILE_SIZE); virtual ~F_MultiFileHdl(); void FLMAPI close( FLMBOOL bDelete = FALSE); RCODE FLMAPI create( const char * pszPath); RCODE FLMAPI createUnique( const char * pszPath, const char * pszFileExtension); RCODE FLMAPI deleteMultiFile( const char * pszPath); RCODE FLMAPI open( const char * pszPath); RCODE FLMAPI flush( void); RCODE FLMAPI read( FLMUINT64 ui64Offset, FLMUINT uiLength, void * pvBuffer, FLMUINT * puiBytesRead); RCODE FLMAPI write( FLMUINT64 ui64Offset, FLMUINT uiLength, void * pvBuffer, FLMUINT * puiBytesWritten); RCODE FLMAPI getPath( char * pszFilePath); FINLINE RCODE FLMAPI size( FLMUINT64 * pui64FileSize) { *pui64FileSize = m_ui64EOF; return( NE_FLM_OK); } RCODE FLMAPI truncate( FLMUINT64 ui64NewSize); private: RCODE getFileHdl( FLMUINT uiFileNum, FLMBOOL bGetForWrite, IF_FileHdl ** ppFileHdl); RCODE createLockFile( const char * pszBasePath); FINLINE void releaseLockFile( const char * pszBasePath, FLMBOOL bDelete) { #ifndef FLM_UNIX F_UNREFERENCED_PARM( bDelete); F_UNREFERENCED_PARM( pszBasePath); #endif if( m_pLockFileHdl) { // Release the lock file (void)m_pLockFileHdl->close(); m_pLockFileHdl->Release(); m_pLockFileHdl = NULL; #ifdef FLM_UNIX if( bDelete) { IF_FileSystem * pFileSystem = f_getFileSysPtr(); char szTmpPath[ F_PATH_MAX_SIZE]; // Delete the lock file f_strcpy( szTmpPath, pszBasePath); pFileSystem->pathAppend( szTmpPath, "64.LCK"); pFileSystem->deleteFile( szTmpPath); } #endif } } FINLINE void formatFileNum( FLMUINT uiFileNum, char * pszStr) { f_sprintf( pszStr, "%08X.64", (unsigned)uiFileNum); } RCODE getFileNum( const char * pszFileName, FLMUINT * puiFileNum); FINLINE void dataFilePath( FLMUINT uiFileNum, char * pszPath) { char szFileName[ 13]; IF_FileSystem * pFileSystem = f_getFileSysPtr(); f_strcpy( pszPath, m_szPath); formatFileNum( uiFileNum, szFileName); pFileSystem->pathAppend( pszPath, szFileName); } FINLINE FLMUINT getFileNum( FLMUINT64 ui64Offset) { return( (FLMUINT)(ui64Offset / m_uiMaxFileSize)); } FINLINE FLMUINT getFileOffset( FLMUINT64 ui64Offset) { return( (FLMUINT)(ui64Offset % m_uiMaxFileSize)); } FH_INFO m_pFileHdlList[ F_MULTI_FHDL_LIST_SIZE]; char m_szPath[ F_PATH_MAX_SIZE]; FLMBOOL m_bOpen; FLMUINT64 m_ui64EOF; FLMUINT m_uiMaxFileSize; IF_FileHdl * m_pLockFileHdl; }; /**************************************************************************** Desc: ****************************************************************************/ RCODE FLMAPI FlmAllocMultiFileHdl( IF_MultiFileHdl ** ppFileHdl) { if( (*ppFileHdl = f_new F_MultiFileHdl) == NULL) { return( RC_SET( NE_FLM_MEM)); } return( NE_FLM_OK); } /**************************************************************************** Desc: ****************************************************************************/ F_MultiFileHdl::F_MultiFileHdl( FLMUINT uiMaxFileSize) { m_bOpen = FALSE; m_szPath[ 0] = 0; m_ui64EOF = 0; m_pLockFileHdl = NULL; f_memset( m_pFileHdlList, 0, sizeof( FH_INFO) * F_MULTI_FHDL_LIST_SIZE); m_uiMaxFileSize = uiMaxFileSize; if( !m_uiMaxFileSize) { m_uiMaxFileSize = F_MULTI_FHDL_DEFAULT_MAX_FILE_SIZE; } } /**************************************************************************** Desc: ****************************************************************************/ F_MultiFileHdl::~F_MultiFileHdl() { if( m_bOpen) { close(); } f_assert( !m_pLockFileHdl); } /**************************************************************************** Desc: Closes all data files associated with the object ****************************************************************************/ void F_MultiFileHdl::close( FLMBOOL bDelete) { RCODE rc = NE_FLM_OK; FLMUINT uiLoop; IF_DirHdl * pDir = NULL; char szTmpPath[ F_PATH_MAX_SIZE]; IF_FileSystem * pFileSystem = f_getFileSysPtr(); if( !m_bOpen) { return; } for( uiLoop = 0; uiLoop < F_MULTI_FHDL_LIST_SIZE; uiLoop++) { if( m_pFileHdlList[ uiLoop].pFileHdl) { if( m_pFileHdlList[ uiLoop].bDirty) { (void)m_pFileHdlList[ uiLoop].pFileHdl->flush(); } m_pFileHdlList[ uiLoop].pFileHdl->close(); m_pFileHdlList[ uiLoop].pFileHdl->Release(); f_memset( &m_pFileHdlList[ uiLoop], 0, sizeof( FH_INFO)); } } m_ui64EOF = 0; m_bOpen = FALSE; if( bDelete) { if( RC_OK( pFileSystem->openDir( m_szPath, "*.64", &pDir))) { // Remove all data files for( rc = pDir->next(); !RC_BAD( rc) ; rc = pDir->next()) { pDir->currentItemPath( szTmpPath); f_assert( f_strstr( szTmpPath, ".64") != 0); (void)pFileSystem->deleteFile( szTmpPath); } pDir->Release(); pDir = NULL; } // Release and delete the lock file (void)releaseLockFile( m_szPath, TRUE); // Remove the directory (void)pFileSystem->removeDir( m_szPath); } else { (void)releaseLockFile( m_szPath, FALSE); } } /**************************************************************************** Desc: Removes a 64-bit file ****************************************************************************/ RCODE F_MultiFileHdl::deleteMultiFile( const char * pszPath) { RCODE rc = NE_FLM_OK; IF_DirHdl * pDir = NULL; char szTmpPath[ F_PATH_MAX_SIZE]; IF_FileSystem * pFileSystem = f_getFileSysPtr(); // Can't use this handle to delete something if we already // have a file open. if( m_bOpen) { // Can't jump to exit, because it calls releaseLockFile return( RC_SET_AND_ASSERT( NE_FLM_FAILURE)); } if( RC_BAD( rc = pFileSystem->doesFileExist( pszPath))) { goto Exit; } if( !pFileSystem->isDir( pszPath)) { // If the path specifies a single file rather than a // 64-bit directory, just go ahead and delete the file. rc = pFileSystem->deleteFile( pszPath); goto Exit; } if( RC_BAD( rc = createLockFile( pszPath))) { goto Exit; } if( RC_OK( pFileSystem->openDir( pszPath, "*.64", &pDir))) { // Remove all data files for( rc = pDir->next(); !RC_BAD( rc) ; rc = pDir->next()) { pDir->currentItemPath( szTmpPath); f_assert( f_strstr( szTmpPath, ".64") != 0); (void)pFileSystem->deleteFile( szTmpPath); } pDir->Release(); pDir = NULL; rc = NE_FLM_OK; } // Release and delete the lock file (void)releaseLockFile( pszPath, TRUE); // Remove the directory (void)pFileSystem->removeDir( pszPath); Exit: (void)releaseLockFile( pszPath, FALSE); return( rc); } /**************************************************************************** Desc: Creates a new 64-bit "file" ****************************************************************************/ RCODE F_MultiFileHdl::create( const char * pszPath) { RCODE rc = NE_FLM_OK; FLMBOOL bCreatedDir = FALSE; IF_FileSystem * pFileSystem = f_getFileSysPtr(); if( m_bOpen) { rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE); goto Exit; } if( RC_BAD( rc = pFileSystem->createDir( pszPath))) { goto Exit; } f_strcpy( m_szPath, pszPath); bCreatedDir = TRUE; // Create the lock file if( RC_BAD( rc = createLockFile( m_szPath))) { goto Exit; } // Initialize the EOF to 0 and set the state to open m_ui64EOF = 0; m_bOpen = TRUE; Exit: // Release the lock file if( RC_BAD( rc)) { (void)releaseLockFile( m_szPath, TRUE); if( bCreatedDir) { (void)pFileSystem->removeDir( m_szPath); } } return( rc); } /**************************************************************************** Desc: Creates a new 64-bit file with a unique, generated name ****************************************************************************/ RCODE F_MultiFileHdl::createUnique( const char * pszPath, // Directory where the file is to be created const char * pszFileExtension) // Extension to be used on the new file. { RCODE rc = NE_FLM_OK; FLMUINT uiCount; FLMBOOL bModext = TRUE; FLMBOOL bCreatedDir = FALSE; FLMUINT uiBaseTime = 0; FLMBYTE ucHighByte = 0; char szDirName[ F_FILENAME_SIZE]; char szTmpPath[ F_PATH_MAX_SIZE]; char szBasePath[ F_PATH_MAX_SIZE]; IF_FileSystem * pFileSystem = f_getFileSysPtr(); if( m_bOpen) { rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE); goto Exit; } if( !pszPath || pszPath[ 0] == '\0') { #if defined( FLM_UNIX) f_strcpy( szBasePath, "./"); #elif defined( FLM_NLM) f_strcpy( szBasePath, "SYS:_NETWARE"); #else szBasePath[ 0] = '\0'; #endif } else { f_strcpy( szBasePath, pszPath); } if ((pszFileExtension) && (f_strlen( pszFileExtension) >= 3)) { bModext = FALSE; } uiCount = 0; szDirName[ 0] = '\0'; do { pFileSystem->pathCreateUniqueName( &uiBaseTime, szDirName, pszFileExtension, &ucHighByte, bModext); f_strcpy( szTmpPath, szBasePath); pFileSystem->pathAppend( szTmpPath, szDirName); rc = pFileSystem->createDir( szTmpPath); } while ((rc != NE_FLM_OK) && (uiCount++ < 20)); if( RC_BAD( rc)) { goto Exit; } f_strcpy( m_szPath, szTmpPath); bCreatedDir = TRUE; // Create the lock file if( RC_BAD( rc = createLockFile( m_szPath))) { goto Exit; } // Initialize the EOF to 0 and set the state to open m_ui64EOF = 0; m_bOpen = TRUE; Exit: // Release the lock file if( RC_BAD( rc)) { releaseLockFile( m_szPath, TRUE); if( bCreatedDir) { (void)pFileSystem->removeDir( m_szPath); } } return( rc); } /**************************************************************************** Desc: Opens an existing 64-bit file ****************************************************************************/ RCODE F_MultiFileHdl::open( const char * pszPath) { RCODE rc = NE_FLM_OK; IF_FileSystem * pFileSystem = f_getFileSysPtr(); IF_DirHdl * pDir = NULL; FLMUINT uiTmp; FLMUINT uiHighFileNum = 0; FLMUINT64 ui64HighOffset = 0; if( m_bOpen) { rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE); goto Exit; } if( RC_BAD( pFileSystem->doesFileExist( pszPath)) || !pFileSystem->isDir( pszPath)) { rc = RC_SET( NE_FLM_IO_PATH_NOT_FOUND); goto Exit; } f_strcpy( m_szPath, pszPath); // Create the lock file if( RC_BAD( rc = createLockFile( m_szPath))) { goto Exit; } // Need to determine the current EOF if( RC_BAD( rc = pFileSystem->openDir( m_szPath, (char *)"*.64", &pDir))) { goto Exit; } // Find all data files to determine the EOF for( rc = pDir->next(); !RC_BAD( rc) ; rc = pDir->next()) { if( RC_OK( getFileNum( pDir->currentItemName(), &uiTmp))) { if( uiTmp >= uiHighFileNum) { uiHighFileNum = uiTmp; ui64HighOffset = pDir->currentItemSize(); } } } rc = NE_FLM_OK; m_ui64EOF = (((FLMUINT64)uiHighFileNum) * m_uiMaxFileSize) + ui64HighOffset; m_bOpen = TRUE; Exit: if( pDir) { pDir->Release(); } // Release the lock file if( RC_BAD( rc)) { releaseLockFile( m_szPath, FALSE); } return( rc); } /**************************************************************************** Desc: Flushes cached data to the data file(s) ****************************************************************************/ RCODE F_MultiFileHdl::flush( void) { FLMUINT uiLoop; RCODE rc = NE_FLM_OK; if( !m_bOpen) { rc = RC_SET_AND_ASSERT( NE_FLM_FAILURE); goto Exit; } for( uiLoop = 0; uiLoop < F_MULTI_FHDL_LIST_SIZE; uiLoop++) { if( m_pFileHdlList[ uiLoop].bDirty) { if( RC_BAD( rc = m_pFileHdlList[ uiLoop].pFileHdl->flush())) { goto Exit; } m_pFileHdlList[ uiLoop].bDirty = FALSE; } } Exit: return( rc); } /**************************************************************************** Desc: Reads data from the file ****************************************************************************/ RCODE F_MultiFileHdl::read( FLMUINT64 ui64Offset, // Offset to begin reading FLMUINT uiLength, // Number of bytes to read void * pvBuffer, // Buffer FLMUINT * puiBytesRead) // [out] Number of bytes read { FLMUINT uiFileNum = getFileNum( ui64Offset); FLMUINT uiFileOffset = getFileOffset( ui64Offset); FLMUINT uiTmp; FLMUINT uiTotalBytesRead = 0; FLMUINT uiBytesToRead; FLMUINT uiMaxReadLen; IF_FileHdl * pFileHdl; RCODE rc = NE_FLM_OK; // Handle the case of a 0-byte read if( !uiLength) { if( ui64Offset >= m_ui64EOF) { rc = RC_SET( NE_FLM_IO_END_OF_FILE); } goto Exit; } // Read the data file(s), moving to new files as needed. for( ;;) { if( ui64Offset >= m_ui64EOF) { rc = RC_SET( NE_FLM_IO_END_OF_FILE); goto Exit; } uiMaxReadLen = m_uiMaxFileSize - uiFileOffset; f_assert( uiMaxReadLen != 0); uiTmp = (uiLength >= uiMaxReadLen ? uiMaxReadLen : uiLength); uiBytesToRead = (((FLMUINT64)uiTmp > (FLMUINT64)(m_ui64EOF - ui64Offset)) ? (FLMUINT)(m_ui64EOF - ui64Offset) : uiTmp); if( RC_BAD( rc = getFileHdl( uiFileNum, FALSE, &pFileHdl))) { if( rc == NE_FLM_IO_PATH_NOT_FOUND) { // Handle the case of a sparse file by filling the unread // portion of the buffer with zeros. f_memset( pvBuffer, 0, uiBytesToRead); uiTmp = uiBytesToRead; rc = NE_FLM_OK; } else { goto Exit; } } else { if( RC_BAD( rc = pFileHdl->read( uiFileOffset, uiBytesToRead, pvBuffer, &uiTmp))) { if( rc == NE_FLM_IO_END_OF_FILE) { // Handle the case of a sparse file by filling the unread // portion of the buffer with zeros. f_memset( &(((FLMBYTE *)(pvBuffer))[ uiTmp]), 0, (FLMUINT)(uiBytesToRead - uiTmp)); uiTmp = uiBytesToRead; rc = NE_FLM_OK; } else { goto Exit; } } } uiTotalBytesRead += uiTmp; uiLength -= uiTmp; if( !uiLength) { break; } // Set up for next read pvBuffer = ((FLMBYTE *)pvBuffer) + uiTmp; ui64Offset += uiTmp; uiFileNum = getFileNum( ui64Offset); uiFileOffset = getFileOffset( ui64Offset); } Exit: *puiBytesRead = uiTotalBytesRead; return( rc); } /**************************************************************************** Desc: Writes data to the file ****************************************************************************/ RCODE F_MultiFileHdl::write( FLMUINT64 ui64Offset, // Offset FLMUINT uiLength, // Number of bytes to write. void * pvBuffer, // Buffer that contains bytes to be written FLMUINT * puiBytesWritten) // Number of bytes written. { RCODE rc = NE_FLM_OK; FLMUINT uiFileNum = getFileNum( ui64Offset); FLMUINT uiFileOffset = getFileOffset( ui64Offset); FLMUINT uiTmp; FLMUINT uiTotalBytesWritten = 0; FLMUINT uiBytesToWrite; FLMUINT uiMaxWriteLen; IF_FileHdl * pFileHdl; // Don't allow zero-length writes f_assert( uiLength); // Write to the data file(s), moving to new files as needed. for( ;;) { if( RC_BAD( rc = getFileHdl( uiFileNum, TRUE, &pFileHdl))) { goto Exit; } uiMaxWriteLen = m_uiMaxFileSize - uiFileOffset; f_assert( uiMaxWriteLen != 0); uiBytesToWrite = uiLength >= uiMaxWriteLen ? uiMaxWriteLen : uiLength; uiTmp = 0; rc = pFileHdl->write( uiFileOffset, uiBytesToWrite, pvBuffer, &uiTmp); uiTotalBytesWritten += uiTmp; uiLength -= uiTmp; ui64Offset += uiTmp; if( RC_BAD( rc)) { goto Exit; } if( !uiLength) { break; } // Set up for next write pvBuffer = ((FLMBYTE *)pvBuffer) + uiTmp; uiFileNum = getFileNum( ui64Offset); uiFileOffset = getFileOffset( ui64Offset); } Exit: if( ui64Offset > m_ui64EOF) { m_ui64EOF = ui64Offset; } *puiBytesWritten = uiTotalBytesWritten; return( rc); } /**************************************************************************** Desc: Returns the requested file handle ****************************************************************************/ RCODE F_MultiFileHdl::getFileHdl( FLMUINT uiFileNum, FLMBOOL bGetForWrite, IF_FileHdl ** ppFileHdl) { RCODE rc = NE_FLM_OK; IF_FileSystem * pFileSystem = f_getFileSysPtr(); FLMUINT uiSlot; IF_FileHdl * pTmpHdl; char szPath[ F_PATH_MAX_SIZE]; f_assert( m_bOpen); *ppFileHdl = NULL; uiSlot = uiFileNum % F_MULTI_FHDL_LIST_SIZE; pTmpHdl = m_pFileHdlList[ uiSlot].pFileHdl; if( pTmpHdl && m_pFileHdlList[ uiSlot].uiFileNum != uiFileNum) { if( RC_BAD( rc = pTmpHdl->flush())) { goto Exit; } pTmpHdl->close(); pTmpHdl->Release(); pTmpHdl = NULL; f_memset( &m_pFileHdlList[ uiSlot], 0, sizeof( FH_INFO)); } if( !pTmpHdl) { dataFilePath( uiFileNum, szPath); if( RC_BAD( rc = pFileSystem->openFile( szPath, FLM_IO_RDWR, &pTmpHdl))) { if( rc == NE_FLM_IO_PATH_NOT_FOUND && bGetForWrite) { if( RC_BAD( rc = pFileSystem->createFile( szPath, FLM_IO_RDWR, &pTmpHdl))) { goto Exit; } } else { goto Exit; } } m_pFileHdlList[ uiSlot].pFileHdl = pTmpHdl; m_pFileHdlList[ uiSlot].uiFileNum = uiFileNum; f_assert( !m_pFileHdlList[ uiSlot].bDirty); } *ppFileHdl = m_pFileHdlList[ uiSlot].pFileHdl; if( bGetForWrite) { m_pFileHdlList[ uiSlot].bDirty = TRUE; } Exit: return( rc); } /**************************************************************************** Desc: Given a data file name, returns the file's number ****************************************************************************/ RCODE F_MultiFileHdl::getFileNum( const char * pszFileName, FLMUINT * puiFileNum) { FLMUINT uiCnt = 0; FLMUINT uiDigit; FLMUINT uiFileNum = 0; RCODE rc = NE_FLM_OK; if( f_strlen( pszFileName) != 11) // XXXXXXXX.64 { rc = RC_SET( NE_FLM_IO_INVALID_FILENAME); goto Exit; } if( f_strcmp( &pszFileName[ 8], ".64") != 0) { rc = RC_SET( NE_FLM_IO_INVALID_FILENAME); goto Exit; } while( uiCnt < 8) { uiDigit = pszFileName[ uiCnt]; if( uiDigit >= NATIVE_LOWER_A && uiDigit <= NATIVE_LOWER_F) { uiDigit = (FLMUINT)(uiDigit - NATIVE_LOWER_A) + 10; } else if( uiDigit >= NATIVE_UPPER_A && uiDigit <= NATIVE_UPPER_F) { uiDigit = (FLMUINT)(uiDigit - NATIVE_UPPER_A) + 10; } else if( uiDigit >= NATIVE_ZERO && uiDigit <= NATIVE_NINE) { uiDigit -= NATIVE_ZERO; } else { rc = RC_SET( NE_FLM_IO_INVALID_FILENAME); goto Exit; } uiFileNum <<= 4; uiFileNum += uiDigit; uiCnt++; } *puiFileNum = uiFileNum; Exit: return( rc); } /**************************************************************************** Desc: This routine obtains exclusive access to a 64-bit file by creating a .lck file. The object holds the .lck file open as long as the 64-bit file is open. ****************************************************************************/ RCODE F_MultiFileHdl::createLockFile( const char * pszBasePath) { RCODE rc = NE_FLM_OK; char szLockPath [F_PATH_MAX_SIZE]; F_FileHdl * pLockFileHdl = NULL; FLMUINT uiIoFlags = FLM_IO_RDWR | FLM_IO_EXCL | FLM_IO_SH_DENYRW; IF_FileSystem * pFileSystem = f_getFileSysPtr(); f_strcpy( szLockPath, pszBasePath); pFileSystem->pathAppend( szLockPath, "64.LCK"); // Attempt to create the lock file. If it fails, the lock file // may have been left because of a crash. Hence, we first try // to delete the file. If that succeeds, we then attempt to // create the file again. If it, or the 2nd create fail, we simply // return an access denied error. if( RC_BAD( rc = f_allocFileHdl( &pLockFileHdl))) { goto Exit; } #ifndef FLM_UNIX // On Unix, we do not want to delete the file because it // will succeed even if someone else has the file open. uiIoFlags |= FLM_IO_DELETE_ON_RELEASE; #endif if( RC_BAD( pLockFileHdl->create( szLockPath, uiIoFlags))) { #ifndef FLM_UNIX if (RC_BAD( pFileSystem->deleteFile( szLockPath))) { rc = RC_SET( NE_FLM_IO_ACCESS_DENIED); goto Exit; } else if (RC_BAD( pLockFileHdl->create( szLockPath, uiIoFlags))) { rc = RC_SET( NE_FLM_IO_ACCESS_DENIED); goto Exit; } #else if( RC_BAD( pLockFileHdl->open( szLockPath, uiIoFlags))) { rc = RC_SET( NE_FLM_IO_ACCESS_DENIED); goto Exit; } #endif } #ifdef FLM_UNIX if( RC_BAD( pLockFileHdl->lock())) { rc = RC_SET( NE_FLM_IO_ACCESS_DENIED); goto Exit; } #endif m_pLockFileHdl = pLockFileHdl; pLockFileHdl = NULL; Exit: if (pLockFileHdl) { (void)pLockFileHdl->close(); pLockFileHdl->Release(); pLockFileHdl = NULL; } return( rc); } /**************************************************************************** Desc: This is a private method that will truncate the spill file back to the specified size. ****************************************************************************/ RCODE F_MultiFileHdl::truncate( FLMUINT64 ui64NewSize) { RCODE rc = NE_FLM_OK; FLMUINT uiFileNum = getFileNum( ui64NewSize); IF_FileHdl * pFileHdl; if( RC_BAD( rc = getFileHdl( uiFileNum, TRUE, &pFileHdl))) { goto Exit; } if (RC_BAD( rc = pFileHdl->truncate( getFileOffset( ui64NewSize)))) { goto Exit; } Exit: return( rc); } /**************************************************************************** Desc: ****************************************************************************/ RCODE FLMAPI F_MultiFileHdl::getPath( char * pszPath) { f_strcpy( pszPath, m_szPath); return( NE_FLM_OK); }