From: Eric Biggers Date: Thu, 23 May 2013 04:06:54 +0000 (-0500) Subject: Add wimlib_{get,set}_wim_info() X-Git-Tag: v1.4.1~14 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=bcec8f6839a4e72db751bb8fd5d7559e1cd7ea7f Add wimlib_{get,set}_wim_info() --- diff --git a/NEWS b/NEWS index 5cc48a9c..4b82820b 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,8 @@ Version 1.4.1: Progress callbacks have been added to wimlib's wimlib_update_image() function. + Added wimlib_get_wim_info() and wimlib_set_wim_info() functions. + NTFS-3g capture now only warns about two conditions previously treated as errors. diff --git a/include/wimlib.h b/include/wimlib.h index 09059eb5..6d3c3caa 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -200,6 +200,13 @@ typedef char wimlib_tchar; # define WIMLIB_WIM_PATH_SEPARATOR '/' # define WIMLIB_WIM_PATH_SEPARATOR_STRING "/" #endif + +#ifdef __GNUC__ +# define _wimlib_deprecated __attribute__((deprecated)) +#else +# define _wimlib_deprecated +#endif + /** * Specifies the compression type of a WIM file. */ @@ -615,6 +622,97 @@ struct wimlib_capture_config { size_t _prefix_num_tchars; }; +/** Set or unset the WIM header flag that marks it read-only + * (WIM_HDR_FLAG_READONLY in Microsoft's documentation), based on the + * ::wimlib_wim_info.is_marked_readonly member of the @a info parameter. This + * is distinct from basic file permissions; this flag can be set on a WIM file + * that is physically writable. If this flag is set, all further operations to + * modify the WIM will fail, except calling wimlib_overwrite() with + * ::WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG specified, which is a loophole that + * allows you to set this flag persistently on the underlying WIM file. + */ +#define WIMLIB_CHANGE_READONLY_FLAG 0x00000001 + +/** Set the GUID (globally unique identifier) of the WIM file to the value + * specified in ::wimlib_wim_info.guid of the @a info parameter. */ +#define WIMLIB_CHANGE_GUID 0x00000002 + +/** Change the bootable image of the WIM to the value specified in + * ::wimlib_wim_info.boot_index of the @a info parameter. */ +#define WIMLIB_CHANGE_BOOT_INDEX 0x00000004 + +/** Change the WIM_HDR_FLAG_RP_FIX flag of the WIM file to the value specified + * in ::wimlib_wim_info.has_rpfix of the @a info parameter. This flag generally + * indicates whether an image in the WIM has been captured with reparse-point + * fixups enabled. wimlib also treats this flag as specifying whether to do + * reparse-point fixups by default when capturing or applying WIM images. */ +#define WIMLIB_CHANGE_RPFIX_FLAG 0x00000008 + +#define WIMLIB_GUID_LEN 16 + +/** General information about a WIM file. */ +struct wimlib_wim_info { + + /** Globally unique identifier for the WIM file. Note: all parts of a + * split WIM should have an identical value in this field. */ + uint8_t guid[WIMLIB_GUID_LEN]; + + /** Number of images in the WIM. */ + uint32_t image_count; + + /** 1-based index of the bootable image in the WIM, or 0 if no image is + * bootable. */ + uint32_t boot_index; + + /** Version of the WIM file. */ + uint32_t wim_version; + + /** Chunk size used for compression. */ + uint32_t chunk_size; + + /** 1-based index of this part within a split WIM, or 1 if the WIM is + * standalone. */ + uint16_t part_number; + + /** Total number of parts in the split WIM, or 1 if the WIM is + * standalone. */ + uint16_t total_parts; + + /** One of the ::wimlib_compression_type values that specifies the + * method used to compress resources in the WIM. */ + int32_t compression_type; + + /** Size of the WIM file in bytes, excluding the XML data and integrity + * table. */ + uint64_t total_bytes; + + /** 1 if the WIM has an integrity table */ + uint32_t has_integrity_table : 1; + + /** 1 if the WIM was created via wimlib_open_wim() rather than + * wimlib_create_new_wim(). */ + uint32_t opened_from_file : 1; + + /** 1 if the WIM is considered readonly for any reason. */ + uint32_t is_readonly : 1; + + /** 1 if reparse-point fixups are supposedly enabled for one or more + * images in the WIM. */ + uint32_t has_rpfix : 1; + + /** 1 if the WIM is marked as read-only. */ + uint32_t is_marked_readonly : 1; + + /** 1 if the WIM is part of a spanned set. */ + uint32_t spanned : 1; + + uint32_t write_in_progress : 1; + uint32_t metadata_only : 1; + uint32_t resource_only : 1; + uint32_t reserved_flags : 24; + uint32_t reserved[9]; +}; + /***************************** * WIMLIB_ADD_FLAG_* @@ -882,6 +980,12 @@ struct wimlib_capture_config { * deleting an image in this way. */ #define WIMLIB_WRITE_FLAG_SOFT_DELETE 0x00000010 +/** With wimlib_overwrite(), allow overwriting the WIM even if the readonly flag + * is set in the WIM header; this can be used in combination with + * wimlib_set_wim_info() with the ::WIMLIB_CHANGE_READONLY_FLAG flag to actually + * set the readonly flag on the on-disk WIM file. */ +#define WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG 0x00000020 + /****************************** * WIMLIB_INIT_FLAG_* ******************************/ @@ -1579,30 +1683,16 @@ extern void wimlib_free(WIMStruct *wim); /** - * Returns the index of the bootable image of the WIM. - * - * @param wim - * Pointer to the ::WIMStruct for a WIM file. - * - * @return - * 0 if no image is marked as bootable, or the number of the image marked - * as bootable (numbered starting at 1). + * Deprecated in favor of wimlib_get_wim_info(). */ extern int -wimlib_get_boot_idx(const WIMStruct *wim); +wimlib_get_boot_idx(const WIMStruct *wim) _wimlib_deprecated; /** - * Returns the compression type used in the WIM. - * - * @param wim - * Pointer to the ::WIMStruct for a WIM file - * - * @return - * ::WIMLIB_COMPRESSION_TYPE_NONE, ::WIMLIB_COMPRESSION_TYPE_LZX, or - * ::WIMLIB_COMPRESSION_TYPE_XPRESS. + * Deprecated in favor of wimlib_get_wim_info(). */ extern int -wimlib_get_compression_type(const WIMStruct *wim); +wimlib_get_compression_type(const WIMStruct *wim) _wimlib_deprecated; /** * Converts a ::wimlib_compression_type value into a string. @@ -1674,33 +1764,31 @@ wimlib_get_image_name(const WIMStruct *wim, int image); /** - * Returns the number of images contained in a WIM. - * - * @param wim - * Pointer to the ::WIMStruct for a WIM file. It may be either a - * standalone WIM or a split WIM part. - * - * @return - * The number of images contained in the WIM file. + * Deprecated in favor of wimlib_get_wim_info(). + */ +extern int +wimlib_get_num_images(const WIMStruct *wim) _wimlib_deprecated; + +/** + * Deprecated in favor of wimlib_get_wim_info(). */ extern int -wimlib_get_num_images(const WIMStruct *wim); +wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret) _wimlib_deprecated; /** - * Returns the part number of a WIM in a split WIM and the total number of parts - * of the split WIM. + * Get basic information about a WIM file. * * @param wim - * Pointer to the ::WIMStruct for a WIM file. - * @param total_parts_ret - * If non-@c NULL, the total number of parts in the split WIM (1 for - * non-split WIMs) is written to this location. - * + * Pointer to the ::WIMStruct for a WIM file. It may be for either a + * standalone WIM or part of a split WIM. + * @param info + * A ::wimlib_wim_info structure that will be filled in with information + * about the WIM file. * @return - * The part number of the WIM (1 for non-split WIMs) + * 0 */ extern int -wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret); +wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info); /** * Initialization function for wimlib. Call before using any other wimlib @@ -2287,23 +2375,10 @@ wimlib_resolve_image(WIMStruct *wim, const wimlib_tchar *image_name_or_num); /** - * Sets which image in the WIM is marked as bootable. - * - * @param wim - * Pointer to the ::WIMStruct for a WIM file. - * @param boot_idx - * The number of the image to mark as bootable, or 0 to mark no image as - * bootable. - * @return 0 on success; nonzero on error. - * @retval ::WIMLIB_ERR_INVALID_IMAGE - * @a boot_idx does not specify an existing image in @a wim, and it was not - * 0. - * @retval ::WIMLIB_ERR_WIM_IS_READONLY - * @a wim is considered read-only because of any of the reasons mentioned - * in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag. + * Deprecated in favor of wimlib_set_wim_info(). */ extern int -wimlib_set_boot_idx(WIMStruct *wim, int boot_idx); +wimlib_set_boot_idx(WIMStruct *wim, int boot_idx) _wimlib_deprecated; /** * Changes the description of an image in the WIM. @@ -2332,6 +2407,36 @@ extern int wimlib_set_image_descripton(WIMStruct *wim, int image, const wimlib_tchar *description); +/** + * Set basic information about a WIM. + * + * @param wim + * A WIMStruct for a standalone WIM file. + * @param info + * A struct ::wimlib_wim_info that contains the information to set. Only + * the information explicitly specified in the @a which flags need be + * valid. + * @param which + * Flags that specify which information to set. This is a bitwise OR of + * ::WIMLIB_CHANGE_READONLY_FLAG, ::WIMLIB_CHANGE_GUID, + * ::WIMLIB_CHANGE_BOOT_INDEX, and/or ::WIMLIB_CHANGE_RPFIX_FLAG. + * + * @return 0 on success; nonzero on failure. + * @retval ::WIMLIB_ERR_WIM_IS_READONLY + * The WIM file is considered read-only because of any of the reasons + * mentioned in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS + * flag. However, as a special case, if you are using + * ::WIMLIB_CHANGE_READONLY_FLAG to unset the readonly flag, then this + * function will not fail due to the readonly flag being previously set. + * @retval ::WIMLIB_ERR_IMAGE_COUNT + * ::WIMLIB_CHANGE_BOOT_INDEX was specified, but + * ::wimlib_wim_info.boot_index did not specify 0 or a valid 1-based image + * index in the WIM. + */ +extern int +wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, + int which); + /** * Changes what is written in the \ element in the WIM XML data * (something like "Core" or "Ultimate") @@ -2355,8 +2460,8 @@ wimlib_set_image_descripton(WIMStruct *wim, int image, * @a wim is considered read-only because of any of the reasons mentioned * in the documentation for the ::WIMLIB_OPEN_FLAG_WRITE_ACCESS flag. */ -extern int wimlib_set_image_flags(WIMStruct *wim, int image, - const wimlib_tchar *flags); +extern int +wimlib_set_image_flags(WIMStruct *wim, int image, const wimlib_tchar *flags); /** * Changes the name of an image in the WIM. diff --git a/src/wim.c b/src/wim.c index cfe100d6..2a3c08c1 100644 --- a/src/wim.c +++ b/src/wim.c @@ -152,12 +152,6 @@ out_free: return ret; } -WIMLIBAPI int -wimlib_get_num_images(const WIMStruct *w) -{ - return w->hdr.image_count; -} - int select_wim_image(WIMStruct *w, int image) { @@ -208,13 +202,6 @@ select_wim_image(WIMStruct *w, int image) } -/* Returns the compression type of the WIM file. */ -WIMLIBAPI int -wimlib_get_compression_type(const WIMStruct *w) -{ - return w->compression_type; -} - WIMLIBAPI const tchar * wimlib_get_compression_type_string(int ctype) { @@ -350,34 +337,128 @@ wimlib_print_files(WIMStruct *w, int image) return for_image(w, image, image_print_files); } -/* Sets the index of the bootable image. */ WIMLIBAPI int -wimlib_set_boot_idx(WIMStruct *wim, int boot_idx) +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); + info->image_count = wim->hdr.image_count; + info->boot_index = wim->hdr.boot_idx; + info->wim_version = WIM_VERSION; + 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; + if (wim->wim_info) + info->total_bytes = wim->wim_info->total_bytes; + else + info->total_bytes = 0; + info->has_integrity_table = wim->hdr.integrity.offset != 0; + info->opened_from_file = (wim->filename != NULL); + info->is_readonly == (wim->hdr.flags & WIM_HDR_FLAG_READONLY) || + (wim->hdr.total_parts != 1) || + (wim->filename && taccess(wim->filename, W_OK)); + info->has_rpfix = (wim->hdr.flags & WIM_HDR_FLAG_RP_FIX) != 0; + info->is_marked_readonly = (wim->hdr.flags & WIM_HDR_FLAG_READONLY) != 0; + info->write_in_progress = (wim->hdr.flags & WIM_HDR_FLAG_WRITE_IN_PROGRESS) != 0; + info->metadata_only = (wim->hdr.flags & WIM_HDR_FLAG_METADATA_ONLY) != 0; + info->resource_only = (wim->hdr.flags & WIM_HDR_FLAG_RESOURCE_ONLY) != 0; + info->spanned = (wim->hdr.flags & WIM_HDR_FLAG_SPANNED) != 0; + return 0; +} + + +/* Deprecated */ +WIMLIBAPI int +wimlib_get_boot_idx(const WIMStruct *wim) { - int ret; + struct wimlib_wim_info info; - ret = can_modify_wim(wim); - if (ret) - return ret; - if (boot_idx < 0 || boot_idx > wim->hdr.image_count) - return WIMLIB_ERR_INVALID_IMAGE; - wim->hdr.boot_idx = boot_idx; - return 0; + wimlib_get_wim_info((WIMStruct*)wim, &info); + return info.boot_index; +} + +/* Deprecated */ +WIMLIBAPI int +wimlib_get_compression_type(const WIMStruct *wim) +{ + struct wimlib_wim_info info; + + wimlib_get_wim_info((WIMStruct*)wim, &info); + return info.compression_type; +} + +/* Deprecated */ +WIMLIBAPI int +wimlib_get_num_images(const WIMStruct *wim) +{ + struct wimlib_wim_info info; + + wimlib_get_wim_info((WIMStruct*)wim, &info); + return info.image_count; } +/* Deprecated */ WIMLIBAPI int -wimlib_get_part_number(const WIMStruct *w, int *total_parts_ret) +wimlib_get_part_number(const WIMStruct *wim, int *total_parts_ret) { + struct wimlib_wim_info info; + + wimlib_get_wim_info((WIMStruct*)wim, &info); if (total_parts_ret) - *total_parts_ret = w->hdr.total_parts; - return w->hdr.part_number; + *total_parts_ret = info.total_parts; + return info.part_number; } +WIMLIBAPI int +wimlib_set_wim_info(WIMStruct *wim, const struct wimlib_wim_info *info, int which) +{ + int ret; + + if (which & WIMLIB_CHANGE_READONLY_FLAG) { + if (info->is_marked_readonly) + wim->hdr.flags |= WIM_HDR_FLAG_READONLY; + else + wim->hdr.flags &= ~WIM_HDR_FLAG_READONLY; + } + if ((which & ~WIMLIB_CHANGE_READONLY_FLAG) == 0) + return 0; + + ret = can_modify_wim(wim); + if (ret) + return ret; + + if (which & WIMLIB_CHANGE_GUID) + memcpy(wim->hdr.guid, info->guid, WIM_GID_LEN); + + if (which & WIMLIB_CHANGE_BOOT_INDEX) { + if (info->boot_index < 0 || 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); + return WIMLIB_ERR_INVALID_IMAGE; + } + wim->hdr.boot_idx = info->boot_index; + } + + if (which & WIMLIB_CHANGE_RPFIX_FLAG) { + if (info->has_rpfix) + wim->hdr.flags |= WIM_HDR_FLAG_RP_FIX; + else + wim->hdr.flags &= ~WIM_HDR_FLAG_RP_FIX; + } + return 0; +} + +/* Deprecated */ WIMLIBAPI int -wimlib_get_boot_idx(const WIMStruct *w) +wimlib_set_boot_idx(WIMStruct *wim, int boot_idx) { - return w->hdr.boot_idx; + struct wimlib_wim_info info; + + info.boot_index = boot_idx; + return wimlib_set_wim_info(wim, &info, WIMLIB_CHANGE_BOOT_INDEX); } static int diff --git a/src/write.c b/src/write.c index 4c68921c..75193dfc 100644 --- a/src/write.c +++ b/src/write.c @@ -2227,13 +2227,18 @@ wimlib_overwrite(WIMStruct *w, int write_flags, wimlib_progress_func_t progress_func) { int ret; + u32 orig_hdr_flags; write_flags &= WIMLIB_WRITE_MASK_PUBLIC; if (!w->filename) return WIMLIB_ERR_NO_FILENAME; + orig_hdr_flags = w->hdr.flags; + if (write_flags & WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG) + w->hdr.flags &= ~WIM_HDR_FLAG_READONLY; ret = can_modify_wim(w); + w->hdr.flags = orig_hdr_flags; if (ret) return ret;