X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwim.c;h=11e2f9048aeb345995b8ddea83a3250c138129be;hp=11bb2e50a616b79c397d9c30b0b5c5d3a8d84c98;hb=d92446abf69f8a9eff9aed1123f37122647cc7e0;hpb=3ffb2cde078ae8f62d542ab89166e1059c13d758 diff --git a/src/wim.c b/src/wim.c index 11bb2e50..11e2f904 100644 --- a/src/wim.c +++ b/src/wim.c @@ -38,6 +38,8 @@ #include "wimlib/security.h" #include "wimlib/wim.h" #include "wimlib/xml.h" +#include "wimlib/compressor_ops.h" +#include "wimlib/decompressor_ops.h" #ifdef __WIN32__ # include "wimlib/win32.h" /* for realpath() replacement */ @@ -62,14 +64,34 @@ image_print_metadata(WIMStruct *wim) wim->lookup_table); } +static int +wim_default_pack_compression_type(void) +{ + return WIMLIB_COMPRESSION_TYPE_LZMS; +} + +static u32 +wim_default_pack_chunk_size(int ctype) { + switch (ctype) { + case WIMLIB_COMPRESSION_TYPE_LZMS: + /* Note: WIMGAPI uses 1 << 26, but lower sizes are compatible. + * */ + return 1U << 25; /* 33554432 */ + default: + return 1U << 15; /* 32768 */ + } +} static WIMStruct * new_wim_struct(void) { WIMStruct *wim = CALLOC(1, sizeof(WIMStruct)); if (wim) { - wim->in_fd.fd = -1; - wim->out_fd.fd = -1; + filedes_invalidate(&wim->in_fd); + filedes_invalidate(&wim->out_fd); + wim->out_pack_compression_type = wim_default_pack_compression_type(); + wim->out_pack_chunk_size = wim_default_pack_chunk_size( + wim->out_pack_compression_type); INIT_LIST_HEAD(&wim->subwims); } return wim; @@ -125,23 +147,15 @@ wim_chunk_size_valid(u32 chunk_size, int ctype) return order >= 15 && order <= 21; case WIMLIB_COMPRESSION_TYPE_XPRESS: - /* WIMGAPI (Windows 7) didn't seem to support XPRESS chunk size - * below 32768 bytes, but larger power-of-two sizes appear to be - * supported. 67108864 was the largest size that worked. - * (Note, however, that the offsets of XPRESS matches are still - * limited to 65535 bytes even when a much larger chunk size is - * used!) - * - * WIMGAPI (Windows 8) seemed to have removed the support for - * larger XPRESS chunk sizes and will refuse to open such WIMs. - * - * 2^15 = 32768 is the default value used for compatibility, but - * wimlib can actually use up to 2^26. */ + /* WIMGAPI (Windows 7, Windows 8) doesn't seem to support XPRESS + * chunk size below 32768 bytes, but larger power-of-two sizes, + * up ta 67108864 bytes, appear to work. (Note, however, that + * the offsets of XPRESS matches are still limited to 65535 + * bytes even when a much larger chunk size is used!) */ return order >= 15 && order <= 26; case WIMLIB_COMPRESSION_TYPE_LZMS: - /* TODO */ - return 131072; + return order >= 15 && order <= 26; } return false; } @@ -152,7 +166,12 @@ wim_chunk_size_valid(u32 chunk_size, int ctype) static u32 wim_default_chunk_size(int ctype) { - return 32768; + switch (ctype) { + case WIMLIB_COMPRESSION_TYPE_LZMS: + return 1U << 17; /* 131072 */ + default: + return 1U << 15; /* 32768 */ + } } /* @@ -378,7 +397,7 @@ wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info) info->image_count = wim->hdr.image_count; info->boot_index = wim->hdr.boot_idx; info->wim_version = wim->hdr.wim_version; - info->chunk_size = wim->hdr.chunk_size; + info->chunk_size = wim->chunk_size; info->part_number = wim->hdr.part_number; info->total_parts = wim->hdr.total_parts; info->compression_type = wim->compression_type; @@ -441,9 +460,8 @@ wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int whic return 0; } -/* API function documented in wimlib.h */ -WIMLIBAPI int -wimlib_set_output_compression_type(WIMStruct *wim, int ctype) +static int +set_out_ctype(int ctype, u8 *out_ctype_p) { switch (ctype) { case WIMLIB_COMPRESSION_TYPE_INVALID: @@ -452,50 +470,85 @@ wimlib_set_output_compression_type(WIMStruct *wim, int ctype) case WIMLIB_COMPRESSION_TYPE_LZX: case WIMLIB_COMPRESSION_TYPE_XPRESS: case WIMLIB_COMPRESSION_TYPE_LZMS: - wim->out_compression_type = ctype; - - /* Reset the chunk size if it's no longer valid. */ - if (!wim_chunk_size_valid(wim->out_chunk_size, - wim->out_compression_type)) - wim->out_chunk_size = wim_default_chunk_size(wim->out_compression_type); + *out_ctype_p = ctype; return 0; } - return WIMLIB_ERR_INVALID_PARAM; + return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; } /* API function documented in wimlib.h */ WIMLIBAPI int -wimlib_set_output_chunk_size(WIMStruct *wim, uint32_t chunk_size) +wimlib_set_output_compression_type(WIMStruct *wim, int ctype) +{ + int ret = set_out_ctype(ctype, &wim->out_compression_type); + if (ret) + return ret; + + /* Reset the chunk size if it's no longer valid. */ + if (!wim_chunk_size_valid(ctype, wim->out_chunk_size)) + wim->out_chunk_size = wim_default_chunk_size(ctype); + return 0; +} + +/* API function documented in wimlib.h */ +WIMLIBAPI int +wimlib_set_output_pack_compression_type(WIMStruct *wim, int ctype) { - if (!wim_chunk_size_valid(chunk_size, wim->out_compression_type)) { + int ret = set_out_ctype(ctype, &wim->out_pack_compression_type); + if (ret) + return ret; + + /* Reset the chunk size if it's no longer valid. */ + if (!wim_chunk_size_valid(ctype, wim->out_pack_chunk_size)) + wim->out_pack_chunk_size = wim_default_pack_chunk_size(ctype); + return 0; +} + +static int +set_out_chunk_size(u32 chunk_size, int ctype, u32 *out_chunk_size_p) +{ + if (!wim_chunk_size_valid(chunk_size, ctype)) { ERROR("Invalid chunk size (%"PRIu32" bytes) " "for compression type %"TS"!", chunk_size, - wimlib_get_compression_type_string(wim->out_compression_type)); - switch (wim->out_compression_type) { - case WIMLIB_COMPRESSION_TYPE_XPRESS: - ERROR("Valid chunk sizes for XPRESS are " - "32768, 65536, 131072, ..., 67108864."); - break; - case WIMLIB_COMPRESSION_TYPE_LZX: - ERROR("Valid chunk sizes for LZX are " - "32768, 65536, 131072, ..., 2097152."); - break; - case WIMLIB_COMPRESSION_TYPE_LZMS: - ERROR("Valid chunk sizes for LZMS are 131072."); - break; - } + wimlib_get_compression_type_string(ctype)); return WIMLIB_ERR_INVALID_CHUNK_SIZE; } - if (chunk_size != 32768) { - WARNING ("Changing the compression chunk size to any value other than\n" - " the default of 32768 bytes eliminates compatibility with\n" - " Microsoft's software!"); - } - wim->out_chunk_size = chunk_size; + + *out_chunk_size_p = chunk_size; return 0; } +/* API function documented in wimlib.h */ +WIMLIBAPI int +wimlib_set_output_chunk_size(WIMStruct *wim, uint32_t chunk_size) +{ + if (chunk_size == 0) { + wim->out_chunk_size = + wim_default_chunk_size(wim->out_compression_type); + return 0; + } + + return set_out_chunk_size(chunk_size, + wim->out_compression_type, + &wim->out_chunk_size); +} + +/* API function documented in wimlib.h */ +WIMLIBAPI int +wimlib_set_output_pack_chunk_size(WIMStruct *wim, uint32_t chunk_size) +{ + if (chunk_size == 0) { + wim->out_pack_chunk_size = + wim_default_pack_chunk_size(wim->out_pack_compression_type); + return 0; + } + + return set_out_chunk_size(chunk_size, + wim->out_pack_compression_type, + &wim->out_pack_chunk_size); +} + static int do_open_wim(const tchar *filename, struct filedes *fd_ret) { @@ -622,7 +675,8 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, wim->out_compression_type = wim->compression_type; /* Check and cache the chunk size. */ - wim->chunk_size = wim->out_chunk_size = wim->hdr.chunk_size; + wim->chunk_size = wim->hdr.chunk_size; + wim->out_chunk_size = wim->chunk_size; if (!wim_chunk_size_valid(wim->chunk_size, wim->compression_type)) { ERROR("Invalid chunk size (%"PRIu32" bytes) " "for compression type %"TS"!", @@ -655,9 +709,6 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, if (wim->lookup_table == NULL) return WIMLIB_ERR_NOMEM; } else { - ret = read_wim_lookup_table(wim); - if (ret) - return ret; ret = read_wim_xml_data(wim); if (ret) @@ -671,6 +722,11 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, " element per image.", wim->hdr.image_count); return WIMLIB_ERR_IMAGE_COUNT; } + + ret = read_wim_lookup_table(wim); + if (ret) + return ret; + DEBUG("Done beginning read of WIM file `%"TS"'.", wimfile); } return 0; @@ -836,9 +892,12 @@ wim_checksum_unhashed_streams(WIMStruct *wim) struct wim_lookup_table_entry *lte, *tmp; struct wim_image_metadata *imd = wim->image_metadata[i]; image_for_each_unhashed_stream_safe(lte, tmp, imd) { - ret = hash_unhashed_stream(lte, wim->lookup_table, NULL); + struct wim_lookup_table_entry *new_lte; + ret = hash_unhashed_stream(lte, wim->lookup_table, &new_lte); if (ret) return ret; + if (new_lte != lte) + free_lookup_table_entry(lte); } } return 0; @@ -927,10 +986,10 @@ wimlib_free(WIMStruct *wim) if (filedes_valid(&wim->out_fd)) filedes_close(&wim->out_fd); - wimlib_lzx_free_context(wim->lzx_context); - free_lookup_table(wim->lookup_table); + wimlib_free_decompressor(wim->decompressor); + FREE(wim->filename); free_wim_info(wim->wim_info); if (wim->image_metadata) { @@ -961,7 +1020,6 @@ WIMLIBAPI int wimlib_global_init(int init_flags) { static bool already_inited = false; - int ret; if (already_inited) return 0; @@ -974,14 +1032,19 @@ wimlib_global_init(int init_flags) #endif } #ifdef __WIN32__ - ret = win32_global_init(init_flags); - if (ret) - return ret; -#else - ret = 0; + { + int ret = win32_global_init(init_flags); + if (ret) + return ret; + } #endif + init_upcase(); + if (init_flags & WIMLIB_INIT_FLAG_DEFAULT_CASE_SENSITIVE) + default_ignore_case = false; + else if (init_flags & WIMLIB_INIT_FLAG_DEFAULT_CASE_INSENSITIVE) + default_ignore_case = true; already_inited = true; - return ret; + return 0; } /* API function documented in wimlib.h */ @@ -993,4 +1056,6 @@ wimlib_global_cleanup(void) #ifdef __WIN32__ win32_global_cleanup(); #endif + cleanup_decompressor_params(); + cleanup_compressor_params(); }