/** * Writes the settings of a MIDlet suite to persistent storage. * <pre> * The format of the properties file will be: * * push interrupt setting as an jbyte * length of a permissions as an int * array of permissions jbytes * push options as jint * </pre> * * @param ppszError pointer to character string pointer to accept an error * @param suiteId ID of the suite * @param enabled enabled setting * @param pushInterrupt pointer to a push interruptSetting * @param pushOptions user options for push interrupts * @param pPermissions pointer a pointer to accept a permissions array * @param numberOfPermissions length of pPermissions * * @return error code (ALL_OK if successful) */ MIDPError write_settings(char** ppszError, SuiteIdType suiteId, jboolean enabled, jbyte pushInterrupt, jint pushOptions, jbyte* pPermissions, int numberOfPermissions) { pcsl_string filename; int handle; char* pszTemp; MIDPError status; *ppszError = NULL; status = build_suite_filename(suiteId, &SETTINGS_FILENAME, &filename); if (status != ALL_OK) { return status; } handle = storage_open(ppszError, &filename, OPEN_READ_WRITE_TRUNCATE); pcsl_string_free(&filename); if (*ppszError != NULL) { return IO_ERROR; } storageWrite(ppszError, handle, (char*)&enabled, sizeof (jboolean)); do { if (*ppszError != NULL) { break; } storageWrite(ppszError, handle, (char*)&pushInterrupt, sizeof (jbyte)); if (*ppszError != NULL) { break; } storageWrite(ppszError, handle, (char*)&numberOfPermissions, sizeof (int)); if (*ppszError != NULL) { break; } storageWrite(ppszError, handle, (char*)pPermissions, numberOfPermissions * sizeof (jbyte)); storageWrite(ppszError, handle, (char*)&pushOptions, sizeof (jint)); if (*ppszError != NULL) { break; } } while (0); if (*ppszError != NULL) { status = IO_ERROR; } storageClose(&pszTemp, handle); storageFreeError(pszTemp); return ALL_OK; }
/** * Gets location of the file associated with the named resource * of the suite with the specified suiteId. * * Note that in/out parameter filename MUST be allocated by callee with * pcsl_mem_malloc(), the caller is responsible for freeing it. * * @param suiteId The application suite ID * @param resourceName The name of suite resource whose location is requested * @param checkSuiteExists true if suite should be checked for existence or not * @param filename The in/out parameter that contains returned filename * @return error code that should be one of the following: * <pre> * ALL_OK, OUT_OF_MEMORY, NOT_FOUND, * SUITE_CORRUPTED_ERROR, BAD_PARAMS * </pre> */ static MIDPError get_suite_resource_file(SuiteIdType suiteId, const pcsl_string* resourceName, jboolean checkSuiteExists, pcsl_string *filename) { pcsl_string returnFileName = PCSL_STRING_NULL; int rc; *filename = PCSL_STRING_NULL; if (checkSuiteExists) { rc = build_suite_filename(suiteId, resourceName, &returnFileName); } else { rc = get_suite_filename(suiteId, resourceName, &returnFileName); } if (rc == ALL_OK) { *filename = returnFileName; } return ALL_OK; }
/** * Gets the amount of storage on the device that this suite is using. * This includes the JAD, JAR, management data, and RMS. * * @param suiteId ID of the suite * * @return number of bytes of storage the suite is using or less than * OUT_OF_MEM_LEN if out of memory */ long midp_get_suite_storage_size(SuiteIdType suiteId) { long used = 0; long rms = 0; pcsl_string filename[NUM_SUITE_FILES]; int i; char* pszError; StorageIdType storageId; MIDPError status; MidletSuiteData* pData; pcsl_string filenameBase; // get the filename base from the suite id status = build_suite_filename(suiteId, &PCSL_STRING_EMPTY, &filenameBase); if (status != ALL_OK) { return status; } pData = get_suite_data(suiteId); if (pData) { used = (jint)pData->suiteSize; } if (used <= 0) { /* Suite size is not cached (should not happen!), calculate it. */ for (i = 0; i < NUM_SUITE_FILES; i++) { filename[i] = PCSL_STRING_NULL; } /* * 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(LIST_LEVEL) != 0) { return OUT_OF_MEM_LEN; } status = midp_suite_get_suite_storage(suiteId, &storageId); if (status != ALL_OK) { return OUT_OF_MEM_LEN; } status = build_suite_filename(suiteId, &INSTALL_INFO_FILENAME, &filename[0]); if (status != ALL_OK) { return status; } status = build_suite_filename(suiteId, &SETTINGS_FILENAME, &filename[1]); if (status != ALL_OK) { return status; } midp_suite_get_class_path(suiteId, storageId, KNI_TRUE, &filename[2]); get_property_file(suiteId, KNI_TRUE, &filename[3]); for (i = 0; i < NUM_SUITE_FILES; i++) { long tmp; if (pcsl_string_is_null(&filename[i])) { continue; } tmp = storage_size_of_file_by_name(&pszError, &filename[i]); pcsl_string_free(&filename[i]); if (pszError != NULL) { storageFreeError(pszError); continue; } used += tmp; } if (pData) { /* cache the calculated size */ pData->suiteSize = (jint)used; status = write_suites_data(&pszError); if (status != ALL_OK) { storageFreeError(pszError); return OUT_OF_MEM_LEN; } } } rms = rmsdb_get_rms_storage_size(&filenameBase, suiteId); if (rms == OUT_OF_MEM_LEN) { return OUT_OF_MEM_LEN; } return used + rms; }
/** * Gets the settings of a MIDlet suite from persistent storage. * <pre> * The format of the properties file will be: * * push interrupt setting as an jbyte * length of a permissions as an int * array of permissions jbytes * push options as jint * </pre> * * @param ppszError pointer to character string pointer to accept an error * @param suiteId ID of the suite * @param pEnabled pointer to an enabled setting * @param pPushInterrupt pointer to a push interruptSetting * @param pPushOptions user options for push interrupts * @param ppPermissions pointer a pointer to accept a permissions array * @param pNumberOfPermissions pointer to an int * * @return error code (ALL_OK if successful) */ MIDPError read_settings(char** ppszError, SuiteIdType suiteId, jboolean* pEnabled, jbyte* pPushInterrupt, jint* pPushOptions, jbyte** ppPermissions, int* pNumberOfPermissions) { pcsl_string filename; int handle; int bytesRead; char* pszTemp; MIDPError status; *ppszError = NULL; *ppPermissions = NULL; *pNumberOfPermissions = 0; status = build_suite_filename(suiteId, &SETTINGS_FILENAME, &filename); if (status != ALL_OK) { return status; } handle = storage_open(ppszError, &filename, OPEN_READ); pcsl_string_free(&filename); if (*ppszError != NULL) { return IO_ERROR; } bytesRead = storageRead(ppszError, handle, (char*)pEnabled, sizeof (jboolean)); do { if (*ppszError != NULL) { status = IO_ERROR; break; } bytesRead = storageRead(ppszError, handle, (char*)pPushInterrupt, sizeof (jbyte)); if (*ppszError != NULL) { status = IO_ERROR; break; } bytesRead = storageRead(ppszError, handle, (char*)pNumberOfPermissions, sizeof (int)); if (bytesRead != sizeof (int) || *pNumberOfPermissions == 0) { status = IO_ERROR; break; } *ppPermissions = (jbyte*)pcsl_mem_malloc( *pNumberOfPermissions * sizeof (jbyte)); if (*ppPermissions == NULL) { status = OUT_OF_MEMORY; break; } bytesRead = storageRead(ppszError, handle, (char*)(*ppPermissions), *pNumberOfPermissions * sizeof (jbyte)); if (bytesRead != *pNumberOfPermissions) { *pNumberOfPermissions = 0; pcsl_mem_free(*ppPermissions); status = SUITE_CORRUPTED_ERROR; break; } /* Old versions of the file may not have options. */ status = ALL_OK; *pPushOptions = 0; bytesRead = storageRead(ppszError, handle, (char*)pPushOptions, sizeof (jint)); if (*ppszError != NULL) { storageFreeError(*ppszError); *ppszError = NULL; break; } } while (0); storageClose(&pszTemp, handle); storageFreeError(pszTemp); return status; }
/** * 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; }