static int file_archive_parse_file_init(file_archive_transfer_t *state, const char *file) { state->backend = file_archive_get_default_file_backend(); if (!state->backend) return -1; state->handle = file_archive_open(file); if (!state->handle) return -1; state->zip_size = file_archive_size(state->handle); if (state->zip_size < 22) return -1; state->data = file_archive_data(state->handle); state->footer = state->data + state->zip_size - 22; for (;; state->footer--) { if (state->footer <= state->data + 22) return -1; if (read_le(state->footer, 4) == END_OF_CENTRAL_DIR_SIGNATURE) { unsigned comment_len = read_le(state->footer + 20, 2); if (state->footer + 22 + comment_len == state->data + state->zip_size) break; } } state->directory = state->data + read_le(state->footer + 16, 4); return 0; }
static struct rpng_process *rpng_process_init(rpng_t *rpng, unsigned *width, unsigned *height) { uint8_t *inflate_buf = NULL; struct rpng_process *process = (struct rpng_process*)calloc(1, sizeof(*process)); if (!process) return NULL; process->stream_backend = file_archive_get_default_file_backend(); png_pass_geom(&rpng->ihdr, rpng->ihdr.width, rpng->ihdr.height, NULL, NULL, &process->inflate_buf_size); if (rpng->ihdr.interlace == 1) /* To be sure. */ process->inflate_buf_size *= 2; process->stream = process->stream_backend->stream_new(); if (!process->stream) { free(process); return NULL; } if (!process->stream_backend->stream_decompress_init(process->stream)) { free(process); return NULL; } inflate_buf = (uint8_t*)malloc(process->inflate_buf_size); if (!inflate_buf) goto error; process->inflate_buf = inflate_buf; process->stream_backend->stream_set( process->stream, rpng->idat_buf.size, process->inflate_buf_size, rpng->idat_buf.data, process->inflate_buf); return process; error: if (process) { if (process->stream) process->stream_backend->stream_free(process->stream); free(process); } return NULL; }
/** * read_content_file: * @path : buffer of the content file. * @buf : size of the content file. * @length : size of the content file that has been read from. * * Read the content file. If read into memory, also performs soft patching * (see patch_content function) in case soft patching has not been * blocked by the enduser. * * Returns: true if successful, false on error. **/ static bool read_content_file(unsigned i, const char *path, void **buf, ssize_t *length) { #ifdef HAVE_ZLIB content_stream_t stream_info; uint32_t *content_crc_ptr = NULL; #endif uint8_t *ret_buf = NULL; global_t *global = global_get_ptr(); RARCH_LOG("%s: %s.\n", msg_hash_to_str(MSG_LOADING_CONTENT_FILE), path); if (!content_file_read(path, (void**) &ret_buf, length)) return false; if (*length < 0) return false; if (i != 0) return true; /* Attempt to apply a patch. */ if (!global->patch.block_patch) patch_content(&ret_buf, length); #ifdef HAVE_ZLIB content_get_crc(&content_crc_ptr); stream_info.a = 0; stream_info.b = ret_buf; stream_info.c = *length; if (!stream_backend) stream_backend = file_archive_get_default_file_backend(); stream_info.crc = stream_backend->stream_crc_calculate( stream_info.a, stream_info.b, stream_info.c); *content_crc_ptr = stream_info.crc; RARCH_LOG("CRC32: 0x%x .\n", (unsigned)*content_crc_ptr); #endif *buf = ret_buf; return true; }
static bool content_zip_file_decompressed_handle( file_archive_file_handle_t *handle, const uint8_t *cdata, uint32_t csize, uint32_t size, uint32_t crc32) { int ret = 0; handle->backend = file_archive_get_default_file_backend(); if (!handle->backend) goto error; if (!handle->backend->stream_decompress_data_to_file_init( handle, cdata, csize, size)) return false; do{ ret = handle->backend->stream_decompress_data_to_file_iterate( handle->stream); }while(ret == 0); handle->real_checksum = handle->backend->stream_crc_calculate(0, handle->data, size); if (handle->real_checksum != crc32) { RARCH_ERR("Inflated checksum did not match CRC32!\n"); goto error; } if (handle->stream) free(handle->stream); return true; error: if (handle->stream) free(handle->stream); if (handle->data) free(handle->data); return false; }
bool file_archive_perform_mode(const char *path, const char *valid_exts, const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, uint32_t crc32, void *userdata) { switch (cmode) { case ZLIB_MODE_UNCOMPRESSED: if (!filestream_write_file(path, cdata, size)) goto error; break; case ZLIB_MODE_DEFLATE: { int ret = 0; file_archive_file_handle_t handle = {0}; handle.backend = file_archive_get_default_file_backend(); if (!handle.backend->stream_decompress_data_to_file_init(&handle, cdata, csize, size)) goto error; do { ret = handle.backend->stream_decompress_data_to_file_iterate( handle.stream); } while(ret == 0); if (!file_archive_decompress_data_to_file(&handle, ret, path, valid_exts, cdata, csize, size, crc32)) goto error; } break; default: goto error; } return true; error: return false; }
static bool file_get_crc(database_state_handle_t *db_state, const char *name, uint32_t *crc) { ssize_t ret; int read_from = filestream_read_file( name, (void**)&db_state->buf, &ret); #ifdef HAVE_ZLIB const struct file_archive_file_backend *stream_backend = file_archive_get_default_file_backend(); #endif if (read_from != 1 || ret <= 0) return 0; #ifdef HAVE_ZLIB *crc = stream_backend->stream_crc_calculate( 0, db_state->buf, ret); #endif return 1; }
bool content_ctl(enum content_ctl_state state, void *data) { unsigned i; static const struct file_archive_file_backend *stream_backend = NULL; static struct string_list *temporary_content = NULL; static bool content_is_inited = false; static bool core_does_not_need_content = false; static uint32_t content_crc = 0; switch(state) { case CONTENT_CTL_LOAD_RAM_FILE: return load_ram_file(data); case CONTENT_CTL_SAVE_RAM_FILE: { ram_type_t *ram = (ram_type_t*)data; if (!ram) return false; save_ram_file(ram); } break; case CONTENT_CTL_DOES_NOT_NEED_CONTENT: return core_does_not_need_content; case CONTENT_CTL_SET_DOES_NOT_NEED_CONTENT: core_does_not_need_content = true; break; case CONTENT_CTL_GET_CRC: { uint32_t **content_crc_ptr = (uint32_t**)data; if (!content_crc_ptr) return false; *content_crc_ptr = &content_crc; } break; case CONTENT_CTL_LOAD_STATE: { const char *path = (const char*)data; if (!path) return false; return content_load_state(path); } case CONTENT_CTL_SAVE_STATE: { const char *path = (const char*)data; if (!path) return false; return content_save_state(path); } case CONTENT_CTL_IS_INITED: return content_is_inited; case CONTENT_CTL_DEINIT: content_ctl(CONTENT_CTL_TEMPORARY_FREE, NULL); content_crc = 0; content_is_inited = false; core_does_not_need_content = false; break; case CONTENT_CTL_INIT: content_is_inited = false; temporary_content = string_list_new(); if (!temporary_content) return false; if (content_init_file(temporary_content)) { content_is_inited = true; return true; } content_ctl(CONTENT_CTL_DEINIT, NULL); return false; case CONTENT_CTL_TEMPORARY_FREE: if (!temporary_content) return false; for (i = 0; i < temporary_content->size; i++) { const char *path = temporary_content->elems[i].data; RARCH_LOG("%s: %s.\n", msg_hash_to_str(MSG_REMOVING_TEMPORARY_CONTENT_FILE), path); if (remove(path) < 0) RARCH_ERR("%s: %s.\n", msg_hash_to_str(MSG_FAILED_TO_REMOVE_TEMPORARY_FILE), path); } string_list_free(temporary_content); temporary_content = NULL; break; case CONTENT_CTL_STREAM_INIT: #ifdef HAVE_ZLIB if (!stream_backend) stream_backend = file_archive_get_default_file_backend(); #endif break; case CONTENT_CTL_STREAM_CRC_CALCULATE: { content_stream_t *stream = NULL; content_ctl(CONTENT_CTL_STREAM_INIT, NULL); stream = (content_stream_t*)data; stream->crc = stream_backend->stream_crc_calculate( stream->a, stream->b, stream->c); } break; case CONTENT_CTL_LOAD: return content_load((content_ctx_info_t*)data); case CONTENT_CTL_NONE: default: break; } return true; }
bool content_ctl(enum content_ctl_state state, void *data) { static const struct file_archive_file_backend *stream_backend = NULL; static struct string_list *temporary_content = NULL; static bool content_is_inited = false; static bool core_does_not_need_content = false; static uint32_t content_crc = 0; switch(state) { case CONTENT_CTL_LOAD_RAM_FILE: return load_ram_file(data); case CONTENT_CTL_SAVE_RAM_FILE: return save_ram_file((ram_type_t*)data); case CONTENT_CTL_DOES_NOT_NEED_CONTENT: return core_does_not_need_content; case CONTENT_CTL_SET_DOES_NOT_NEED_CONTENT: core_does_not_need_content = true; break; case CONTENT_CTL_UNSET_DOES_NOT_NEED_CONTENT: core_does_not_need_content = false; break; case CONTENT_CTL_GET_CRC: { uint32_t **content_crc_ptr = (uint32_t**)data; if (!content_crc_ptr) return false; *content_crc_ptr = &content_crc; } break; case CONTENT_CTL_LOAD_STATE: { const char *path = (const char*)data; if (!path) return false; return content_load_state(path); } case CONTENT_CTL_SAVE_STATE: { const char *path = (const char*)data; if (!path) return false; return content_save_state(path); } case CONTENT_CTL_IS_INITED: return content_is_inited; case CONTENT_CTL_DEINIT: content_ctl(CONTENT_CTL_TEMPORARY_FREE, NULL); content_crc = 0; content_is_inited = false; core_does_not_need_content = false; break; case CONTENT_CTL_INIT: content_is_inited = false; temporary_content = string_list_new(); if (!temporary_content) return false; if (content_file_init(temporary_content)) { content_is_inited = true; return true; } content_ctl(CONTENT_CTL_DEINIT, NULL); return false; case CONTENT_CTL_TEMPORARY_FREE: content_file_free(temporary_content); temporary_content = NULL; break; case CONTENT_CTL_STREAM_INIT: #ifdef HAVE_ZLIB if (!stream_backend) stream_backend = file_archive_get_default_file_backend(); #endif break; case CONTENT_CTL_STREAM_CRC_CALCULATE: { content_stream_t *stream = NULL; content_ctl(CONTENT_CTL_STREAM_INIT, NULL); stream = (content_stream_t*)data; #ifdef HAVE_ZLIB stream->crc = stream_backend->stream_crc_calculate( stream->a, stream->b, stream->c); #endif } break; case CONTENT_CTL_LOAD: return content_load((content_ctx_info_t*)data); case CONTENT_CTL_NONE: default: break; } return true; }