X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fwim.c;h=6954dedaa3a0805f2590346f50db3213882b07e3;hb=054f366c7dfde356ca8d3c9f1262f68505976c02;hp=2dd0787238863a7dac8dafbe003f0ba41b2bbea9;hpb=81c83fa2dbb44e788f234ddd5427c00e33c12d52;p=wimlib diff --git a/src/wim.c b/src/wim.c index 2dd07872..6954deda 100644 --- a/src/wim.c +++ b/src/wim.c @@ -1,9 +1,9 @@ /* - * wim.c - Stuff that doesn't fit into any other file + * wim.c - High-level code dealing with WIMStructs and images. */ /* - * Copyright (C) 2012, 2013 Eric Biggers + * Copyright (C) 2012, 2013, 2014 Eric Biggers * * This file is part of wimlib, a library for working with WIM files. * @@ -25,7 +25,7 @@ # include "config.h" #endif -#include "wimlib/error.h" +#include "wimlib.h" #include "wimlib/dentry.h" #include "wimlib/encoding.h" #include "wimlib/file_io.h" @@ -38,8 +38,6 @@ #include "wimlib/security.h" #include "wimlib/wim.h" #include "wimlib/xml.h" -#include "wimlib/compressor_ops.h" -#include "wimlib/decompressor_ops.h" #include "wimlib/version.h" #ifdef __WIN32__ @@ -51,8 +49,6 @@ #ifndef __WIN32__ # include #endif -#include -#include #include #include @@ -66,7 +62,7 @@ static u32 wim_default_pack_chunk_size(int ctype) { switch (ctype) { case WIMLIB_COMPRESSION_TYPE_LZMS: - return 1U << 26; /* 67108864 */ + return 1U << 25; /* 33554432 */ default: return 1U << 15; /* 32768 */ } @@ -76,14 +72,15 @@ static WIMStruct * new_wim_struct(void) { WIMStruct *wim = CALLOC(1, sizeof(WIMStruct)); - if (wim) { - 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); - } + if (!wim) + return NULL; + + 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; } @@ -126,9 +123,8 @@ wim_chunk_size_valid(u32 chunk_size, int ctype) switch (ctype) { case WIMLIB_COMPRESSION_TYPE_LZX: return order >= 15 && order <= 21; - case WIMLIB_COMPRESSION_TYPE_XPRESS: - return order >= 12 && order <= 26; + return order >= 12 && order <= 16; case WIMLIB_COMPRESSION_TYPE_LZMS: return order >= 15 && order <= 30; } @@ -191,24 +187,22 @@ wimlib_create_new_wim(int ctype, WIMStruct **wim_ret) struct wim_lookup_table *table; int ret; - wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8); - - DEBUG("Creating new WIM with %"TS" compression.", - wimlib_get_compression_type_string(ctype)); + ret = wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8); + if (ret) + return ret; - /* Allocate the WIMStruct. */ wim = new_wim_struct(); - if (wim == NULL) + if (!wim) return WIMLIB_ERR_NOMEM; ret = init_wim_header(&wim->hdr, ctype, wim_default_chunk_size(ctype)); if (ret) - goto out_free; + goto out_free_wim; table = new_lookup_table(9001); - if (table == NULL) { + if (!table) { ret = WIMLIB_ERR_NOMEM; - goto out_free; + goto out_free_wim; } wim->lookup_table = table; wim->refcnts_ok = 1; @@ -218,7 +212,8 @@ wimlib_create_new_wim(int ctype, WIMStruct **wim_ret) wim->out_chunk_size = wim->hdr.chunk_size; *wim_ret = wim; return 0; -out_free: + +out_free_wim: FREE(wim); return ret; } @@ -237,7 +232,7 @@ destroy_image_metadata(struct wim_image_metadata *imd, free_lookup_table_entry(imd->metadata_lte); imd->metadata_lte = NULL; } - if (table == NULL) { + if (!table) { struct wim_lookup_table_entry *lte, *tmp; list_for_each_entry_safe(lte, tmp, &imd->unhashed_streams, unhashed_list) free_lookup_table_entry(lte); @@ -269,12 +264,10 @@ append_image_metadata(WIMStruct *wim, struct wim_image_metadata *imd) { struct wim_image_metadata **imd_array; - DEBUG("Reallocating image metadata array for image_count = %u", - wim->hdr.image_count + 1); imd_array = REALLOC(wim->image_metadata, sizeof(wim->image_metadata[0]) * (wim->hdr.image_count + 1)); - if (imd_array == NULL) + if (!imd_array) return WIMLIB_ERR_NOMEM; wim->image_metadata = imd_array; imd_array[wim->hdr.image_count++] = imd; @@ -291,9 +284,6 @@ new_image_metadata(void) imd->refcnt = 1; INIT_LIST_HEAD(&imd->inode_list); INIT_LIST_HEAD(&imd->unhashed_streams); - DEBUG("Created new image metadata (refcnt=1)"); - } else { - ERROR_WITH_ERRNO("Failed to allocate new image metadata structure"); } return imd; } @@ -303,19 +293,13 @@ new_image_metadata_array(unsigned num_images) { struct wim_image_metadata **imd_array; - DEBUG("Creating new image metadata array for %u images", - num_images); - imd_array = CALLOC(num_images, sizeof(imd_array[0])); - if (imd_array == NULL) { - ERROR("Failed to allocate memory for %u image metadata structures", - num_images); + if (!imd_array) return NULL; - } for (unsigned i = 0; i < num_images; i++) { imd_array[i] = new_image_metadata(); - if (imd_array[i] == NULL) { + if (unlikely(!imd_array[i])) { for (unsigned j = 0; j < i; j++) put_image_metadata(imd_array[j], NULL); FREE(imd_array); @@ -348,28 +332,17 @@ select_wim_image(WIMStruct *wim, int image) struct wim_image_metadata *imd; int ret; - DEBUG("Selecting image %d", image); - - if (image == WIMLIB_NO_IMAGE) { - ERROR("Invalid image: %d", WIMLIB_NO_IMAGE); + if (image == WIMLIB_NO_IMAGE) return WIMLIB_ERR_INVALID_IMAGE; - } if (image == wim->current_image) return 0; - if (image < 1 || image > wim->hdr.image_count) { - ERROR("Cannot select image %d: There are only %u images", - image, wim->hdr.image_count); + if (image < 1 || image > wim->hdr.image_count) return WIMLIB_ERR_INVALID_IMAGE; - } - if (!wim_has_metadata(wim)) { - ERROR("\"%"TS"\" does not contain metadata resources!", wim->filename); - if (wim->hdr.part_number != 1) - ERROR("Specify the first part of the split WIM instead."); + if (!wim_has_metadata(wim)) return WIMLIB_ERR_METADATA_NOT_FOUND; - } /* If a valid image is currently selected, its metadata can be freed if * it has not been modified. */ @@ -377,7 +350,6 @@ select_wim_image(WIMStruct *wim, int image) imd = wim_get_current_image_metadata(wim); if (!imd->modified) { wimlib_assert(list_empty(&imd->unhashed_streams)); - DEBUG("Freeing image %u", wim->current_image); destroy_image_metadata(imd, NULL, false); } } @@ -399,16 +371,16 @@ WIMLIBAPI const tchar * wimlib_get_compression_type_string(int ctype) { switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_NONE: - return T("None"); - case WIMLIB_COMPRESSION_TYPE_LZX: - return T("LZX"); - case WIMLIB_COMPRESSION_TYPE_XPRESS: - return T("XPRESS"); - case WIMLIB_COMPRESSION_TYPE_LZMS: - return T("LZMS"); - default: - return T("Invalid"); + case WIMLIB_COMPRESSION_TYPE_NONE: + return T("None"); + case WIMLIB_COMPRESSION_TYPE_XPRESS: + return T("XPRESS"); + case WIMLIB_COMPRESSION_TYPE_LZX: + return T("LZX"); + case WIMLIB_COMPRESSION_TYPE_LZMS: + return T("LZMS"); + default: + return T("Invalid"); } } @@ -528,11 +500,8 @@ wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int whic memcpy(wim->hdr.guid, info->guid, WIM_GUID_LEN); if (which & WIMLIB_CHANGE_BOOT_INDEX) { - if (info->boot_index > wim->hdr.image_count) { - ERROR("%u is not 0 or a valid image in the WIM to mark as bootable", - info->boot_index); + if (info->boot_index > wim->hdr.image_count) return WIMLIB_ERR_INVALID_IMAGE; - } wim->hdr.boot_idx = info->boot_index; } @@ -549,8 +518,6 @@ static int set_out_ctype(int ctype, u8 *out_ctype_p) { switch (ctype) { - case WIMLIB_COMPRESSION_TYPE_INVALID: - break; case WIMLIB_COMPRESSION_TYPE_NONE: case WIMLIB_COMPRESSION_TYPE_LZX: case WIMLIB_COMPRESSION_TYPE_XPRESS: @@ -592,13 +559,8 @@ wimlib_set_output_pack_compression_type(WIMStruct *wim, int ctype) 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(ctype)); + if (!wim_chunk_size_valid(chunk_size, ctype)) return WIMLIB_ERR_INVALID_CHUNK_SIZE; - } *out_chunk_size_p = chunk_size; return 0; @@ -691,12 +653,13 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) * replacement function in win32_replacements.c. */ wim->filename = realpath(wimfile, NULL); - if (wim->filename == NULL) { - ERROR_WITH_ERRNO("Failed to resolve WIM filename"); + if (!wim->filename) { + ERROR_WITH_ERRNO("Failed to get full path to file " + "\"%"TS"\"", wimfile); if (errno == ENOMEM) return WIMLIB_ERR_NOMEM; else - return WIMLIB_ERR_OPEN; + return WIMLIB_ERR_NO_FILENAME; } } @@ -721,13 +684,9 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) (wim->hdr.total_parts != 1)) return WIMLIB_ERR_IS_SPLIT_WIM; - DEBUG("According to header, WIM contains %u images", wim->hdr.image_count); - /* If the boot index is invalid, print a warning and set it to 0 */ if (wim->hdr.boot_idx > wim->hdr.image_count) { - WARNING("In `%"TS"', image %u is marked as bootable, " - "but there are only %u images in the WIM", - wimfile, wim->hdr.boot_idx, wim->hdr.image_count); + WARNING("Ignoring invalid boot index."); wim->hdr.boot_idx = 0; } @@ -741,9 +700,6 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) } else if (wim->hdr.flags & WIM_HDR_FLAG_COMPRESS_LZMS) { wim->compression_type = WIMLIB_COMPRESSION_TYPE_LZMS; } else { - ERROR("The compression flag is set on \"%"TS"\", but " - "a flag for a recognized format is not", - wimfile); return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; } } else { @@ -756,8 +712,7 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) 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"!", - wim->chunk_size, + "for compression type %"TS"!", wim->chunk_size, wimlib_get_compression_type_string(wim->compression_type)); return WIMLIB_ERR_INVALID_CHUNK_SIZE; } @@ -765,10 +720,10 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) if (open_flags & WIMLIB_OPEN_FLAG_CHECK_INTEGRITY) { ret = check_wim_integrity(wim); if (ret == WIM_INTEGRITY_NONEXISTENT) { - WARNING("No integrity information for `%"TS"'; skipping " - "integrity check.", wimfile); + WARNING("\"%"TS"\" does not contain integrity " + "information. Skipping integrity check.", + wimfile); } else if (ret == WIM_INTEGRITY_NOT_OK) { - ERROR("WIM is not intact! (Failed integrity check)"); return WIMLIB_ERR_INTEGRITY; } else if (ret != WIM_INTEGRITY_OK) { return ret; @@ -777,13 +732,13 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) if (wim->hdr.image_count != 0 && wim->hdr.part_number == 1) { wim->image_metadata = new_image_metadata_array(wim->hdr.image_count); - if (wim->image_metadata == NULL) + if (!wim->image_metadata) return WIMLIB_ERR_NOMEM; } if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) { wim->lookup_table = new_lookup_table(9001); - if (wim->lookup_table == NULL) + if (!wim->lookup_table) return WIMLIB_ERR_NOMEM; } else { @@ -793,18 +748,15 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) xml_num_images = wim_info_get_num_images(wim->wim_info); if (xml_num_images != wim->hdr.image_count) { - ERROR("In the file `%"TS"', there are %u elements " - "in the XML data,", wimfile, xml_num_images); - ERROR("but %u images in the WIM! There must be exactly one " - " element per image.", wim->hdr.image_count); + ERROR("The WIM's header is inconsistent with its XML data.\n" + " Please submit a bug report if you believe this " + "WIM file should be considered valid."); 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; } @@ -817,18 +769,12 @@ open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags, WIMStruct *wim; int ret; - if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) - DEBUG("Opening pipable WIM from file descriptor %d.", *(const int*)wim_filename_or_fd); - else - DEBUG("Opening WIM file \"%"TS"\"", (const tchar*)wim_filename_or_fd); - - wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8); - - if (wim_ret == NULL) - return WIMLIB_ERR_INVALID_PARAM; + ret = wimlib_global_init(WIMLIB_INIT_FLAG_ASSUME_UTF8); + if (ret) + return ret; wim = new_wim_struct(); - if (wim == NULL) + if (!wim) return WIMLIB_ERR_NOMEM; wim->progfunc = progfunc; @@ -840,7 +786,6 @@ open_wim_as_WIMStruct(const void *wim_filename_or_fd, int open_flags, return ret; } - DEBUG("Successfully opened WIM and created WIMStruct."); *wim_ret = wim; return 0; } @@ -856,6 +801,9 @@ wimlib_open_wim_with_progress(const tchar *wimfile, int open_flags, WIMLIB_OPEN_FLAG_WRITE_ACCESS)) return WIMLIB_ERR_INVALID_PARAM; + if (!wimfile || !*wimfile || !wim_ret) + return WIMLIB_ERR_INVALID_PARAM; + return open_wim_as_WIMStruct(wimfile, open_flags, wim_ret, progfunc, progctx); } @@ -957,18 +905,14 @@ can_delete_from_wim(WIMStruct *wim) WIMLIBAPI void wimlib_free(WIMStruct *wim) { - if (wim == NULL) + if (!wim) return; - DEBUG("Freeing WIMStruct (filename=\"%"TS"\", image_count=%u)", - wim->filename, wim->hdr.image_count); - while (!list_empty(&wim->subwims)) { WIMStruct *subwim; subwim = list_entry(wim->subwims.next, WIMStruct, subwim_node); list_del(&subwim->subwim_node); - DEBUG("Freeing subwim."); wimlib_free(subwim); } @@ -1013,15 +957,20 @@ wimlib_get_version(void) return WIMLIB_VERSION_CODE; } +static bool lib_initialized = false; + /* API function documented in wimlib.h */ WIMLIBAPI int wimlib_global_init(int init_flags) { - static bool already_inited = false; - - if (already_inited) + if (lib_initialized) return 0; +#ifdef ENABLE_ERROR_MESSAGES + if (!wimlib_error_file) + wimlib_error_file = stderr; +#endif + if (init_flags & ~(WIMLIB_INIT_FLAG_ASSUME_UTF8 | WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES | WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES | @@ -1045,12 +994,13 @@ wimlib_global_init(int init_flags) return ret; } #endif + iconv_global_init(); 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; + lib_initialized = true; return 0; } @@ -1058,11 +1008,14 @@ wimlib_global_init(int init_flags) WIMLIBAPI void wimlib_global_cleanup(void) { + if (!lib_initialized) + return; libxml_global_cleanup(); iconv_global_cleanup(); #ifdef __WIN32__ win32_global_cleanup(); #endif - cleanup_decompressor_params(); - cleanup_compressor_params(); + + wimlib_set_error_file(NULL); + lib_initialized = false; }