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 + -
显示快捷键?