static int seekChars(void* state, long offset, int whence) { long absPos; char* pszError; switch (whence) { case SEEK_SET: absPos = offset; storagePosition(&pszError, (int)state, absPos); break; case SEEK_END: absPos = sizeOfFile(state) + offset; storagePosition(&pszError, (int)state, absPos); break; case SEEK_CUR: absPos = storageRelativePosition(&pszError, (int)state, offset); break; default: return -1; } storageFreeError(pszError); return absPos; }
/** * Store content handler information into a registry. * * @param handler description of a registering handler. Implementation MUST NOT * retain pointed object * @return JSR211_OK if content handler registered successfully */ jsr211_result jsr211_register_handler(const JSR211_content_handler* handler) { long current_position; unsigned int record_size = sizeof(int); if (open_table_file(1) != JSR211_OK) { return JSR211_FAILED; } storagePosition(&io_error_message, table_file, storageSizeOf(&io_error_message, table_file)); current_position = storageRelativePosition(&io_error_message, table_file, 0); storageWrite(&io_error_message, table_file, (char *)&record_size, sizeof(record_size)); /* Placeholder for record size */ record_size += write_string(&(handler->id)); record_size += write_int(handler->flag); record_size += write_int(handler->suite_id); record_size += write_string(&(handler->class_name)); record_size += write_string_array(handler->type_num, handler->types); record_size += write_string_array(handler->suff_num, handler->suffixes); record_size += write_string_array(handler->act_num, handler->actions); record_size += write_string_array(handler->locale_num, handler->locales); record_size += write_string_array(handler->locale_num * handler->act_num, handler->action_map); record_size += write_string_array(handler->access_num, handler->accesses); storagePosition(&io_error_message, table_file, current_position); storageWrite(&io_error_message, table_file, (char *)&record_size, sizeof(record_size)); storageRelativePosition(&io_error_message, table_file, record_size - sizeof(int)); close_table_file(); return JSR211_OK; }
/** * Searches the next content handler in the file by its suite id. * * @param suite search suite ID * @return offset of found record or -1 */ static long find_next_by_suite(int suite) { long current_position; int record_size; int testSuite; int found = 0; current_position = storageRelativePosition(&io_error_message, table_file, 0); do { record_size = position_field(JSR211_CHR_SUITE); if (record_size <= 0) { current_position = -1; break; } storageRead(&io_error_message, table_file, (char*)&testSuite, sizeof(int)); found = (testSuite == suite? 1: 0); storagePosition(&io_error_message, table_file, current_position); if (found) { break; } current_position = storageRelativePosition(&io_error_message, table_file, record_size); } while (current_position > 0); return current_position; }
/** * Loads current handler's main fields (ID, suite_ID, class_name, flag). * @param handler loaded structure pointer. * @return operation result */ static void load_current_handler(JSR211_CH* ch) { long pos = storageRelativePosition(&io_error_message, table_file, sizeof(int)) - sizeof(int); read_string(&(ch->id)); storageRead(&io_error_message, table_file, (char*)&(ch->flag), sizeof(int)); storageRead(&io_error_message, table_file, (char*)&(ch->suite_id), sizeof(int)); read_string(&(ch->class_name)); storagePosition(&io_error_message, table_file, pos); }
/* Directly write to storage. File position will be updated also. */ static void uncachedWrite(char** ppszError, int handle, char *buffer, int length) { *ppszError = NULL; storagePosition(ppszError, handle, mFileCache->cachedPosition); if (*ppszError == NULL) { storageWrite(ppszError, handle, buffer, length); if (*ppszError == NULL) { updateCachedSizes(length); } } }
/** * Flush the cache and stop current file caching. * Seek cached position for the case the file won't be closed after * flushing (it's possible if a few files are openned simultaneously). */ static void midp_file_cache_finalize(char **ppszError, int stayOpen) { *ppszError = NULL; if (mFileCache != NULL) { midp_file_cache_flush(ppszError, mFileCache->handle); /* Do no seek for the file that is either damaged or to be closed */ if (*ppszError == NULL && stayOpen) { storagePosition(ppszError, mFileCache->handle, mFileCache->cachedPosition); } /* If read is cached, free all read blocks here */ midpFree(mFileCache); mFileCache = NULL; } }
/** * Searches the next content handler in the file by specified conditions. * * @param caller_id caller ID * @param number number of key field * @param key search key * @param case_sensitive case sensivity flag * @param cond comparision mode * @return offset of found record or -1 */ static long find_next_by_field(const pcsl_string* caller_id, jsr211_field number, const pcsl_string* key, jsr211_boolean case_sensitive, find_condition cond) { long current_position; int current_size, access; int found = 0; int chr = CHR_INDEX((int)(number)); // Content Handler Record index int isString; switch (record_struct[chr]) { case field_string: isString = 1; break; case field_array: isString = 0; break; default: return -1; } current_position = storageRelativePosition(&io_error_message, table_file, 0); for (;;) { /* check access */ access = check_access(caller_id, current_position, ¤t_size); if (access == -1) { return -1; } else if (access) { position_field(chr); found = (isString? compare_string(key, case_sensitive, cond): compare_array(key, case_sensitive, cond)); } storagePosition(&io_error_message, table_file, current_position); if (found) { break; } current_position += current_size; goto_next_record(); } return current_position; }
/** * Deletes content handler information from a registry. * * @param handler_id content handler ID * @return JSR211_OK if content handler unregistered successfully */ jsr211_result jsr211_unregister_handler(const pcsl_string* handler_id) { long current_position, file_size, buffer_size; int record_size; char *buffer; if (open_table_file(1) != JSR211_OK) { return JSR211_FAILED; } if (find_next_by_field(NULL, JSR211_FIELD_ID, handler_id, JSR211_TRUE, find_exact) == -1) { close_table_file(); return JSR211_FAILED; } storageRead(&io_error_message, table_file, (char *)&record_size, sizeof(int)); current_position = storageRelativePosition(&io_error_message, table_file, -(long)sizeof(int)); file_size = storageSizeOf(&io_error_message, table_file); goto_next_record(); if (!(buffer = JSR211_MALLOC((buffer_size = file_size - current_position - record_size)))) { close_table_file(); return JSR211_FAILED; } storageRead(&io_error_message, table_file, buffer, buffer_size); storagePosition(&io_error_message, table_file, current_position); storageWrite(&io_error_message, table_file, buffer, buffer_size); JSR211_FREE(buffer); storageTruncate(&io_error_message, table_file, current_position + buffer_size); close_table_file(); return JSR211_OK; }
/** * Verifies access of caller for current content handler. * Reads access restrictions from a current record and * compares it with a passed caller_id. * * @param caller_id caller * @param current_position current position of the file * @param current_size [out] size of current record * @return 1 if access is permitted */ static int check_access(const pcsl_string* caller_id, long current_position, int* current_size) { int access_len, access_ok; if ((*current_size = position_field(JSR211_CHR_ACCESSES)) <= 0) { return -1; } if (caller_id != NULL && pcsl_string_length(caller_id) > 0) { storageRelativePosition(&io_error_message, table_file, sizeof(int)); storageRead(&io_error_message, table_file, (char*)&access_len, sizeof(int)); if (!access_len) { access_ok = 1; } else { storageRelativePosition(&io_error_message, table_file, -2 * (long)sizeof(int)); access_ok = compare_array(caller_id, JSR211_TRUE, find_first); } } else { access_ok = 1; } storagePosition(&io_error_message, table_file, current_position); return access_ok; }
/** * Writes string array to the file. * * @param array_len length of array to be written * @param array array to be written * @return number of bytes written */ static int write_string_array(int array_len, const pcsl_string* array) { long current_pos; int write_count; const pcsl_string *current_string, *end; current_pos = storageRelativePosition(&io_error_message, table_file, 0); /* array size placeholder */ storageWrite(&io_error_message, table_file, (char*)&write_count, sizeof(int)); /* array size saving */ storageWrite(&io_error_message, table_file, (char *)&array_len, sizeof(int)); write_count = sizeof(int); for (current_string = array, end = array + array_len; current_string < end; current_string ++) { write_count += write_string(current_string); } storagePosition(&io_error_message, table_file, current_pos); storageWrite(&io_error_message, table_file, (char*)&write_count, sizeof(int)); storageRelativePosition(&io_error_message, table_file, write_count); return write_count + sizeof(int); }
/** A helper function for midp_file_cache_flush(). */ static void midp_file_cache_flush_using_buffer(char** ppszError, int handle, char* buf, long bufsize) { MidpFileCacheBlock *b; /* current cache block */ MidpFileCacheBlock *n; /* next cache block */ MidpFileCacheBlock *q; /* first block not (yet) copied to the buffer, finally, the value to be stored in mFileCache->blocks */ char *bufPos; /* first not yet used byte in the write buffer */ long startPos, endPos; /* positions in the file cached in a series of buffers, from...upto */ long len; *ppszError = NULL; while ((b = mFileCache->blocks) != NULL) { if ( NULL != buf && NULL != (n = b->next) && n->position == b->position + b->length /* adjacent? */ && b->length + n->length < bufsize ) { /* begin merging blocks */ /* position in the buffer */ bufPos = buf; /* position in the file */ startPos = endPos = b->position; b = mFileCache->blocks; /* now copy a series of adjacent blocks to the write buffer */ do { len = b->length; memcpy(bufPos,DATA(b),len); endPos += len; bufPos += len; b = b->next; } while ( NULL != b && b->position == endPos && endPos - startPos + b->length < bufsize ); q = b; /* q is next to the last copied block */ /* the cache state has not been modified yet */ /* now write from the write buffer */ storagePosition(ppszError, handle, startPos); CHECK_ERROR(*ppszError); storageWrite(ppszError, handle, buf, endPos-startPos); CHECK_ERROR(*ppszError); /* write successful, now free the cache blocks */ while ( q != (b = mFileCache->blocks)) { mFileCache->size -= b->length + sizeof(MidpFileCacheBlock); mFileCache->blocks = b->next; midpFree(b); } } else { storagePosition(ppszError, handle, b->position); CHECK_ERROR(*ppszError); storageWrite(ppszError, handle, DATA(b), b->length); CHECK_ERROR(*ppszError); mFileCache->size -= b->length + sizeof(MidpFileCacheBlock); mFileCache->blocks = b->next; midpFree(b); } } storageCommitWrite(ppszError, handle); CHECK_ERROR(*ppszError); /* ASSERT (mFileCache->size == 0) */ if (mFileCache->size != 0) { REPORT_ERROR(LC_RMS, "File cache out of sync"); } }
/** * Returns all found values for specified field. Tha allowed fields are: <ul> * <li> JSR211_FIELD_ID, <li> JSR211_FIELD_TYPES, <li> JSR211_FIELD_SUFFIXES, * <li> and JSR211_FIELD_ACTIONS. </ul> * Values should be selected only from handlers accessible for given caller_id. * * @param caller_id calling application identifier. * @param field search field id * @param result output structure where result is placed to. * <br>Use @link jsr211_fillStringArray function to fill this structure. * @return status of the operation */ jsr211_result jsr211_get_all(const pcsl_string* caller_id, jsr211_field field, /*OUT*/ JSR211_RESULT_STRARRAY* result) { long current_position; int found_num, access, current_size; pcsl_string *res_buffer = NULL; pcsl_string *current_result, *last; int chr = CHR_INDEX((int)(field)); int isString; switch (record_struct[chr]) { case field_string: isString = 1; break; case field_array: isString = 0; break; default: return JSR211_FAILED; } if (open_table_file(0) != JSR211_OK) { return JSR211_FAILED; } res_buffer = alloc_pcsl_string_list(JSR211_MAX_RESULT_SET); if (res_buffer == NULL) { close_table_file(); return JSR211_FAILED; } current_position = 0; for (current_result = res_buffer, last = res_buffer + JSR211_MAX_RESULT_SET; current_result < last;) { access = check_access(caller_id, current_position, ¤t_size); if (access == -1) { break; } if (access && position_field(chr) > 0) { if (isString) { read_string(current_result); if (!findStringInArray(res_buffer, current_result - res_buffer, current_result)) { current_result++; } } else { pcsl_string *array_res = NULL, *results, *last_res; int array_length = 0; read_string_array(&array_length, &array_res); if (array_length > 0) { for (results = array_res, last_res = array_res + array_length; results < last_res && current_result < last; results++) { if (!findStringInArray(res_buffer, current_result - res_buffer, results)) { *(current_result++) = *results; *results = PCSL_STRING_NULL; } } free_pcsl_string_list(array_res, array_length); } } } storagePosition(&io_error_message, table_file, current_position); current_position += current_size; goto_next_record(); } if ((found_num = (int)(current_result - res_buffer))) { jsr211_fillStringArray(res_buffer, found_num, result); } free_pcsl_string_list(res_buffer, JSR211_MAX_RESULT_SET); close_table_file(); return JSR211_OK; }