X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=src%2Fwim.c;h=b5827171ba91e139d9f7a5c83cc756d8b08041c0;hp=a82bd479117831b217af8c5400a0163c8fff1cb2;hb=3d9eb49da969c4ac2c8579db7baf96ae3fd04e1c;hpb=2fc33f535a398ea85964c0e483c5692821d775f3 diff --git a/src/wim.c b/src/wim.c index a82bd479..b5827171 100644 --- a/src/wim.c +++ b/src/wim.c @@ -40,15 +40,11 @@ #include "wimlib/file_io.h" #include "wimlib/integrity.h" #include "wimlib/metadata.h" -#ifdef WITH_NTFS_3G -# include "wimlib/ntfs_3g.h" /* for do_ntfs_umount() */ -#endif +#include "wimlib/ntfs_3g.h" /* for libntfs3g_global_init() */ #include "wimlib/security.h" #include "wimlib/wim.h" #include "wimlib/xml.h" -#ifdef __WIN32__ -# include "wimlib/win32.h" /* for realpath() replacement */ -#endif +#include "wimlib/win32.h" /* Information about the available compression types for the WIM format. */ static const struct { @@ -92,8 +88,8 @@ static const struct { static bool wim_compression_type_valid(enum wimlib_compression_type ctype) { - return ctype >= 0 && ctype < ARRAY_LEN(wim_ctype_info) && - wim_ctype_info[ctype].name != NULL; + return (unsigned)ctype < ARRAY_LEN(wim_ctype_info) && + wim_ctype_info[(unsigned)ctype].name != NULL; } /* Is the specified chunk size valid for the compression type? */ @@ -103,8 +99,8 @@ wim_chunk_size_valid(u32 chunk_size, enum wimlib_compression_type ctype) if (!(chunk_size == 0 || is_power_of_2(chunk_size))) return false; - return chunk_size >= wim_ctype_info[ctype].min_chunk_size && - chunk_size <= wim_ctype_info[ctype].max_chunk_size; + return chunk_size >= wim_ctype_info[(unsigned)ctype].min_chunk_size && + chunk_size <= wim_ctype_info[(unsigned)ctype].max_chunk_size; } /* Return the default chunk size to use for the specified compression type in @@ -112,7 +108,7 @@ wim_chunk_size_valid(u32 chunk_size, enum wimlib_compression_type ctype) static u32 wim_default_nonsolid_chunk_size(enum wimlib_compression_type ctype) { - return wim_ctype_info[ctype].default_nonsolid_chunk_size; + return wim_ctype_info[(unsigned)ctype].default_nonsolid_chunk_size; } /* Return the default chunk size to use for the specified compression type in @@ -120,7 +116,7 @@ wim_default_nonsolid_chunk_size(enum wimlib_compression_type ctype) static u32 wim_default_solid_chunk_size(enum wimlib_compression_type ctype) { - return wim_ctype_info[ctype].default_solid_chunk_size; + return wim_ctype_info[(unsigned)ctype].default_solid_chunk_size; } /* Return the default compression type to use in solid resources. */ @@ -150,12 +146,12 @@ new_wim_struct(void) if (!wim) return NULL; + wim->refcnt = 1; filedes_invalidate(&wim->in_fd); filedes_invalidate(&wim->out_fd); wim->out_solid_compression_type = wim_default_solid_compression_type(); wim->out_solid_chunk_size = wim_default_solid_chunk_size( wim->out_solid_compression_type); - INIT_LIST_HEAD(&wim->subwims); return wim; } @@ -180,18 +176,30 @@ wimlib_create_new_wim(enum wimlib_compression_type ctype, WIMStruct **wim_ret) if (!wim) return WIMLIB_ERR_NOMEM; + wim->xml_info = xml_new_info_struct(); wim->blob_table = new_blob_table(9001); - if (!wim->blob_table) { + if (!wim->xml_info || !wim->blob_table) { wimlib_free(wim); return WIMLIB_ERR_NOMEM; } - init_wim_header(&wim->hdr, ctype, - wim_default_nonsolid_chunk_size(ctype)); - wim->compression_type = ctype; - wim->out_compression_type = ctype; + /* Fill in wim->hdr with default values */ + wim->hdr.magic = WIM_MAGIC; + wim->hdr.wim_version = WIM_VERSION_DEFAULT; + wim->hdr.flags = 0; + wim->hdr.chunk_size = 0; + generate_guid(wim->hdr.guid); + wim->hdr.part_number = 1; + wim->hdr.total_parts = 1; + wim->hdr.image_count = 0; + wim->hdr.boot_idx = 0; + + wim->compression_type = WIMLIB_COMPRESSION_TYPE_NONE; wim->chunk_size = wim->hdr.chunk_size; - wim->out_chunk_size = wim->hdr.chunk_size; + + /* Set the output compression type */ + wim->out_compression_type = ctype; + wim->out_chunk_size = wim_default_nonsolid_chunk_size(ctype); *wim_ret = wim; return 0; @@ -218,12 +226,6 @@ destroy_image_metadata(struct wim_image_metadata *imd, } INIT_LIST_HEAD(&imd->unhashed_blobs); INIT_HLIST_HEAD(&imd->inode_list); -#ifdef WITH_NTFS_3G - if (imd->ntfs_vol) { - do_ntfs_umount(imd->ntfs_vol); - imd->ntfs_vol = NULL; - } -#endif } void @@ -323,11 +325,11 @@ select_wim_image(WIMStruct *wim, int image) return WIMLIB_ERR_METADATA_NOT_FOUND; /* If a valid image is currently selected, its metadata can be freed if - * it has not been modified. */ + * it is not dirty and no other WIMStructs may have it selected. */ deselect_current_wim_image(wim); wim->current_image = image; imd = wim_get_current_image_metadata(wim); - if (imd->root_dentry || imd->modified) { + if (imd->root_dentry || is_image_dirty(imd)) { ret = 0; } else { ret = read_metadata_resource(imd); @@ -344,7 +346,7 @@ deselect_current_wim_image(WIMStruct *wim) if (wim->current_image == WIMLIB_NO_IMAGE) return; imd = wim_get_current_image_metadata(wim); - if (!imd->modified) { + if (!is_image_dirty(imd) && imd->refcnt == 1) { wimlib_assert(list_empty(&imd->unhashed_blobs)); destroy_image_metadata(imd, NULL, false); } @@ -439,7 +441,7 @@ wimlib_print_available_images(const WIMStruct *wim, int image) tputchar(T('-')); tputchar(T('\n')); for (i = first; i <= last; i++) - print_image_info(wim->wim_info, i); + xml_print_image_info(wim->xml_info, i); } /* API function documented in wimlib.h */ @@ -447,7 +449,7 @@ WIMLIBAPI int wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info) { memset(info, 0, sizeof(struct wimlib_wim_info)); - memcpy(info->guid, wim->hdr.guid, WIMLIB_GUID_LEN); + copy_guid(info->guid, wim->hdr.guid); info->image_count = wim->hdr.image_count; info->boot_index = wim->hdr.boot_idx; info->wim_version = wim->hdr.wim_version; @@ -455,7 +457,7 @@ wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info) info->part_number = wim->hdr.part_number; info->total_parts = wim->hdr.total_parts; info->compression_type = wim->compression_type; - info->total_bytes = wim_info_get_total_bytes(wim->wim_info); + info->total_bytes = xml_get_total_bytes(wim->xml_info); info->has_integrity_table = wim_has_integrity_table(wim); info->opened_from_file = (wim->filename != NULL); info->is_readonly = (wim->hdr.flags & WIM_HDR_FLAG_READONLY) || @@ -493,7 +495,7 @@ wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int whic } if (which & WIMLIB_CHANGE_GUID) - memcpy(wim->hdr.guid, info->guid, WIM_GUID_LEN); + copy_guid(wim->hdr.guid, info->guid); if (which & WIMLIB_CHANGE_BOOT_INDEX) wim->hdr.boot_idx = info->boot_index; @@ -584,7 +586,7 @@ wimlib_get_compression_type_string(enum wimlib_compression_type ctype) if (!wim_compression_type_valid(ctype)) return T("Invalid"); - return wim_ctype_info[ctype].name; + return wim_ctype_info[(unsigned)ctype].name; } WIMLIBAPI void @@ -618,7 +620,6 @@ static int begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) { int ret; - int xml_num_images; const tchar *wimfile; if (open_flags & WIMLIB_OPEN_FLAG_FROM_PIPE) { @@ -732,13 +733,15 @@ begin_read(WIMStruct *wim, const void *wim_filename_or_fd, int open_flags) if (!wim->blob_table) return WIMLIB_ERR_NOMEM; } else { + if (wim->hdr.blob_table_reshdr.uncompressed_size == 0 && + wim->hdr.xml_data_reshdr.uncompressed_size == 0) + return WIMLIB_ERR_WIM_IS_INCOMPLETE; ret = read_wim_xml_data(wim); if (ret) return ret; - xml_num_images = wim_info_get_num_images(wim->wim_info); - if (xml_num_images != wim->hdr.image_count) { + if (xml_get_image_count(wim->xml_info) != 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."); @@ -864,38 +867,45 @@ can_modify_wim(WIMStruct *wim) return 0; } -/* API function documented in wimlib.h */ -WIMLIBAPI void -wimlib_free(WIMStruct *wim) +/* Release a reference to a WIMStruct. If the reference count reaches 0, the + * WIMStruct is freed. */ +void +wim_decrement_refcnt(WIMStruct *wim) { - if (!wim) + wimlib_assert(wim->refcnt > 0); + if (--wim->refcnt != 0) return; - - while (!list_empty(&wim->subwims)) { - WIMStruct *subwim; - - subwim = list_entry(wim->subwims.next, WIMStruct, subwim_node); - list_del(&subwim->subwim_node); - wimlib_free(subwim); - } - if (filedes_valid(&wim->in_fd)) filedes_close(&wim->in_fd); if (filedes_valid(&wim->out_fd)) filedes_close(&wim->out_fd); + wimlib_free_decompressor(wim->decompressor); + xml_free_info_struct(wim->xml_info); + FREE(wim->filename); + FREE(wim); +} - free_blob_table(wim->blob_table); +/* API function documented in wimlib.h */ +WIMLIBAPI void +wimlib_free(WIMStruct *wim) +{ + if (!wim) + return; - wimlib_free_decompressor(wim->decompressor); + /* The blob table and image metadata are freed immediately, but other + * members of the WIMStruct such as the input file descriptor are + * retained until no more exported resources reference the WIMStruct. */ - FREE(wim->filename); - free_wim_info(wim->wim_info); - if (wim->image_metadata) { - for (unsigned i = 0; i < wim->hdr.image_count; i++) + free_blob_table(wim->blob_table); + wim->blob_table = NULL; + if (wim->image_metadata != NULL) { + for (int i = 0; i < wim->hdr.image_count; i++) put_image_metadata(wim->image_metadata[i], NULL); FREE(wim->image_metadata); + wim->image_metadata = NULL; } - FREE(wim); + + wim_decrement_refcnt(wim); } static bool @@ -960,7 +970,7 @@ wimlib_global_init(int init_flags) WIMLIB_INIT_FLAG_DEFAULT_CASE_INSENSITIVE)) goto out_unlock; - libxml_global_init(); + xml_global_init(); if (!(init_flags & WIMLIB_INIT_FLAG_ASSUME_UTF8)) { wimlib_mbs_is_utf8 = test_locale_ctype_utf8(); #ifdef WITH_NTFS_3G @@ -999,7 +1009,7 @@ wimlib_global_cleanup(void) if (!lib_initialized) goto out_unlock; - libxml_global_cleanup(); + xml_global_cleanup(); iconv_global_cleanup(); #ifdef __WIN32__ win32_global_cleanup();