/**************************************************************************** Desc: All of the fromAscii() functions convert values stored in strings to various native formats ****************************************************************************/ void F_IniFile::fromAscii( FLMBOOL * pbVal, const char * pszParamValue) { if( f_stricmp( pszParamValue, "true") == 0 || f_stricmp( pszParamValue, "enabled") == 0 || f_stricmp( pszParamValue, "on") == 0 || f_stricmp( pszParamValue, "1") == 0) { *pbVal = TRUE; } else { *pbVal = FALSE; } }
/******************************************************************** Desc: Edit Text *********************************************************************/ FLMBOOL ViewEditText( const char * pszPrompt, char * pszText, FLMUINT uiTextLen, FLMBOOL * pbValEntered) { char szTempBuf [100]; FLMUINT uiNumCols; FLMUINT uiNumRows; f_conGetScreenSize( &uiNumCols, &uiNumRows); f_conSetBackFore( FLM_BLACK, FLM_WHITE); f_conClearScreen( 0, uiNumRows - 2); ViewAskInput( pszPrompt, szTempBuf, sizeof( szTempBuf) - 1); f_conSetBackFore( FLM_BLACK, FLM_WHITE); f_conClearScreen( 0, uiNumRows - 2); if (f_stricmp( szTempBuf, "\\") == 0) { *pbValEntered = FALSE; return( FALSE); } if( !szTempBuf[ 0]) { *pbValEntered = FALSE; return( TRUE); } if (f_strlen( szTempBuf) >= uiTextLen) { szTempBuf [uiTextLen - 1] = 0; } f_strcpy( pszText, szTempBuf); *pbValEntered = TRUE; return( TRUE); }
/**************************************************************************** Desc: Returns the length of the base part of a database name. If the name ends with a '.' or ".db", this will not be included in the returned length. ****************************************************************************/ void flmGetDbBasePath( char * pszBaseDbName, const char * pszDbName, FLMUINT * puiBaseDbNameLen) { FLMUINT uiBaseLen = f_strlen( pszDbName); if( uiBaseLen <= 3 || f_stricmp( &pszDbName[ uiBaseLen - 3], ".db") != 0) { if( pszDbName[ uiBaseLen - 1] == '.') { uiBaseLen--; } } else { uiBaseLen -= 3; } f_memcpy( pszBaseDbName, pszDbName, uiBaseLen); pszBaseDbName[ uiBaseLen] = 0; if( puiBaseDbNameLen) { *puiBaseDbNameLen = uiBaseLen; } }
/******************************************************************** Desc: Get a number from the user *********************************************************************/ FLMBOOL ViewGetNum( const char * pszPrompt, void * pvNum, FLMBOOL bEnterHexFlag, FLMUINT uiNumBytes, FLMUINT64 ui64MaxValue, FLMBOOL * pbValEntered) { FLMBOOL bOk = FALSE; char szTempBuf[ 20]; FLMUINT uiLoop; FLMUINT uiChar; FLMBOOL bGetOK; FLMUINT64 ui64Num; FLMUINT uiMaxDigits; FLMUINT uiNumCols; FLMUINT uiNumRows; f_conGetScreenSize( &uiNumCols, &uiNumRows); if (bEnterHexFlag) { uiMaxDigits = uiNumBytes * 2; } else { uiMaxDigits = (uiNumBytes == 8 ? 20 : (uiNumBytes == 4 ? 10 : (uiNumBytes == 2 ? 5 : 3))); } for (;;) { bGetOK = TRUE; f_conSetBackFore( FLM_BLACK, FLM_WHITE); f_conClearScreen( 0, uiNumRows - 2); ViewAskInput( pszPrompt, szTempBuf, sizeof( szTempBuf)); f_conSetBackFore( FLM_BLACK, FLM_WHITE); f_conClearScreen( 0, uiNumRows - 2); if (f_stricmp( szTempBuf, "\\") == 0) { *pbValEntered = FALSE; goto Exit; } if( !szTempBuf[ 0]) { *pbValEntered = FALSE; bOk = TRUE; goto Exit; } uiLoop = 0; ui64Num = 0; while (szTempBuf[ uiLoop] && uiLoop < uiMaxDigits) { uiChar = szTempBuf[ uiLoop]; if (bEnterHexFlag) { ui64Num <<= 4; if (uiChar >= '0' && uiChar <= '9') { ui64Num += (FLMUINT64)(uiChar - '0'); } else if (uiChar >= 'a' && uiChar <= 'f') { ui64Num += (FLMUINT64)(uiChar - 'a' + 10); } else if (uiChar >= 'A' && uiChar <= 'F') { ui64Num += (FLMUINT64)(uiChar - 'A' + 10); } else { ViewShowError( "Illegal digit in number - must be hex digits"); bGetOK = FALSE; break; } } else if (uiChar < '0' || uiChar > '9') { ViewShowError( "Illegal digit in number - must be 0 through 9"); bGetOK = FALSE; break; } else { if (ui64MaxValue / 10 < ui64Num) { ViewShowError( "Number is too large"); bGetOK = FALSE; break; } else { ui64Num *= 10; if (ui64MaxValue - (FLMUINT64)(uiChar - '0') < ui64Num) { ViewShowError( "Number is too large"); bGetOK = FALSE; break; } else { ui64Num += (FLMUINT64)(uiChar - '0'); } } } uiLoop++; } if (bGetOK) { if (uiNumBytes == 8) { *((FLMUINT64 *)(pvNum)) = ui64Num; } else if (uiNumBytes == 4) { *((FLMUINT32 *)(pvNum)) = (FLMUINT32)ui64Num; } else if( uiNumBytes == 2) { *((FLMUINT16 *)(pvNum)) = (FLMUINT16)ui64Num; } else { *((FLMBYTE *)(pvNum)) = (FLMBYTE)ui64Num; } *pbValEntered = TRUE; bOk = TRUE; goto Exit; } } Exit: return( bOk); }
/******************************************************************** Desc: Edit binary data *********************************************************************/ FLMBOOL ViewEditBinary( const char * pszPrompt, FLMBYTE * pucBuf, FLMUINT * puiByteCount, FLMBOOL * pbValEntered) { FLMUINT uiMaxBytes = *puiByteCount; FLMUINT uiByteCount; FLMBOOL bOdd; char szTempBuf [300]; FLMUINT uiLoop; FLMUINT uiNumCols; FLMUINT uiNumRows; f_conGetScreenSize( &uiNumCols, &uiNumRows); if (!pszPrompt) { pszPrompt = "Enter Binary Values (in hex): "; } for (;;) { f_conSetBackFore( FLM_BLACK, FLM_WHITE); f_conClearScreen( 0, uiNumRows - 2); ViewAskInput( pszPrompt, szTempBuf, sizeof( szTempBuf)); f_conSetBackFore( FLM_BLACK, FLM_WHITE); f_conClearScreen( 0, uiNumRows - 2); if( f_stricmp( szTempBuf, "\\") == 0) { *pbValEntered = FALSE; return( FALSE); } if (!szTempBuf[ 0]) { *pbValEntered = FALSE; return( TRUE); } bOdd = FALSE; uiByteCount = 0; uiLoop = 0; while (szTempBuf [uiLoop]) { FLMBYTE ucValue; ucValue = szTempBuf [uiLoop]; if (ucValue >= '0' && ucValue <= '9') { ucValue -= '0'; } else if (ucValue >= 'a' && ucValue <= 'f') { ucValue = ucValue - 'a' + 10; } else if (ucValue >= 'A' && ucValue <= 'F') { ucValue = ucValue - 'A' + 10; } else if (ucValue == ' ' || ucValue == '\t') { bOdd = FALSE; uiLoop++; continue; } else { uiByteCount = 0; ViewShowError( "Non-HEX digits are illegal"); break; } // If we get here, we have another digit if (bOdd) { bOdd = FALSE; (*pucBuf) <<= 4; (*pucBuf) |= ucValue; } else { if (uiByteCount == uiMaxBytes) { break; } // Don't increment pucBuf the first time through if (uiByteCount) { pucBuf++; } uiByteCount++; *pucBuf = ucValue; bOdd = TRUE; } uiLoop++; } if (!uiByteCount) { if (!szTempBuf[ uiLoop]) { ViewShowError( "No HEX digits entered"); } } else if (szTempBuf[ uiLoop]) { ViewShowError( "Too many digits entered"); } else { *puiByteCount = uiByteCount; *pbValEntered = TRUE; return( TRUE); } } }
/**************************************************************************** Desc: Renames all files of a database ****************************************************************************/ RCODE F_DbSystem::dbRename( const char * pszDbName, // [IN] Database to be renamed. const char * pszDataDir, // [IN] Directory for data files. const char * pszRflDir, // [IN] RFL directory of database. NULL can be // passed to indicate that the log files are located // in the same directory as the other database files. const char * pszNewDbName, // [IN] New name to be given to the database. May be // the short name only, or include a directory. If it // includes a directory, it must be the same directory // as the directory given in pszDbName. FLMBOOL bOverwriteDestOk, // [IN] Ok to overwrite existing file with rename? IF_DbRenameStatus * ifpStatus) // [IN] Status callback function. { RCODE rc = NE_SFLM_OK; FLMUINT uiFileNumber; DBRenameInfo * pRenameList = NULL; FLMBOOL bFileFound; char * pszOldName = NULL; char * pszNewName; char * pszOldDataName; char * pszNewDataName; char * pszFullNewName; char szOldBase [F_FILENAME_SIZE]; char szNewBase [F_FILENAME_SIZE]; char * pszExtOld; char * pszExtNew; char * pszDataExtOld; char * pszDataExtNew; // Cannot handle empty database name. flmAssert( pszDbName && *pszDbName); flmAssert( pszNewDbName && *pszNewDbName); // Allocate memory for a read buffer, the log header, and various // file names. if (RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE * 5, &pszOldName))) { goto Exit; } pszNewName = pszOldName + F_PATH_MAX_SIZE; pszOldDataName = pszNewName + F_PATH_MAX_SIZE; pszNewDataName = pszOldDataName + F_PATH_MAX_SIZE; pszFullNewName = pszNewDataName + F_PATH_MAX_SIZE; // There must be either no directory specified for the new name, or // it must be identical to the old directory. if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->pathReduce( pszDbName, pszOldName, szOldBase))) { goto Exit; } if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->pathReduce( pszNewDbName, pszNewName, szNewBase))) { goto Exit; } // Directories must be the same. if (*pszNewName && f_stricmp( pszOldName, pszNewName) != 0) { rc = RC_SET( NE_SFLM_INVALID_PARM); goto Exit; } f_strcpy( pszNewName, pszOldName); if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->pathAppend( pszNewName, szNewBase))) { goto Exit; } f_strcpy( pszFullNewName, pszNewName); f_strcpy( pszOldName, pszDbName); if (pszDataDir && *pszDataDir) { f_strcpy( pszOldDataName, pszDataDir); f_strcpy( pszNewDataName, pszDataDir); if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->pathAppend( pszOldDataName, szOldBase))) { goto Exit; } if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->pathAppend( pszNewDataName, szNewBase))) { goto Exit; } } else { f_strcpy( pszNewDataName, pszNewName); f_strcpy( pszOldDataName, pszOldName); } // First make sure we have closed the databases and gotten rid of // them from our internal memory tables - in case they had been open. if (RC_BAD( rc = checkDatabaseClosed( pszDbName, pszDataDir))) { goto Exit; } if (RC_BAD( rc = checkDatabaseClosed( pszFullNewName, pszDataDir))) { goto Exit; } // Start renaming files, beginning with the main DB file. if (RC_BAD( rc = flmRenameFile( pszDbName, pszFullNewName, bOverwriteDestOk, FALSE, &pRenameList, &bFileFound, ifpStatus))) { goto Exit; } // Find where the extension of the old and new database names are pszExtOld = pszOldName + f_strlen( pszOldName) - 1; pszDataExtOld = pszOldDataName + f_strlen( pszOldDataName) - 1; while (pszExtOld != pszOldName && *pszExtOld != '.') { pszExtOld--; // Both the old db name and old data name have the same // base name, so we can decrement pszDataExtOld // at the same time we decrement pszExtOld. pszDataExtOld--; } if (*pszExtOld != '.') { pszExtOld = pszOldName + f_strlen( pszOldName); pszDataExtOld = pszOldDataName + f_strlen( pszOldDataName); } pszExtNew = pszNewName + f_strlen( pszNewName) - 1; pszDataExtNew = pszNewDataName + f_strlen( pszNewDataName) - 1; while (pszExtNew != pszOldName && *pszExtNew != '.') { pszExtNew--; // Both the new db name and new data name have the same // base name, so we can decrement pszDataExtNew // at the same time we decrement pszExtNew. pszDataExtNew--; } if (*pszExtNew != '.') { pszExtNew = pszNewName + f_strlen( pszNewName); pszDataExtNew = pszNewDataName + f_strlen( pszNewDataName); } // Rename the .lck file, if any. This is necessary for UNIX. f_strcpy( pszExtOld, ".lck"); f_strcpy( pszExtNew, ".lck"); if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, ifpStatus))) { goto Exit; } // Rename block (data) files. uiFileNumber = 1; for (;;) { F_SuperFileClient::bldSuperFileExtension( uiFileNumber, pszDataExtOld); F_SuperFileClient::bldSuperFileExtension( uiFileNumber, pszDataExtNew); if (RC_BAD( rc = flmRenameFile( pszOldDataName, pszNewDataName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, ifpStatus))) { goto Exit; } if (!bFileFound) { break; } if (uiFileNumber == MAX_DATA_BLOCK_FILE_NUMBER) { break; } uiFileNumber++; } // Rename rollback log files. uiFileNumber = FIRST_LOG_BLOCK_FILE_NUMBER; for (;;) { F_SuperFileClient::bldSuperFileExtension( uiFileNumber, pszExtOld); F_SuperFileClient::bldSuperFileExtension( uiFileNumber, pszExtNew); if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, ifpStatus))) { goto Exit; } if (!bFileFound) { break; } if (uiFileNumber == MAX_LOG_BLOCK_FILE_NUMBER) { break; } uiFileNumber++; } // Rename the RFL directory. if (RC_BAD( rc = rflGetDirAndPrefix( pszDbName, pszRflDir, pszOldName))) { goto Exit; } if (RC_BAD( rc = rflGetDirAndPrefix( pszFullNewName, pszRflDir, pszNewName))) { goto Exit; } if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, ifpStatus))) { goto Exit; } Exit: if (pszOldName) { f_free( &pszOldName); } // Free the list of renamed files. while (pRenameList) { DBRenameInfo * pRenameFile; pRenameFile = pRenameList; pRenameList = pRenameList->pNext; // If we had an error of some sort, attempt to un-rename // the file that had been renamed. if (RC_BAD( rc)) { gv_SFlmSysData.pFileSystem->renameFile( pRenameFile->Info.szDstFileName, pRenameFile->Info.szSrcFileName); } f_free( &pRenameFile); } return( rc); }
/**************************************************************************** Desc: Rename a database file and add to list of renamed files. ****************************************************************************/ FSTATIC RCODE flmRenameFile( const char * pszSrcFileName, const char * pszDstFileName, FLMBOOL bOverwriteDestOk, FLMBOOL bPathNotFoundOk, DBRenameInfo ** ppRenameList, FLMBOOL * pbFileFound, IF_DbRenameStatus * ifpStatus) { RCODE rc = NE_SFLM_OK; DBRenameInfo * pRenameFile = NULL; *pbFileFound = FALSE; // Should not do anything if the source and destination names // are the same. if (f_stricmp( pszSrcFileName, pszDstFileName) == 0) { if (gv_SFlmSysData.pFileSystem->doesFileExist( pszSrcFileName) == NE_SFLM_OK) { *pbFileFound = TRUE; } goto Exit; } if (RC_BAD( rc = f_alloc( sizeof( DBRenameInfo), &pRenameFile))) { goto Exit; } // If a destination file exists, and it is OK to overwrite // it, it must be deleted. if (bOverwriteDestOk) { if (gv_SFlmSysData.pFileSystem->isDir( pszDstFileName)) { if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->removeDir( pszDstFileName, TRUE))) { goto Exit; } } else { if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->deleteFile( pszDstFileName))) { if (rc == NE_FLM_IO_PATH_NOT_FOUND || rc == NE_FLM_IO_INVALID_FILENAME) { rc = NE_SFLM_OK; } else { goto Exit; } } } } // If names are the same, no need to actually do the // rename. if (RC_BAD( rc = gv_SFlmSysData.pFileSystem->renameFile( pszSrcFileName, pszDstFileName))) { if (rc == NE_FLM_IO_PATH_NOT_FOUND || rc == NE_FLM_IO_INVALID_FILENAME) { if (bPathNotFoundOk) { rc = NE_SFLM_OK; } else { goto Exit; } } else { goto Exit; } } else { *pbFileFound = TRUE; pRenameFile->pNext = *ppRenameList; *ppRenameList = pRenameFile; // Do user callback. User could choose to stop the rename // from continuing. if (ifpStatus) { f_strcpy( pRenameFile->Info.szSrcFileName, pszSrcFileName); f_strcpy( pRenameFile->Info.szDstFileName, pszDstFileName); if (RC_BAD( rc = ifpStatus->dbRenameStatus( pRenameFile->Info.szSrcFileName, pRenameFile->Info.szDstFileName))) { goto Exit; } } // So it won't get deallocated at exit. pRenameFile = NULL; } Exit: if (pRenameFile) { f_free( &pRenameFile); } return( rc); }
/**************************************************************************** Desc: This routine is used to see if a file is already in use somewhere. This is only called for files which are opened directly by the application. Notes: This routine assumes that the global mutex is locked, but it may unlock and re-lock the mutex if needed. ****************************************************************************/ RCODE F_DbSystem::findDatabase( const char * pszDbPath, const char * pszDataDir, F_Database ** ppDatabase) { RCODE rc = NE_XFLM_OK; F_BUCKET * pBucket; FLMUINT uiBucket; FLMBOOL bMutexLocked = TRUE; F_Database * pDatabase; char szDbPathStr1 [F_PATH_MAX_SIZE]; char szDbPathStr2 [F_PATH_MAX_SIZE]; F_SEM hWaitSem = F_SEM_NULL; *ppDatabase = NULL; // Normalize the path to a string before looking for it. // NOTE: On non-UNIX, non-WIN platforms, this will basically convert // the string to upper case. if (RC_BAD( rc = gv_XFlmSysData.pFileSystem->pathToStorageString( pszDbPath, szDbPathStr1))) { goto Exit; } Retry: *ppDatabase = NULL; if( !bMutexLocked) { f_mutexLock( gv_XFlmSysData.hShareMutex); bMutexLocked = TRUE; } pBucket = gv_XFlmSysData.pDatabaseHashTbl; uiBucket = f_strHashBucket( szDbPathStr1, pBucket, FILE_HASH_ENTRIES); pDatabase = (F_Database *)pBucket [uiBucket].pFirstInBucket; while (pDatabase) { // Compare the strings. On non-Unix platforms we must use // f_stricmp, because case does not matter for file names // on those platforms. #ifdef FLM_UNIX if( f_strcmp( szDbPathStr1, pDatabase->m_pszDbPath) == 0) #else if( f_stricmp( szDbPathStr1, pDatabase->m_pszDbPath) == 0) #endif { // Make sure data paths match. if (pszDataDir && *pszDataDir) { if (RC_BAD( rc = gv_XFlmSysData.pFileSystem->pathToStorageString( pszDataDir, szDbPathStr2))) { goto Exit; } if (pDatabase->m_pszDataDir) { // f_stricmp must be used on non-unix platforms because file // names are case insensitive on those platforms. #ifdef FLM_UNIX if (f_strcmp( pDatabase->m_pszDataDir, szDbPathStr2) != 0) #else if (f_stricmp( pDatabase->m_pszDataDir, szDbPathStr2) != 0) #endif { rc = RC_SET( NE_XFLM_DATA_PATH_MISMATCH); goto Exit; } } else { rc = RC_SET( NE_XFLM_DATA_PATH_MISMATCH); goto Exit; } } else if (pDatabase->m_pszDataDir) { rc = RC_SET( NE_XFLM_DATA_PATH_MISMATCH); goto Exit; } *ppDatabase = pDatabase; break; } pDatabase = pDatabase->m_pNext; } if (*ppDatabase && pDatabase->m_uiFlags & DBF_BEING_CLOSED) { if( RC_BAD( rc = f_semCreate( &hWaitSem))) { goto Exit; } // Put ourselves into the notify list and then re-try // the lookup when we wake up if (RC_BAD( rc = f_notifyWait( gv_XFlmSysData.hShareMutex, hWaitSem, NULL, &pDatabase->m_pCloseNotifies))) { goto Exit; } f_semDestroy( &hWaitSem); // The mutex will be locked at this point. Re-try the lookup. // IMPORTANT NOTE: pDatabase will have been destroyed by this // time. DO NOT use it for anything! goto Retry; } Exit: if( hWaitSem != F_SEM_NULL) { f_semDestroy( &hWaitSem); } // Make sure the global mutex is re-locked before exiting if( !bMutexLocked) { f_mutexLock( gv_XFlmSysData.hShareMutex); } return( rc); }
/******************************************************************************* Desc: Renames a database *******************************************************************************/ FLMEXP RCODE FLMAPI FlmDbRename( const char * pszDbName, const char * pszDataDir, const char * pszRflDir, const char * pszNewDbName, FLMBOOL bOverwriteDestOk, STATUS_HOOK fnStatusCallback, void * UserData) { RCODE rc = FERR_OK; IF_FileHdl * pFileHdl = NULL; FLMUINT uiFileNumber; FILE_HDR FileHdr; LOG_HDR LogHdr; DBRenameInfo * pRenameList = NULL; FLMBOOL bFileFound; FLMBYTE * pucBuffer = NULL; FLMBYTE * pucLogHdr; char * pszOldName; char * pszNewName; char * pszOldDataName; char * pszNewDataName; char * pszFullNewName; char szOldBase[ F_FILENAME_SIZE]; char szNewBase[ F_FILENAME_SIZE]; char * pszExtOld; char * pszExtNew; char * pszDataExtOld; char * pszDataExtNew; // Cannot handle empty database name. flmAssert( pszDbName && *pszDbName); flmAssert( pszNewDbName && *pszNewDbName); // Allocate memory for a read buffer, the log header, and various // file names. if( RC_BAD( rc = f_allocAlignedBuffer( 2048 + LOG_HEADER_SIZE + F_PATH_MAX_SIZE * 5, &pucBuffer))) { goto Exit; } pucLogHdr = pucBuffer + 2048; pszOldName = (char *)(pucLogHdr + LOG_HEADER_SIZE); pszNewName = pszOldName + F_PATH_MAX_SIZE; pszOldDataName = pszNewName + F_PATH_MAX_SIZE; pszNewDataName = pszOldDataName + F_PATH_MAX_SIZE; pszFullNewName = pszNewDataName + F_PATH_MAX_SIZE; // There must be either no directory specified for the new name, or // it must be identical to the old directory. if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathReduce( pszDbName, pszOldName, szOldBase))) { goto Exit; } if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathReduce( pszNewDbName, pszNewName, szNewBase))) { goto Exit; } // Directories must be the same. if (*pszNewName && f_stricmp( pszOldName, pszNewName) != 0) { rc = RC_SET( FERR_INVALID_PARM); goto Exit; } f_strcpy( pszNewName, pszOldName); if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathAppend( pszNewName, szNewBase))) { goto Exit; } f_strcpy( pszFullNewName, pszNewName); f_strcpy( pszOldName, pszDbName); if( pszDataDir && *pszDataDir) { f_strcpy( pszOldDataName, pszDataDir); f_strcpy( pszNewDataName, pszDataDir); if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathAppend( pszOldDataName, szOldBase))) { goto Exit; } if (RC_BAD( rc = gv_FlmSysData.pFileSystem->pathAppend( pszNewDataName, szNewBase))) { goto Exit; } } else { f_strcpy( pszNewDataName, pszNewName); f_strcpy( pszOldDataName, pszOldName); } // First make sure we have closed the databases and gotten rid of // them from our internal memory tables - in case they had been open. if( RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, (void *)pszDbName, (void *)pszDataDir))) { goto Exit; } if( RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, (void *)pszFullNewName, (void *)pszDataDir))) { goto Exit; } gv_FlmSysData.pFileHdlCache->closeUnusedFiles(); // Open the file so we can get the log header. if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( pszDbName, gv_FlmSysData.uiFileOpenFlags, &pFileHdl))) { goto Exit; } // Read the header to get the low and high RFL log // file numbers. if (RC_BAD( flmReadAndVerifyHdrInfo( NULL, pFileHdl, pucBuffer, &FileHdr, &LogHdr, pucLogHdr))) { goto Exit; } // Close the file. pFileHdl->Release(); pFileHdl = NULL; // Start renaming files, beginning with the main DB file. if( RC_BAD( rc = flmRenameFile( pszDbName, pszFullNewName, bOverwriteDestOk, FALSE, &pRenameList, &bFileFound, fnStatusCallback, UserData))) { goto Exit; } // Find where the extension of the old and new database names are pszExtOld = pszOldName + f_strlen( pszOldName) - 1; pszDataExtOld = pszOldDataName + f_strlen( pszOldDataName) - 1; while (pszExtOld != pszOldName && *pszExtOld != '.') { pszExtOld--; // Both the old db name and old data name have the same // base name, so we can decrement pszDataExtOld // at the same time we decrement pszExtOld. pszDataExtOld--; } if (*pszExtOld != '.') { pszExtOld = pszOldName + f_strlen( pszOldName); pszDataExtOld = pszOldDataName + f_strlen( pszOldDataName); } pszExtNew = pszNewName + f_strlen( pszNewName) - 1; pszDataExtNew = pszNewDataName + f_strlen( pszNewDataName) - 1; while (pszExtNew != pszOldName && *pszExtNew != '.') { pszExtNew--; // Both the new db name and new data name have the same // base name, so we can decrement pszDataExtNew // at the same time we decrement pszExtNew. pszDataExtNew--; } if (*pszExtNew != '.') { pszExtNew = pszNewName + f_strlen( pszNewName); pszDataExtNew = pszNewDataName + f_strlen( pszNewDataName); } // Rename the .lck file, if any. This is necessary for UNIX. f_strcpy( pszExtOld, ".lck"); f_strcpy( pszExtNew, ".lck"); if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, fnStatusCallback, UserData))) { goto Exit; } // Rename block (data) files. uiFileNumber = 1; for (;;) { F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum, uiFileNumber, pszDataExtOld); F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum, uiFileNumber, pszDataExtNew); if (RC_BAD( rc = flmRenameFile( pszOldDataName, pszNewDataName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, fnStatusCallback, UserData))) { goto Exit; } if (!bFileFound) { break; } if (uiFileNumber == MAX_DATA_BLOCK_FILE_NUMBER( FileHdr.uiVersionNum)) { break; } uiFileNumber++; } // Rename rollback log files. uiFileNumber = FIRST_LOG_BLOCK_FILE_NUMBER (FileHdr.uiVersionNum); for (;;) { F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum, uiFileNumber, pszExtOld); F_SuperFileClient::bldSuperFileExtension( FileHdr.uiVersionNum, uiFileNumber, pszExtNew); if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, fnStatusCallback, UserData))) { goto Exit; } if (!bFileFound) { break; } if (uiFileNumber == MAX_LOG_BLOCK_FILE_NUMBER( FileHdr.uiVersionNum)) { break; } uiFileNumber++; } // Rename roll-forward log files. if (FileHdr.uiVersionNum < FLM_FILE_FORMAT_VER_4_3) { // For pre-4.3 versions, only need to rename one RFL file. if (RC_BAD( rc = rflGetFileName( FileHdr.uiVersionNum, pszDbName, pszRflDir, 1, pszOldName))) { goto Exit; } if (RC_BAD( rc = rflGetFileName( FileHdr.uiVersionNum, pszFullNewName, pszRflDir, 1, pszNewName))) { goto Exit; } if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, fnStatusCallback, UserData))) { goto Exit; } } else { // For 4.3 and greater, rename the RFL directory. if (RC_BAD( rc = rflGetDirAndPrefix( FileHdr.uiVersionNum, pszDbName, pszRflDir, pszOldName, szOldBase))) { goto Exit; } if (RC_BAD( rc = rflGetDirAndPrefix( FileHdr.uiVersionNum, pszFullNewName, pszRflDir, pszNewName, szNewBase))) { goto Exit; } if (RC_BAD( rc = flmRenameFile( pszOldName, pszNewName, bOverwriteDestOk, TRUE, &pRenameList, &bFileFound, fnStatusCallback, UserData))) { goto Exit; } } Exit: if( pFileHdl) { pFileHdl->Release(); } if( pucBuffer) { f_freeAlignedBuffer( &pucBuffer); } // Free the list of renamed files. while( pRenameList) { DBRenameInfo * pRenameFile; pRenameFile = pRenameList; pRenameList = pRenameList->pNext; // If we had an error of some sort, attempt to un-rename // the file that had been renamed. if (RC_BAD( rc)) { gv_FlmSysData.pFileSystem->renameFile( pRenameFile->Info.szDstFileName, pRenameFile->Info.szSrcFileName); } f_free( &pRenameFile); } return( rc); }
/**************************************************************************** Desc: This function handle the details of extracting the parameters needed to interpret the request and then generating the response HTML page ****************************************************************************/ RCODE F_FFilePage::display( FLMUINT uiNumParams, const char ** ppszParams) { RCODE rc = FERR_OK; #define GENERIC_SIZE_B 20 char szFrom[ GENERIC_SIZE_B]; char szBucket[ 4]; FLMUINT uiBucket; FFILE localFFile; FFILE * pFile; FLMBOOL bRefresh; void * pvAddress; char szAddress[GENERIC_SIZE_B]; char szLink[GENERIC_SIZE_B]; FLMBOOL bFlmLocked = FALSE; DATASTRUCT DataStruct; FLMBYTE * pszTemp = NULL; FLMBYTE * pszTemp1 = NULL; if( RC_BAD( rc = f_alloc( 150, &pszTemp))) { printErrorPage( rc, TRUE, (char *)"Failed to allocate temporary buffer"); goto Exit; } if( RC_BAD( rc = f_alloc( 150, &pszTemp1))) { printErrorPage( rc, TRUE, (char *)"Failed to allocate temporary buffer"); goto Exit; } // Initialize a few variables first... szFrom[0] = '\0'; szBucket[0] = '\0'; pFile = NULL; // Get the "From" parameter. We use this to determine everything else. if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "From", sizeof( szFrom), szFrom))) { goto Exit; } f_mutexLock( gv_FlmSysData.hShareMutex); bFlmLocked = TRUE; if (!f_stricmp( szFrom, "FileHashTbl")) { // Get the hash bucket index if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Bucket", sizeof( szBucket), szBucket))) { goto Exit; } uiBucket = f_atoud( szBucket); pFile = (FFILE *)gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket; } else if ( (f_stricmp( szFrom, "SCacheBlock") == 0) || (f_stricmp( szFrom, "RCache") == 0) || (f_stricmp( szFrom, "FDB") == 0)) { // Get the FFile address and the Hash Bucket if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Bucket", sizeof( szBucket), szBucket))) { goto Exit; } uiBucket = f_atoud( szBucket); if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Address", sizeof( szAddress), szAddress))) { goto Exit; } pvAddress = (void *)f_atoud( szAddress); pFile = (FFILE *)gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket; while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pNext; } } else if (f_stricmp( szFrom, "FlmSysData") == 0) { // Get the Link and the FFile address if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Link", sizeof( szLink), szLink))) { goto Exit; } if (RC_BAD( rc = ExtractParameter( uiNumParams, ppszParams, "Address", sizeof( szAddress), szAddress))) { goto Exit; } pvAddress = (void *)f_atoud( szAddress); if (f_stricmp( szLink, "pMrnuFile") == 0) { pFile = gv_FlmSysData.pMrnuFile; // Now let's make sure we are looking at the right FFile... while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pNextNUFile; } } else if (f_stricmp( szLink, "pLrnuFile") == 0) { pFile = gv_FlmSysData.pLrnuFile; // Now let's make sure we are looking at the right FFile... while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pPrevNUFile; } } } else if (f_stricmp( szFrom, "FFile") == 0) { // We need to get the Link, Bucket & Address if (RC_BAD(rc = ExtractParameter( uiNumParams, ppszParams, "Link", sizeof( szLink), szLink))) { goto Exit; } if (RC_BAD(rc = ExtractParameter( uiNumParams, ppszParams, "Address", sizeof( szAddress), szAddress))) { goto Exit; } pvAddress = (void *)f_atoud( szAddress); if (RC_BAD(rc = ExtractParameter( uiNumParams, ppszParams, "Bucket", sizeof( szBucket), szBucket))) { goto Exit; } uiBucket = f_atoud( szBucket); // First, let's get a reference to an FFile from the specified bucket if (gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket) { pFile = (FFILE *)gv_FlmSysData.pFileHashTbl[uiBucket].pFirstInBucket; } // Now let's make sure we are looking at the right FFile... while (pFile && (void *)pFile != pvAddress) { pFile = pFile->pNext; } // Now what link are we supposed to follow? if (f_stricmp( szLink, "pNext") == 0) { pFile = pFile->pNext; } else if (f_stricmp( szLink, "pPrev") == 0) { pFile = pFile->pPrev; } else if (f_stricmp( szLink, "pNextNUFile") == 0) { pFile = pFile->pNextNUFile; } else if (f_stricmp( szLink, "pPrevNUFile") == 0) { pFile = pFile->pPrevNUFile; } } // Gather additional data if present. Initialize the structure before // using it. f_memset( &DataStruct, 0, sizeof(DataStruct)); if (pFile) { f_memcpy( &localFFile, pFile, sizeof(localFFile)); if (pFile->pSCacheList) { DataStruct.SCacheBlkAddress = pFile->pSCacheList->uiBlkAddress; DataStruct.SCacheLowTransID = scaGetLowTransID( pFile->pSCacheList), DataStruct.SCacheHighTransID = pFile->pSCacheList->uiHighTransID; } if (pFile->pPendingWriteList) { DataStruct.PendingWriteBlkAddress = pFile->pPendingWriteList->uiBlkAddress; DataStruct.PendingWriteLowTransID = scaGetLowTransID( pFile->pPendingWriteList), DataStruct.PendingWriteHighTransID = pFile->pPendingWriteList->uiHighTransID; } if (pFile->pLastDirtyBlk) { DataStruct.LastDirtyBlkAddress = pFile->pLastDirtyBlk->uiBlkAddress; DataStruct.LastDirtyLowTransID = scaGetLowTransID( pFile->pLastDirtyBlk), DataStruct.LastDirtyHighTransID = pFile->pLastDirtyBlk->uiHighTransID; } if (pFile->pFirstRecord) { DataStruct.FirstRecordContainer = pFile->pFirstRecord->uiContainer; DataStruct.FirstRecordDrn = pFile->pFirstRecord->uiDrn; DataStruct.FirstRecordLowTransId = pFile->pFirstRecord->uiLowTransId; } if (pFile->pLastRecord) { DataStruct.LastRecordContainer = pFile->pLastRecord->uiContainer; DataStruct.LastRecordDrn = pFile->pLastRecord->uiDrn; DataStruct.LastRecordLowTransId = pFile->pLastRecord->uiLowTransId; } } f_mutexUnlock( gv_FlmSysData.hShareMutex); bFlmLocked = FALSE; stdHdr(); fnPrintf( m_pHRequest, HTML_DOCTYPE); fnPrintf( m_pHRequest, "<html>\n"); // Determine if we are being requested to refresh this page or not. if ((bRefresh = DetectParameter( uiNumParams, ppszParams, "Refresh")) == TRUE) { // Send back the page with a refresh command in the header f_sprintf( (char *)pszTemp, "%s/FFile?Refresh&From=%s&Bucket=%s", m_pszURLString, szFrom, szBucket); fnPrintf( m_pHRequest, "<HEAD>" "<META http-equiv=\"refresh\" content=\"5; url=%s\">" "<TITLE>FFile Structure</TITLE>\n", pszTemp); } else { fnPrintf( m_pHRequest, "<HEAD><TITLE>FFile Structure</TITLE>\n"); } printStyle(); fnPrintf( m_pHRequest, "</HEAD>\n"); fnPrintf( m_pHRequest, "<body>\n"); // If we are not to refresh this page, then don't include the // refresh meta command if (!bRefresh) { f_sprintf( (char *)pszTemp, "<A HREF=%s/FFile?Refresh&From=%s&Bucket=%s>Start Auto-refresh (5 sec.)</A>", m_pszURLString, szFrom, szBucket); } else { f_sprintf( (char *)pszTemp, "<A HREF=%s/FFile?From=%s&Bucket=%s>Stop Auto-refresh</A>", m_pszURLString, szFrom, szBucket); } // Prepare the refresh link. f_sprintf( (char *)pszTemp1, "<A HREF=%s/FFile?From=%s&Bucket=%s>Refresh</A>", m_pszURLString, szFrom, szBucket); // Show the table headings and the refresh option. if (pFile) { // Write out the table headings printTableStart( "FFile Structure", 4, 100); printTableRowStart(); printColumnHeading( "", JUSTIFY_LEFT, FLM_IMON_COLOR_PUTTY_1, 4, 1, FALSE); fnPrintf( m_pHRequest, "%s, ", pszTemp1); fnPrintf( m_pHRequest, "%s\n", pszTemp); printColumnHeadingClose(); printTableRowEnd(); // Write out the table headings. printTableRowStart(); printColumnHeading( "Byte Offset (hex)"); printColumnHeading( "Field Name"); printColumnHeading( "Field Type"); printColumnHeading( "Value"); printTableRowEnd(); write_data( (pFile ? &localFFile: NULL), (void *)pFile, &DataStruct); } else { // Write out an error page... fnPrintf( m_pHRequest, "<P>Unable to find the FFile structure that you requested." " This is probably because the state of the cache changed between " "the time that you displayed the previous page and the time that you " "clicked on the link that brought you here.\n" "<P>Click on your browser's \"Back\" button, then click \"Reload\" " "and then try the link again.\n"); } fnPrintf( m_pHRequest, "</body></html>\n"); fnEmit(); Exit: if (bFlmLocked) { f_mutexUnlock( gv_FlmSysData.hShareMutex); bFlmLocked = FALSE; } if (pszTemp) { f_free( &pszTemp); } if (pszTemp1) { f_free( &pszTemp1); } return( rc); }
/******************************************************************** Desc: ? *********************************************************************/ FLMINT ViewGetKey( void) { RCODE rc = FERR_OK; FlmRecord * pKey = NULL; void * pvFld; char Prompt [80]; FLMUINT Num; FLMUINT ValEntered; FLMUINT Len; char TempBuf [80]; FLMUINT NumFields; FLMUINT i; FLMINT GetOK; FLMBYTE FieldName [80]; FLMBYTE FieldType [16]; FLMINT KeyEntered = FALSE; FLMBYTE LFH[ LFH_SIZE]; FLMUINT FileOffset; LFILE * pLFile = NULL; IXD * pIxd; IFD * pIfd; FLMUINT uiRootBlkAddress; FLMBOOL bTruncated; if (!gv_bViewHdrRead) ViewReadHdr(); /* See if we can get dictionary information. */ ViewGetDictInfo(); if (gv_bViewHaveDictInfo) { /* Find the logical file */ if ((RC_BAD( fdictGetIndex( ((FDB *)gv_hViewDb)->pDict, ((FDB *)gv_hViewDb)->pFile->bInLimitedMode, gv_uiViewSearchLfNum, &pLFile, NULL))) && (RC_BAD( fdictGetContainer( ((FDB *)gv_hViewDb)->pDict, gv_uiViewSearchLfNum, &pLFile)))) { pLFile = NULL; } } /* See if we have a valid logical file */ if ((gv_uiViewSearchLfNum == FLM_DATA_CONTAINER) || (gv_uiViewSearchLfNum == FLM_DICT_CONTAINER) || (pLFile)) { /* Get the LFH information for the logical file */ if (!ViewGetLFH( gv_uiViewSearchLfNum, LFH, &FileOffset)) { ViewShowError( "Could not get LFH for logical file"); return( FALSE); } uiRootBlkAddress = FB2UD( &LFH [LFH_ROOT_BLK_OFFSET]); if (uiRootBlkAddress == 0xFFFFFFFF) { ViewShowError( "Logical file is empty"); return( FALSE); } } else { ViewShowError( "Logical file not defined"); return( FALSE); } if ((gv_uiViewSearchLfNum == FLM_DATA_CONTAINER) || (gv_uiViewSearchLfNum == FLM_DICT_CONTAINER) || ((pLFile) && (pLFile->uiLfType == LF_CONTAINER))) { if (gv_uiViewSearchLfNum == FLM_DICT_CONTAINER) f_strcpy( TempBuf, "Enter Dictionary Record Number: "); else if (gv_uiViewSearchLfNum == FLM_DATA_CONTAINER) f_strcpy( TempBuf, "Enter Data Container Record Number: "); else f_sprintf( (char *)TempBuf, "Enter Record Number For Container %u: ", (unsigned)gv_uiViewSearchLfNum); if ((!ViewGetNum( TempBuf, &Num, FALSE, 4, 0xFFFFFFFF, &ValEntered)) || (!ValEntered)) return( FALSE); f_UINT32ToBigEndian( (FLMUINT32)Num, gv_ucViewSearchKey); gv_uiViewSearchKeyLen = 4; return( TRUE); } /* At this point, we are dealing with an index. */ if (gv_uiViewSearchLfNum == FLM_DICT_INDEX) { FLMUINT wTagType = 0; FLMUINT wElmLen; while (!wTagType) { if ((!ViewEditText( "Enter Type:", TempBuf, sizeof( TempBuf), &ValEntered)) || (!ValEntered)) return( FALSE); else if ((f_stricmp( TempBuf, "F") == 0) || (f_stricmp( TempBuf, "FIELD") == 0)) { wTagType = FLM_FIELD_TAG; } else if ((f_stricmp( TempBuf, "I") == 0) || (f_stricmp( TempBuf, "INDEX") == 0)) { wTagType = FLM_INDEX_TAG; } else if ((f_stricmp( TempBuf, "C") == 0) || (f_stricmp( TempBuf, "CONTAINER") == 0)) { wTagType = FLM_CONTAINER_TAG; } else if ((f_stricmp( TempBuf, "A") == 0) || (f_stricmp( TempBuf, "AREA") == 0)) { wTagType = FLM_AREA_TAG; } else { ViewShowError( "Illegal type, must be F)ield, I)ndex, C)ontainer, R)ecord, or A)rea"); wTagType = 0; } } gv_ucViewSearchKey [0] = KY_CONTEXT_PREFIX; f_UINT16ToBigEndian( (FLMUINT16)wTagType, &gv_ucViewSearchKey [1]); gv_uiViewSearchKeyLen += KY_CONTEXT_LEN; gv_ucViewSearchKey [gv_uiViewSearchKeyLen++] = COMPOUND_MARKER; if (!ViewEditText( "Enter Name:", TempBuf, sizeof( TempBuf), &ValEntered)) return( FALSE); /* Collate the name. */ wElmLen = MAX_KEY_SIZ - gv_uiViewSearchKeyLen; if (RC_BAD( rc = KYCollateValue( &gv_ucViewSearchKey [gv_uiViewSearchKeyLen], &wElmLen, (const FLMBYTE *)TempBuf, (FLMUINT)f_strlen( TempBuf), FLM_TEXT_TYPE, MAX_KEY_SIZ, NULL, NULL, gv_ViewHdrInfo.FileHdr.uiDefaultLanguage, FALSE, FALSE, FALSE, &bTruncated))) { ViewShowRCError( "collating name", rc); return( FALSE); } gv_uiViewSearchKeyLen += wElmLen; return( TRUE); } else if (!pLFile) { ViewShowError( "Cannot get logical file information"); return( FALSE); } else if (RC_BAD( fdictGetIndex( ((FDB *)gv_hViewDb)->pDict, ((FDB *)gv_hViewDb)->pFile->bInLimitedMode, gv_uiViewSearchLfNum, &pLFile, &pIxd))) { ViewShowError( "Cannot get index field information"); return( FALSE); } else { pIfd = pIxd->pFirstIfd; NumFields = pIxd->uiNumFlds; if (!(pIfd->uiFlags & IFD_COMPOUND)) { NumFields = 1; } if( (pKey = f_new FlmRecord) == NULL) { rc = RC_SET( FERR_MEM); ViewShowRCError( "creating key", rc); goto Exit_False; } if (RC_BAD( rc = pKey->insertLast( 0, FLM_KEY_TAG, FLM_CONTEXT_TYPE, &pvFld))) { ViewShowRCError( "adding key tag", rc); goto Exit_False; } /* Ask for data for each field and link into key tree */ i = 0; while (i < NumFields) { /* Get the name of the field and its type */ f_sprintf( (char *)FieldName, "FIELD %u", (unsigned)pIfd->uiFldNum); switch( IFD_GET_FIELD_TYPE( pIfd)) { case FLM_TEXT_TYPE: f_strcpy( (char *)FieldType, "TEXT"); break; case FLM_NUMBER_TYPE: f_strcpy( (char *)FieldType, "NUMBER"); break; case FLM_BINARY_TYPE: f_strcpy( (char *)FieldType, "BINARY"); break; case FLM_CONTEXT_TYPE: f_strcpy( (char *)FieldType, "CONTEXT"); break; default: f_sprintf( (char *)FieldType, "UNK: %u!", (unsigned)IFD_GET_FIELD_TYPE( pIfd)); break; } if (pIfd->uiFlags & IFD_OPTIONAL) f_sprintf( (char *)Prompt, "%s (%s-OPTIONAL): ", FieldName, FieldType); else f_sprintf( (char *)Prompt, "%s (%s-REQUIRED): ", FieldName, FieldType); switch( IFD_GET_FIELD_TYPE( pIfd)) { case FLM_TEXT_TYPE: if (!ViewEditText( Prompt, TempBuf, sizeof( TempBuf), &ValEntered)) goto Exit_False; break; case FLM_NUMBER_TYPE: case FLM_CONTEXT_TYPE: if (!ViewGetNum( Prompt, &Num, FALSE, 4, 0xFFFFFFFF, &ValEntered)) goto Exit_False; break; case FLM_BINARY_TYPE: Len = sizeof( TempBuf); if (!ViewEditBinary( Prompt, TempBuf, &Len, &ValEntered)) goto Exit_False; break; } if (!ValEntered) { i++; } else { FLMUINT uiDataType; /* See if the entered data can be converted to the */ /* correct type */ uiDataType = IFD_GET_FIELD_TYPE( pIfd); if (RC_BAD( rc = pKey->insertLast( 1, pIfd->uiFldNum, uiDataType, &pvFld))) { ViewShowRCError( "creating field", rc); } else { switch( IFD_GET_FIELD_TYPE( pIfd)) { case FLM_TEXT_TYPE: rc = pKey->setNative( pvFld, TempBuf); break; case FLM_NUMBER_TYPE: rc = pKey->setUINT( pvFld, Num); break; case FLM_CONTEXT_TYPE: rc = pKey->setRecPointer( pvFld, Num); break; case FLM_BINARY_TYPE: rc = pKey->setBinary( pvFld, TempBuf, Len); break; } if (RC_BAD( rc)) { ViewShowRCError( "putting data in field", rc); } } if (RC_OK(rc)) { i++; pIfd++; KeyEntered = TRUE; } } } // If index is on all containers, prompt for container number. if (!pIxd->uiContainerNum) { f_strcpy( Prompt, "CONTAINER: "); if (!ViewGetNum( Prompt, &Num, FALSE, sizeof( Num), 0xFFFF, &ValEntered)) { goto Exit_False; } if (ValEntered) { pKey->setContainerID( Num); KeyEntered = TRUE; } } /* Convert the key to binary format */ if (!KeyEntered) goto Exit_False; if ((rc = FlmKeyBuild( gv_hViewDb, gv_uiViewSearchLfNum, pKey->getContainerID(), pKey, 0, gv_ucViewSearchKey, &gv_uiViewSearchKeyLen)) != FERR_OK) ViewShowRCError( "building key", rc); else { GetOK = TRUE; goto Exit_GetKey; } } Exit_False: GetOK = FALSE; Exit_GetKey: if (pKey) { pKey->Release(); } return( GetOK); }
/**************************************************************************** Desc: Copy a database's files, including roll-forward log files. *****************************************************************************/ FSTATIC RCODE flmCopyDb( FLMUINT uiDbVersion, const char * pszSrcDbName, const char * pszSrcDataDir, const char * pszSrcRflDir, const char * pszDestDbName, const char * pszDestDataDir, const char * pszDestRflDir, STATUS_HOOK fnStatusCallback, void * UserData) { RCODE rc = FERR_OK; DB_COPY_INFO DbCopyInfo; F_SuperFileHdl * pSrcSFileHdl = NULL; F_SuperFileHdl * pDestSFileHdl = NULL; F_SuperFileClient * pSrcSFileClient = NULL; F_SuperFileClient * pDestSFileClient = NULL; FLMUINT uiFileNumber; FLMUINT uiHighFileNumber; FLMUINT uiHighLogFileNumber; FLMUINT64 ui64FileSize; FFILE * pFile = NULL; FLMBOOL bMutexLocked = FALSE; IF_FileHdl * pLockFileHdl = NULL; IF_FileHdl * pTmpFileHdl = NULL; IF_DirHdl * pDirHdl = NULL; FLMBOOL bFileLocked = FALSE; FLMBOOL bWriteLocked = FALSE; IF_LockObject * pWriteLockObj = NULL; IF_LockObject * pFileLockObj = NULL; COPIED_NAME * pCopiedList = NULL; FLMBOOL bUsedFFile = FALSE; FLMBYTE * pucInMemLogHdr = NULL; eLockType currLockType; FLMUINT uiLockThreadId; char * pszActualSrcRflPath = NULL; char * pszSrcPrefix = NULL; char * pszActualDestRflPath = NULL; char * pszDestPrefix = NULL; FLMBOOL bCreatedDestRflDir = FALSE; F_SEM hWaitSem = F_SEM_NULL; f_memset( &DbCopyInfo, 0, sizeof( DbCopyInfo)); // Should not do anything if the source and destination names // are the same. if (f_stricmp( pszSrcDbName, pszDestDbName) == 0) { goto Exit; } // Allocate a semaphore if( RC_BAD( rc = f_semCreate( &hWaitSem))) { goto Exit; } // Allocate memory for paths we don't want to push onto the stack. if (RC_BAD( rc = f_calloc( (F_PATH_MAX_SIZE + F_FILENAME_SIZE) * 2, &pszActualSrcRflPath))) { goto Exit; } pszSrcPrefix = &pszActualSrcRflPath[ F_PATH_MAX_SIZE]; pszActualDestRflPath = &pszSrcPrefix[ F_FILENAME_SIZE]; pszDestPrefix = &pszActualDestRflPath[ F_PATH_MAX_SIZE]; // Set up the super file object for the source database. // Must at least open the control file. if( (pSrcSFileClient = f_new F_SuperFileClient) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } if( RC_BAD( rc = pSrcSFileClient->setup( pszSrcDbName, pszSrcDataDir, uiDbVersion))) { goto Exit; } if( (pSrcSFileHdl = f_new F_SuperFileHdl) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } if( RC_BAD( rc = pSrcSFileHdl->setup( pSrcSFileClient, gv_FlmSysData.pFileHdlCache, gv_FlmSysData.uiFileOpenFlags, 0))) { goto Exit; } // Lock the destination database, if not already locked. // This is so we can overwrite it without necessarily // deleting it. May unlock and re-lock the global mutex. f_mutexLock( gv_FlmSysData.hShareMutex); bMutexLocked = TRUE; if (RC_BAD( rc = flmFindFile( pszDestDbName, pszDestDataDir, &pFile))) { goto Exit; } // If we didn't find an FFILE structure, get an // exclusive lock on the file. if (!pFile) { f_mutexUnlock( gv_FlmSysData.hShareMutex); bMutexLocked = FALSE; // Attempt to get an exclusive lock on the file. if (RC_BAD( rc = flmCreateLckFile( pszDestDbName, &pLockFileHdl))) { goto Exit; } } else { // The call to flmVerifyFileUse will wait if the file is in // the process of being opened by another thread. if (RC_BAD( rc = flmVerifyFileUse( gv_FlmSysData.hShareMutex, &pFile))) { goto Exit; } // Increment the use count on the FFILE so it will not // disappear while we are copying the file. if (++pFile->uiUseCount == 1) { flmUnlinkFileFromNUList( pFile); } bUsedFFile = TRUE; f_mutexUnlock( gv_FlmSysData.hShareMutex); bMutexLocked = FALSE; pucInMemLogHdr = &pFile->ucLastCommittedLogHdr [0]; // Lock the destination file object and transaction // object, if not already locked. pFile->pFileLockObj->getLockInfo( 0, &currLockType, &uiLockThreadId, NULL); if (currLockType != FLM_LOCK_EXCLUSIVE || uiLockThreadId != f_threadId()) { pFileLockObj = pFile->pFileLockObj; pFileLockObj->AddRef(); if (RC_BAD( rc = pFileLockObj->lock( hWaitSem, TRUE, FLM_NO_TIMEOUT, 0))) { goto Exit; } bFileLocked = TRUE; } // Lock the write object, if not already locked pFile->pWriteLockObj->getLockInfo( 0, &currLockType, &uiLockThreadId, NULL); if( currLockType != FLM_LOCK_EXCLUSIVE || uiLockThreadId != f_threadId()) { pWriteLockObj = pFile->pWriteLockObj; pWriteLockObj->AddRef(); // Only contention here is with the checkpoint thread - wait // forever until the checkpoint thread gives it up. if( RC_BAD( rc = pWriteLockObj->lock( hWaitSem, TRUE, FLM_NO_TIMEOUT, 0))) { goto Exit; } bWriteLocked = TRUE; } } // Set up the super file object for the destination database. if( (pDestSFileClient = f_new F_SuperFileClient) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } if( RC_BAD( rc = pDestSFileClient->setup( pszDestDbName, pszDestDataDir, uiDbVersion))) { goto Exit; } if( (pDestSFileHdl = f_new F_SuperFileHdl) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } if( RC_BAD( rc = pDestSFileHdl->setup( pDestSFileClient, gv_FlmSysData.pFileHdlCache, gv_FlmSysData.uiFileOpenFlags, gv_FlmSysData.uiFileCreateFlags))) { goto Exit; } // See how many files we have and calculate the total size. uiHighFileNumber = 0; for (;;) { if( RC_BAD( rc = pSrcSFileHdl->getFileSize( uiHighFileNumber, &ui64FileSize)) || !ui64FileSize) { if (rc == FERR_IO_PATH_NOT_FOUND || rc == FERR_IO_INVALID_PATH || !ui64FileSize) { // If the control file doesn't exist, we will return // path not found. if (!uiHighFileNumber) { goto Exit; } uiHighFileNumber--; rc = FERR_OK; break; } goto Exit; } DbCopyInfo.ui64BytesToCopy += ui64FileSize; if (uiHighFileNumber == MAX_DATA_BLOCK_FILE_NUMBER( uiDbVersion)) { break; } uiHighFileNumber++; } // See how many rollback log files we have, and calculate // their total size. uiHighLogFileNumber = FIRST_LOG_BLOCK_FILE_NUMBER( uiDbVersion); for (;;) { if ((RC_BAD( rc = pSrcSFileHdl->getFileSize( uiHighLogFileNumber, &ui64FileSize))) || !ui64FileSize) { if (rc == FERR_IO_PATH_NOT_FOUND || rc == FERR_IO_INVALID_PATH || !ui64FileSize) { if (uiHighLogFileNumber == FIRST_LOG_BLOCK_FILE_NUMBER( uiDbVersion)) { uiHighLogFileNumber = 0; } else { uiHighLogFileNumber--; } rc = FERR_OK; break; } goto Exit; } DbCopyInfo.ui64BytesToCopy += ui64FileSize; if (uiHighLogFileNumber == MAX_LOG_BLOCK_FILE_NUMBER( uiDbVersion)) { break; } uiHighLogFileNumber++; } // Get the sizes of the roll-forward log files if( uiDbVersion < FLM_FILE_FORMAT_VER_4_3) { // For pre-4.3 versions, only need to copy one RFL file. if (RC_BAD( rc = rflGetFileName( uiDbVersion, pszSrcDbName, pszSrcRflDir, 1, pszActualSrcRflPath))) { goto Exit; } if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( pszActualSrcRflPath, gv_FlmSysData.uiFileOpenFlags, &pTmpFileHdl))) { if (rc == FERR_IO_PATH_NOT_FOUND || rc == FERR_IO_INVALID_PATH) { rc = FERR_OK; } else { goto Exit; } } else { if (RC_BAD( rc = pTmpFileHdl->size( &ui64FileSize))) { goto Exit; } DbCopyInfo.ui64BytesToCopy += ui64FileSize; pTmpFileHdl->Release(); pTmpFileHdl = NULL; } } else { if( RC_BAD( rc = rflGetDirAndPrefix( uiDbVersion, pszSrcDbName, pszSrcRflDir, pszActualSrcRflPath, pszSrcPrefix))) { goto Exit; } if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openDir( pszActualSrcRflPath, (char *)"*", &pDirHdl))) { goto Exit; } for (;;) { if( RC_BAD( rc = pDirHdl->next())) { if (rc == FERR_IO_NO_MORE_FILES) { rc = FERR_OK; break; } else { goto Exit; } } // If the current file is an RFL file, increment ui64BytesToCopy if( rflGetFileNum( uiDbVersion, pszSrcPrefix, pDirHdl->currentItemName(), &uiFileNumber)) { DbCopyInfo.ui64BytesToCopy += pDirHdl->currentItemSize(); } } pDirHdl->Release(); pDirHdl = NULL; } // Close all file handles in the source and destination pSrcSFileHdl->releaseFiles(); pDestSFileHdl->releaseFiles(); // Copy the database files. for (uiFileNumber = 0; uiFileNumber <= uiHighFileNumber; uiFileNumber++) { // Get the source file path and destination file path. if( RC_BAD( rc = pSrcSFileHdl->getFilePath( uiFileNumber, DbCopyInfo.szSrcFileName))) { goto Exit; } if( RC_BAD( rc = pDestSFileHdl->getFilePath( uiFileNumber, DbCopyInfo.szDestFileName))) { goto Exit; } // For the control file, don't copy first 2K - it will be set up // to show maintenance in progress. Then the first 2K will be copied // later. if (!uiFileNumber) { DbCopyInfo.bNewSrcFile = TRUE; if (RC_BAD( rc = flmCopyFile( gv_FlmSysData.pFileSystem, 2048, 0xFFFFFFFF, &DbCopyInfo, &pCopiedList, pucInMemLogHdr, TRUE, fnStatusCallback, UserData))) { goto Exit; } } else { DbCopyInfo.bNewSrcFile = TRUE; if (RC_BAD( rc = flmCopyFile( gv_FlmSysData.pFileSystem, 0, 0xFFFFFFFF, &DbCopyInfo, &pCopiedList, NULL, TRUE, fnStatusCallback, UserData))) { goto Exit; } } } // Copy the additional rollback log files, if any. for (uiFileNumber = FIRST_LOG_BLOCK_FILE_NUMBER( uiDbVersion); uiFileNumber <= uiHighLogFileNumber; uiFileNumber++) { // Get the source file path and destination file path. if (RC_BAD( rc = pSrcSFileHdl->getFilePath( uiFileNumber, DbCopyInfo.szSrcFileName))) { goto Exit; } if (RC_BAD( rc = pDestSFileHdl->getFilePath( uiFileNumber, DbCopyInfo.szDestFileName))) { goto Exit; } DbCopyInfo.bNewSrcFile = TRUE; if (RC_BAD( rc = flmCopyFile( gv_FlmSysData.pFileSystem, 0, 0xFFFFFFFF, &DbCopyInfo, &pCopiedList, NULL, TRUE, fnStatusCallback, UserData))) { goto Exit; } } // Copy the RFL files if( uiDbVersion < FLM_FILE_FORMAT_VER_4_3) { // Get the source file path and the destination file path. if (RC_BAD( rc = rflGetFileName( uiDbVersion, pszSrcDbName, pszSrcRflDir, 1, DbCopyInfo.szSrcFileName))) { goto Exit; } if (RC_BAD( rc = rflGetFileName( uiDbVersion, pszDestDbName, pszDestRflDir, 1, DbCopyInfo.szDestFileName))) { goto Exit; } DbCopyInfo.bNewSrcFile = TRUE; if (RC_BAD( rc = flmCopyFile( gv_FlmSysData.pFileSystem, 0, 0xFFFFFFFF, &DbCopyInfo, &pCopiedList, NULL, TRUE, fnStatusCallback, UserData))) { goto Exit; } } else { // Create the destination RFL directory, if needed. The purpose of this // code is two-fold: 1) We want to keep track of the fact that we tried // to create the destination RFL directory so we can try to remove it // if the copy fails; 2) If the destination RFL directory path specifies // a directory with existing files, we want to remove them. if( RC_BAD( rc = rflGetDirAndPrefix( uiDbVersion, pszDestDbName, pszDestRflDir, pszActualDestRflPath, pszDestPrefix))) { goto Exit; } if( RC_OK( gv_FlmSysData.pFileSystem->doesFileExist( pszActualDestRflPath))) { if( gv_FlmSysData.pFileSystem->isDir( pszActualDestRflPath)) { // Remove the existing directory and all files, etc. (void)gv_FlmSysData.pFileSystem->removeDir( pszActualDestRflPath, TRUE); } else { (void)gv_FlmSysData.pFileSystem->deleteFile( pszActualDestRflPath); } } // Try to create the destination RFL directory. This might fail if // another process was accessing the directory for some reason // (i.e., from a command prompt), when we tried to remove it above. // We really don't care if the call to CreateDir is sucessful, because // when we try to create the destination files (below), the FLAIM file // file system code will try to create any necessary directories. (void)gv_FlmSysData.pFileSystem->createDir( pszActualDestRflPath); bCreatedDestRflDir = TRUE; // Copy the RFL files. NOTE: We need to copy all of the RFL files // in the source RFL directory so that they will be available // when performing a database restore operation. if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openDir( pszActualSrcRflPath, (char *)"*", &pDirHdl))) { goto Exit; } for (;;) { if( RC_BAD( rc = pDirHdl->next())) { if (rc == FERR_IO_NO_MORE_FILES) { rc = FERR_OK; break; } else { goto Exit; } } // If the current file is an RFL file, copy it to the destination if( rflGetFileNum( uiDbVersion, pszSrcPrefix, pDirHdl->currentItemName(), &uiFileNumber)) { // Get the source file path and the destination file path. if (RC_BAD( rc = rflGetFileName( uiDbVersion, pszSrcDbName, pszSrcRflDir, uiFileNumber, DbCopyInfo.szSrcFileName))) { goto Exit; } if (RC_BAD( rc = rflGetFileName( uiDbVersion, pszDestDbName, pszDestRflDir, uiFileNumber, DbCopyInfo.szDestFileName))) { goto Exit; } DbCopyInfo.bNewSrcFile = TRUE; if (RC_BAD( rc = flmCopyFile( gv_FlmSysData.pFileSystem, 0, 0xFFFFFFFF, &DbCopyInfo, &pCopiedList, NULL, TRUE, fnStatusCallback, UserData))) { goto Exit; } } } pDirHdl->Release(); pDirHdl = NULL; } // Do one final copy on the control file to copy just the first 2K if (RC_BAD( rc = pSrcSFileHdl->getFilePath( 0, DbCopyInfo.szSrcFileName))) { goto Exit; } if (RC_BAD( rc = pDestSFileHdl->getFilePath( 0, DbCopyInfo.szDestFileName))) { goto Exit; } DbCopyInfo.bNewSrcFile = FALSE; if (RC_BAD( rc = flmCopyFile( gv_FlmSysData.pFileSystem, 0, 2048, &DbCopyInfo, NULL, pucInMemLogHdr, FALSE, fnStatusCallback, UserData))) { goto Exit; } Exit: if (bUsedFFile) { if (!bMutexLocked) { f_mutexLock( gv_FlmSysData.hShareMutex); bMutexLocked = TRUE; } if (!(--pFile->uiUseCount)) { flmLinkFileToNUList( pFile); } } if (bMutexLocked) { f_mutexUnlock( gv_FlmSysData.hShareMutex); bMutexLocked = FALSE; } if (bWriteLocked) { if( RC_BAD( rc = pWriteLockObj->unlock())) { goto Exit; } bWriteLocked = FALSE; } if (bFileLocked) { RCODE rc3; if (RC_BAD( rc3 = pFileLockObj->unlock())) { if (RC_OK( rc)) rc = rc3; } bFileLocked = FALSE; } if (pWriteLockObj) { pWriteLockObj->Release(); pWriteLockObj = NULL; } if (pFileLockObj) { pFileLockObj->Release(); pFileLockObj = NULL; } if (pLockFileHdl) { pLockFileHdl->Release(); pLockFileHdl = NULL; } if( pTmpFileHdl) { pTmpFileHdl->Release(); } if( pDirHdl) { pDirHdl->Release(); } // Free all the names of files that were copied. // If the copy didn't finish, try to delete any files // that were copied. while (pCopiedList) { COPIED_NAME * pNext = pCopiedList->pNext; // If the overall copy failed, delete the copied file. if (RC_BAD( rc)) { (void)gv_FlmSysData.pFileSystem->deleteFile( pCopiedList->szPath); } f_free( &pCopiedList); pCopiedList = pNext; } if( RC_BAD( rc) && bCreatedDestRflDir) { (void)gv_FlmSysData.pFileSystem->removeDir( pszActualDestRflPath); } if( pszActualSrcRflPath) { f_free( &pszActualSrcRflPath); } if( hWaitSem != F_SEM_NULL) { f_semDestroy( &hWaitSem); } if( pSrcSFileHdl) { pSrcSFileHdl->Release(); } if( pSrcSFileClient) { pSrcSFileClient->Release(); } if( pDestSFileHdl) { pDestSFileHdl->Release(); } if( pDestSFileClient) { pDestSFileClient->Release(); } return( rc); }
/******************************************************************** Desc: Get command line parameters. *********************************************************************/ FLMBOOL gigaGetParams( FLMINT iArgC, const char ** ppszArgV) { FLMBOOL bOk = FALSE; FLMUINT uiLoop; const char * pszPtr; FLMBOOL bHaveNumToLoad = FALSE; #ifdef FLM_NLM FLMBOOL bWaitToSync = FALSE; #endif char szMsg [100]; gv_uiCacheSize = 0; gv_uiBlockCachePercentage = 50; gv_uiMaxDirtyCache = 0; gv_uiLowDirtyCache = 0; gv_uiTotalToLoad = 100000; gv_uiTransSize = 100; gv_uiTotalLoaded = 0; #ifdef FLM_NLM f_strcpy( gv_szDibName, "sys:\\_netware\\gigatest.db"); #else f_strcpy( gv_szDibName, "gigatest.db"); #endif gv_szDataDir[ 0] = 0; gv_szRflDir[ 0] = 0; // If no parameters were entered, show a help screen. if( iArgC < 2) { gigaShowHelp(); goto Exit; } uiLoop = 1; while( uiLoop < (FLMUINT)iArgC) { pszPtr = ppszArgV [uiLoop]; // See if they specified an option #ifdef FLM_UNIX if( *pszPtr == '-') #else if( (*pszPtr == '-') || (*pszPtr == '/')) #endif { pszPtr++; if ((*pszPtr == 'c') || (*pszPtr == 'C')) { gv_uiCacheSize = f_atol( (pszPtr + 1)); } else if ((*pszPtr == 'i') || (*pszPtr == 'I')) { gv_uiCPInterval = f_atol( (pszPtr + 1)); } else if ((*pszPtr == 'p') || (*pszPtr == 'P')) { gv_uiBlockCachePercentage = f_atol( (pszPtr + 1)); } else if ((*pszPtr == 'm') || (*pszPtr == 'M')) { pszPtr++; if ((*pszPtr == 'd') || (*pszPtr == 'D')) { gv_uiMaxDirtyCache = f_atol( (pszPtr + 1)); } } else if ((*pszPtr == 'l') || (*pszPtr == 'L')) { pszPtr++; if ((*pszPtr == 'd') || (*pszPtr == 'D')) { gv_uiLowDirtyCache = f_atol( (pszPtr + 1)); } } else if ((*pszPtr == 't') || (*pszPtr == 'T')) { gv_uiTransSize = f_atol( (pszPtr + 1)); } else if ((*pszPtr == 'n') || (*pszPtr == 'N')) { f_strcpy( gv_szDibName, pszPtr + 1); } else if (*pszPtr == 'd' || *pszPtr == 'D') { if( f_stricmp( pszPtr, "dio") == 0) { gv_bDisableDirectIO = TRUE; } else { pszPtr++; if (*pszPtr == 'r' || *pszPtr == 'R') { f_strcpy( gv_szRflDir, pszPtr + 1); } else if (*pszPtr == 'd' || *pszPtr == 'D') { f_strcpy( gv_szDataDir, pszPtr + 1); } else { f_sprintf( szMsg, "Invalid option %s", (pszPtr - 1)); gigaOutputErrMsg( szMsg); goto Exit; } } } else if (f_stricmp( pszPtr, "B") == 0) { gv_bBatchMode = TRUE; } #ifdef FLM_NLM else if (f_stricmp( pszPtr, "W") == 0) { bWaitToSync = TRUE; } #endif else if (f_stricmp( pszPtr, "?") == 0 || f_stricmp( pszPtr, "HELP") == 0) { gigaShowHelp(); goto Exit; } else { f_sprintf( szMsg, "Invalid option %s", pszPtr); gigaOutputErrMsg( szMsg); goto Exit; } } else if (f_stricmp( pszPtr, "?") == 0) { gigaShowHelp(); return( FALSE); } else if (!bHaveNumToLoad) { gv_uiTotalToLoad = f_atol( pszPtr); bHaveNumToLoad = TRUE; } uiLoop++; } #ifdef FLM_NLM if (!bWaitToSync && !gv_bSynchronized) { SynchronizeStart(); gv_bSynchronized = TRUE; } #endif bOk = TRUE; Exit: return( bOk); }
/******************************************************************** Desc: ? *********************************************************************/ FSTATIC FLMBOOL bldParseHdrInfo( const char * pucBuffer) { FLMUINT uiNum; FLMBOOL bHaveParam; CREATE_OPTS CreateOpts; FLMUINT uiFieldNum; f_memcpy( &CreateOpts, &gv_DefaultCreateOpts, sizeof( CREATE_OPTS)); uiFieldNum = 1; for (;;) { uiNum = 0; bHaveParam = FALSE; while ((*pucBuffer == ' ') || (*pucBuffer == ':') || (*pucBuffer == ',') || (*pucBuffer == ';') || (*pucBuffer == '\t')) { pucBuffer++; } if( uiFieldNum == 8) // Language { char pszTmpBuf[ 100]; FLMUINT uiTmpLen = 0; while ((*pucBuffer) && (*pucBuffer != ':') && (*pucBuffer != ',') && (*pucBuffer != ';') && (*pucBuffer != ' ') && (*pucBuffer != '\t')) { pszTmpBuf[ uiTmpLen++] = *pucBuffer++; } pszTmpBuf[ uiTmpLen] = 0; if( uiTmpLen) { uiNum = f_languageToNum( pszTmpBuf); if( (!uiNum) && (f_stricmp( pszTmpBuf, "US") != 0)) { bldShowError( "Illegal language in header information"); return( FALSE); } bHaveParam = TRUE; } } else { while( (*pucBuffer >= '0') && (*pucBuffer <= '9')) { uiNum *= 10; uiNum += (FLMUINT)(*pucBuffer - '0'); pucBuffer++; bHaveParam = TRUE; } } if( ((*pucBuffer != 0) && (*pucBuffer != ' ') && (*pucBuffer != ':') && (*pucBuffer != ',') && (*pucBuffer != ';') && (*pucBuffer != '\t'))) { bldShowError( "Illegal value in header information"); return( FALSE); } if( bHaveParam) { switch( uiFieldNum) { case 1: if( uiNum != 0 && !VALID_BLOCK_SIZE( uiNum)) { bldShowError( "Illegal block size"); return( FALSE); } CreateOpts.uiBlockSize = uiNum; break; case 4: if( uiNum > 255) { bldShowError( "Illegal application major version"); return( FALSE); } CreateOpts.uiAppMajorVer = uiNum; break; case 5: if( uiNum > 255) { bldShowError( "Illegal application minor version"); return( FALSE); } CreateOpts.uiAppMinorVer = uiNum; break; case 6: CreateOpts.uiMaxRflFileSize = uiNum; break; case 7: CreateOpts.uiDefaultLanguage = uiNum; break; case 8: CreateOpts.uiVersionNum = uiNum; break; default: bldShowError( "Too many parameters in header information"); return( FALSE); } } if( !(*pucBuffer)) { break; } uiFieldNum++; } gv_bFixHdrInfo = TRUE; f_memcpy( &gv_DefaultCreateOpts, &CreateOpts, sizeof( CREATE_OPTS)); return( TRUE); }
/******************************************************************** Desc: ? *********************************************************************/ FSTATIC FLMBOOL bldGetParams( FLMINT iArgC, const char ** ppszArgV) { #define MAX_ARGS 30 FLMUINT uiLoop; char szErrMsg [100]; const char * pszPtr; const char * ppszArgs[ MAX_ARGS]; char szCommandBuffer [300]; gv_szSrcFileName [0] = 0; gv_szSrcDataDir [0] = 0; gv_szDestFileName [0] = 0; gv_szDestDataDir [0] = 0; gv_szDestRflDir [0] = 0; gv_szDictFileName [0] = 0; gv_szLogFileName [0] = 0; gv_bFixHdrInfo = FALSE; gv_DefaultCreateOpts.uiBlockSize = DEFAULT_BLKSIZ; gv_DefaultCreateOpts.uiMinRflFileSize = DEFAULT_MIN_RFL_FILE_SIZE; gv_DefaultCreateOpts.uiMaxRflFileSize = DEFAULT_MAX_RFL_FILE_SIZE; gv_DefaultCreateOpts.bKeepRflFiles = DEFAULT_KEEP_RFL_FILES_FLAG; gv_DefaultCreateOpts.bLogAbortedTransToRfl = DEFAULT_LOG_ABORTED_TRANS_FLAG; gv_DefaultCreateOpts.uiDefaultLanguage = DEFAULT_LANG; gv_DefaultCreateOpts.uiVersionNum = FLM_CUR_FILE_FORMAT_VER_NUM; gv_DefaultCreateOpts.uiAppMajorVer = gv_DefaultCreateOpts.uiAppMinorVer = 0; gv_uiCacheSize = 30000; gv_bBatchMode = FALSE; // Ask the user to enter parameters if none were entered on the command // line. if( iArgC < 2) { for (;;) { f_conStrOut( "\nRebuild Params (enter ? for help): "); szCommandBuffer[ 0] = 0; f_conLineEdit( szCommandBuffer, sizeof( szCommandBuffer) - 1); if( gv_bShutdown) { return( FALSE); } if( f_stricmp( szCommandBuffer, "?") == 0) { bldShowHelp(); } else { break; } } flmUtilParseParams( szCommandBuffer, MAX_ARGS, &iArgC, &ppszArgs [1]); ppszArgs[ 0] = ppszArgV[ 0]; iArgC++; ppszArgV = &ppszArgs[ 0]; } uiLoop = 1; while (uiLoop < (FLMUINT)iArgC) { pszPtr = ppszArgV [uiLoop]; // See if they specified an option #ifdef FLM_UNIX if (*pszPtr == '-') #else if (*pszPtr == '-' || *pszPtr == '/') #endif { pszPtr++; if (*pszPtr == 'c' || *pszPtr == 'C') { gv_uiCacheSize = f_atoi( (pszPtr + 1)); } else if (*pszPtr == 'd' || *pszPtr == 'D') { pszPtr++; if (*pszPtr == 'r' || *pszPtr == 'R') { pszPtr++; if (*pszPtr) { f_strcpy( gv_szDestRflDir, pszPtr); } else { bldShowError( "Destination RFL directory not specified"); return( FALSE); } } else if (*pszPtr == 'd' || *pszPtr == 'D') { pszPtr++; if (*pszPtr) { f_strcpy( gv_szDestDataDir, pszPtr); } else { bldShowError( "Destination data directory not specified"); return( FALSE); } } else if (*pszPtr == 'c' || *pszPtr == 'C') { pszPtr++; if (*pszPtr) { f_strcpy( gv_szDictFileName, pszPtr); } else { bldShowError( "Dictionary file name not specified"); return( FALSE); } } else { f_sprintf( szErrMsg, "Invalid option %s", pszPtr-1); bldShowError( szErrMsg); return( FALSE); } } else if (*pszPtr == 's' || *pszPtr == 'S') { pszPtr++; if (*pszPtr == 'd' || *pszPtr == 'D') { pszPtr++; if (*pszPtr) { f_strcpy( gv_szSrcDataDir, pszPtr); } else { bldShowError( "Source data directory not specified"); return( FALSE); } } else { f_sprintf( szErrMsg, "Invalid option %s", pszPtr-1); bldShowError( szErrMsg); return( FALSE); } } else if (*pszPtr == 'h' || *pszPtr == 'H') { pszPtr++; if( *pszPtr) { if( !bldParseHdrInfo( pszPtr)) { return( FALSE); } } else { bldShowError( "Block sizes not specified"); return( FALSE); } } else if (*pszPtr == 'l' || *pszPtr == 'L') { pszPtr++; if (*pszPtr) { f_strcpy( gv_szLogFileName, pszPtr); } else { bldShowError( "Log file name not specified"); return( FALSE); } } else if (f_stricmp( pszPtr, "P") == 0) { gv_bPauseBeforeExiting = TRUE; } else if (f_stricmp( pszPtr, "B") == 0) { gv_bBatchMode = TRUE; } else if (f_stricmp( pszPtr, "?") == 0) { goto Show_Help; } else { f_sprintf( szErrMsg, "Invalid option %s", pszPtr); bldShowError( szErrMsg); return( FALSE); } } else if (f_stricmp( pszPtr, "?") == 0) { Show_Help: bldShowHelp(); gv_bPauseBeforeExiting = TRUE; return( FALSE); } else if (!gv_szSrcFileName[ 0]) { f_strcpy( gv_szSrcFileName, pszPtr); } else if (!gv_szDestFileName[ 0]) { f_strcpy( gv_szDestFileName, pszPtr); } uiLoop++; } if (!gv_szSrcFileName [0] || !gv_szDestFileName [0]) { goto Show_Help; } return( TRUE); }