/** * Writes the contents of the given buffer into the given file. * * Note that if the length of the input buffer is zero or less, * the file will be truncated. * * @param ppszError pointer to character string pointer to accept an error * @param pFileName file to write * @param inBuffer buffer with data that will be stored * @param inBufferLen length of the inBuffer * * @return status code (ALL_OK if there was no errors) */ MIDPError write_file(char** ppszError, const pcsl_string* pFileName, char* inBuffer, long inBufferLen) { int handle, status = ALL_OK; char* pszTemp; pcsl_string tmpFileName; pcsl_string_status rc; *ppszError = NULL; /* get the name of the temporary file */ rc = pcsl_string_cat(pFileName, &TMP_FILE_EXTENSION, &tmpFileName); if (rc != PCSL_STRING_OK) { return OUT_OF_MEMORY; } /* open the file */ handle = storage_open(ppszError, &tmpFileName, OPEN_READ_WRITE_TRUNCATE); if (*ppszError != NULL) { pcsl_string_free(&tmpFileName); return IO_ERROR; } /* write the whole buffer */ if (inBufferLen > 0) { storageWrite(ppszError, handle, inBuffer, inBufferLen); } if (*ppszError != NULL) { status = IO_ERROR; } /* close the file */ storageClose(&pszTemp, handle); storageFreeError(pszTemp); if (status == ALL_OK) { /* rename the temporary file */ storage_rename_file(ppszError, &tmpFileName, pFileName); if (*ppszError != NULL) { status = IO_ERROR; storage_delete_file(&pszTemp, &tmpFileName); storageFreeError(pszTemp); } } else { storage_delete_file(&pszTemp, &tmpFileName); storageFreeError(pszTemp); } pcsl_string_free(&tmpFileName); return (MIDPError)status; }
/* * Rename a file in storage. * * If not successful *ppszError will set to point to an error string, * on success it will be set to NULL. */ void storage_rename_file(char** ppszError, const pcsl_string* oldFilename_str, const pcsl_string* newFilename_str) { int status; *ppszError = NULL; DEBUGP2F("renaming %s", oldFilename_str); DEBUGP2F(" to %s\n", newFilename_str); if (!storage_file_exists(oldFilename_str)) { *ppszError = (char *)NOT_EXIST_RENAME_ERROR; } if (storage_file_exists(newFilename_str)) { storage_delete_file(ppszError, newFilename_str); if (*ppszError != NULL) { return; } } status = pcsl_file_rename(oldFilename_str, newFilename_str); if (status < 0) { *ppszError = storage_get_last_file_error("storageRename", newFilename_str); return; } *ppszError = NULL; }
/** * Finishes the previously started transaction. * * @return ALL_OK if the transaction was successfully finished, * NOT_FOUND if the transaction has not been started, * IO_ERROR if I/O error */ MIDPError finish_transaction() { pcsl_string_status rc; pcsl_string transDataFile; char* pszTemp = NULL; MIDPError status = ALL_OK; if (!g_transactionStarted) { return NOT_FOUND; } /* transaction is finished, removed the transaction file */ /* get a full path to the transaction data file */ rc = pcsl_string_cat(storage_get_root(INTERNAL_STORAGE_ID), &TRANSACTION_DATA_FILENAME, &transDataFile); if (rc != PCSL_STRING_OK) { return OUT_OF_MEMORY; } storage_delete_file(&pszTemp, &transDataFile); pcsl_string_free(&transDataFile); if (pszTemp != NULL) { storageFreeError(pszTemp); status = IO_ERROR; } g_transactionStarted = 0; return status; }
/** * Tries to repair the suite database. * * @return ALL_OK if succeeded, other value if failed */ MIDPError repair_suite_db() { /* IMPL_NOTE: should be replaced with more sophisticated routine. */ MIDPError status = ALL_OK; pcsl_string_status rc; pcsl_string suitesDataFile; char* pszTemp = NULL; /* get a full path to the _suites.dat */ rc = pcsl_string_cat(storage_get_root(INTERNAL_STORAGE_ID), &SUITE_DATA_FILENAME, &suitesDataFile); if (rc != PCSL_STRING_OK) { return OUT_OF_MEMORY; } storage_delete_file(&pszTemp, &suitesDataFile); pcsl_string_free(&suitesDataFile); if (pszTemp != NULL) { storageFreeError(pszTemp); status = IO_ERROR; } if (g_isSuitesDataLoaded) { free_suites_data(); g_isSuitesDataLoaded = 0; } return status; }
/** * Removes the files belonging to the specified component, or to all * components owned by the given suite. * * @param suiteId ID of the suite whose components are being removed * @param componentId ID of the component to remove or UNUSED_COMPONENT_ID * if all components of the suite are being removed * * @return status code, ALL_OK if no errors */ static MIDPError delete_components_files(SuiteIdType suiteId, ComponentIdType componentId) { pcsl_string componentFileName; char* pszError; int suiteFound = 0; MIDPError status = ALL_OK; MidletSuiteData* pData = g_pSuitesData; /* handle the list entries having the given suiteId */ while (pData != NULL) { if (pData->suiteId == suiteId) { suiteFound = 1; if (pData->type == COMPONENT_DYNAMIC && (componentId == UNUSED_COMPONENT_ID || pData->componentId == componentId)) { /* remove the file holding the component */ status = get_jar_path(COMPONENT_DYNAMIC, (jint)pData->componentId, &componentFileName); if (status != ALL_OK) { break; } storage_delete_file(&pszError, &componentFileName); if (pszError != NULL) { storageFreeError(pszError); /* it's an error only if the file exists */ if (storage_file_exists(&componentFileName)) { status = IO_ERROR; pcsl_string_free(&componentFileName); break; } } pcsl_string_free(&componentFileName); } } pData = pData->nextEntry; } if (status == ALL_OK && suiteFound == 0) { /* suite doesn't exist */ status = NOT_FOUND; } return status; }
/** * Removes the storage file for record store <code>filename</code> * if it exists. * * @param ppszError pointer to a string that will hold an error message * if there is a problem, or null if the function is * successful (This function sets <tt>ppszError</tt>'s value.) * @param suiteId ID of the MIDlet suite that owns the record store * @param name name of the record store * @param extension extension number to add to the end of the file name * * @return 1 if successful * 0 if an IOException occurred * -1 if file is locked by another isolate * -2 if out of memory error occurs * */ int rmsdb_record_store_delete(char** ppszError, SuiteIdType suiteId, const pcsl_string* name_str, int extension) { StorageIdType storageId; MIDPError status; pcsl_string filename_str; lockFileList* searchedNodePtr = NULL; *ppszError = NULL; if ((extension == DB_EXTENSION_INDEX)&&(lockFileListPtr != NULL)) { /* linked list is already initialised for a db file */ searchedNodePtr = findLockById(suiteId, name_str); if (searchedNodePtr != NULL) { /* File is in use by another isolate */ *ppszError = (char *)FILE_LOCK_ERROR; return -1; } } /* * IMPL Note: here is assumed that the record store is located in the same * storage as the midlet suite. This may not be true. */ status = midp_suite_get_suite_storage(suiteId, &storageId); if (status != ALL_OK) { return 0; } if (MIDP_ERROR_NONE != rmsdb_get_unique_id_path(suiteId, storageId, name_str, extension, &filename_str)) { return -2; } storage_delete_file(ppszError, &filename_str); pcsl_string_free(&filename_str); if (*ppszError != NULL) { return 0; } return 1; }
/** * multitape_metadata_delete(S, C, mdat): * Delete specified metadata file; ${mdat} must have been initialized by a * call to multitape_metadata_get_by(hash|name). Call * chunks_delete_extrastats on ${C} and the metadata file length. */ int multitape_metadata_delete(STORAGE_D * S, CHUNKS_D * C, struct tapemetadata * mdat) { uint8_t hbuf[32]; if (crypto_hash_data(CRYPTO_KEY_HMAC_NAME, (uint8_t *)mdat->name, strlen(mdat->name), hbuf)) goto err0; if (storage_delete_file(S, 'm', hbuf)) goto err0; chunks_delete_extrastats(C, mdat->metadatalen); /* Success! */ return (0); err0: /* Failure! */ return (-1); }
/** * Removes the storage file for record store <code>filename</code> * if it exists. * * @param ppszError pointer to a string that will hold an error message * if there is a problem, or null if the function is * successful (This function sets <tt>ppszError</tt>'s value.) * @param filenameBase filenameBase of the MIDlet suite that owns the record * store * @param name name of the record store * @param extension extension number to add to the end of the file name * * @return 1 if successful * 0 if an IOException occurred * -1 if file is locked by another isolate * -2 if out of memory error occurs * */ int rmsdb_record_store_delete(char** ppszError, pcsl_string* filenameBase, const pcsl_string* name_str, int extension) { pcsl_string filename_str; #if ENABLE_RECORDSTORE_FILE_LOCK lockFileList* searchedNodePtr = NULL; #endif *ppszError = NULL; #if ENABLE_RECORDSTORE_FILE_LOCK if (extension == DB_EXTENSION_INDEX) { searchedNodePtr = rmsdb_find_file_lock_by_id(filenameBase, name_str); if (searchedNodePtr != NULL) { /* File is in use by another isolate */ *ppszError = (char *)FILE_LOCK_ERROR; return -1; } } #endif /* * IMPL_NOTE: for security reasons the record store is always * located in the internal storage. */ if (MIDP_ERROR_NONE != rmsdb_get_unique_id_path(filenameBase, INTERNAL_STORAGE_ID, name_str, extension, &filename_str)) { return -2; } storage_delete_file(ppszError, &filename_str); pcsl_string_free(&filename_str); if (*ppszError != NULL) { return 0; } return 1; }
/** * Rolls back the transaction being in progress. * * @return ALL_OK if the transaction was rolled back, * NOT_FOUND if the transaction has not been started, * IO_ERROR if I/O error */ MIDPError rollback_transaction() { MIDPError status = ALL_OK; pcsl_string_status rc; pcsl_string transDataFile; char *pszTemp = NULL; /* get a full path to the transaction data file */ rc = pcsl_string_cat(storage_get_root(INTERNAL_STORAGE_ID), &TRANSACTION_DATA_FILENAME, &transDataFile); if (rc != PCSL_STRING_OK) { return OUT_OF_MEMORY; } storage_delete_file(&pszTemp, &transDataFile); pcsl_string_free(&transDataFile); if (pszTemp != NULL) { storageFreeError(pszTemp); status = IO_ERROR; } else { g_transactionStarted = 0; } return ALL_OK; }
/** * Removes a software package given its suite ID * <p> * If the component is in use it must continue to be available * to the other components that are using it. The resources it * consumes must not be released until it is not in use. * * @param suiteId ID of the suite * * @return ALL_OK if no errors, * NOT_FOUND if the suite does not exist, * SUITE_LOCKED if the suite is locked, * BAD_PARAMS this suite cannot be removed */ MIDPError midp_remove_suite(SuiteIdType suiteId) { pcsl_string filename; char* pszError; pcsl_string suiteRoot; MIDPError status; int operationStarted = 0; void* fileIteratorHandle = NULL; MidpProperties properties; pcsl_string* pproperty; MidletSuiteData* pData = NULL; pcsl_string filenameBase; lockStorageList *node = NULL; /* get the filename base from the suite id */ status = build_suite_filename(suiteId, &PCSL_STRING_EMPTY, &filenameBase); if (status != ALL_OK) { return status; } node = find_storage_lock(suiteId); if (node != NULL) { if (node->update != KNI_TRUE) { return SUITE_LOCKED; } } /* * This is a public API which can be called without the VM running * so we need automatically init anything needed, to make the * caller's code less complex. * * Initialization is performed in steps so that we do use any * extra resources such as the VM for the operation being performed. */ if (midpInit(REMOVE_LEVEL) != 0) { return OUT_OF_MEMORY; } do { int rc; /* return code for rmsdb_... and storage_... */ /* load _suites.dat */ status = read_suites_data(&pszError); storageFreeError(pszError); if (status != ALL_OK) { break; } /* check that the suite exists and it is not a preloaded one */ pData = get_suite_data(suiteId); if (pData == NULL) { status = NOT_FOUND; break; } /* notify the listeners that we starting to remove the suite */ operationStarted = 1; suite_listeners_notify(SUITESTORE_LISTENER_TYPE_REMOVE, SUITESTORE_OPERATION_START, ALL_OK, pData); if (pData->type == COMPONENT_PREINSTALLED_SUITE) { status = BAD_PARAMS; break; } status = begin_transaction(TRANSACTION_REMOVE_SUITE, suiteId, NULL); if (status != ALL_OK) { return status; } /* * Remove the files * Call the native RMS method to remove the RMS data. * This function call is needed for portability */ rc = rmsdb_remove_record_stores_for_suite(&filenameBase, suiteId); if (rc == KNI_FALSE) { status = SUITE_LOCKED; break; } pushdeletesuite(suiteId); /* * If there is a delete notify property, add the value to the delete * notify URL list. */ properties = midp_get_suite_properties(suiteId); if (properties.numberOfProperties > 0) { pproperty = midp_find_property(&properties, &DELETE_NOTIFY_PROP); if (pcsl_string_length(pproperty) > 0) { midpAddDeleteNotification(suiteId, pproperty); } pproperty = midp_find_property(&properties, &INSTALL_NOTIFY_PROP); if (pcsl_string_length(pproperty) > 0) { /* * Remove any pending install notifications since they are only * retried when the suite is run. */ midpRemoveInstallNotification(suiteId); } midp_free_properties(&properties); } if ((status = get_suite_storage_root(suiteId, &suiteRoot)) != ALL_OK) { break; } fileIteratorHandle = storage_open_file_iterator(&suiteRoot); if (!fileIteratorHandle) { status = IO_ERROR; break; } #if ENABLE_ICON_CACHE midp_remove_suite_icons(suiteId); #endif for (;;) { rc = storage_get_next_file_in_iterator(&suiteRoot, fileIteratorHandle, &filename); if (0 != rc) { break; } storage_delete_file(&pszError, &filename); pcsl_string_free(&filename); if (pszError != NULL) { storageFreeError(pszError); break; } } } while (0); pcsl_string_free(&suiteRoot); storageCloseFileIterator(fileIteratorHandle); (void)finish_transaction(); /* * Notify the listeners the we've finished removing the suite. * It should be done before remove_from_suite_list_and_save() * call because it frees pData structure. */ if (operationStarted) { suite_listeners_notify(SUITESTORE_LISTENER_TYPE_REMOVE, SUITESTORE_OPERATION_END, status, pData); } if (status == ALL_OK) { (void)remove_from_suite_list_and_save(suiteId); } remove_storage_lock(suiteId); return status; }