📄 rms.c
字号:
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include "kni.h"#include "midp_file_cache.h"#include <midpStorage.h>#include <midpMalloc.h>#include <midpInit.h>#include <midpRMS.h>#include <midpUtilKni.h>#include <suitestore_rms.h>#include <limits.h> /* for LONG_MAX */#include <pcsl_esc.h>#include <pcsl_string.h>#if ENABLE_RECORDSTORE_FILE_LOCK#include "rms_file_lock.h"#endif/** Easily recognize record store files in the file system */static const int DB_EXTENSION_INDEX = 0;static const int IDX_EXTENSION_INDEX = 1;/*PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START( DB_EXTENSION ) {'.', 'd', 'b', '\0'}PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END( DB_EXTENSION );PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START( IDX_EXTENSION ) {'.', 'i', 'd', 'x', '\0'}PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END( IDX_EXTENSION );*/static const char* const FILE_LOCK_ERROR = "File is locked, can not open";/* Forward declarations for local functions */static MIDPError buildSuiteFilename(pcsl_string * filenameBase, const pcsl_string* name, jint extension, pcsl_string * pFileName);/** * Returns a storage system unique string for this record store file * based on the current vendor and suite of the running MIDlet. * <ul> * <li>The native storage path for the desired MIDlet suite * is acquired from the Scheduler. * * <li>The <code>filename</code> arg is converted into an ascii * equivalent safe to use directly in the underlying * file system and appended to the native storage path. See the * com.sun.midp.io.j2me.storage.File.unicodeToAsciiFilename() * method for conversion details. * * <li>Finally the extension number given by the extension parameter * is appended to the file name. * <ul> * @param filenameBase filename base of the MIDlet suite that owns the record * store * @param storageId ID of the storage where the RMS will be located * @param name name of the record store * @param extension extension number to add to the end of the file name * * @return a unique identifier for this record store file */static MIDP_ERRORrmsdb_get_unique_id_path(pcsl_string* filenameBase, StorageIdType storageId, const pcsl_string* name, int extension, pcsl_string * res_path) { pcsl_string temp = PCSL_STRING_NULL; MIDP_ERROR midpErr; pcsl_string_status pcslErr; *res_path = PCSL_STRING_NULL; /* null in case of any error */ if (pcsl_string_is_null(name)) { return MIDP_ERROR_ILLEGAL_ARGUMENT; } midpErr = buildSuiteFilename(filenameBase, name, extension == IDX_EXTENSION_INDEX ? MIDP_RMS_IDX_EXT : MIDP_RMS_DB_EXT, res_path); if (midpErr != MIDP_ERROR_NONE) { return midpErr; } if (pcsl_string_is_null(res_path)) { /* Assume this is special case where the suite was not installed and create a filename from the ID. */ pcslErr = pcsl_string_cat(storage_get_root(storageId), filenameBase, &temp); if (pcslErr != PCSL_STRING_OK || pcsl_string_is_null(&temp) ) { return MIDP_ERROR_FOREIGN; } pcslErr = pcsl_string_cat(&temp, name, res_path); pcsl_string_free(&temp); if (PCSL_STRING_OK != pcslErr) { return MIDP_ERROR_FOREIGN; } } return MIDP_ERROR_NONE;}/** * Looks to see if the storage file for record store * identified by <code>uidPath</code> exists * * @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 true if the file exists, false if it does not. */int rmsdb_record_store_exists(pcsl_string* filenameBase, const pcsl_string* name, int extension) { pcsl_string filename; int intStatus; /* * 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, extension, &filename)) { return 0; } if (pcsl_string_is_null(&filename)) { return 0; } intStatus = storage_file_exists(&filename); pcsl_string_free(&filename); return 0 != intStatus;}/** * 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 * */intrmsdb_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;}/** * Returns the number of record stores owned by the * MIDlet suite. * * @param root storage root a MIDlet suite * * @return number of record stores or OUT_OF_MEM_LEN */static intrmsdb_get_number_of_record_stores_int(const pcsl_string* root) { pcsl_string filename; int numberOfStores = 0; void* handle = NULL; int errc = 0; /* 0 for ok, -1 for error -- see pcsl docs */ handle = storage_open_file_iterator(root); if (!handle) { return OUT_OF_MEM_LEN; } for(;;) { errc = storage_get_next_file_in_iterator(root, handle, &filename); if ( 0 != errc ) { break; } if (pcsl_string_ends_with(&filename, &DB_EXTENSION)) { numberOfStores++; } pcsl_string_free(&filename); } storageCloseFileIterator(handle); return numberOfStores;}/** * Returns the number of record stores owned by the * MIDlet suite. * * @param filenameBase filenameBase of the MIDlet suite that owns the record * store * * @return number of record stores or OUT_OF_MEM_LEN */intrmsdb_get_number_of_record_stores(pcsl_string* filenameBase) { int numberOfStores; /* * IMPL_NOTE: for security reasons the record store is always * located in the internal storage. */ if (filenameBase->data == NULL) { return 0; } numberOfStores = rmsdb_get_number_of_record_stores_int(filenameBase); return numberOfStores;}/** * Returns an array of the names of record stores owned by the * MIDlet suite. * * @param filenameBase filenameBase of the suite * @param ppNames pointer to pointer that will be filled in with names * * @return number of record store names or OUT_OF_MEM_LEN */intrmsdb_get_record_store_list(pcsl_string* filenameBase, pcsl_string* *const ppNames) { int numberOfStores; pcsl_string root; pcsl_string* pStores; pcsl_string filename; pcsl_string ascii_name = PCSL_STRING_NULL_INITIALIZER; int i; void* handle = NULL; MIDPError status; int f_errc; pcsl_string_status s_errc; /* IMPL_NOTE: how can we get it statically? */ const int dbext_len = pcsl_string_length(&DB_EXTENSION); *ppNames = NULL; /* * IMPL_NOTE: for security reasons the record store is always * located in the internal storage. */ status = buildSuiteFilename(filenameBase, &PCSL_STRING_EMPTY, -1, &root); if (status != MIDP_ERROR_NONE) { return status; } if (pcsl_string_is_null(&root)) { return 0; } numberOfStores = rmsdb_get_number_of_record_stores_int(&root); if (numberOfStores <= 0) { pcsl_string_free(&root); return numberOfStores; } pStores = alloc_pcsl_string_list(numberOfStores); if (pStores == NULL) { pcsl_string_free(&root); return OUT_OF_MEM_LEN; } handle = storage_open_file_iterator(&root); if (!handle) { pcsl_string_free(&root); return OUT_OF_MEM_LEN; } /* the main loop */ for (i=0,f_errc=0,s_errc=0;;) { f_errc = storage_get_next_file_in_iterator(&root, handle, &filename); if (0 != f_errc) { f_errc = 0; break; } if (pcsl_string_ends_with(&filename, &DB_EXTENSION)) { s_errc = pcsl_string_substring(&filename, pcsl_string_length(&root), pcsl_string_length(&filename) - dbext_len, &ascii_name); pcsl_string_free(&filename); if (PCSL_STRING_OK != s_errc ) { break; } s_errc = pcsl_esc_extract_attached(0, &ascii_name, &pStores[i]); pcsl_string_free(&ascii_name); if (PCSL_STRING_OK != s_errc ) { break; } i++; } pcsl_string_free(&filename); /* IMPL_NOTE: do we need this one? isn't it useless? */ if (i == numberOfStores) { break; } } pcsl_string_free(&root); storageCloseFileIterator(handle); if (f_errc || s_errc) { /* The loop stopped because we ran out of memory. */ free_pcsl_string_list(pStores, i); return OUT_OF_MEM_LEN; } *ppNames = pStores; return numberOfStores;}/** * Remove all the Record Stores for a suite. * * @param filenameBase filenameBase of the suite * @param id ID of the suite * Only one of the parameters will be used by a given implementation. In the * case where the implementation might store data outside of the MIDlet storage, * the filenameBase will be ignored and only the suite id will be pertinent. * * @return false if out of memory else true */intrmsdb_remove_record_stores_for_suite(pcsl_string* filenameBase, SuiteIdType id) { int numberOfNames; pcsl_string* pNames; int i; int result = 1; char* pszError; (void)id; /* avoid a compiler warning */ /* * 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 0; } numberOfNames = rmsdb_get_record_store_list(filenameBase, &pNames); if (numberOfNames == OUT_OF_MEM_LEN) { return 0; } if (numberOfNames <= 0) { return 1; } for (i = 0; i < numberOfNames; i++) { if (rmsdb_record_store_delete(&pszError, filenameBase, &pNames[i], DB_EXTENSION_INDEX) <= 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -