/**
 * Gets the storage root for a MIDlet suite by ID.
 * Free the data of the string returned with pcsl_string_free().
 *
 * @param suiteId suite ID
 * @param sRoot receives storage root (gets set to NULL in the case of an error)
 *
 * @return status: ALL_OK if success,
 * OUT_OF_MEMORY if out-of-memory
 */
MIDPError
get_suite_storage_root(SuiteIdType suiteId, pcsl_string* sRoot) {
    StorageIdType storageId;
    const pcsl_string* root;
    MIDPError status;

    *sRoot = PCSL_STRING_EMPTY;

    /* get an id of the storage where the suite is located */
    status = midp_suite_get_suite_storage(suiteId, &storageId);
    if (status != ALL_OK) {
        return status;
    }

    root = storage_get_root(storageId);

    pcsl_string_predict_size(sRoot,
        pcsl_string_length(root) + GET_SUITE_ID_LEN(suiteId));

    if (PCSL_STRING_OK == pcsl_string_append(sRoot, root) &&
            PCSL_STRING_OK == pcsl_string_append(sRoot,
                midp_suiteid2pcsl_string(suiteId))) {
        return ALL_OK;
    }

    pcsl_string_free(sRoot);
    *sRoot = PCSL_STRING_NULL;

    return OUT_OF_MEMORY;
}
Beispiel #2
0
/**
 * Builds a full file name using the storage root and MIDlet suite by ID.
 *
 * @param suiteId suite ID
 * @param filename filename without a root path
 * @param sRoot receives full name of the file
 *
 * @return the status: ALL_OK if ok, OUT_OF_MEMORY if out of memory
 */
static MIDPError
get_suite_filename(SuiteIdType suiteId, const pcsl_string* filename,
                   pcsl_string* sRoot) {
  int sRoot_len;
  const pcsl_string* root;
  StorageIdType storageId;
  MIDPError status;

  /* get an id of the storage where the suite is located */
  status = midp_suite_get_suite_storage(suiteId, &storageId);
  if (status != ALL_OK) {
      return status;
  }

  root = storage_get_root(storageId);

  *sRoot = PCSL_STRING_EMPTY;

  sRoot_len = pcsl_string_length(root)
            + GET_SUITE_ID_LEN(suiteId)
            + pcsl_string_length(filename);
  pcsl_string_predict_size(sRoot, sRoot_len);

  if (PCSL_STRING_OK == pcsl_string_append(sRoot, root) &&
      PCSL_STRING_OK == pcsl_string_append(sRoot,
          midp_suiteid2pcsl_string(suiteId)) &&
      PCSL_STRING_OK == pcsl_string_append(sRoot, filename)) {
      return ALL_OK;
  } else {
        pcsl_string_free(sRoot);
        *sRoot = PCSL_STRING_NULL;
        return OUT_OF_MEMORY;
  }
}
Beispiel #3
0
/**
 * Returns the number of record stores owned by the
 * MIDlet suite.
 *
 * @param suiteId ID of the MIDlet suite that owns the record store
 *
 * @return number of record stores or OUT_OF_MEM_LEN
 */
int
rmsdb_get_number_of_record_stores(SuiteIdType suiteId) {
    pcsl_string root = PCSL_STRING_NULL;
    int numberOfStores;
    MIDPError status;
    StorageIdType storageId;

    /*
     * 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 OUT_OF_MEM_LEN;
    }

    status = midp_suite_get_rms_filename(suiteId, storageId, -1,
                                         &PCSL_STRING_EMPTY, &root);
    if (status != ALL_OK) {
      return OUT_OF_MEM_LEN;
    }

    if (root.data == NULL) {
        return 0;
    }

    numberOfStores = rmsdb_get_number_of_record_stores_int(&root);

    pcsl_string_free(&root);

    return numberOfStores;
}
Beispiel #4
0
/**
 * Approximation of remaining RMS space in storage for a suite.
 *
 * Usage Warning:  This may be a slow operation if
 * the platform has to look at the size of each file
 * stored in the MIDP memory space and include its size
 * in the total.
 *
 * @param handle handle to record store storage
 * @param id ID of the suite
 *
 * @return the approximate space available to grow the
 *         record store in bytes.
 */
long
rmsdb_get_record_store_space_available(int handle, SuiteIdType id) {
    /* Storage may have more then 2Gb space available so use 64-bit type */
    jlong availSpace;
    long availSpaceUpTo2Gb;
    char* pszError;
    StorageIdType storageId;
    MIDPError status;

    (void)id; /* Avoid compiler warnings */

    /*
     * IMPL_NOTE: here we introduce a limitation that the suite's RMS
     * must be located at the same storage as the midlet suite.
     * This is done because the public RecordStore API doesn't support
     * a storageId parameter.
     * There is a plan to get rid of such limitation by introducing a
     * function that will return a storage ID by the suite ID and RMS name.
     */
    status = midp_suite_get_suite_storage(id, &storageId);
    if (status != ALL_OK) {
        return 0; /* Error: report that no space is available */
    }

    availSpace = midp_file_cache_available_space(&pszError, handle, storageId);

    /*
     * Public RecordStore API uses Java int type for the available space
     * so here we trim the real space to 2Gb limit.
     */
    availSpaceUpTo2Gb = (availSpace <= LONG_MAX) ? availSpace : LONG_MAX;

    return availSpaceUpTo2Gb;
}
Beispiel #5
0
/**
 * Looks to see if the storage file for record store
 * identified by <code>uidPath</code> exists
 *
 * @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 true if the file exists, false if it does not.
 */
int rmsdb_record_store_exists(SuiteIdType suiteId,
                              const pcsl_string* name,
                              int extension) {
    pcsl_string filename;
    int intStatus;
    StorageIdType storageId;
    MIDPError status;

    /*
     * 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, extension, &filename)) {
        return 0;
    }
    if (pcsl_string_is_null(&filename)) {
        return 0;
    }

    intStatus = storage_file_exists(&filename);
    pcsl_string_free(&filename);

    return 0 != intStatus;
}
Beispiel #6
0
int
rmsdb_record_store_open(char** ppszError, SuiteIdType suiteId,
                        const pcsl_string * name_str, int extension) {
    StorageIdType storageId;
    MIDPError status;
    pcsl_string filename_str;
    int handle;
    lockFileList* searchedNodePtr = NULL;
    int addflag = 0;

    *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 already opened by another isolate, return an error */
            *ppszError = (char *)FILE_LOCK_ERROR;
            return -2;
        } else { /* remember to add a node */
            addflag = 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 -1;
    }
    handle = midp_file_cache_open(ppszError, storageId,
                                  &filename_str, OPEN_READ_WRITE);

    pcsl_string_free(&filename_str);
    if (*ppszError != NULL) {
        return -1;
    }

    /*
     * Add the node only if it's a db file AND lockFileListPtr is NULL or
     * addflag is 1
     */
    if ((extension == DB_EXTENSION_INDEX)&&
        ( (lockFileListPtr == NULL) || (addflag == 1)) ) {
            if (recordStoreCreateLock(suiteId, name_str, handle) != 0) {
                return -1;
            }
    }

    return handle;
}
/**
 * Check if the suite is corrupted
 * @param suiteId ID of a suite
 *
 * @return ALL_OK if the suite is not corrupted,
 *         SUITE_CORRUPTED_ERROR is suite is corrupted,
 *         OUT_OF_MEMORY if out of memory,
 *         IO_ERROR if I/O error
 */
MIDPError
check_for_corrupted_suite(SuiteIdType suiteId) {
    pcsl_string filename[NUM_SUITE_FILES];
    int arc[NUM_SUITE_FILES];
    int i;
    StorageIdType storageId;
    MIDPError status = ALL_OK; /* Default to no error */
    MidletSuiteData *pData = get_suite_data(suiteId);

    if (!pData) {
        return SUITE_CORRUPTED_ERROR;
    }

    /* if this suite was already checked, just return "OK" status */
    if (pData->isChecked) {
        return status;
    }

    /* get an id of the storage where the suite is located */
    status = midp_suite_get_suite_storage(suiteId, &storageId);
    if (status != ALL_OK) {
        return status;
    }

    arc[0] = get_suite_filename(suiteId, &INSTALL_INFO_FILENAME, &filename[0]);
    arc[1] = get_suite_filename(suiteId, &SETTINGS_FILENAME, &filename[1]);
    arc[2] = midp_suite_get_class_path(suiteId, storageId,
                                       KNI_FALSE, &filename[2]);
    arc[3] = get_property_file(suiteId, KNI_FALSE, &filename[3]);

    for (i = 0; i < NUM_SUITE_FILES; i++) {
        if (arc[i] != ALL_OK) {
            status = (MIDPError)arc[i];
            break;
        }

        if (!storage_file_exists(&filename[i])) {
            /* File does not exist; suite must be corrupted */
            status = SUITE_CORRUPTED_ERROR;
            break;
        }
    }

    if (status == ALL_OK) {
        /* if the suite is not currupted, mark it as "checked" */
        pData->isChecked = 1;
    }

    pcsl_string_free(&filename[0]);
    pcsl_string_free(&filename[1]);
    pcsl_string_free(&filename[2]);
    pcsl_string_free(&filename[3]);

    return status;
}
Beispiel #8
0
/**
 * 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;
}
Beispiel #9
0
/**
 * Returns an array of the names of record stores owned by the
 * MIDlet suite.
 *
 * @param suiteId
 * @param ppNames pointer to pointer that will be filled in with names
 *
 * @return number of record store names or OUT_OF_MEM_LEN
 */
int
rmsdb_get_record_store_list(SuiteIdType suiteId, 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;
    StorageIdType storageId;
    /* IMPL_NOTE: how can we get it statically? */
    const int dbext_len = pcsl_string_length(&DB_EXTENSION);

    *ppNames = NULL;

    /*
     * 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 OUT_OF_MEM_LEN;
    }

    status = midp_suite_get_rms_filename(suiteId, storageId, -1,
                                         &PCSL_STRING_EMPTY, &root);
    if (status != ALL_OK) {
        return OUT_OF_MEM_LEN;
    }

    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 = escaped_ascii_to_unicode(&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;
}
/**
 * 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;
}