X-Git-Url: https://wimlib.net/git/?p=wimlib;a=blobdiff_plain;f=include%2Fwimlib.h;h=71ef0a8e160d0270bf3497b3621f663bc2cfbe2e;hp=081dfca845aee487e5a2f64ec9df9e1db52abb84;hb=5816eba3f41b63910c5d932a8ed22a2c9f65c492;hpb=cb877891bfb9d911db2372444a9990aeb4bc0cdd diff --git a/include/wimlib.h b/include/wimlib.h index 081dfca8..71ef0a8e 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -33,7 +33,7 @@ * * @section sec_intro Introduction * - * This is the documentation for the library interface of wimlib 1.5.1, a C + * This is the documentation for the library interface of wimlib 1.5.3, a C * library for creating, modifying, extracting, and mounting files in the * Windows Imaging Format. This documentation is intended for developers only. * If you have installed wimlib and want to know how to use the @b wimlib-imagex @@ -355,7 +355,7 @@ #define WIMLIB_MINOR_VERSION 5 /** Patch version of the library (for example, the 5 in 1.2.5). */ -#define WIMLIB_PATCH_VERSION 1 +#define WIMLIB_PATCH_VERSION 3 #ifdef __cplusplus extern "C" { @@ -425,6 +425,13 @@ enum wimlib_compression_type { /** Compressed resources in the WIM use XPRESS compression. */ WIMLIB_COMPRESSION_TYPE_XPRESS = 2, + + /** Compressed resources in the WIM use LZMS compression. Currently, + * wimlib has a decompressor for this format but not a compressor. LZMS + * compression is only compatible with wimlib v1.6.0 and later and with + * WIMGAPI Windows 8 and later (and some restrictions apply on the + * latter). */ + WIMLIB_COMPRESSION_TYPE_LZMS = 3, }; /** @} */ @@ -630,6 +637,21 @@ union wimlib_progress_info { * ::WIMLIB_PROGRESS_MSG_SCAN_BEGIN and * ::WIMLIB_PROGRESS_MSG_SCAN_END. */ const wimlib_tchar *wim_target_path; + + /** Number of directories scanned so far, including the root + * directory but excluding any unsupported/excluded directories. + * */ + uint64_t num_dirs_scanned; + + /** Number of non-directories scanned so far, excluding any + * unsupported/excluded files. */ + uint64_t num_nondirs_scanned; + + /** Number of bytes of file data that have been detected so far. + * This data may not actually have been read yet, and it will + * not actually be written to the WIM file until wimlib_write() + * or wimlib_overwrite() has been called. */ + uint64_t num_bytes_scanned; } scan; /** Valid on messages ::WIMLIB_PROGRESS_MSG_EXTRACT_IMAGE_BEGIN, @@ -944,48 +966,64 @@ struct wimlib_wim_info { uint32_t reserved[9]; }; -/** Information about a unique resource in the WIM file. - */ +/** Information about a unique stream in the WIM file. (A stream is the same + * thing as a "resource", except in the case of packed resources.) */ struct wimlib_resource_entry { - /** Uncompressed size of the resource in bytes. */ + /** Uncompressed size of the stream in bytes. */ uint64_t uncompressed_size; - /** Compressed size of the resource in bytes. This will be the same as - * @p uncompressed_size if the resource is uncompressed. */ + /** Compressed size of the stream in bytes. This will be the same as @p + * uncompressed_size if the stream is uncompressed. Or, if @p + * is_packed_streams is 1, this will be 0. */ uint64_t compressed_size; - /** Offset, in bytes, of this resource from the start of the WIM file. + /** Offset, in bytes, of this stream from the start of the WIM file. Or + * if @p packed is 1, then this is actually the offset at which this + * stream begins in the uncompressed contents of the packed resource. */ uint64_t offset; - /** SHA1 message digest of the resource's uncompressed contents. */ + /** SHA1 message digest of the stream's uncompressed contents. */ uint8_t sha1_hash[20]; - /** Which part number of the split WIM this resource is in. This should + /** Which part number of the split WIM this stream is in. This should * be the same as the part number provided by wimlib_get_wim_info(). */ uint32_t part_number; - /** Number of times this resource is referenced over all WIM images. */ + /** Number of times this stream is referenced over all WIM images. */ uint32_t reference_count; - /** 1 if this resource is compressed. */ + /** 1 if this stream is compressed. */ uint32_t is_compressed : 1; - /** 1 if this resource is a metadata resource rather than a file - * resource. */ + /** 1 if this stream is a metadata resource rather than a file resource. + * */ uint32_t is_metadata : 1; uint32_t is_free : 1; uint32_t is_spanned : 1; - /** 1 if this resource was not found in the lookup table of the + /** 1 if this stream was not found in the lookup table of the * ::WIMStruct. This normally implies a missing call to * wimlib_reference_resource_files() or wimlib_reference_resources(). - */ + * */ uint32_t is_missing : 1; - uint32_t reserved_flags : 27; - uint64_t reserved[4]; + /** 1 if this stream is located in a packed resource which may contain + * other streams (all compressed together) as well. */ + uint32_t packed : 1; + + uint32_t reserved_flags : 26; + + /** If @p packed is 1, then this will specify the offset of the packed + * resource in the WIM. */ + uint64_t raw_resource_offset_in_wim; + + /** If @p is_packed_streams is 1, then this will specify the compressed + * size of the packed resource in the WIM. */ + uint64_t raw_resource_compressed_size; + + uint64_t reserved[2]; }; /** A stream of a file in the WIM. */ @@ -1279,7 +1317,9 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour /** This flag no longer does anything but is reserved for future use. */ #define WIMLIB_EXTRACT_FLAG_VERBOSE 0x00000008 -/** Read the WIM file sequentially while extracting the image. */ +/** Read the WIM file sequentially while extracting the image. As of wimlib + * v1.6.0 this is the default behavior, and this flag no longer does anything. + */ #define WIMLIB_EXTRACT_FLAG_SEQUENTIAL 0x00000010 /** Extract special UNIX data captured with ::WIMLIB_ADD_FLAG_UNIX_DATA. Only @@ -1342,6 +1382,13 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * behavior is currently less than satisfactory. Do not use (yet). */ #define WIMLIB_EXTRACT_FLAG_RESUME 0x00010000 +/** Perform the extraction ordered by the tree of files to extract rather than + * how the underlying streams are arranged in the WIM file. For regular WIM + * files this may decrease or increase performance, depending on various + * factors. For WIM files containing packed streams this will decrease + * performance. */ +#define WIMLIB_EXTRACT_FLAG_FILE_ORDER 0x00020000 + /** @} */ /** @ingroup G_mounting_wim_images * @{ */ @@ -1501,6 +1548,31 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * already implied for wimlib_overwrite(). */ #define WIMLIB_WRITE_FLAG_STREAMS_OK 0x00000400 +#define WIMLIB_WRITE_FLAG_RESERVED 0x00000800 + +/** When writing streams in the resulting WIM file, pack multiple streams into a + * single WIM resource instead of compressing them independently. This tends to + * produce a better compression ratio at the cost of less random access. + * Furthermore, WIMs created with this flag are only compatible with wimlib + * v1.6.0 or later and WIMGAPI Windows 8 or later, seemingly for Windows Setup + * only and not including ImageX and Dism. WIMs created with this flag + * use version number 3584 in their header instead of 68864. If this flag is + * passed to wimlib_overwrite() and the WIM did not previously contain packed + * streams, the WIM's version number will be changed to 3584 and the new streams + * will be written packed. */ +#define WIMLIB_WRITE_FLAG_PACK_STREAMS 0x00001000 + +/** Compress all streams independently. This produces a WIM optimized for + * random access and compatibility, as noted in the documentation for + * ::WIMLIB_WRITE_RESOURCE_FLAG_PACK_STREAMS. For wimlib_write(), this is the + * default behavior. For wimlib_overwrite(), this is the default if the WIM file + * did not already contain packed streams. Also, for wimlib_overwrite(), if the + * WIM already contained packed streams, specifying this flag but not + * ::WIMLIB_WRITE_FLAG_REBUILD will cause new streams to be written unpacked, + * but the WIM itself will not be rebuilt and may still contain packed streams. + */ +#define WIMLIB_WRITE_FLAG_NO_PACK_STREAMS 0x00002000 + /** @} */ /** @ingroup G_general * @{ */ @@ -1642,6 +1714,98 @@ struct wimlib_extract_command { int extract_flags; }; +/** @} */ +/** @ingroup G_compression + * @{ */ + +/** LZX compression parameters to pass to wimlib_lzx_alloc_context(). */ +struct wimlib_lzx_params { + /** Must be set to the size of this structure, in bytes. */ + uint32_t size_of_this; + + /** Relatively fast LZX compression algorithm with a decent compression + * ratio; the suggested default. */ +#define WIMLIB_LZX_ALGORITHM_FAST 0 + + /** Slower LZX compression algorithm that provides a better compression + * ratio. */ +#define WIMLIB_LZX_ALGORITHM_SLOW 1 + + /** Algorithm to use to perform the compression: either + * ::WIMLIB_LZX_ALGORITHM_FAST or ::WIMLIB_LZX_ALGORITHM_SLOW. The + * format is still LZX; this refers to the method the code will use to + * perform LZX-compatible compression. */ + uint32_t algorithm : 3; + + /** If set to 1, the default parameters for the specified algorithm are + * used rather than the ones specified in the following union. */ + uint32_t use_defaults : 1; + + union { + /** Parameters for the fast algorithm. */ + struct wimlib_lzx_fast_params { + uint32_t fast_reserved1[10]; + } fast; + + /** Parameters for the slow algorithm. */ + struct wimlib_lzx_slow_params { + /** If set to 1, the compressor can output length 2 + * matches. If set 0, the compressor only outputs + * matches of length 3 or greater. Suggested value: 1 + */ + uint32_t use_len2_matches : 1; + + uint32_t slow_reserved1 : 31; + + /** Matches with length (in bytes) longer than this + * value are immediately taken without spending time on + * minimum-cost measurements. Suggested value: 32. */ + uint32_t num_fast_bytes; + + /** Number of passes to compute a match/literal sequence + * for each LZX block. This is for an iterative + * algorithm that attempts to minimize the cost of the + * match/literal sequence by using a cost model provided + * by the previous iteration. Must be at least 1. + * Suggested value: 2. */ + uint32_t num_optim_passes; + + /** Reserved; set to 0. */ + uint32_t slow_reserved_blocksplit; + + /** Maximum depth to search for matches at each + * position. Suggested value: 50. */ + uint32_t max_search_depth; + + /** Maximum number of potentially good matches to + * consider for each position. Suggested value: 3. */ + uint32_t max_matches_per_pos; + + uint32_t slow_reserved2[2]; + + /** Assumed cost of a main symbol with zero frequency. + * Must be at least 1 and no more than 16. Suggested + * value: 15. */ + uint8_t main_nostat_cost; + + /** Assumed cost of a length symbol with zero frequency. + * Must be at least 1 and no more than 16. Suggested + * value: 15. */ + uint8_t len_nostat_cost; + + /** Assumed cost of an aligned symbol with zero + * frequency. Must be at least 1 and no more than 8. + * Suggested value: 7. */ + uint8_t aligned_nostat_cost; + + uint8_t slow_reserved3[5]; + } slow; + } alg_params; +}; + +/** Opaque LZX compression context. */ +struct wimlib_lzx_context; + /** @} */ /** @ingroup G_general * @{ */ @@ -2276,6 +2440,8 @@ wimlib_extract_image_from_pipe(int pipe_fd, * Extracts the XML data of a WIM file to a file stream. Every WIM file * includes a string of XML that describes the images contained in the WIM. * + * See wimlib_get_xml_data() to read the XML data into memory instead. + * * @param wim * Pointer to the ::WIMStruct for a WIM file, which does not necessarily * have to be standalone (e.g. it could be part of a split WIM). @@ -2400,6 +2566,36 @@ wimlib_get_image_name(const WIMStruct *wim, int image); extern int wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info); +/** + * @ingroup G_wim_information + * + * Read the XML data of a WIM file into an in-memory buffer. Every WIM file + * includes a string of XML that describes the images contained in the WIM. + * + * See wimlib_extract_xml_data() to extract the XML data to a file stream + * instead. + * + * @param wim + * Pointer to the ::WIMStruct for a WIM file, which does not necessarily + * have to be standalone (e.g. it could be part of a split WIM). + * @param buf_ret + * On success, a pointer to an allocated buffer containing the raw UTF16-LE + * XML data is written to this location. + * @param bufsize_ret + * The size of the XML data in bytes is written to this location. + * + * @return 0 on success; nonzero on error. + * @retval ::WIMLIB_ERR_INVALID_PARAM + * @p wim is not a ::WIMStruct that was created by wimlib_open_wim(), or + * @p buf_ret or @p bufsize_ret was @c NULL. + * @retval ::WIMLIB_ERR_NOMEM + * @retval ::WIMLIB_ERR_READ + * @retval ::WIMLIB_ERR_UNEXPECTED_END_OF_FILE + * Failed to read the XML data from the WIM. + */ +extern int +wimlib_get_xml_data(WIMStruct *wim, void **buf_ret, size_t *bufsize_ret); + /** * @ingroup G_general * @@ -2588,6 +2784,45 @@ wimlib_join(const wimlib_tchar * const *swms, int wim_write_flags, wimlib_progress_func_t progress_func); +/** + * @ingroup G_compression + * + * Decompresses a block of LZMS-compressed data. + * + * This function is exported for convenience only and should only be used by + * library clients looking to make use of wimlib's compression code for another + * purpose. + * + * This decompressor only implements "raw" decompression, which decompresses a + * single LZMS-compressed block. This behavior is the same as that of + * Decompress() in the Windows 8 compression API when using a compression handle + * created with CreateDecompressor() with the Algorithm parameter specified as + * COMPRESS_ALGORITHM_LZMS | COMPRESS_RAW. Presumably, non-raw LZMS data + * is a container format from which the locations and sizes (both compressed and + * uncompressed) of the constituent blocks can be determined. + * + * This function should not be called for blocks with compressed size equal to + * uncompressed size, since such blocks are actually stored uncompressed. + * + * @param compressed_data + * Pointer to the compressed data. + * + * @param compressed_len + * Length of the compressed data, in bytes. + * + * @param uncompressed_data + * Pointer to the buffer into which to write the uncompressed data. + * + * @param uncompressed_len + * Length of the uncompressed data. + * + * @return + * 0 on success; non-zero on failure. + */ +extern int +wimlib_lzms_decompress(const void *compressed_data, unsigned compressed_len, + void *uncompressed_data, unsigned uncompressed_len); + /** * @ingroup G_compression * @@ -2612,7 +2847,53 @@ wimlib_join(const wimlib_tchar * const *swms, * format and therefore requires (@p chunk_size <= 32768). */ extern unsigned -wimlib_lzx_compress(const void *chunk, unsigned chunk_size, void *out); +wimlib_lzx_compress(const void *chunk, unsigned chunk_size, void *out) + _wimlib_deprecated; + +/** + * @ingroup G_compression + * + * Equivalent to wimlib_lzx_compress(), but uses the specified compression + * context, allocated by wimlib_lzx_alloc_context(). + */ +extern unsigned +wimlib_lzx_compress2(const void *chunk, unsigned chunk_size, void *out, + struct wimlib_lzx_context *ctx); + +/** + * @ingroup G_compression + * + * Allocate a LZX compression context using the specified parameters. + * + * This function is exported for convenience only and should only be used by + * library clients looking to make use of wimlib's compression code for another + * purpose. + * + * @param window_size + * Size of the LZX window. Must be a power of 2 between 2^15 and 2^21, + * inclusively. + * + * @param params + * Compression parameters to use, or @c NULL to use the default parameters. + * + * @param ctx_ret + * A pointer to either @c NULL or an existing ::wimlib_lzx_context. If + * *ctx_ret == NULL, the new context is allocated. If + * *ctx_ret != NULL, the existing context is re-used if + * possible. Alternatively, this argument can itself be @c NULL to + * indicate that only parameter validation is to be performed. + * + * @return 0 on success; nonzero on error. + * + * @retval ::WIMLIB_ERR_INVALID_PARAM + * The window size or compression parameters were invalid. + * @retval ::WIMLIB_ERR_NOMEM + * Not enough memory to allocate the compression context. + */ +extern int +wimlib_lzx_alloc_context(uint32_t window_size, + const struct wimlib_lzx_params *params, + struct wimlib_lzx_context **ctx_pp); /** * @ingroup G_compression @@ -2645,6 +2926,56 @@ extern int wimlib_lzx_decompress(const void *compressed_data, unsigned compressed_len, void *uncompressed_data, unsigned uncompressed_len); +/** + * @ingroup G_compression + * + * Equivalent to wimlib_lzx_decompress(), except the window size is specified in + * @p max_window_size as any power of 2 between 2^15 and 2^21, inclusively, and + * @p uncompressed_len may be any size less than or equal to @p max_window_size. + */ +extern int +wimlib_lzx_decompress2(const void *compressed_data, unsigned compressed_len, + void *uncompressed_data, unsigned uncompressed_len, + uint32_t max_window_size); + +/** + * @ingroup G_compression + * + * Free the specified LZX compression context, allocated with + * wimlib_lzx_alloc_context(). + */ +extern void +wimlib_lzx_free_context(struct wimlib_lzx_context *ctx); + +/** + * @ingroup G_compression + * + * Set the global default LZX compression parameters. + * + * @param params + * The LZX compression parameters to set. These default parameters will be + * used by any calls to wimlib_lzx_alloc_context() with @c NULL LZX + * parameters specified, as well as by any future compression performed by + * the library itself. Passing @p NULL here resets the default LZX + * parameters to their original value. + * + * @return 0 on success; nonzero on error. + * + * @retval ::WIMLIB_ERR_INVALID_PARAM + * The compression parameters were invalid. + */ +extern int +wimlib_lzx_set_default_params(const struct wimlib_lzx_params *params); + +/** + * @ingroup G_compression + * + * Free the specified LZX compression context, allocated with + * wimlib_lzx_alloc_context(). + */ +extern void +wimlib_lzx_free_context(struct wimlib_lzx_context *ctx); + /** * @ingroup G_mounting_wim_images @@ -2768,7 +3099,8 @@ wimlib_mount_image(WIMStruct *wim, * chunk of the WIM does not match the corresponding message digest given * in the integrity table. * @retval ::WIMLIB_ERR_INVALID_CHUNK_SIZE - * Resources in @p wim_file are compressed, but the chunk size is not 32768. + * Resources in @p wim_file are compressed, but the chunk size was invalid + * for the WIM's compression format. * @retval ::WIMLIB_ERR_INVALID_COMPRESSION_TYPE * The header of @p wim_file says that resources in the WIM are compressed, * but the header flag indicating LZX or XPRESS compression is not set. @@ -3151,6 +3483,61 @@ extern int wimlib_set_image_descripton(WIMStruct *wim, int image, const wimlib_tchar *description); +/** + * @ingroup G_writing_and_overwriting_wims + * + * Set the compression chunk size of a WIM to use in subsequent calls to + * wimlib_write() or wimlib_overwrite(). + * + * A compression chunk size will result in a greater compression ratio, but the + * speed of random access to the WIM will be reduced, and the effect of an + * increased compression chunk size is limited by the size of each file being + * compressed. + * + * WARNING: Changing the compression chunk size to any value other than the + * default of 32768 bytes eliminates compatibility with Microsoft's software, + * except when increasing the XPRESS chunk size before Windows 8. Chunk sizes + * other than 32768 are also incompatible with wimlib v1.5.3 and earlier. + * + * @param wim + * ::WIMStruct for a WIM. + * @param out_chunk_size + * The chunk size (in bytes) to set. The valid chunk sizes are dependent + * on the compression format. The XPRESS compression format supports chunk + * sizes that are powers of 2 with exponents between 15 and 26 inclusively, + * whereas the LZX compression format supports chunk sizes that are powers + * of 2 with exponents between 15 and 21 inclusively. + * + * @return 0 on success; nonzero on error. + * + * @retval ::WIMLIB_ERR_INVALID_CHUNK_SIZE + * @p ctype is not a supported chunk size. + */ +extern int +wimlib_set_output_chunk_size(WIMStruct *wim, uint32_t chunk_size); + +/** + * @ingroup G_writing_and_overwriting_wims + * + * Set the compression type of a WIM to use in subsequent calls to + * wimlib_write() or wimlib_overwrite(). + * + * @param wim + * ::WIMStruct for a WIM. + * @param ctype + * The compression type to set (one of ::wimlib_compression_type). If this + * compression type is incompatible with the current output chunk size + * (either the default or as set with wimlib_set_output_chunk_size()), the + * output chunk size is reset to the default for that compression type. + * + * @return 0 on success; nonzero on error. + * + * @retval ::WIMLIB_ERR_INVALID_PARAM + * @p ctype did not specify a valid compression type. + */ +extern int +wimlib_set_output_compression_type(WIMStruct *wim, int ctype); + /** * @ingroup G_modifying_wims * @@ -3645,8 +4032,28 @@ wimlib_write_to_fd(WIMStruct *wim, /** * @ingroup G_compression * - * This function is equivalent to wimlib_lzx_compress(), but instead compresses - * the data using "XPRESS" compression. + * Compress a chunk of data using XPRESS compression. + * + * This function is exported for convenience only and should only be used by + * library clients looking to make use of wimlib's compression code for another + * purpose. + * + * As of wimlib v1.6.0, this function can be used with @p chunk_size greater + * than 32768 bytes and is only limited by available memory. However, the + * XPRESS format itself still caps match offsets to 65535, so if a larger chunk + * size is chosen, then the matching will effectively occur in a sliding window + * over it. + * + * @param chunk + * Uncompressed data of the chunk. + * @param chunk_size + * Size of the uncompressed chunk, in bytes. + * @param out + * Pointer to output buffer of size at least (@p chunk_size - 1) bytes. + * + * @return + * The size of the compressed data written to @p out in bytes, or 0 if the + * data could not be compressed to (@p chunk_size - 1) bytes or fewer. */ extern unsigned wimlib_xpress_compress(const void *chunk, unsigned chunk_size, void *out); @@ -3654,8 +4061,26 @@ wimlib_xpress_compress(const void *chunk, unsigned chunk_size, void *out); /** * @ingroup G_compression * - * This function is equivalent to wimlib_lzx_decompress(), but instead assumes - * the data is compressed using "XPRESS" compression. + * Decompresses a chunk of XPRESS-compressed data. + * + * This function is exported for convenience only and should only be used by + * library clients looking to make use of wimlib's compression code for another + * purpose. + * + * @param compressed_data + * Pointer to the compressed data. + * + * @param compressed_len + * Length of the compressed data, in bytes. + * + * @param uncompressed_data + * Pointer to the buffer into which to write the uncompressed data. + * + * @param uncompressed_len + * Length of the uncompressed data. + * + * @return + * 0 on success; non-zero on failure. */ extern int wimlib_xpress_decompress(const void *compressed_data, unsigned compressed_len,