midpstorage.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,022 行 · 第 1/2 页

C
1,022
字号
/* * * * Copyright  1990-2008 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. *//** * @file * * Manage storage for internal API's. *//* * Functions in this file make file system calls that are * the same (similar) across platforms with Posix * library support.  Calls which are system dependent and may vary * across platforms are encapsulated by functions defined in the file * storagePosix_md.h. */#include <string.h>#ifndef UNDER_CE#include <errno.h>#else#include <windows.h>#endif#include <midpUtilKni.h>#include <midpMalloc.h>#include <midpString.h>#include <midpStorage.h>#include <midp_logging.h>#include <midpResourceLimit.h>#include <pcsl_file.h>#include <pcsl_string.h>#include <pcsl_esc.h>#include <pcsl_string_status.h>#include <pcsl_memory.h>/* local prototypes */static int initializeConfigRoot (char*);static char* getLastError(char*);static char* storage_get_last_file_error(char*, const pcsl_string*);static const char* const OUT_OF_MEM_ERROR =    "out of memory, cannot perform file operation";static const char* const NOT_EXIST_RENAME_ERROR =    "The file to be renamed does not exist.";static const char* const FILE_LIMIT_ERROR =    "Resource limit exceeded for file handles";static const char* const STRING_CORRUPT_ERROR =    "string data corrupt or invalid, cannot perform i/o operation";/* * Name of the external storage directory. */PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START(MEMORY_CARD_DIR)    {'m', 'e', 'm', 'o', 'r', 'y', '_', 'c', 'a', 'r', 'd', '\0'}PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END(MEMORY_CARD_DIR);/* * IMPL_NOTE: currently the following two strings are unused (APP_DIR *            and CONFIG_DIR are defined in commandLineUtil_md.c), *            but this is not quite correct. *//* * Name of the storage directory. *//*PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START(APP_DIR)    {'a', 'p', 'p', 'd', 'b', '\0'}PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END(APP_DIR);PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_START(CONFIG_SUBDIR)    {'l', 'i', 'b', '\0'}PCSL_DEFINE_STATIC_ASCII_STRING_LITERAL_END(CONFIG_SUBDIR);*/#if REPORT_LEVEL <= LOG_INFORMATION#define DEBUGP2F(x, y) { \    const char* pszTemp = pcsl_string_get_utf8_data(y); \        if (pszTemp != NULL) { \            REPORT_INFO1(LC_CORE, x, pszTemp); \            pcsl_string_release_utf8_data(pszTemp,y); \        } \    }#else#define DEBUGP2F(x, y)#endif/* * Porting note: <tt>DEFAULT_TOTAL_SPACE</tt> defines the * default maximum space allotted for storage of MIDlet suites and their * associated record stores on a platform.  This storage space may * be set to a value other than <tt>DEFAULT_STORAGE_SPACE</tt> using * the <tt>storageSetTotalSpace</tt> method or providing the configuration * value system.jam_space (see midpInit.c). */#define DEFAULT_TOTAL_SPACE (4 * 1024 * 1024) /* 4 Meg. *//* Local variables */static long totalSpace = DEFAULT_TOTAL_SPACE;static pcsl_string sRoot[MAX_STORAGE_NUM];static pcsl_string configRoot[MAX_STORAGE_NUM];static int storageInitDone = 0;#define MAX_ERROR_LEN 159static char errorBuffer[MAX_ERROR_LEN + 1] = {0};/* * Set the system directory for storage * * @param config_home file system path to where MIDP is installed * @param midp_home file system path to where MIDP should store its * data like suites and such * * @return 0 for success, non-zero for out of memory */intstorageInitialize(char *config_home, char *app_dir) {    jchar fsep = storageGetFileSeparator();    if (storageInitDone) {        /* Already initialized */        return 0;    }    if (PCSL_STRING_OK != pcsl_string_initialize()) {        REPORT_ERROR(LC_CORE, "Error: cannot initialize string library.\n");        return -1;    }    pcsl_esc_init();    if(pcsl_file_init() < 0)  {        REPORT_ERROR(LC_CORE, "Error: out of memory.\n");        return -1;    }    /* set up a path to the internal storage */    if (PCSL_STRING_OK != pcsl_string_from_chars(app_dir, &sRoot[0])) {        REPORT_ERROR(LC_CORE, "Error: out of memory.\n");        storageFinalize();        return -1;    }    if (PCSL_STRING_OK != pcsl_string_append_char(&sRoot[0], fsep)) {        REPORT_ERROR(LC_CORE, "Error: out of memory.\n");        storageFinalize();        return -1;    }    if (MAX_STORAGE_NUM > 1) {        int i;        char* midp_home = NULL;        char* sep_pos = NULL;        /*         * this is sample implementation and should         * be rewritten for the real platforms         */        /* IMPL_NOTE: work around - restore midp home from appdb directory path */        midp_home = (char*)pcsl_mem_malloc(strlen(app_dir) + 1);        if (NULL == midp_home) {            REPORT_ERROR(LC_CORE, "Error: out of memory.\n");            storageFinalize();            return -1;        }        sep_pos = strrchr(app_dir, fsep);        if (NULL == sep_pos) {            REPORT_ERROR(LC_CORE, "Error: bad application dir.\n");            pcsl_mem_free(midp_home);            storageFinalize();            return -1;        }        i = (int)(sep_pos - app_dir) + 1;        strncpy(midp_home, app_dir, i);        midp_home[i] = 0;        if (PCSL_STRING_OK != pcsl_string_from_chars(midp_home, &sRoot[1])) {            REPORT_ERROR(LC_CORE, "Error: out of memory.\n");            pcsl_mem_free(midp_home);            storageFinalize();            return -1;        }        pcsl_mem_free(midp_home);        pcsl_string_predict_size(&sRoot[1], pcsl_string_length(&sRoot[1]) + 2                                        + PCSL_STRING_LITERAL_LENGTH(MEMORY_CARD_DIR));        if (PCSL_STRING_OK != pcsl_string_append_char(&sRoot[1], fsep)         || PCSL_STRING_OK != pcsl_string_append(&sRoot[1], &MEMORY_CARD_DIR)         || PCSL_STRING_OK != pcsl_string_append_char(&sRoot[1], fsep)) {            REPORT_ERROR(LC_CORE, "Error: out of memory.\n");            storageFinalize();            return -1;        }        /*         * If more than one external storage is needed, write extra initialization here.         * By default we just redirect all to internal storage.         */        for (i = 2; i < MAX_STORAGE_NUM; i++) {            if (PCSL_STRING_OK != pcsl_string_dup(&sRoot[0], &sRoot[i])) {                storageFinalize();                return -1;            }         }    }    if (0 != initializeConfigRoot(config_home)) {        storageFinalize();        return -1;    }    storageInitDone = 1;    return 0;}static intinitializeConfigRoot(char* config_home) {    jchar fileSep = storageGetFileSeparator();    int i;    if (PCSL_STRING_OK != pcsl_string_from_chars(config_home, &configRoot[0])) {        return -1;    }    if (PCSL_STRING_OK != pcsl_string_append_char(&configRoot[0], fileSep)) {        pcsl_string_free(&configRoot[0]);        return -1;    }    for (i = 1; i < MAX_STORAGE_NUM; i++) {        if (PCSL_STRING_OK != pcsl_string_dup(&configRoot[0], &configRoot[i])) {            return -1;        }    }    return 0;}/* * Set the MIDlet suite storage allowable space different than the default * * This function cannot be part of initialStorage since the space parameter * is normally obtained from the config system which cannot be used until * initializeStorage is called. * * @param space total file space allocated to MIDP */voidstorageSetTotalSpace(long space) {    totalSpace = space;}/* * Finalize the storage subsystem. */voidstorageFinalize() {    int i;    for (i = 0; i < MAX_STORAGE_NUM; i++) {        pcsl_string_free(&sRoot[i]);        pcsl_string_free(&configRoot[i]);    }    storageInitDone = 0;    pcsl_file_finalize();}/* * Returns root string that all files should begin with, including * a trailing file separator if needed. By including the any trailing file * separators the Java API does not need to know about file separators * or subdirectories. * * Since the lifetime of the returned object is from storageInitialize * until storageFinalize, you do not have to free the returned object. * * @param storageId ID of the storage the root of which must be returned * * @return prefix used for all file names in the given storage. *         It may be empty, but not PCSL_STRING_NULL. */const pcsl_string*storage_get_root(StorageIdType storageId) {    /*     * Change MAX_STORAGE_NUM value if you want to have more than one     * external storage. This will also require modification of the functions     * initializing and returning sRoot[<index>] and configRoot[<index>], namely     * storageInitialize(), storage_get_root() and storage_get_config_root().     */    pcsl_string* pRes;    if (storageId == INTERNAL_STORAGE_ID) {        pRes = &sRoot[0];    } else if ((storageId >= 0)            && (storageId < MAX_STORAGE_NUM)) {        pRes = &sRoot[storageId];    } else {        /*         * IMPL_NOTE: if invalid storage id is specified         * we return internal storage         */        pRes = &sRoot[0];    }    return pRes;}/* * Returns the root string that configuration files start with, including a * trailing file separator when necessary. If the string includes a trailing * file separator, callers do not need access to file separators or * subdirectories. * * Since the lifetime of the returned object is from initializeConfigRoot * until storageFinalize, you do not have to free the returned object. * * @param storageId ID of the storage the config root of which must be returned * * @return prefix used for all configuration file names. It may be empty, *         but not PCSL_STRING_NULL */const pcsl_string*storage_get_config_root(StorageIdType storageId) {    pcsl_string* pRes;    if (storageId == INTERNAL_STORAGE_ID) {        pRes = &configRoot[0];    } else if ((storageId >= 0)            && (storageId < MAX_STORAGE_NUM)) {        pRes = &configRoot[storageId];    } else {        /*         * IMPL_NOTE: if invalid storage id is specified         * we return internal storage         */        pRes = &configRoot[0];    }    return pRes;}/* * Free the error string returned from a storage function. * Does nothing if a NULL is passed in. * This allows for systems that provide error messages that are allocated * dynamically. */voidstorageFreeError(char* pszError) {    /*     * This is a place holder, so that an implementation, like a debuggable     * one can create dynamic error messages.     */    if (NULL == pszError || OUT_OF_MEM_ERROR == pszError ||        NOT_EXIST_RENAME_ERROR == pszError) {        return;    }}/* * Return a non-zero integer if a file with the given name exists else return * zero. */intstorage_file_exists(const pcsl_string* filename_str) {    /* Mapping 0 and -1 (error) to 0 (file not exists). */    return pcsl_file_exist(filename_str) > 0;}/* * Returns the file separator as a string. * * This function only called by the main native code to * to manage files outside of the MIDP implementation simulated storage. */jcharstorageGetFileSeparator() {    return (jchar)pcsl_file_getfileseparator();}/* * The function is provided for development platforms so we can manage * local files outside of the MIDP implementation simulated storage. */jcharstorageGetPathSeparator() {    return (jchar)pcsl_file_getpathseparator();}/* * Return a 32 bit handle to an open a file in storage in different modes. * * See "I/O Modes" and "Filenames" above for move information. * * If not successful *ppszError will set to point to an error string, * on success it will be set to NULL. */intstorage_open(char** ppszError, const pcsl_string* filename_str, int ioMode) {    int flags = 0;    int openStatus;    void *handle;    *ppszError = NULL;    if (OPEN_READ == ioMode) {        DEBUGP2F("opening for read only %s\n", filename_str);        flags |= PCSL_FILE_O_RDONLY;    } else {        if (!storage_file_exists(filename_str)) {            flags |= PCSL_FILE_O_CREAT;        } else if (OPEN_READ_WRITE_TRUNCATE == ioMode) {            flags |= PCSL_FILE_O_TRUNC;        }        if (OPEN_WRITE == ioMode) {            DEBUGP2F("opening write only %s\n", filename_str);            flags |= PCSL_FILE_O_WRONLY;        } else {            DEBUGP2F("opening read write %s\n", filename_str);            flags |= PCSL_FILE_O_RDWR;        }    }    /**     * Verify that the resource is available well within limit as per     * the policy in ResourceLimiter     */    if (midpCheckResourceLimit(RSC_TYPE_FILE, 1) == 0) {        REPORT_INFO(LC_CORE, "Resource limit exceeded for file handles");        *ppszError = (char *)FILE_LIMIT_ERROR;        return -1;    }    openStatus = pcsl_file_open(filename_str, flags, &handle);    REPORT_INFO1(LC_CORE, "storage_open allocated file_desc %d\n", (int)handle);    if (-1 == openStatus) {        *ppszError = storage_get_last_file_error("storage_open()", filename_str);        return -1;    }    /* Update the resource count  */    if (midpIncResourceCount(RSC_TYPE_FILE, 1) == 0) {        REPORT_INFO(LC_CORE, "FILE : resource limit update error");    }#if REPORT_LEVEL <= LOG_INFORMATION    DEBUGP2F("created %s\n", filename_str);#endif    return (int)handle;}/* * Close a opened by storage_open. Does no block. * * If not successful *ppszError will set to point to an error string, * on success it will be set to NULL. */voidstorageClose(char** ppszError, int handle) {    int status;    *ppszError = NULL;    status = pcsl_file_close((void *)handle);    REPORT_INFO2(LC_CORE, "storageClose on file_desc %d returns %d\n",          handle, status);    if (status < 0) {        *ppszError = getLastError("storageClose()");    }    /* File is successfully closed, decrement the count */    if (midpDecResourceCount(RSC_TYPE_FILE, 1) == 0) {        REPORT_INFO(LC_CORE, "FILE: resource"                             " limit update error");    }}/*

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?