├── .clang-format ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── COPYING ├── COPYING.GPLv3 ├── COPYING.LGPLv3 ├── Makefile.am ├── NEWS.md ├── README.WINDOWS.md ├── README.md ├── bootstrap ├── build-aux └── config.rpath ├── configure.ac ├── doc ├── Doxyfile.in └── man1 │ ├── mkwinpeimg.1 │ ├── wimappend.1 │ ├── wimapply.1 │ ├── wimcapture.1 │ ├── wimdelete.1 │ ├── wimdir.1 │ ├── wimexport.1 │ ├── wimextract.1 │ ├── wiminfo.1 │ ├── wimjoin.1 │ ├── wimlib-imagex.1 │ ├── wimmount.1 │ ├── wimmountrw.1 │ ├── wimoptimize.1 │ ├── wimsplit.1 │ ├── wimunmount.1 │ ├── wimupdate.1 │ └── wimverify.1 ├── examples ├── Makefile ├── README ├── applywim.c ├── capturewim.c ├── compressfile.c ├── decompressfile.c └── updatewim.c ├── include ├── wimlib.h ├── wimlib │ ├── alloca.h │ ├── apply.h │ ├── assert.h │ ├── avl_tree.h │ ├── bitops.h │ ├── blob_table.h │ ├── bt_matchfinder.h │ ├── case.h │ ├── chunk_compressor.h │ ├── compiler.h │ ├── compress_common.h │ ├── compressor_ops.h │ ├── cpu_features.h │ ├── decompress_common.h │ ├── decompressor_ops.h │ ├── dentry.h │ ├── divsufsort.h │ ├── encoding.h │ ├── endianness.h │ ├── error.h │ ├── file_io.h │ ├── glob.h │ ├── guid.h │ ├── hc_matchfinder.h │ ├── header.h │ ├── inode.h │ ├── inode_table.h │ ├── integrity.h │ ├── lcpit_matchfinder.h │ ├── list.h │ ├── lzms_common.h │ ├── lzms_constants.h │ ├── lzx_common.h │ ├── lzx_constants.h │ ├── matchfinder_common.h │ ├── metadata.h │ ├── ntfs_3g.h │ ├── object_id.h │ ├── pathlist.h │ ├── paths.h │ ├── pattern.h │ ├── progress.h │ ├── registry.h │ ├── reparse.h │ ├── resource.h │ ├── scan.h │ ├── security.h │ ├── security_descriptor.h │ ├── sha1.h │ ├── solid.h │ ├── tagged_items.h │ ├── test_support.h │ ├── textfile.h │ ├── threads.h │ ├── timestamp.h │ ├── types.h │ ├── unaligned.h │ ├── unix_data.h │ ├── util.h │ ├── wim.h │ ├── wimboot.h │ ├── win32.h │ ├── win32_common.h │ ├── win32_vss.h │ ├── wof.h │ ├── write.h │ ├── xattr.h │ ├── xml.h │ ├── xml_windows.h │ ├── xmlproc.h │ └── xpress_constants.h └── wimlib_tchar.h ├── m4 └── ax_pthread.m4 ├── programs ├── imagex-win32.c ├── imagex-win32.h ├── imagex.c ├── mkwinpeimg.in ├── wgetopt.c └── wgetopt.h ├── src ├── add_image.c ├── avl_tree.c ├── blob_table.c ├── compress.c ├── compress_common.c ├── compress_parallel.c ├── compress_serial.c ├── cpu_features.c ├── decompress.c ├── decompress_common.c ├── delete_image.c ├── dentry.c ├── divsufsort.c ├── encoding.c ├── error.c ├── export_image.c ├── extract.c ├── file_io.c ├── header.c ├── inode.c ├── inode_fixup.c ├── inode_table.c ├── integrity.c ├── iterate_dir.c ├── join.c ├── lcpit_matchfinder.c ├── lzms_common.c ├── lzms_compress.c ├── lzms_decompress.c ├── lzx_common.c ├── lzx_compress.c ├── lzx_decompress.c ├── metadata_resource.c ├── mount_image.c ├── ntfs-3g_apply.c ├── ntfs-3g_capture.c ├── pathlist.c ├── paths.c ├── pattern.c ├── progress.c ├── reference.c ├── registry.c ├── reparse.c ├── resource.c ├── scan.c ├── security.c ├── sha1.c ├── solid.c ├── split.c ├── tagged_items.c ├── template.c ├── test_support.c ├── textfile.c ├── threads.c ├── timestamp.c ├── unix_apply.c ├── unix_capture.c ├── update_image.c ├── util.c ├── verify.c ├── wim.c ├── wimboot.c ├── win32_apply.c ├── win32_capture.c ├── win32_common.c ├── win32_replacements.c ├── win32_vss.c ├── write.c ├── xml.c ├── xml_windows.c ├── xmlproc.c ├── xpress_compress.c └── xpress_decompress.c ├── tests ├── common_tests.sh ├── exclusionlists │ ├── anchored_exception_in_excluded_dir │ ├── anchored_prefix_match │ ├── anchored_simple │ ├── case_insensitive │ ├── case_sensitive │ ├── inner_star │ ├── multiple_stars │ ├── prefix_match │ ├── question_mark │ ├── recursive_match │ ├── simple_exception │ ├── suffix_match │ └── wildcard_exception ├── security_descriptor_1.base64 ├── security_descriptor_1.bin ├── security_descriptor_2.base64 ├── security_descriptor_2.bin ├── set_reparse_point.c ├── test-imagex ├── test-imagex-capture_and_apply ├── test-imagex-mount ├── test-imagex-ntfs ├── test-imagex-update_and_extract ├── test_utils.sh ├── tree-cmp.c ├── wims │ ├── README │ ├── corrupted_file_1.wim │ ├── corrupted_file_2.wim │ ├── cyclic.wim │ ├── dotdot.wim │ ├── duplicate_names.wim │ ├── empty_dacl.wim │ ├── linux_xattrs_old.wim │ └── longpaths.wim ├── win32-test-imagex-capture_and_apply.bat ├── win32-test-imagex-capture_and_apply.sh ├── win32-tree-cmp.c └── wlfuzz.c ├── tools ├── compress_upcase_table.c ├── generate_language_id_map.c ├── get-version-number.sh ├── libFuzzer │ ├── compress │ │ ├── corpus │ │ │ ├── lzms20 │ │ │ ├── lzms50 │ │ │ ├── lzms80 │ │ │ ├── lzx20 │ │ │ ├── lzx50 │ │ │ ├── lzx80 │ │ │ ├── xpress20 │ │ │ ├── xpress50 │ │ │ └── xpress80 │ │ └── fuzz.c │ ├── decompress │ │ ├── corpus │ │ │ ├── lzms │ │ │ ├── lzx │ │ │ └── xpress │ │ └── fuzz.c │ ├── encoding │ │ ├── corpus │ │ │ ├── 0 │ │ │ └── 1 │ │ └── fuzz.c │ ├── fault-injection.c │ ├── fuzz.sh │ ├── fuzzer.h │ ├── test-one-input.c │ ├── wim │ │ ├── corpus │ │ │ └── 0 │ │ └── fuzz.c │ ├── xml_windows │ │ ├── corpus │ │ │ ├── dll │ │ │ └── registry │ │ └── fuzz.c │ └── xmlproc │ │ ├── corpus │ │ └── 0 │ │ └── fuzz.c ├── log2_interpolation.r ├── make-releases.sh ├── msvc-test-examples.bat ├── ntfs_fragreport.c ├── repack-windows-release.sh ├── run-sparse.sh ├── run_compression_benchmarks.c ├── test-examples.sh ├── update-version.sh ├── wimgapi_wrapper.h └── windows-build.sh └── wimlib.pc.in /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | AllowShortFunctionsOnASingleLine: false 3 | AllowShortIfStatementsOnASingleLine: false 4 | AlignConsecutiveMacros: Consecutive 5 | AlwaysBreakAfterReturnType: All 6 | BreakBeforeBraces: Linux 7 | Cpp11BracedListStyle: false 8 | ForEachMacros: 9 | - 'avl_tree_for_each_in_order' 10 | - 'avl_tree_for_each_in_postorder' 11 | - 'avl_tree_for_each_in_reverse_order' 12 | - 'dentry_for_each_ci_match' 13 | - 'for_dentry_child' 14 | - 'for_dentry_child_postorder' 15 | - 'for_inode_child' 16 | - 'for_inode_child_postorder' 17 | - 'hlist_for_each_entry' 18 | - 'hlist_for_each_entry_safe' 19 | - 'image_for_each_inode' 20 | - 'image_for_each_inode_safe' 21 | - 'image_for_each_unhashed_blob' 22 | - 'image_for_each_unhashed_blob_safe' 23 | - 'inode_for_each_dentry' 24 | - 'inode_for_each_extraction_alias' 25 | - 'list_for_each' 26 | - 'list_for_each_entry' 27 | - 'list_for_each_entry_reverse' 28 | - 'list_for_each_entry_safe' 29 | - 'xml_node_for_each_child' 30 | IncludeBlocks: Preserve 31 | IndentCaseLabels: false 32 | IndentWidth: 8 33 | SpaceBeforeParens: ControlStatementsExceptControlMacros 34 | UseTab: Always 35 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Do not mess with line endings 2 | * -text 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.lo 2 | *.o 3 | .deps 4 | .dirstamp 5 | .libs 6 | 7 | /Makefile 8 | /Makefile.in 9 | /aclocal.m4 10 | /autom4te.cache/ 11 | /bin/ 12 | /build-aux/ar-lib 13 | /build-aux/compile 14 | /build-aux/config.guess 15 | /build-aux/config.sub 16 | /build-aux/depcomp 17 | /build-aux/install-sh 18 | /build-aux/ltmain.sh 19 | /build-aux/missing 20 | /build-aux/test-driver 21 | /config.h 22 | /config.h.in 23 | /config.h.in~ 24 | /config.log 25 | /config.status 26 | /configure 27 | /configure~ 28 | /cscope.* 29 | /doc/Doxyfile 30 | /doc/html/ 31 | /doc/man1/*.html 32 | /libtool 33 | /libwim.la 34 | /m4/libtool.m4 35 | /m4/ltoptions.m4 36 | /m4/ltsugar.m4 37 | /m4/ltversion.m4 38 | /m4/lt~obsolete.m4 39 | /programs/mkwinpeimg 40 | /stamp-h1 41 | /tags 42 | /test-suite.log 43 | /tests/*.log 44 | /tests/*.trs 45 | /tests/tree-cmp 46 | /tests/wlfuzz 47 | /tests/wlfuzz.exe 48 | /tools/libFuzzer/*/fuzz 49 | /tools/libFuzzer/test-one-input 50 | /wimlib-*-bin/ 51 | /wimlib-*.tar 52 | /wimlib-*.tar.* 53 | /wimlib-*.zip 54 | /wimlib-imagex 55 | /wimlib-imagex.exe 56 | /wimlib.pc 57 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | wimlib (meaning all programs, scripts, libraries, documentation, and other files 2 | that are part of the wimlib project -- not just the "libwim" library) may be 3 | redistributed and/or modified under the terms of the GNU General Public License; 4 | either version 3 of the License, or (at your option) any later version. A copy 5 | of this license can be found in the file COPYING.GPLv3. 6 | 7 | Also, when not prohibited by a third-party software license, libwim (the library 8 | portion of wimlib) may be redistributed and/or modified under the terms of the 9 | GNU Lesser General Public License; either version 3 of the License, or (at your 10 | option) any later version. A copy of this license can be found in the file 11 | COPYING.LGPLv3. This is offered as a "dual license", meaning that you can 12 | choose either this LGPLv3+ option or the above-mentioned GPLv3+ option. 13 | 14 | In either case there is NO WARRANTY, to the extent permitted by law. 15 | 16 | -------------------------------------------------------------------------------- 17 | 18 | NOTE! The reason for the "when not prohibited by a third-party software license" 19 | condition on the LGPL option for libwim is that libwim can optionally be linked 20 | to the third-party library "libntfs-3g", which is licensed under the GPL. 21 | Usually the GPL is interpreted in a way that means that any binary that uses a 22 | GPL library must be licensed under the GPL as well, not (for example) the LGPL. 23 | 24 | Therefore, if your build of libwim links to libntfs-3g, then you can't choose 25 | the LGPL option. You may choose the LGPL option for Windows builds of libwim, 26 | since they don't link to libntfs-3g. Likewise, you may choose the LGPL option 27 | for UNIX builds of libwim that were built with './configure --without-ntfs-3g'. 28 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | autoreconf -i 4 | -------------------------------------------------------------------------------- /build-aux/config.rpath: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/build-aux/config.rpath -------------------------------------------------------------------------------- /doc/Doxyfile.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = wimlib 2 | OUTPUT_DIRECTORY = . 3 | EXTRACT_ALL = YES 4 | EXTRACT_LOCAL_CLASSES = YES 5 | HIDE_UNDOC_MEMBERS = YES 6 | SHOW_INCLUDE_FILES = YES 7 | JAVADOC_AUTOBRIEF = YES 8 | OPTIMIZE_OUTPUT_FOR_C = YES 9 | SHOW_USED_FILES = YES 10 | INPUT = @top_srcdir@/include/wimlib.h 11 | FULL_PATH_NAMES = NO 12 | OPTIMIZE_FOR_C = YES 13 | GENERATE_HTML = YES 14 | HTML_OUTPUT = html 15 | HTML_FILE_EXTENSION = .html 16 | HTML_TIMESTAMP = NO 17 | GENERATE_HTMLHELP = NO 18 | GENERATE_LATEX = NO 19 | GENERATE_RTF = NO 20 | GENERATE_MAN = NO 21 | GENERATE_XML = NO 22 | GENERATE_AUTOGEN_DEF = NO 23 | CLASS_DIAGRAMS = NO 24 | SORT_MEMBER_DOCS = NO 25 | -------------------------------------------------------------------------------- /doc/man1/wimappend.1: -------------------------------------------------------------------------------- 1 | .so man1/wimcapture.1 2 | -------------------------------------------------------------------------------- /doc/man1/wimdelete.1: -------------------------------------------------------------------------------- 1 | .TH WIMDELETE "1" "February 2024" "wimlib 1.14.4" "User Commands" 2 | .SH NAME 3 | wimdelete \- Delete an image from a WIM archive 4 | .SH SYNOPSIS 5 | \fBwimdelete\fR \fIWIMFILE\fR \fIIMAGE\fR [\fIOPTION\fR...] 6 | .SH DESCRIPTION 7 | \fBwimdelete\fR, or equivalently \fBwimlib-imagex delete\fR, deletes the 8 | specified image from the Windows Imaging (WIM) archive \fIWIMFILE\fR. 9 | .PP 10 | \fIIMAGE\fR specifies the WIM image in \fIWIMFILE\fR to delete. It may be the 11 | 1-based index of an image, the name of an image, or the keyword "all" to specify 12 | all images. You can use \fBwiminfo\fR(1) to list the images contained in 13 | \fIWIMFILE\fR. 14 | .SH NOTES 15 | By default, \fBwimdelete\fR rebuilds the WIM with all unnecessary file data 16 | removed. This is different from Microsoft's ImageX and DISM, which only will 17 | delete the directory tree metadata and XML data for this operation. Use 18 | \fB--soft\fR if you want the other kind of delete. 19 | .PP 20 | wimlib allows you to delete all the images from a WIM and have a WIM with 0 21 | images, although such a file may not be very useful. 22 | .PP 23 | \fBwimdelete\fR does not support split WIMs. 24 | .SH OPTIONS 25 | .TP 6 26 | \fB--check\fR 27 | Before deleting the image, verify the WIM's integrity if extra integrity 28 | information is present. In addition, include extra integrity information in the 29 | modified WIM, even if it was not present before. 30 | .TP 31 | \fB--include-integrity\fR 32 | Include extra integrity information in the modified WIM, i.e. like \fB--check\fR 33 | but don't do any verification beforehand. 34 | .TP 35 | \fB--soft\fR 36 | Perform a "soft delete". Specifying this flag overrides the default behavior of 37 | rebuilding the entire WIM after deleting an image. Instead, only minimal 38 | changes to correctly remove the image from the WIM will be taken. In 39 | particular, all file resources will be left alone, even if they are no longer 40 | referenced. This may not be what you want, because no space will be saved by 41 | deleting an image in this way. However, \fBwimoptimize\fR can later be used to 42 | rebuild a WIM file that has had images soft-deleted from it. 43 | .TP 44 | \fB--unsafe-compact\fR 45 | Compact the WIM archive in-place, eliminating "holes". This is efficient, but 46 | in general this option should \fInot\fR be used because a failed or interrupted 47 | compaction will corrupt the WIM archive. For more information, see the 48 | documentation for this option to \fBwimoptimize\fR(1). 49 | .SH EXAMPLES 50 | Delete the first image from 'boot.wim': 51 | .RS 52 | .PP 53 | wimdelete boot.wim 1 54 | .RE 55 | .PP 56 | .SH SEE ALSO 57 | .BR wimlib-imagex (1) 58 | .BR wiminfo (1) 59 | .BR wimoptimize (1) 60 | -------------------------------------------------------------------------------- /doc/man1/wimdir.1: -------------------------------------------------------------------------------- 1 | .TH WIMDIR "1" "February 2024" "wimlib 1.14.4" "User Commands" 2 | .SH NAME 3 | wimdir \- List the files contained in a WIM image 4 | .SH SYNOPSIS 5 | \fBwimdir\fR \fIWIMFILE\fR [\fIIMAGE\fR] [\fIOPTION\fR...] 6 | .SH DESCRIPTION 7 | \fBwimdir\fR, or equivalently \fBwimlib-imagex dir\fR, lists the files and 8 | directories contained in the specified image of the Windows Imaging (WIM) 9 | archive \fIWIMFILE\fR. 10 | .PP 11 | \fIIMAGE\fR specifies the image in \fIWIMFILE\fR to list. It may be the 1-based 12 | index of an image, the name of an image, or the keyword "all" to specify all 13 | images. It may be omitted if \fBWIMFILE\fR contains only one image. You can 14 | use \fBwiminfo\fR(1) to list the images contained in \fIWIMFILE\fR. 15 | .SH OPTIONS 16 | .TP 6 17 | \fB--path\fR=\fIPATH\fR 18 | List the files under \fIPATH\fR instead of under the root directory. 19 | .TP 20 | \fB--detailed\fR 21 | List detailed information about each file. 22 | .TP 23 | \fB--one-file-only\fR 24 | List information about the specified file only. Intended for use with both 25 | \fB--path\fR and \fB--detailed\fR. 26 | .TP 27 | \fB--ref\fR="\fIGLOB\fR" 28 | File glob of additional WIMs or split WIM parts to reference resources from. 29 | This option can be specified multiple times. This option is only useful when 30 | \fB--detailed\fR is also specified. 31 | .SH NOTES 32 | \fBwimdir\fR supports split WIMs, but it only works on the first part of the 33 | split WIM. 34 | .PP 35 | Detailed metadata such as timestamps and data streams is not shown unless the 36 | \fB--detailed\fR option is used. 37 | .SH EXAMPLES 38 | List all files and directories in the first image of 'boot.wim': 39 | .RS 40 | .PP 41 | wimdir boot.wim 1 42 | .RE 43 | .PP 44 | .SH SEE ALSO 45 | .BR wimlib-imagex (1) 46 | .BR wiminfo (1) 47 | -------------------------------------------------------------------------------- /doc/man1/wiminfo.1: -------------------------------------------------------------------------------- 1 | .TH WIMINFO "1" "February 2024" "wimlib 1.14.4" "User Commands" 2 | .SH NAME 3 | wiminfo \- Display or change information about a WIM file or image 4 | .SH SYNOPSIS 5 | \fBwiminfo\fR \fIWIMFILE\fR [\fIIMAGE\fR [\fINEW_NAME\fR [\fINEW_DESC\fR]]] [\fIOPTION\fR...] 6 | .SH DESCRIPTION 7 | \fBwiminfo\fR, or equivalently \fBwimlib-imagex info\fR, displays information 8 | about \fIWIMFILE\fR or the specified \fIIMAGE\fR in it, and optionally changes 9 | properties of \fIIMAGE\fR such as its name and description, or changes the 10 | bootable image of the WIM. 11 | .PP 12 | If neither an image nor any flags other than \fB--check\fR are specified, then 13 | basic information about the WIM and the images contained in it is shown. If an 14 | image is specified by \fIIMAGE\fR (as a 1-based image index or an image name), 15 | then the information is restricted to that concerning the specified image. 16 | .PP 17 | Changes to the WIM are made if \fINEW_NAME\fR and/or \fB--boot\fR and/or 18 | \fB--image-property\fR are specified. \fINEW_NAME\fR is taken to be the new 19 | name of the image specified by \fIIMAGE\fR while \fINEW_DESC\fR is taken to be 20 | its new description. If \fINEW_DESC\fR is not specified, then the image's 21 | description is not changed. 22 | .PP 23 | \fBwiminfo\fR does not support modifying a split WIM, although you may display 24 | information about one, including any of its parts. 25 | .SH OPTIONS 26 | .TP 6 27 | \fB--boot\fR 28 | Mark the specified \fIIMAGE\fR as the "bootable" image of the WIM. The 29 | "bootable" image is the image which the Windows bootloader will use when loading 30 | Windows PE from the WIM. 31 | .TP 32 | \fB--check\fR 33 | Verify the integrity of WIM if it contains extra integrity information. In 34 | addition, if modifying the WIM, add extra integrity information if it was not 35 | present before. 36 | .TP 37 | \fB--nocheck\fR 38 | If modifying the WIM, remove its extra integrity information, if it had any. 39 | .TP 40 | \fB--include-integrity\fR 41 | If modifying the WIM, add extra integrity information if it was not present 42 | before, i.e. like \fB--check\fR but don't also do the verification beforehand. 43 | .TP 44 | \fB--image-property\fR \fINAME\fR=\fIVALUE\fR 45 | Assign an arbitrary property to the specified \fIIMAGE\fR in the XML document of 46 | the WIM. \fINAME\fR is an element path such as "WINDOWS/VERSION/MAJOR", and 47 | \fIVALUE\fR is the string to place in the element, such as "10". See the 48 | documentation for this option to \fBwimcapture\fR(1) for more details. This 49 | option may be specified multiple times. 50 | .TP 51 | \fB--header\fR 52 | Show detailed information from the WIM header. 53 | .TP 54 | \fB--blobs\fR 55 | List all the "blobs" (unique file data) in the WIM. 56 | .TP 57 | \fB--extract-xml\fR=\fIFILE\fR 58 | Extract the WIM's raw XML document to \fIFILE\fR. 59 | .TP 60 | \fB--xml\fR 61 | .br 62 | Extract the WIM's raw XML document to standard output. 63 | .SH SEE ALSO 64 | .BR wimlib-imagex (1) 65 | .BR wimdir (1) 66 | -------------------------------------------------------------------------------- /doc/man1/wimjoin.1: -------------------------------------------------------------------------------- 1 | .TH WIMJOIN "1" "February 2024" "wimlib 1.14.4" "User Commands" 2 | .SH NAME 3 | wimjoin\- Join a split WIM into a standalone WIM 4 | .SH SYNOPSIS 5 | \fBwimjoin\fR [\fIOPTION\fR...] \fIOUT_WIMFILE\fR \fISPLIT_WIM_PART\fR... 6 | .SH DESCRIPTION 7 | \fBwimjoin\fR, or equivalently \fBwimlib-imagex join\fR, joins the 8 | \fISPLIT_WIM_PARTs\fR into a standalone (one-part) WIM \fIOUT_WIMFILE\fR. All 9 | parts of the split WIM must be specified; you probably want to do so using a 10 | shell wildcard. 11 | .SH OPTIONS 12 | .TP 6 13 | \fB--check\fR 14 | When reading each \fISPLIT_WIM_PART\fR, verify its integrity if it contains 15 | extra integrity information. In addition, include extra integrity information 16 | in \fIOUT_WIMFILE\fR, even if the split WIM parts did not contain this 17 | information. 18 | .TP 19 | \fB--include-integrity\fR 20 | Include extra integrity information in \fIOUT_WIMFILE\fR, i.e. like 21 | \fB--check\fR but don't also verify the split WIM parts beforehand. 22 | .SH EXAMPLES 23 | Join a split WIM, with the parts named `windows*.swm' where the * is anything 24 | (usually the number of the part, except for the first part which may have no 25 | number), and write the joined WIM to the file `windows.wim'. 26 | .RS 27 | .PP 28 | wimjoin windows.wim windows*.swm 29 | .RE 30 | .SH NOTES 31 | Both non-pipable and pipable split WIMs may be joined. 32 | .PP 33 | \fBwimjoin\fR is roughly equivalent to: 34 | .RS 35 | .PP 36 | \fBwimexport\fR \fISWM_PART_1\fR --ref="\fISWM_GLOB\fR" all \fIOUT_WIMFILE\fR 37 | .RE 38 | .SH SEE ALSO 39 | .BR wimlib-imagex (1) 40 | .BR wimexport (1) 41 | .BR wimsplit (1) 42 | -------------------------------------------------------------------------------- /doc/man1/wimmountrw.1: -------------------------------------------------------------------------------- 1 | .so man1/wimmount.1 2 | -------------------------------------------------------------------------------- /doc/man1/wimsplit.1: -------------------------------------------------------------------------------- 1 | .TH WIMSPLIT "1" "February 2024" "wimlib 1.14.4" "User Commands" 2 | .SH NAME 3 | wimsplit \- Split a WIM archive into multiple parts 4 | .SH SYNOPSIS 5 | \fBwimsplit\fR \fIWIMFILE\fR \fISPLIT_WIM_PART_1\fR \fIPART_SIZE\fR [\fIOPTION...\fR] 6 | .SH DESCRIPTION 7 | \fBwimsplit\fR, or equivalently \fBwimlib-imagex split\fR, splits \fIWIMFILE\fR 8 | into parts with size at most \fIPART_SIZE\fR mebibytes (power-of-2 megabytes), 9 | with the first part having the name \fISPLIT_WIM_PART_1\fR and the other parts 10 | having names numbered in order of the parts. 11 | .PP 12 | \fBwimsplit\fR can split both non-pipable and pipable WIMs. 13 | .SH OPTIONS 14 | .TP 6 15 | \fB--check\fR 16 | Before splitting the WIM, verify its integrity if it contains extra integrity 17 | information. Also include extra integrity information in each split WIM part, 18 | even if \fIWIMFILE\fR did not contain it. 19 | .TP 20 | \fB--include-integrity\fR 21 | Include extra integrity information in each split WIM part, i.e. like 22 | \fB--check\fR but don't also verify \fIWIMFILE\fR beforehand. 23 | .SH EXAMPLES 24 | Splits the WIM 'windows.wim' into 'windows.swm', 'windows2.swm', 'windows3.swm', 25 | etc. where each part is at most 100 MiB: 26 | .RS 27 | .PP 28 | wimsplit windows.wim windows.swm 100 29 | .RE 30 | .SH LIMITATIONS 31 | It is possible for the size of the parts to exceed the \fIPART_SIZE\fR given. 32 | This is impossible to avoid because the WIM file format provides no way to 33 | divide a single file resource among multiple split WIM parts. So if you, for 34 | example, have a file inside the WIM that is 100 MiB compressed, then the split 35 | WIM will have at least one part that is 100 MiB in size to contain that file. 36 | .SH SEE ALSO 37 | .BR wimlib-imagex (1) 38 | .BR wimjoin (1) 39 | -------------------------------------------------------------------------------- /doc/man1/wimunmount.1: -------------------------------------------------------------------------------- 1 | .so man1/wimmount.1 2 | -------------------------------------------------------------------------------- /doc/man1/wimverify.1: -------------------------------------------------------------------------------- 1 | .TH WIMVERIFY "1" "February 2024" "wimlib 1.14.4" "User Commands" 2 | .SH NAME 3 | wimverify \- Verify a WIM archive 4 | .SH SYNOPSIS 5 | \fBwimverify\fR \fIWIMFILE\fR [\fIOPTION\fR...] 6 | .SH DESCRIPTION 7 | \fBwimverify\fR (or equivalently \fBwimlib-imagex verify\fR) checks the validity 8 | and integrity of the specified WIM archive. 9 | .PP 10 | Specifically, this command performs the following verifications on the WIM: 11 | .IP \[bu] 4 12 | Verify that the WIM can be successfully opened, which involves parsing the 13 | header, blob table, and XML data. 14 | .IP \[bu] 15 | If the WIM contains extra integrity information, verify the integrity of the 16 | entire WIM. 17 | .IP \[bu] 18 | Verify that the metadata for each image in the WIM can be successfully parsed. 19 | .IP \[bu] 20 | Verify that all files needed by each image are actually contained in the WIM or 21 | in one of the WIMs referenced by the \fB--ref\fR option. 22 | .IP \[bu] 23 | Verify that all files contained in the WIM can be successfully decompressed, 24 | with matching checksums. 25 | .SH OPTIONS 26 | .TP 6 27 | \fB--ref\fR="\fIGLOB\fR" 28 | File glob of additional WIMs or split WIM parts to reference resources from. 29 | This option can be specified multiple times. Note: \fIGLOB\fR is listed in 30 | quotes because it is interpreted by \fBwimverify\fR and may need to be quoted to 31 | protect against shell expansion. 32 | .TP 33 | \fB--nocheck\fR 34 | Do not verify the WIM's integrity using the extra integrity information (the 35 | integrity table). 36 | .SH NOTES 37 | \fBwimverify\fR is a read-only operation; it does not modify the WIM file. 38 | .PP 39 | Even if the WIM does not contain extra integrity information (e.g. generated 40 | with the \fB--check\fR option to \fBwimcapture\fR), \fBwimverify\fR may still be 41 | quite useful because all file data is still checksummed. 42 | .PP 43 | In the future, \fBwimverify\fR might do more thorough verifications than it does 44 | now. 45 | .SH EXAMPLES 46 | Verify the WIM file 'boot.wim': 47 | .RS 48 | .PP 49 | wimverify boot.wim 50 | .RE 51 | .PP 52 | Verify the split WIM file consisting of 'boot.swm', 'boot2.swm', 'boot3.swm', ...: 53 | .RS 54 | .PP 55 | wimverify boot.swm --ref="boot*.swm" 56 | .RE 57 | .PP 58 | .SH SEE ALSO 59 | .BR wimlib-imagex (1) 60 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS := -Wall 2 | LDLIBS := -lwim 3 | 4 | EXE := applywim capturewim updatewim compressfile decompressfile 5 | 6 | all:$(EXE) 7 | 8 | clean: 9 | rm -f $(EXE) 10 | 11 | .PHONY: all clean 12 | -------------------------------------------------------------------------------- /examples/README: -------------------------------------------------------------------------------- 1 | This directory shows some simple examples of C programs that use wimlib. 2 | See programs/imagex.c for a more complete example. 3 | -------------------------------------------------------------------------------- /examples/applywim.c: -------------------------------------------------------------------------------- 1 | /* 2 | * applywim.c - A program to extract the first image from a WIM file. 3 | * 4 | * Copyright 2022 Eric Biggers 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | /* 32 | * Windows compatibility defines for string encoding. Applications using wimlib 33 | * that need to run on both UNIX and Windows will need to do something similar 34 | * to this, whereas applications that only need to run on one or the other can 35 | * just use their platform's convention directly. 36 | */ 37 | #ifdef _WIN32 38 | # define main wmain 39 | typedef wchar_t tchar; 40 | # define TS "ls" 41 | #else 42 | typedef char tchar; 43 | # define TS "s" 44 | #endif 45 | 46 | #define TO_PERCENT(numerator, denominator) \ 47 | ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator)))) 48 | 49 | static enum wimlib_progress_status 50 | extract_progress(enum wimlib_progress_msg msg, 51 | union wimlib_progress_info *info, void *progctx) 52 | { 53 | switch (msg) { 54 | case WIMLIB_PROGRESS_MSG_EXTRACT_STREAMS: 55 | printf("Extracting files: %.2f%% complete\n", 56 | TO_PERCENT(info->extract.completed_bytes, 57 | info->extract.total_bytes)); 58 | break; 59 | default: 60 | break; 61 | } 62 | return WIMLIB_PROGRESS_STATUS_CONTINUE; 63 | } 64 | 65 | int main(int argc, tchar **argv) 66 | { 67 | int ret; 68 | WIMStruct *wim = NULL; 69 | const tchar *wimpath; 70 | const tchar *destdir; 71 | 72 | /* Check for the correct number of arguments. */ 73 | if (argc != 3) { 74 | fprintf(stderr, "Usage: applywim WIM DIR\n"); 75 | return 2; 76 | } 77 | 78 | wimpath = argv[1]; 79 | destdir = argv[2]; 80 | 81 | /* Open the WIM file as a WIMStruct. */ 82 | ret = wimlib_open_wim(wimpath, /* Path of WIM file to open */ 83 | 0, /* WIMLIB_OPEN_FLAG_* flags (0 means all defaults) */ 84 | &wim); /* Return the WIMStruct pointer in this location */ 85 | if (ret != 0) /* Always should check the error codes. */ 86 | goto out; 87 | 88 | /* Register our progress function. */ 89 | wimlib_register_progress_function(wim, extract_progress, NULL); 90 | 91 | /* Extract the first image. */ 92 | ret = wimlib_extract_image(wim, /* WIMStruct from which to extract the image */ 93 | 1, /* Image to extract */ 94 | destdir, /* Directory to extract the image to */ 95 | 0); /* WIMLIB_EXTRACT_FLAG_* flags (0 means all defaults) */ 96 | 97 | out: 98 | /* Free the WIMStruct. Has no effect if the pointer to it is NULL. */ 99 | wimlib_free(wim); 100 | 101 | /* Check for error status. */ 102 | if (ret != 0) { 103 | fprintf(stderr, "wimlib error %d: %" TS"\n", 104 | ret, wimlib_get_error_string((enum wimlib_error_code)ret)); 105 | } 106 | 107 | /* Free global memory (optional). */ 108 | wimlib_global_cleanup(); 109 | 110 | return ret; 111 | } 112 | -------------------------------------------------------------------------------- /examples/capturewim.c: -------------------------------------------------------------------------------- 1 | /* 2 | * capturewim.c - A program to capture a directory tree into a WIM file. 3 | * 4 | * Copyright 2022 Eric Biggers 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | /* 32 | * Windows compatibility defines for string encoding. Applications using wimlib 33 | * that need to run on both UNIX and Windows will need to do something similar 34 | * to this, whereas applications that only need to run on one or the other can 35 | * just use their platform's convention directly. 36 | */ 37 | #ifdef _WIN32 38 | # define main wmain 39 | typedef wchar_t tchar; 40 | # define TS "ls" 41 | #else 42 | typedef char tchar; 43 | # define TS "s" 44 | #endif 45 | 46 | #define TO_PERCENT(numerator, denominator) \ 47 | ((float)(((denominator) == 0) ? 0 : ((numerator) * 100 / (float)(denominator)))) 48 | 49 | static enum wimlib_progress_status 50 | write_progress(enum wimlib_progress_msg msg, 51 | union wimlib_progress_info *info, void *progctx) 52 | { 53 | switch (msg) { 54 | case WIMLIB_PROGRESS_MSG_WRITE_STREAMS: 55 | printf("Writing WIM: %.2f%% complete\n", 56 | TO_PERCENT(info->write_streams.completed_bytes, 57 | info->write_streams.total_bytes)); 58 | break; 59 | default: 60 | break; 61 | } 62 | return WIMLIB_PROGRESS_STATUS_CONTINUE; 63 | } 64 | 65 | int main(int argc, tchar **argv) 66 | { 67 | int ret; 68 | WIMStruct *wim = NULL; 69 | const tchar *srcdir; 70 | const tchar *wimpath; 71 | 72 | /* Check for the correct number of arguments. */ 73 | if (argc != 3) { 74 | fprintf(stderr, "Usage: capturewim DIR WIM\n"); 75 | return 2; 76 | } 77 | 78 | srcdir = argv[1]; 79 | wimpath = argv[2]; 80 | 81 | /* Create a WIMStruct for a WIM. */ 82 | ret = wimlib_create_new_wim(WIMLIB_COMPRESSION_TYPE_LZX, &wim); 83 | if (ret != 0) /* Always should check the error codes. */ 84 | goto out; 85 | 86 | /* Register our progress function. */ 87 | wimlib_register_progress_function(wim, write_progress, NULL); 88 | 89 | /* Add the directory tree to the WIMStruct as an image. */ 90 | 91 | ret = wimlib_add_image(wim, /* WIMStruct to which to add the image */ 92 | srcdir, /* Directory from which to add the image */ 93 | NULL, /* Name to give the image (NULL means none) */ 94 | NULL, /* Capture configuration structure (NULL means none) */ 95 | 0); /* WIMLIB_ADD_FLAG_* flags (0 means all defaults) */ 96 | if (ret != 0) 97 | goto out; 98 | 99 | /* Write the WIM file. */ 100 | 101 | ret = wimlib_write(wim, /* WIMStruct from which to write a WIM */ 102 | wimpath, /* Path to write the WIM to */ 103 | WIMLIB_ALL_IMAGES, /* Image(s) in the WIM to write */ 104 | 0, /* WIMLIB_WRITE_FLAG_* flags (0 means all defaults) */ 105 | 0); /* Number of compressor threads (0 means default) */ 106 | 107 | out: 108 | /* Free the WIMStruct. Has no effect if the pointer to it is NULL. */ 109 | wimlib_free(wim); 110 | 111 | /* Check for error status. */ 112 | if (ret != 0) { 113 | fprintf(stderr, "wimlib error %d: %" TS"\n", 114 | ret, wimlib_get_error_string((enum wimlib_error_code)ret)); 115 | } 116 | 117 | /* Free global memory (optional). */ 118 | wimlib_global_cleanup(); 119 | 120 | return ret; 121 | } 122 | -------------------------------------------------------------------------------- /examples/updatewim.c: -------------------------------------------------------------------------------- 1 | /* 2 | * updatewim.c - A program to add a file or directory tree to the first image of 3 | * a WIM file. 4 | * 5 | * Copyright 2022 Eric Biggers 6 | * 7 | * Permission is hereby granted, free of charge, to any person 8 | * obtaining a copy of this software and associated documentation 9 | * files (the "Software"), to deal in the Software without 10 | * restriction, including without limitation the rights to use, 11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the 13 | * Software is furnished to do so, subject to the following 14 | * conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be 17 | * included in all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | * OTHER DEALINGS IN THE SOFTWARE. 27 | */ 28 | 29 | #include 30 | #include 31 | 32 | /* 33 | * Windows compatibility defines for string encoding. Applications using wimlib 34 | * that need to run on both UNIX and Windows will need to do something similar 35 | * to this, whereas applications that only need to run on one or the other can 36 | * just use their platform's convention directly. 37 | */ 38 | #ifdef _WIN32 39 | # define main wmain 40 | typedef wchar_t tchar; 41 | # define TS "ls" 42 | #else 43 | typedef char tchar; 44 | # define TS "s" 45 | #endif 46 | 47 | int main(int argc, tchar **argv) 48 | { 49 | int ret; 50 | tchar *wimfile; 51 | tchar *wim_target_path; 52 | tchar *fs_source_path; 53 | WIMStruct *wim = NULL; 54 | struct wimlib_update_command cmds[1]; 55 | 56 | /* Check for the correct number of arguments. */ 57 | if (argc != 4) { 58 | fprintf(stderr, "Usage: updatewim WIMFILE WIM_PATH EXTERNAL_PATH\n"); 59 | return 2; 60 | } 61 | 62 | wimfile = argv[1]; 63 | wim_target_path = argv[2]; 64 | fs_source_path = argv[3]; 65 | 66 | /* Open the WIM file. */ 67 | ret = wimlib_open_wim(wimfile, 0, &wim); 68 | if (ret != 0) /* Always should check the error codes. */ 69 | goto out; 70 | 71 | /* Update the WIM image. In this simple example, we add a single file 72 | * or directory tree to the specified location in the first image of the 73 | * WIM file, using the default options. 74 | * 75 | * wimlib_add_tree() is actually sufficient for this case, but for the 76 | * sake of demonstration we will use the more general function 77 | * wimlib_update_image(). */ 78 | 79 | memset(cmds, 0, sizeof(cmds)); 80 | 81 | /* Set up an "add" operation. 82 | * 83 | * Other available operations include WIMLIB_UPDATE_OP_RENAME and 84 | * WIMLIB_UPDATE_OP_DELETE. */ 85 | cmds[0].op = WIMLIB_UPDATE_OP_ADD; 86 | 87 | /* Set the arguments to the operation. 88 | * 89 | * Make sure to fill in 'rename' or 'delete_' instead of 'add' if doing 90 | * a rename or delete operation instead! */ 91 | cmds[0].add.wim_target_path = wim_target_path; 92 | cmds[0].add.fs_source_path = fs_source_path; 93 | 94 | /* Note: we don't need to explicitly set 'cmds[0].add.config_file' and 95 | * 'cmds[0].add.add_flags' because we zeroed the 'struct 96 | * wimlib_update_command', and zero means use the defaults. */ 97 | 98 | ret = wimlib_update_image(wim, /* WIMStruct to update */ 99 | 1, /* 1-based index of the image to update */ 100 | cmds, /* Array of command structures */ 101 | 1, /* Number of command structures in array */ 102 | 0); /* WIMLIB_UPDATE_FLAG_* flags (0 for defaults) */ 103 | if (ret != 0) 104 | goto out; 105 | 106 | /* Overwrite the WIM file. 107 | * 108 | * Normally, this will append new data to the file, rather than 109 | * rebuilding the entire file. 110 | * 111 | * Changes do not take effect on-disk until this is done. */ 112 | 113 | ret = wimlib_overwrite(wim, /* WIMStruct to commit to the underlying file */ 114 | 0, /* WIMLIB_WRITE_FLAG_* flags (0 for defaults) */ 115 | 0); /* Number of compressor threads (0 means default) */ 116 | 117 | out: 118 | /* Free the WIMStruct. Has no effect if the pointer to it is NULL. */ 119 | wimlib_free(wim); 120 | 121 | /* Check for error status. */ 122 | if (ret != 0) { 123 | fprintf(stderr, "wimlib error %d: %" TS"\n", 124 | ret, wimlib_get_error_string((enum wimlib_error_code)ret)); 125 | } 126 | 127 | /* Free global memory (optional). */ 128 | wimlib_global_cleanup(); 129 | 130 | return ret; 131 | } 132 | -------------------------------------------------------------------------------- /include/wimlib/alloca.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_ALLOCA_H 2 | #define _WIMLIB_ALLOCA_H 3 | 4 | #ifdef HAVE_ALLOCA_H 5 | # include 6 | #else 7 | # include 8 | #endif 9 | 10 | #endif /* _WIMLIB_ALLOCA_H */ 11 | -------------------------------------------------------------------------------- /include/wimlib/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_ASSERT_H 2 | #define _WIMLIB_ASSERT_H 3 | 4 | #include 5 | #define wimlib_assert(expr) assert(expr) 6 | 7 | #endif /* _WIMLIB_ASSERT_H */ 8 | -------------------------------------------------------------------------------- /include/wimlib/bitops.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bitops.h - inline functions for bit manipulation 3 | * 4 | * Copyright 2022 Eric Biggers 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #ifndef _WIMLIB_BITOPS_H 29 | #define _WIMLIB_BITOPS_H 30 | 31 | #include "wimlib/compiler.h" 32 | #include "wimlib/types.h" 33 | 34 | /* 35 | * Bit Scan Reverse (BSR) - find the 0-based index (relative to the least 36 | * significant bit) of the *most* significant 1 bit in the input value. The 37 | * input value must be nonzero! 38 | */ 39 | 40 | static forceinline unsigned 41 | bsr32(u32 v) 42 | { 43 | return 31 - __builtin_clz(v); 44 | } 45 | 46 | static forceinline unsigned 47 | bsr64(u64 v) 48 | { 49 | return 63 - __builtin_clzll(v); 50 | } 51 | 52 | static forceinline unsigned 53 | bsrw(machine_word_t v) 54 | { 55 | STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64); 56 | if (WORDBITS == 32) 57 | return bsr32(v); 58 | else 59 | return bsr64(v); 60 | } 61 | 62 | /* 63 | * Bit Scan Forward (BSF) - find the 0-based index (relative to the least 64 | * significant bit) of the *least* significant 1 bit in the input value. The 65 | * input value must be nonzero! 66 | */ 67 | 68 | static forceinline unsigned 69 | bsf32(u32 v) 70 | { 71 | return __builtin_ctz(v); 72 | } 73 | 74 | static forceinline unsigned 75 | bsf64(u64 v) 76 | { 77 | return __builtin_ctzll(v); 78 | } 79 | 80 | static forceinline unsigned 81 | bsfw(machine_word_t v) 82 | { 83 | STATIC_ASSERT(WORDBITS == 32 || WORDBITS == 64); 84 | if (WORDBITS == 32) 85 | return bsf32(v); 86 | else 87 | return bsf64(v); 88 | } 89 | 90 | /* Return the log base 2 of 'n', rounded up to the nearest integer. */ 91 | static forceinline unsigned 92 | ilog2_ceil(size_t n) 93 | { 94 | if (n <= 1) 95 | return 0; 96 | return 1 + bsrw(n - 1); 97 | } 98 | 99 | /* Round 'n' up to the nearest power of 2 */ 100 | static forceinline size_t 101 | roundup_pow_of_2(size_t n) 102 | { 103 | return (size_t)1 << ilog2_ceil(n); 104 | } 105 | 106 | #endif /* _WIMLIB_BITOPS_H */ 107 | -------------------------------------------------------------------------------- /include/wimlib/case.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_CASE_H 2 | #define _WIMLIB_CASE_H 3 | 4 | #include 5 | 6 | /* Note: the NTFS-3G headers define CASE_SENSITIVE, hence the WIMLIB prefix. */ 7 | typedef enum { 8 | /* Use either case-sensitive or case-insensitive search, depending on 9 | * the variable @default_ignore_case. */ 10 | WIMLIB_CASE_PLATFORM_DEFAULT = 0, 11 | 12 | /* Use case-sensitive search. */ 13 | WIMLIB_CASE_SENSITIVE = 1, 14 | 15 | /* Use case-insensitive search. */ 16 | WIMLIB_CASE_INSENSITIVE = 2, 17 | } CASE_SENSITIVITY_TYPE; 18 | 19 | extern bool default_ignore_case; 20 | 21 | static inline bool 22 | will_ignore_case(CASE_SENSITIVITY_TYPE case_type) 23 | { 24 | if (case_type == WIMLIB_CASE_SENSITIVE) 25 | return false; 26 | if (case_type == WIMLIB_CASE_INSENSITIVE) 27 | return true; 28 | 29 | return default_ignore_case; 30 | } 31 | 32 | #endif /* _WIMLIB_CASE_H */ 33 | -------------------------------------------------------------------------------- /include/wimlib/chunk_compressor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * chunk_compressor.h 3 | * 4 | * Interface for serial/parallel chunk compression. 5 | */ 6 | 7 | #ifndef _WIMLIB_CHUNK_COMPRESSOR_H 8 | #define _WIMLIB_CHUNK_COMPRESSOR_H 9 | 10 | #include "wimlib/types.h" 11 | 12 | /* Interface for chunk compression. Users can submit chunks of data to be 13 | * compressed, then retrieve them later in order. This interface can be 14 | * implemented either in serial (having the calling thread compress the chunks 15 | * itself) or in parallel (having other threads asynchronously compress the 16 | * chunks). */ 17 | struct chunk_compressor { 18 | /* Variables set by the chunk compressor when it is created. */ 19 | int out_ctype; 20 | u32 out_chunk_size; 21 | unsigned num_threads; 22 | 23 | /* Free the chunk compressor. */ 24 | void (*destroy)(struct chunk_compressor *); 25 | 26 | /* Try to borrow a buffer into which the uncompressed data for the next 27 | * chunk should be prepared. 28 | * 29 | * Only one buffer can be borrowed at a time. 30 | * 31 | * Returns a pointer to the buffer, or NULL if no buffer is available. 32 | * If no buffer is available, you must call ->get_compression_result() 33 | * to retrieve a compressed chunk before trying again. */ 34 | void *(*get_chunk_buffer)(struct chunk_compressor *); 35 | 36 | /* Signals to the chunk compressor that the buffer which was loaned out 37 | * from ->get_chunk_buffer() has finished being filled and contains the 38 | * specified number of bytes of uncompressed data. */ 39 | void (*signal_chunk_filled)(struct chunk_compressor *, u32); 40 | 41 | /* Get the next chunk of compressed data. 42 | * 43 | * The compressed data, along with its size and the size of the original 44 | * uncompressed chunk, are returned in the locations pointed to by 45 | * arguments 2-4. The compressed data is in storage internal to the 46 | * chunk compressor, and it cannot be accessed beyond any subsequent 47 | * calls to the chunk compressor. 48 | * 49 | * Chunks will be returned in the same order in which they were 50 | * submitted for compression. 51 | * 52 | * The resulting compressed length may be up to the uncompressed length. 53 | * In the case where they are equal, the returned data is actually the 54 | * uncompressed data, not the compressed data. 55 | * 56 | * The return value is %true if a chunk of compressed data was 57 | * successfully retrieved, or %false if there are no chunks currently 58 | * being compressed. */ 59 | bool (*get_compression_result)(struct chunk_compressor *, 60 | const void **, u32 *, u32 *); 61 | }; 62 | 63 | 64 | /* Functions that return implementations of the chunk_compressor interface. */ 65 | 66 | int 67 | new_parallel_chunk_compressor(int out_ctype, u32 out_chunk_size, 68 | unsigned num_threads, u64 max_memory, 69 | struct chunk_compressor **compressor_ret); 70 | 71 | int 72 | new_serial_chunk_compressor(int out_ctype, u32 out_chunk_size, 73 | struct chunk_compressor **compressor_ret); 74 | 75 | #endif /* _WIMLIB_CHUNK_COMPRESSOR_H */ 76 | -------------------------------------------------------------------------------- /include/wimlib/compress_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * compress_common.h 3 | * 4 | * Header for compression code shared by multiple compression formats. 5 | */ 6 | 7 | #ifndef _WIMLIB_COMPRESS_COMMON_H 8 | #define _WIMLIB_COMPRESS_COMMON_H 9 | 10 | #include "wimlib/types.h" 11 | 12 | #define MAX_NUM_SYMS 799 /* LZMS_MAX_NUM_SYMS */ 13 | #define MAX_CODEWORD_LEN 16 14 | 15 | void 16 | make_canonical_huffman_code(unsigned num_syms, unsigned max_codeword_len, 17 | const u32 freqs[], u8 lens[], u32 codewords[]); 18 | 19 | #endif /* _WIMLIB_COMPRESS_COMMON_H */ 20 | -------------------------------------------------------------------------------- /include/wimlib/compressor_ops.h: -------------------------------------------------------------------------------- 1 | /* 2 | * compressor_ops.h 3 | * 4 | * Interface implemented by compressors for specific formats. 5 | */ 6 | 7 | #ifndef _WIMLIB_COMPRESSOR_OPS_H 8 | #define _WIMLIB_COMPRESSOR_OPS_H 9 | 10 | #include "wimlib/types.h" 11 | 12 | struct compressor_ops { 13 | 14 | u64 (*get_needed_memory)(size_t max_block_size, 15 | unsigned int compression_level, 16 | bool destructive); 17 | 18 | int (*create_compressor)(size_t max_block_size, 19 | unsigned int compression_level, 20 | bool destructive, 21 | void **private_ret); 22 | 23 | size_t (*compress)(const void *uncompressed_data, 24 | size_t uncompressed_size, 25 | void *compressed_data, 26 | size_t compressed_size_avail, 27 | void *private); 28 | 29 | void (*free_compressor)(void *private); 30 | }; 31 | 32 | extern const struct compressor_ops lzx_compressor_ops; 33 | extern const struct compressor_ops xpress_compressor_ops; 34 | extern const struct compressor_ops lzms_compressor_ops; 35 | 36 | #endif /* _WIMLIB_COMPRESSOR_OPS_H */ 37 | -------------------------------------------------------------------------------- /include/wimlib/cpu_features.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_CPU_FEATURES_H 2 | #define _WIMLIB_CPU_FEATURES_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | #define X86_CPU_FEATURE_SSSE3 0x00000001 7 | #define X86_CPU_FEATURE_SSE4_1 0x00000002 8 | #define X86_CPU_FEATURE_SSE4_2 0x00000004 9 | #define X86_CPU_FEATURE_AVX 0x00000008 10 | #define X86_CPU_FEATURE_BMI2 0x00000010 11 | #define X86_CPU_FEATURE_SHA 0x00000020 12 | 13 | #define ARM_CPU_FEATURE_SHA1 0x00000001 14 | 15 | #if (defined(__i386__) || defined(__x86_64__)) || \ 16 | (defined(__aarch64__) && defined(__linux__)) || \ 17 | (defined(__aarch64__) && defined(__APPLE__)) || \ 18 | (defined(__aarch64__) && defined(_WIN32)) 19 | 20 | #define CPU_FEATURES_ENABLED 1 21 | extern u32 cpu_features; 22 | 23 | void init_cpu_features(void); 24 | 25 | #else 26 | 27 | #define CPU_FEATURES_ENABLED 0 28 | #define cpu_features 0 29 | 30 | static inline void 31 | init_cpu_features(void) 32 | { 33 | } 34 | 35 | #endif 36 | 37 | #endif /* _WIMLIB_CPU_FEATURES_H */ 38 | -------------------------------------------------------------------------------- /include/wimlib/decompressor_ops.h: -------------------------------------------------------------------------------- 1 | /* 2 | * decompressor_ops.h 3 | * 4 | * Interface implemented by decompressors for specific formats. 5 | */ 6 | 7 | #ifndef _WIMLIB_DECOMPRESSOR_OPS_H 8 | #define _WIMLIB_DECOMPRESSOR_OPS_H 9 | 10 | #include 11 | 12 | struct decompressor_ops { 13 | 14 | int (*create_decompressor)(size_t max_block_size, void **private_ret); 15 | 16 | int (*decompress)(const void *compressed_data, 17 | size_t compressed_size, 18 | void *uncompressed_data, 19 | size_t uncompressed_size, 20 | void *private); 21 | 22 | void (*free_decompressor)(void *private); 23 | }; 24 | 25 | extern const struct decompressor_ops lzx_decompressor_ops; 26 | extern const struct decompressor_ops xpress_decompressor_ops; 27 | extern const struct decompressor_ops lzms_decompressor_ops; 28 | 29 | #endif /* _WIMLIB_DECOMPRESSOR_OPS_H */ 30 | -------------------------------------------------------------------------------- /include/wimlib/divsufsort.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_DIVSUFSORT_H 2 | #define _WIMLIB_DIVSUFSORT_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | void 7 | divsufsort(const u8 *T, u32 *SA, u32 n, u32 *tmp); 8 | 9 | #define DIVSUFSORT_TMP_LEN (256 + (256 * 256)) 10 | 11 | #endif /* _WIMLIB_DIVSUFSORT_H */ 12 | -------------------------------------------------------------------------------- /include/wimlib/encoding.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_ENCODING_H 2 | #define _WIMLIB_ENCODING_H 3 | 4 | #include 5 | 6 | #include "wimlib/error.h" 7 | #include "wimlib/util.h" 8 | #include "wimlib/types.h" 9 | 10 | /* String conversion functions */ 11 | 12 | int 13 | utf8_to_utf16le(const char *in, size_t in_nbytes, 14 | utf16lechar **out_ret, size_t *out_nbytes_ret); 15 | 16 | int 17 | utf16le_to_utf8(const utf16lechar *in, size_t in_nbytes, 18 | char **out_ret, size_t *out_nbytes_ret); 19 | 20 | /* Identity conversion: duplicate a 'tchar' string. */ 21 | static inline int 22 | tstr_to_tstr(const tchar *in, size_t in_nbytes, 23 | tchar **out_ret, size_t *out_nbytes_ret) 24 | { 25 | tchar *out = MALLOC(in_nbytes + sizeof(tchar)); 26 | if (unlikely(!out)) 27 | return WIMLIB_ERR_NOMEM; 28 | memcpy(out, in, in_nbytes); 29 | out[in_nbytes / sizeof(tchar)] = 0; 30 | *out_ret = out; 31 | if (out_nbytes_ret) 32 | *out_nbytes_ret = in_nbytes; 33 | return 0; 34 | } 35 | 36 | #if TCHAR_IS_UTF16LE 37 | 38 | /* tstr(UTF-16LE) <=> UTF-16LE */ 39 | # define tstr_to_utf16le tstr_to_tstr 40 | # define utf16le_to_tstr tstr_to_tstr 41 | 42 | /* tstr(UTF-16LE) <=> UTF-8 */ 43 | # define tstr_to_utf8 utf16le_to_utf8 44 | # define utf8_to_tstr utf8_to_utf16le 45 | 46 | #else 47 | 48 | /* tstr(UTF-8) <=> UTF-16LE */ 49 | # define tstr_to_utf16le utf8_to_utf16le 50 | # define utf16le_to_tstr utf16le_to_utf8 51 | 52 | /* tstr(UTF-8) <=> UTF-8 */ 53 | # define tstr_to_utf8 tstr_to_tstr 54 | # define utf8_to_tstr tstr_to_tstr 55 | 56 | #endif 57 | 58 | /* Convert a tchar string to UTF-16LE, but if both encodings are UTF-16LE, then 59 | * simply re-use the string. Release with tstr_put_utf16le() when done. */ 60 | static inline int 61 | tstr_get_utf16le_and_len(const tchar *in, 62 | const utf16lechar **out_ret, size_t *out_nbytes_ret) 63 | { 64 | size_t in_nbytes = tstrlen(in) * sizeof(tchar); 65 | #if TCHAR_IS_UTF16LE 66 | *out_ret = in; 67 | if (out_nbytes_ret) 68 | *out_nbytes_ret = in_nbytes; 69 | return 0; 70 | #else 71 | return tstr_to_utf16le(in, in_nbytes, 72 | (utf16lechar **)out_ret, out_nbytes_ret); 73 | #endif 74 | } 75 | 76 | static inline int 77 | tstr_get_utf16le(const tchar *in, const utf16lechar **out_ret) 78 | { 79 | return tstr_get_utf16le_and_len(in, out_ret, NULL); 80 | } 81 | 82 | /* Release a string acquired with tstr_get_utf16le() or 83 | * tstr_get_utf16le_and_len(). */ 84 | static inline void 85 | tstr_put_utf16le(const utf16lechar *s) 86 | { 87 | #if !TCHAR_IS_UTF16LE 88 | FREE((void *)s); 89 | #endif 90 | } 91 | 92 | /* Convert a UTF-16LE string to a tchar string, but if both encodings are 93 | * UTF-16LE, then simply re-use the string. Release with utf16le_put_tstr() 94 | * when done. */ 95 | static inline int 96 | utf16le_get_tstr(const utf16lechar *in, size_t in_nbytes, 97 | const tchar **out_ret, size_t *out_nbytes_ret) 98 | { 99 | #if TCHAR_IS_UTF16LE 100 | *out_ret = in; 101 | if (out_nbytes_ret) 102 | *out_nbytes_ret = in_nbytes; 103 | return 0; 104 | #else 105 | return utf16le_to_tstr(in, in_nbytes, 106 | (tchar **)out_ret, out_nbytes_ret); 107 | #endif 108 | } 109 | 110 | /* Release a string acquired with utf16le_get_tstr(). */ 111 | static inline void 112 | utf16le_put_tstr(const tchar *s) 113 | { 114 | #if !TCHAR_IS_UTF16LE 115 | FREE((void *)s); 116 | #endif 117 | } 118 | 119 | 120 | /* UTF-16LE utilities */ 121 | 122 | extern u16 upcase[65536]; 123 | 124 | void 125 | init_upcase(void); 126 | 127 | int 128 | cmp_utf16le_strings(const utf16lechar *s1, size_t n1, 129 | const utf16lechar *s2, size_t n2, 130 | bool ignore_case); 131 | 132 | int 133 | cmp_utf16le_strings_z(const utf16lechar *s1, const utf16lechar *s2, 134 | bool ignore_case); 135 | 136 | utf16lechar * 137 | utf16le_dupz(const void *s, size_t size); 138 | 139 | utf16lechar * 140 | utf16le_dup(const utf16lechar *s); 141 | 142 | size_t 143 | utf16le_len_bytes(const utf16lechar *s); 144 | 145 | size_t 146 | utf16le_len_chars(const utf16lechar *s); 147 | 148 | #endif /* _WIMLIB_ENCODING_H */ 149 | -------------------------------------------------------------------------------- /include/wimlib/endianness.h: -------------------------------------------------------------------------------- 1 | /* 2 | * endianness.h - macros and inline functions for endianness conversion 3 | * 4 | * Copyright 2022 Eric Biggers 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #ifndef _WIMLIB_ENDIANNESS_H 29 | #define _WIMLIB_ENDIANNESS_H 30 | 31 | #include "wimlib/compiler.h" 32 | #include "wimlib/types.h" 33 | 34 | #ifdef HAVE_SYS_ENDIAN_H 35 | /* Needed on NetBSD to stop system bswap macros from messing things up */ 36 | # include 37 | # undef bswap16 38 | # undef bswap32 39 | # undef bswap64 40 | #endif 41 | 42 | /* Watch out for conflict with ntfs-3g/endians.h ... */ 43 | #ifndef _NTFS_ENDIANS_H 44 | 45 | #define bswap16_const(n) \ 46 | ((((u16)(n) & 0x00FF) << 8) | \ 47 | (((u16)(n) & 0xFF00) >> 8)) 48 | 49 | #define bswap32_const(n) \ 50 | ((((u32)(n) & 0x000000FF) << 24) | \ 51 | (((u32)(n) & 0x0000FF00) << 8) | \ 52 | (((u32)(n) & 0x00FF0000) >> 8) | \ 53 | (((u32)(n) & 0xFF000000) >> 24)) 54 | 55 | #define bswap64_const(n) \ 56 | ((((u64)(n) & 0x00000000000000FF) << 56) | \ 57 | (((u64)(n) & 0x000000000000FF00) << 40) | \ 58 | (((u64)(n) & 0x0000000000FF0000) << 24) | \ 59 | (((u64)(n) & 0x00000000FF000000) << 8) | \ 60 | (((u64)(n) & 0x000000FF00000000) >> 8) | \ 61 | (((u64)(n) & 0x0000FF0000000000) >> 24) | \ 62 | (((u64)(n) & 0x00FF000000000000) >> 40) | \ 63 | (((u64)(n) & 0xFF00000000000000) >> 56)) 64 | 65 | static forceinline u16 do_bswap16(u16 n) 66 | { 67 | #if GCC_PREREQ(4, 8) || __has_builtin(__builtin_bswap16) 68 | return __builtin_bswap16(n); 69 | #else 70 | return bswap16_const(n); 71 | #endif 72 | } 73 | 74 | static forceinline u32 do_bswap32(u32 n) 75 | { 76 | #if GCC_PREREQ(4, 3) || __has_builtin(__builtin_bswap32) 77 | return __builtin_bswap32(n); 78 | #else 79 | return bswap32_const(n); 80 | #endif 81 | } 82 | 83 | static forceinline u64 do_bswap64(u64 n) 84 | { 85 | #if GCC_PREREQ(4, 3) || __has_builtin(__builtin_bswap64) 86 | return __builtin_bswap64(n); 87 | #else 88 | return bswap64_const(n); 89 | #endif 90 | } 91 | 92 | #define bswap16(n) (__builtin_constant_p(n) ? bswap16_const(n) : do_bswap16(n)) 93 | #define bswap32(n) (__builtin_constant_p(n) ? bswap32_const(n) : do_bswap32(n)) 94 | #define bswap64(n) (__builtin_constant_p(n) ? bswap64_const(n) : do_bswap64(n)) 95 | 96 | #if CPU_IS_BIG_ENDIAN() 97 | # define cpu_to_le16(n) ((_force_attr le16)bswap16(n)) 98 | # define cpu_to_le32(n) ((_force_attr le32)bswap32(n)) 99 | # define cpu_to_le64(n) ((_force_attr le64)bswap64(n)) 100 | # define le16_to_cpu(n) bswap16((_force_attr u16)(le16)(n)) 101 | # define le32_to_cpu(n) bswap32((_force_attr u32)(le32)(n)) 102 | # define le64_to_cpu(n) bswap64((_force_attr u64)(le64)(n)) 103 | # define cpu_to_be16(n) ((_force_attr be16)(u16)(n)) 104 | # define cpu_to_be32(n) ((_force_attr be32)(u32)(n)) 105 | # define cpu_to_be64(n) ((_force_attr be64)(u64)(n)) 106 | # define be16_to_cpu(n) ((_force_attr u16)(be16)(n)) 107 | # define be32_to_cpu(n) ((_force_attr u32)(be32)(n)) 108 | # define be64_to_cpu(n) ((_force_attr u64)(be64)(n)) 109 | #else 110 | # define cpu_to_le16(n) ((_force_attr le16)(u16)(n)) 111 | # define cpu_to_le32(n) ((_force_attr le32)(u32)(n)) 112 | # define cpu_to_le64(n) ((_force_attr le64)(u64)(n)) 113 | # define le16_to_cpu(n) ((_force_attr u16)(le16)(n)) 114 | # define le32_to_cpu(n) ((_force_attr u32)(le32)(n)) 115 | # define le64_to_cpu(n) ((_force_attr u64)(le64)(n)) 116 | # define cpu_to_be16(n) ((_force_attr be16)bswap16(n)) 117 | # define cpu_to_be32(n) ((_force_attr be32)bswap32(n)) 118 | # define cpu_to_be64(n) ((_force_attr be64)bswap64(n)) 119 | # define be16_to_cpu(n) bswap16((_force_attr u16)(be16)(n)) 120 | # define be32_to_cpu(n) bswap32((_force_attr u32)(be32)(n)) 121 | # define be64_to_cpu(n) bswap64((_force_attr u64)(be64)(n)) 122 | #endif 123 | 124 | #endif /* _NTFS_ENDIANS_H */ 125 | #endif /* _WIMLIB_ENDIANNESS_H */ 126 | -------------------------------------------------------------------------------- /include/wimlib/error.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_ERROR_H 2 | #define _WIMLIB_ERROR_H 3 | 4 | #include 5 | 6 | #include "wimlib.h" /* Get error code definitions */ 7 | #include "wimlib/compiler.h" 8 | #include "wimlib/types.h" 9 | 10 | void _format_attribute(printf, 1, 2) __attribute__((cold)) 11 | wimlib_error(const tchar *format, ...); 12 | 13 | void _format_attribute(printf, 1, 2) __attribute__((cold)) 14 | wimlib_error_with_errno(const tchar *format, ...); 15 | 16 | void _format_attribute(printf, 1, 2) __attribute__((cold)) 17 | wimlib_warning(const tchar *format, ...); 18 | 19 | void _format_attribute(printf, 1, 2) __attribute__((cold)) 20 | wimlib_warning_with_errno(const tchar *format, ...); 21 | 22 | #define ERROR(format, ...) wimlib_error(T(format), ## __VA_ARGS__) 23 | #define ERROR_WITH_ERRNO(format, ...) wimlib_error_with_errno(T(format), ## __VA_ARGS__) 24 | #define WARNING(format, ...) wimlib_warning(T(format), ## __VA_ARGS__) 25 | #define WARNING_WITH_ERRNO(format, ...) wimlib_warning_with_errno(T(format), ## __VA_ARGS__) 26 | 27 | extern bool wimlib_print_errors; 28 | extern FILE *wimlib_error_file; 29 | 30 | void 31 | print_byte_field(const u8 *field, size_t len, FILE *out); 32 | 33 | #endif /* _WIMLIB_ERROR_H */ 34 | -------------------------------------------------------------------------------- /include/wimlib/file_io.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_FILE_IO_H 2 | #define _WIMLIB_FILE_IO_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* Wrapper around a file descriptor that keeps track of offset (including in 9 | * pipes, which don't support lseek()) and a cached flag that tells whether the 10 | * file descriptor is a pipe or not. */ 11 | struct filedes { 12 | int fd; 13 | unsigned int is_pipe : 1; 14 | off_t offset; 15 | }; 16 | 17 | int 18 | full_read(struct filedes *fd, void *buf, size_t n); 19 | 20 | int 21 | full_pread(struct filedes *fd, void *buf, size_t nbyte, off_t offset); 22 | 23 | int 24 | full_write(struct filedes *fd, const void *buf, size_t n); 25 | 26 | int 27 | full_pwrite(struct filedes *fd, const void *buf, size_t count, off_t offset); 28 | 29 | #ifndef _WIN32 30 | # define O_BINARY 0 31 | #endif 32 | 33 | off_t 34 | filedes_seek(struct filedes *fd, off_t offset); 35 | 36 | bool 37 | filedes_is_seekable(struct filedes *fd); 38 | 39 | static inline void filedes_init(struct filedes *fd, int raw_fd) 40 | { 41 | fd->fd = raw_fd; 42 | fd->offset = 0; 43 | fd->is_pipe = 0; 44 | } 45 | 46 | static inline void filedes_invalidate(struct filedes *fd) 47 | { 48 | fd->fd = -1; 49 | } 50 | 51 | #define filedes_close(f) close((f)->fd) 52 | 53 | static inline bool 54 | filedes_valid(const struct filedes *fd) 55 | { 56 | return fd->fd != -1; 57 | } 58 | 59 | #endif /* _WIMLIB_FILE_IO_H */ 60 | -------------------------------------------------------------------------------- /include/wimlib/glob.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_GLOB_H 2 | #define _WIMLIB_GLOB_H 3 | 4 | #ifndef _WIN32 5 | # include 6 | #else 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | size_t gl_pathc; 12 | wchar_t **gl_pathv; 13 | size_t gl_offs; 14 | } glob_t; 15 | 16 | /* WARNING: this is a reduced functionality replacement */ 17 | int 18 | win32_wglob(const wchar_t *pattern, int flags, 19 | int (*errfunc)(const wchar_t *epath, int eerrno), 20 | glob_t *pglob); 21 | 22 | void globfree(glob_t *pglob); 23 | 24 | #define GLOB_ERR 0x1 /* Return on read errors. */ 25 | #define GLOB_NOSORT 0x2 /* Don't sort the names. */ 26 | 27 | /* Error returns from `glob'. */ 28 | #define GLOB_NOSPACE 1 /* Ran out of memory. */ 29 | #define GLOB_ABORTED 2 /* Read error. */ 30 | #define GLOB_NOMATCH 3 /* No matches found. */ 31 | 32 | #endif /* _WIN32 */ 33 | 34 | #endif /* _WIMLIB_GLOB_H */ 35 | -------------------------------------------------------------------------------- /include/wimlib/guid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * guid.h 3 | * 4 | * Utility functions for handling 16-byte globally unique identifiers (GUIDs). 5 | */ 6 | 7 | #ifndef _WIMLIB_GUID_H 8 | #define _WIMLIB_GUID_H 9 | 10 | #include 11 | 12 | #include "wimlib/util.h" 13 | 14 | #define GUID_SIZE 16 15 | 16 | static inline void 17 | copy_guid(u8 dest[GUID_SIZE], const u8 src[GUID_SIZE]) 18 | { 19 | memcpy(dest, src, GUID_SIZE); 20 | } 21 | 22 | static inline int 23 | cmp_guids(const u8 guid1[GUID_SIZE], const u8 guid2[GUID_SIZE]) 24 | { 25 | return memcmp(guid1, guid2, GUID_SIZE); 26 | } 27 | 28 | static inline bool 29 | guids_equal(const u8 guid1[GUID_SIZE], const u8 guid2[GUID_SIZE]) 30 | { 31 | return !cmp_guids(guid1, guid2); 32 | } 33 | 34 | static inline void 35 | generate_guid(u8 guid[GUID_SIZE]) 36 | { 37 | return get_random_bytes(guid, GUID_SIZE); 38 | } 39 | 40 | #endif /* _WIMLIB_GUID_H */ 41 | -------------------------------------------------------------------------------- /include/wimlib/inode_table.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_INODE_TABLE_H 2 | #define _WIMLIB_INODE_TABLE_H 3 | 4 | #include "wimlib/list.h" 5 | #include "wimlib/types.h" 6 | #include "wimlib/util.h" 7 | 8 | struct wim_dentry; 9 | 10 | /* Hash table to find inodes for hard link detection, given an inode number (in 11 | * the case of reading a WIM image), or both an inode number and a device number 12 | * (in the case of adding files to a WIM image). Also contains an extra list to 13 | * hold inodes for which no additional hard link detection is desired. In both 14 | * cases the inodes are linked by i_hlist_node. */ 15 | struct wim_inode_table { 16 | struct hlist_head *array; 17 | size_t filled; 18 | size_t capacity; 19 | struct hlist_head extra_inodes; 20 | }; 21 | 22 | 23 | /* Compute the index of the hash bucket to use for the given inode number and 24 | * device number. */ 25 | static inline size_t 26 | hash_inode(const struct wim_inode_table *table, u64 ino, u64 devno) 27 | { 28 | return (hash_u64(ino) + devno) & (table->capacity - 1); 29 | } 30 | 31 | int 32 | init_inode_table(struct wim_inode_table *table, size_t capacity); 33 | 34 | int 35 | inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, 36 | u64 ino, u64 devno, bool noshare, 37 | struct wim_dentry **dentry_ret); 38 | 39 | void 40 | enlarge_inode_table(struct wim_inode_table *table); 41 | 42 | void 43 | inode_table_prepare_inode_list(struct wim_inode_table *table, 44 | struct hlist_head *head); 45 | 46 | void 47 | destroy_inode_table(struct wim_inode_table *table); 48 | 49 | #endif /* _WIMLIB_INODE_TABLE_H */ 50 | -------------------------------------------------------------------------------- /include/wimlib/integrity.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_INTEGRITY_H 2 | #define _WIMLIB_INTEGRITY_H 3 | 4 | #include 5 | 6 | #include "wimlib/types.h" 7 | 8 | #define WIM_INTEGRITY_OK 0 9 | #define WIM_INTEGRITY_NOT_OK -1 10 | #define WIM_INTEGRITY_NONEXISTENT -2 11 | 12 | struct integrity_table; 13 | 14 | int 15 | read_integrity_table(WIMStruct *wim, u64 num_checked_bytes, 16 | struct integrity_table **table_ret); 17 | 18 | #define free_integrity_table(table) FREE(table) 19 | 20 | int 21 | write_integrity_table(WIMStruct *wim, 22 | off_t new_blob_table_end, 23 | off_t old_blob_table_end, 24 | struct integrity_table *old_table); 25 | 26 | int 27 | check_wim_integrity(WIMStruct *wim); 28 | 29 | #endif /* _WIMLIB_INTEGRITY_H */ 30 | -------------------------------------------------------------------------------- /include/wimlib/lcpit_matchfinder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * lcpit_matchfinder.h 3 | * 4 | * A match-finder for Lempel-Ziv compression based on bottom-up construction and 5 | * traversal of the Longest Common Prefix (LCP) interval tree. 6 | * 7 | * Copyright 2022 Eric Biggers 8 | * 9 | * Permission is hereby granted, free of charge, to any person 10 | * obtaining a copy of this software and associated documentation 11 | * files (the "Software"), to deal in the Software without 12 | * restriction, including without limitation the rights to use, 13 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the 15 | * Software is furnished to do so, subject to the following 16 | * conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be 19 | * included in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | * OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef _LCPIT_MATCHFINDER_H 32 | #define _LCPIT_MATCHFINDER_H 33 | 34 | #include "wimlib/types.h" 35 | 36 | struct lcpit_matchfinder { 37 | bool huge_mode; 38 | u32 cur_pos; 39 | u32 *pos_data; 40 | union { 41 | u32 *intervals; 42 | u64 *intervals64; 43 | }; 44 | u32 min_match_len; 45 | u32 nice_match_len; 46 | u32 next[2]; 47 | u32 orig_nice_match_len; 48 | }; 49 | 50 | struct lz_match { 51 | u32 length; 52 | u32 offset; 53 | }; 54 | 55 | u64 56 | lcpit_matchfinder_get_needed_memory(size_t max_bufsize); 57 | 58 | bool 59 | lcpit_matchfinder_init(struct lcpit_matchfinder *mf, size_t max_bufsize, 60 | u32 min_match_len, u32 nice_match_len); 61 | 62 | void 63 | lcpit_matchfinder_load_buffer(struct lcpit_matchfinder *mf, const u8 *T, u32 n); 64 | 65 | u32 66 | lcpit_matchfinder_get_matches(struct lcpit_matchfinder *mf, 67 | struct lz_match *matches); 68 | 69 | void 70 | lcpit_matchfinder_skip_bytes(struct lcpit_matchfinder *mf, u32 count); 71 | 72 | void 73 | lcpit_matchfinder_destroy(struct lcpit_matchfinder *mf); 74 | 75 | #endif /* _LCPIT_MATCHFINDER_H */ 76 | -------------------------------------------------------------------------------- /include/wimlib/lzms_constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * lzms_constants.h 3 | * 4 | * Constants for the LZMS compression format. 5 | */ 6 | 7 | #ifndef _LZMS_CONSTANTS_H 8 | #define _LZMS_CONSTANTS_H 9 | 10 | /* Limits on match lengths and offsets (in bytes) */ 11 | #define LZMS_MIN_MATCH_LENGTH 1 12 | #define LZMS_MAX_MATCH_LENGTH 1073809578 13 | #define LZMS_MIN_MATCH_OFFSET 1 14 | #define LZMS_MAX_MATCH_OFFSET 1180427428 15 | 16 | /* The value to which buffer sizes should be limited. Microsoft's 17 | * implementation seems to use 67108864 (2^26) bytes. However, since the format 18 | * itself supports higher match lengths and offsets, we'll use 2^30 bytes. */ 19 | #define LZMS_MAX_BUFFER_SIZE 1073741824 20 | 21 | /* The length of each LRU queue for match sources: 22 | * 23 | * 1. offsets of LZ matches 24 | * 2. (power, raw offset) pairs of delta matches */ 25 | #define LZMS_NUM_LZ_REPS 3 26 | #define LZMS_NUM_DELTA_REPS 3 27 | 28 | /* The numbers of binary decision classes needed for encoding queue indices */ 29 | #define LZMS_NUM_LZ_REP_DECISIONS (LZMS_NUM_LZ_REPS - 1) 30 | #define LZMS_NUM_DELTA_REP_DECISIONS (LZMS_NUM_DELTA_REPS - 1) 31 | 32 | /* These are the numbers of probability entries for each binary decision class. 33 | * The logarithm base 2 of each of these values is the number of recently 34 | * encoded bits that are remembered for each decision class and are used to 35 | * select the appropriate probability entry when decoding/encoding the next 36 | * binary decision (bit). */ 37 | #define LZMS_NUM_MAIN_PROBS 16 38 | #define LZMS_NUM_MATCH_PROBS 32 39 | #define LZMS_NUM_LZ_PROBS 64 40 | #define LZMS_NUM_LZ_REP_PROBS 64 41 | #define LZMS_NUM_DELTA_PROBS 64 42 | #define LZMS_NUM_DELTA_REP_PROBS 64 43 | 44 | /* These values define the precision for probabilities in LZMS, which are always 45 | * given as a numerator; the denominator is implied. */ 46 | #define LZMS_PROBABILITY_BITS 6 47 | #define LZMS_PROBABILITY_DENOMINATOR (1 << LZMS_PROBABILITY_BITS) 48 | 49 | /* These values define the initial state of each probability entry. */ 50 | #define LZMS_INITIAL_PROBABILITY 48 51 | #define LZMS_INITIAL_RECENT_BITS 0x0000000055555555 52 | 53 | /* The number of symbols in each Huffman-coded alphabet */ 54 | #define LZMS_NUM_LITERAL_SYMS 256 55 | #define LZMS_NUM_LENGTH_SYMS 54 56 | #define LZMS_NUM_DELTA_POWER_SYMS 8 57 | #define LZMS_MAX_NUM_OFFSET_SYMS 799 58 | #define LZMS_MAX_NUM_SYMS 799 59 | 60 | /* The rebuild frequencies, in symbols, for each Huffman code */ 61 | #define LZMS_LITERAL_CODE_REBUILD_FREQ 1024 62 | #define LZMS_LZ_OFFSET_CODE_REBUILD_FREQ 1024 63 | #define LZMS_LENGTH_CODE_REBUILD_FREQ 512 64 | #define LZMS_DELTA_OFFSET_CODE_REBUILD_FREQ 1024 65 | #define LZMS_DELTA_POWER_CODE_REBUILD_FREQ 512 66 | 67 | /* The maximum length, in bits, of any Huffman codeword. This is guaranteed by 68 | * the way frequencies are updated. */ 69 | #define LZMS_MAX_CODEWORD_LENGTH 15 70 | 71 | /* The maximum number of verbatim bits, in addition to the Huffman-encoded 72 | * length slot symbol, that may be required to encode a match length */ 73 | #define LZMS_MAX_EXTRA_LENGTH_BITS 30 74 | 75 | /* The maximum number of verbatim bits, in addition to the Huffman-encoded 76 | * offset slot symbol, that may be required to encode a match offset */ 77 | #define LZMS_MAX_EXTRA_OFFSET_BITS 30 78 | 79 | /* Parameters for x86 machine code pre/post-processing */ 80 | #define LZMS_X86_ID_WINDOW_SIZE 65535 81 | #define LZMS_X86_MAX_TRANSLATION_OFFSET 1023 82 | 83 | #endif /* _LZMS_CONSTANTS_H */ 84 | -------------------------------------------------------------------------------- /include/wimlib/lzx_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * lzx_common.h 3 | * 4 | * Declarations shared between LZX compression and decompression. 5 | */ 6 | 7 | #ifndef _LZX_COMMON_H 8 | #define _LZX_COMMON_H 9 | 10 | #include "wimlib/lzx_constants.h" 11 | #include "wimlib/types.h" 12 | 13 | extern const s32 lzx_offset_slot_base[LZX_MAX_OFFSET_SLOTS + 1]; 14 | 15 | extern const u8 lzx_extra_offset_bits[LZX_MAX_OFFSET_SLOTS]; 16 | 17 | unsigned 18 | lzx_get_window_order(size_t max_bufsize); 19 | 20 | unsigned 21 | lzx_get_num_main_syms(unsigned window_order); 22 | 23 | void 24 | lzx_preprocess(u8 *data, u32 size); 25 | 26 | void 27 | lzx_postprocess(u8 *data, u32 size); 28 | 29 | #endif /* _LZX_COMMON_H */ 30 | -------------------------------------------------------------------------------- /include/wimlib/lzx_constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * lzx_constants.h 3 | * 4 | * Constants for the LZX compression format. 5 | */ 6 | 7 | #ifndef _LZX_CONSTANTS_H 8 | #define _LZX_CONSTANTS_H 9 | 10 | /* Number of literal byte values. */ 11 | #define LZX_NUM_CHARS 256 12 | 13 | /* The smallest and largest allowed match lengths. */ 14 | #define LZX_MIN_MATCH_LEN 2 15 | #define LZX_MAX_MATCH_LEN 257 16 | 17 | /* Number of distinct match lengths that can be represented. */ 18 | #define LZX_NUM_LENS (LZX_MAX_MATCH_LEN - LZX_MIN_MATCH_LEN + 1) 19 | 20 | /* Number of match lengths for which no length symbol is required. */ 21 | #define LZX_NUM_PRIMARY_LENS 7 22 | #define LZX_NUM_LEN_HEADERS (LZX_NUM_PRIMARY_LENS + 1) 23 | 24 | /* The first length which requires a length symbol. */ 25 | #define LZX_MIN_SECONDARY_LEN (LZX_MIN_MATCH_LEN + LZX_NUM_PRIMARY_LENS) 26 | 27 | /* Valid values of the 3-bit block type field. */ 28 | #define LZX_BLOCKTYPE_VERBATIM 1 29 | #define LZX_BLOCKTYPE_ALIGNED 2 30 | #define LZX_BLOCKTYPE_UNCOMPRESSED 3 31 | 32 | /* 'LZX_MIN_WINDOW_SIZE' and 'LZX_MAX_WINDOW_SIZE' are the minimum and maximum 33 | * sizes of the sliding window. */ 34 | #define LZX_MIN_WINDOW_ORDER 15 35 | #define LZX_MAX_WINDOW_ORDER 21 36 | #define LZX_MIN_WINDOW_SIZE (1UL << LZX_MIN_WINDOW_ORDER) /* 32768 */ 37 | #define LZX_MAX_WINDOW_SIZE (1UL << LZX_MAX_WINDOW_ORDER) /* 2097152 */ 38 | 39 | /* Maximum number of offset slots. (The actual number of offset slots depends 40 | * on the window size.) */ 41 | #define LZX_MAX_OFFSET_SLOTS 50 42 | 43 | /* Maximum number of symbols in the main code. (The actual number of symbols in 44 | * the main code depends on the window size.) */ 45 | #define LZX_MAINCODE_MAX_NUM_SYMBOLS \ 46 | (LZX_NUM_CHARS + (LZX_MAX_OFFSET_SLOTS * LZX_NUM_LEN_HEADERS)) 47 | 48 | /* Number of symbols in the length code. */ 49 | #define LZX_LENCODE_NUM_SYMBOLS (LZX_NUM_LENS - LZX_NUM_PRIMARY_LENS) 50 | 51 | /* Number of symbols in the pre-code. */ 52 | #define LZX_PRECODE_NUM_SYMBOLS 20 53 | 54 | /* Number of bits in which each pre-code codeword length is represented. */ 55 | #define LZX_PRECODE_ELEMENT_SIZE 4 56 | 57 | /* Number of low-order bits of each match offset that are entropy-encoded in 58 | * aligned offset blocks. */ 59 | #define LZX_NUM_ALIGNED_OFFSET_BITS 3 60 | 61 | /* Number of symbols in the aligned offset code. */ 62 | #define LZX_ALIGNEDCODE_NUM_SYMBOLS (1 << LZX_NUM_ALIGNED_OFFSET_BITS) 63 | 64 | /* Mask for the match offset bits that are entropy-encoded in aligned offset 65 | * blocks. */ 66 | #define LZX_ALIGNED_OFFSET_BITMASK ((1 << LZX_NUM_ALIGNED_OFFSET_BITS) - 1) 67 | 68 | /* Number of bits in which each aligned offset codeword length is represented. */ 69 | #define LZX_ALIGNEDCODE_ELEMENT_SIZE 3 70 | 71 | /* The first offset slot which requires an aligned offset symbol in aligned 72 | * offset blocks. */ 73 | #define LZX_MIN_ALIGNED_OFFSET_SLOT 8 74 | 75 | /* The offset slot base for LZX_MIN_ALIGNED_OFFSET_SLOT. */ 76 | #define LZX_MIN_ALIGNED_OFFSET 14 77 | 78 | /* The maximum number of extra offset bits in verbatim blocks. (One would need 79 | * to subtract LZX_NUM_ALIGNED_OFFSET_BITS to get the number of extra offset 80 | * bits in *aligned* blocks.) */ 81 | #define LZX_MAX_NUM_EXTRA_BITS 17 82 | 83 | /* Maximum lengths (in bits) for length-limited Huffman code construction. */ 84 | #define LZX_MAX_MAIN_CODEWORD_LEN 16 85 | #define LZX_MAX_LEN_CODEWORD_LEN 16 86 | #define LZX_MAX_PRE_CODEWORD_LEN ((1 << LZX_PRECODE_ELEMENT_SIZE) - 1) 87 | #define LZX_MAX_ALIGNED_CODEWORD_LEN ((1 << LZX_ALIGNEDCODE_ELEMENT_SIZE) - 1) 88 | 89 | /* For LZX-compressed blocks in WIM resources, this value is always used as the 90 | * filesize parameter for the call instruction (0xe8 byte) preprocessing, even 91 | * though the blocks themselves are not this size, and the size of the actual 92 | * file resource in the WIM file is very likely to be something entirely 93 | * different as well. */ 94 | #define LZX_WIM_MAGIC_FILESIZE 12000000 95 | 96 | /* Assumed LZX block size when the encoded block size begins with a 0 bit. 97 | * This is probably WIM-specific. */ 98 | #define LZX_DEFAULT_BLOCK_SIZE 32768 99 | 100 | /* Number of offsets in the recent (or "repeat") offsets queue. */ 101 | #define LZX_NUM_RECENT_OFFSETS 3 102 | 103 | /* An offset of n bytes is actually encoded as (n + LZX_OFFSET_ADJUSTMENT). */ 104 | #define LZX_OFFSET_ADJUSTMENT (LZX_NUM_RECENT_OFFSETS - 1) 105 | 106 | #endif /* _LZX_CONSTANTS_H */ 107 | -------------------------------------------------------------------------------- /include/wimlib/matchfinder_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * matchfinder_common.h - common code for Lempel-Ziv matchfinding 3 | * 4 | * Copyright 2022 Eric Biggers 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #ifndef _WIMLIB_MATCHFINDER_COMMON_H 29 | #define _WIMLIB_MATCHFINDER_COMMON_H 30 | 31 | #include "wimlib/bitops.h" 32 | #include "wimlib/unaligned.h" 33 | 34 | /* 35 | * Given a 32-bit value that was loaded with the platform's native endianness, 36 | * return a 32-bit value whose high-order 8 bits are 0 and whose low-order 24 37 | * bits contain the first 3 bytes, arranged in octets in a platform-dependent 38 | * order, at the memory location from which the input 32-bit value was loaded. 39 | */ 40 | static forceinline u32 41 | loaded_u32_to_u24(u32 v) 42 | { 43 | if (CPU_IS_LITTLE_ENDIAN()) 44 | return v & 0xFFFFFF; 45 | else 46 | return v >> 8; 47 | } 48 | 49 | /* 50 | * Load the next 3 bytes from @p into the 24 low-order bits of a 32-bit value. 51 | * The order in which the 3 bytes will be arranged as octets in the 24 bits is 52 | * platform-dependent. At least 4 bytes (not 3) must be available at @p. 53 | */ 54 | static forceinline u32 55 | load_u24_unaligned(const u8 *p) 56 | { 57 | #if UNALIGNED_ACCESS_IS_FAST 58 | return loaded_u32_to_u24(load_u32_unaligned(p)); 59 | #else 60 | if (CPU_IS_LITTLE_ENDIAN()) 61 | return ((u32)p[0] << 0) | ((u32)p[1] << 8) | ((u32)p[2] << 16); 62 | else 63 | return ((u32)p[2] << 0) | ((u32)p[1] << 8) | ((u32)p[0] << 16); 64 | #endif 65 | } 66 | 67 | /* 68 | * The hash function: given a sequence prefix held in the low-order bits of a 69 | * 32-bit value, multiply by a carefully-chosen large constant. Discard any 70 | * bits of the product that don't fit in a 32-bit value, but take the 71 | * next-highest @num_bits bits of the product as the hash value, as those have 72 | * the most randomness. 73 | */ 74 | static forceinline u32 75 | lz_hash(u32 seq, unsigned num_bits) 76 | { 77 | return (u32)(seq * 0x1E35A7BD) >> (32 - num_bits); 78 | } 79 | 80 | /* 81 | * Return the number of bytes at @matchptr that match the bytes at @strptr, up 82 | * to a maximum of @max_len. Initially, @start_len bytes are matched. 83 | */ 84 | static forceinline unsigned 85 | lz_extend(const u8 * const strptr, const u8 * const matchptr, 86 | const unsigned start_len, const unsigned max_len) 87 | { 88 | unsigned len = start_len; 89 | machine_word_t v_word; 90 | 91 | if (UNALIGNED_ACCESS_IS_FAST) { 92 | 93 | if (likely(max_len - len >= 4 * WORDBYTES)) { 94 | 95 | #define COMPARE_WORD_STEP \ 96 | v_word = load_word_unaligned(&matchptr[len]) ^ \ 97 | load_word_unaligned(&strptr[len]); \ 98 | if (v_word != 0) \ 99 | goto word_differs; \ 100 | len += WORDBYTES; \ 101 | 102 | COMPARE_WORD_STEP 103 | COMPARE_WORD_STEP 104 | COMPARE_WORD_STEP 105 | COMPARE_WORD_STEP 106 | #undef COMPARE_WORD_STEP 107 | } 108 | 109 | while (len + WORDBYTES <= max_len) { 110 | v_word = load_word_unaligned(&matchptr[len]) ^ 111 | load_word_unaligned(&strptr[len]); 112 | if (v_word != 0) 113 | goto word_differs; 114 | len += WORDBYTES; 115 | } 116 | } 117 | 118 | while (len < max_len && matchptr[len] == strptr[len]) 119 | len++; 120 | return len; 121 | 122 | word_differs: 123 | if (CPU_IS_LITTLE_ENDIAN()) 124 | len += (bsfw(v_word) >> 3); 125 | else 126 | len += (WORDBITS - 1 - bsrw(v_word)) >> 3; 127 | return len; 128 | } 129 | 130 | #endif /* _WIMLIB_MATCHFINDER_COMMON_H */ 131 | -------------------------------------------------------------------------------- /include/wimlib/ntfs_3g.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_NTFS_3G_H 2 | #define _WIMLIB_NTFS_3G_H 3 | 4 | #ifdef WITH_NTFS_3G 5 | 6 | #include "wimlib/types.h" 7 | 8 | struct blob_descriptor; 9 | struct consume_chunk_callback; 10 | struct ntfs_location; 11 | 12 | int 13 | read_ntfs_attribute_prefix(const struct blob_descriptor *blob, u64 size, 14 | const struct consume_chunk_callback *cb, 15 | bool recover_data); 16 | 17 | struct ntfs_location * 18 | clone_ntfs_location(const struct ntfs_location *loc); 19 | 20 | void 21 | free_ntfs_location(struct ntfs_location *loc); 22 | 23 | int 24 | cmp_ntfs_locations(const struct ntfs_location *loc1, 25 | const struct ntfs_location *loc2); 26 | 27 | #endif /* WITH_NTFS_3G */ 28 | 29 | #endif /* _WIMLIB_NTFS_3G_H */ 30 | -------------------------------------------------------------------------------- /include/wimlib/object_id.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_OBJECT_ID_H 2 | #define _WIMLIB_OBJECT_ID_H 3 | 4 | #include "wimlib/tagged_items.h" 5 | 6 | /* Unconfirmed: are all 64 bytes of the object ID always present? Since NTFS-3G 7 | * permits shorter object IDs, we'll do the same for now. */ 8 | #define OBJECT_ID_MIN_LENGTH 16 9 | 10 | static inline const void * 11 | inode_get_object_id(const struct wim_inode *inode, u32 *len_ret) 12 | { 13 | return inode_get_tagged_item(inode, TAG_OBJECT_ID, OBJECT_ID_MIN_LENGTH, 14 | len_ret); 15 | } 16 | 17 | static inline bool 18 | inode_has_object_id(const struct wim_inode *inode) 19 | { 20 | return inode_get_object_id(inode, NULL) != NULL; 21 | } 22 | 23 | static inline bool 24 | inode_set_object_id(struct wim_inode *inode, const void *object_id, u32 len) 25 | { 26 | return inode_set_tagged_item(inode, TAG_OBJECT_ID, object_id, len); 27 | } 28 | 29 | #endif /* _WIMLIB_OBJECT_ID_H */ 30 | -------------------------------------------------------------------------------- /include/wimlib/pathlist.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_PATHLIST_H 2 | #define _WIMLIB_PATHLIST_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | int 7 | read_path_list_file(const tchar *listfile, 8 | tchar ***paths_ret, size_t *num_paths_ret, 9 | void **mem_ret); 10 | 11 | #endif /* _WIMLIB_PATHLIST_H */ 12 | -------------------------------------------------------------------------------- /include/wimlib/paths.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_PATHS_H 2 | #define _WIMLIB_PATHS_H 3 | 4 | #include "wimlib/compiler.h" 5 | #include "wimlib/types.h" 6 | 7 | const tchar * 8 | path_basename(const tchar *path); 9 | 10 | const tchar * 11 | path_basename_with_len(const tchar *path, size_t len); 12 | 13 | const tchar * 14 | path_stream_name(const tchar *path); 15 | 16 | void 17 | do_canonicalize_path(const tchar *in, tchar *out); 18 | 19 | tchar * 20 | canonicalize_wim_path(const tchar *wim_path); 21 | 22 | /* is_any_path_separator() - characters treated as path separators in WIM path 23 | * specifications and capture configuration files (the former will be translated 24 | * to WIM_PATH_SEPARATOR; the latter will be translated to 25 | * OS_PREFERRED_PATH_SEPARATOR) 26 | * 27 | * OS_PREFERRED_PATH_SEPARATOR - preferred (or only) path separator on the 28 | * operating system. Used when constructing filesystem paths to extract or 29 | * archive. 30 | * 31 | * WIM_PATH_SEPARATOR - character treated as path separator for WIM paths. 32 | * Currently needs to be '/' on UNIX for the WIM mounting code to work properly. 33 | */ 34 | 35 | #ifdef _WIN32 36 | # define OS_PREFERRED_PATH_SEPARATOR L'\\' 37 | # define is_any_path_separator(c) ((c) == L'/' || (c) == L'\\') 38 | #else 39 | # define OS_PREFERRED_PATH_SEPARATOR '/' 40 | # define is_any_path_separator(c) ((c) == '/' || (c) == '\\') 41 | #endif 42 | 43 | #define WIM_PATH_SEPARATOR WIMLIB_WIM_PATH_SEPARATOR 44 | 45 | #endif /* _WIMLIB_PATHS_H */ 46 | -------------------------------------------------------------------------------- /include/wimlib/pattern.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_PATTERN_H 2 | #define _WIMLIB_PATTERN_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | struct wim_dentry; 7 | 8 | /* Flags for match_path() and match_pattern_list() */ 9 | 10 | /* 11 | * If set, subdirectories (and sub-files) are also matched. 12 | * For example, the pattern "/dir" would match the path "/dir/file". 13 | */ 14 | #define MATCH_RECURSIVELY 0x01 15 | 16 | /* 17 | * If set, ancestor directories are also matched. 18 | * For example, the pattern "/dir/file" would match the path "/dir". 19 | */ 20 | #define MATCH_ANCESTORS 0x02 21 | 22 | bool 23 | match_path(const tchar *path, const tchar *pattern, int match_flags); 24 | 25 | int 26 | expand_path_pattern(struct wim_dentry *root, const tchar *pattern, 27 | int (*consume_dentry)(struct wim_dentry *, void *), 28 | void *ctx); 29 | 30 | #endif /* _WIMLIB_PATTERN_H */ 31 | -------------------------------------------------------------------------------- /include/wimlib/progress.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_PROGRESS_H 2 | #define _WIMLIB_PROGRESS_H 3 | 4 | #include "wimlib.h" 5 | #include "wimlib/paths.h" 6 | #include "wimlib/types.h" 7 | 8 | /* If specified, call the user-provided progress function and check its result. 9 | */ 10 | static inline int 11 | call_progress(wimlib_progress_func_t progfunc, 12 | enum wimlib_progress_msg msg, 13 | union wimlib_progress_info *info, 14 | void *progctx) 15 | { 16 | if (progfunc) { 17 | enum wimlib_progress_status status; 18 | 19 | status = (*progfunc)(msg, info, progctx); 20 | 21 | switch (status) { 22 | case WIMLIB_PROGRESS_STATUS_CONTINUE: 23 | return 0; 24 | case WIMLIB_PROGRESS_STATUS_ABORT: 25 | return WIMLIB_ERR_ABORTED_BY_PROGRESS; 26 | default: 27 | return WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS; 28 | } 29 | } 30 | return 0; 31 | } 32 | 33 | int 34 | report_error(wimlib_progress_func_t progfunc, 35 | void *progctx, int error_code, const tchar *path); 36 | 37 | /* Rate-limiting of byte-count based progress messages: update *next_progress_p 38 | * to the value that completed_bytes needs to reach before the next progress 39 | * message will be sent. */ 40 | static inline void 41 | set_next_progress(u64 completed_bytes, u64 total_bytes, u64 *next_progress_p) 42 | { 43 | if (*next_progress_p < total_bytes) { 44 | /* 45 | * Send the next message as soon as: 46 | * - another 1/100 of the total has been processed; 47 | * - OR another 1 GiB has been processed; 48 | * - OR all bytes have been processed. 49 | */ 50 | *next_progress_p = min(min(completed_bytes + total_bytes / 100, 51 | completed_bytes + (1UL << 30)), 52 | total_bytes); 53 | } else { 54 | /* Last message has been sent. */ 55 | *next_progress_p = ~0; 56 | } 57 | } 58 | 59 | /* Windows: temporarily remove the stream name from the path */ 60 | static inline tchar * 61 | progress_get_streamless_path(const tchar *path) 62 | { 63 | tchar *cookie = NULL; 64 | #ifdef _WIN32 65 | cookie = (wchar_t *)path_stream_name(path); 66 | if (cookie) 67 | *--cookie = L'\0'; /* Overwrite the colon */ 68 | #endif 69 | return cookie; 70 | } 71 | 72 | /* Windows: temporarily replace \??\ with \\?\ (to make an NT namespace path 73 | * into a Win32 namespace path) */ 74 | static inline tchar * 75 | progress_get_win32_path(const tchar *path) 76 | { 77 | #ifdef _WIN32 78 | if (!wcsncmp(path, L"\\??\\", 4)) { 79 | ((wchar_t *)path)[1] = L'\\'; 80 | return (wchar_t *)&path[1]; 81 | } 82 | #endif 83 | return NULL; 84 | } 85 | 86 | /* Windows: restore the NT namespace path */ 87 | static inline void 88 | progress_put_win32_path(tchar *cookie) 89 | { 90 | #ifdef _WIN32 91 | if (cookie) 92 | *cookie = L'?'; 93 | #endif 94 | } 95 | 96 | /* Windows: restore the stream name part of the path */ 97 | static inline void 98 | progress_put_streamless_path(tchar *cookie) 99 | { 100 | #ifdef _WIN32 101 | if (cookie) 102 | *cookie = L':'; 103 | #endif 104 | } 105 | 106 | #endif /* _WIMLIB_PROGRESS_H */ 107 | -------------------------------------------------------------------------------- /include/wimlib/registry.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_REGISTRY_H 2 | #define _WIMLIB_REGISTRY_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | struct regf; 7 | 8 | enum hive_status { 9 | HIVE_OK, 10 | HIVE_CORRUPT, 11 | HIVE_UNSUPPORTED, 12 | HIVE_KEY_NOT_FOUND, 13 | HIVE_VALUE_NOT_FOUND, 14 | HIVE_VALUE_IS_WRONG_TYPE, 15 | HIVE_OUT_OF_MEMORY, 16 | HIVE_ITERATION_STOPPED, 17 | }; 18 | 19 | enum hive_status 20 | hive_validate(const void *hive_mem, size_t hive_size); 21 | 22 | enum hive_status 23 | hive_get_string(const struct regf *regf, const tchar *key_name, 24 | const tchar *value_name, tchar **value_ret); 25 | 26 | enum hive_status 27 | hive_get_number(const struct regf *regf, const tchar *key_name, 28 | const tchar *value_name, s64 *value_ret); 29 | 30 | enum hive_status 31 | hive_list_subkeys(const struct regf *regf, const tchar *key_name, 32 | tchar ***subkeys_ret); 33 | 34 | void 35 | hive_free_subkeys_list(tchar **subkeys); 36 | 37 | const char * 38 | hive_status_to_string(enum hive_status status); 39 | 40 | #endif /* _WIMLIB_REGISTRY_H */ 41 | -------------------------------------------------------------------------------- /include/wimlib/reparse.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_REPARSE_H 2 | #define _WIMLIB_REPARSE_H 3 | 4 | #include "wimlib/inode.h" /* for reparse tag definitions */ 5 | #include "wimlib/types.h" 6 | 7 | struct blob_descriptor; 8 | struct blob_table; 9 | 10 | /* Windows enforces this limit on the size of a reparse point buffer. */ 11 | #define REPARSE_POINT_MAX_SIZE 16384 12 | 13 | /* 14 | * On-disk format of a reparse point buffer. See: 15 | * https://msdn.microsoft.com/en-us/library/dd541671.aspx 16 | * 17 | * Note: we are not using __attribute__((packed)) for this structure, so only 18 | * cast to this if properly aligned! 19 | */ 20 | struct reparse_buffer_disk { 21 | le32 rptag; 22 | le16 rpdatalen; 23 | le16 rpreserved; 24 | union { 25 | u8 rpdata[REPARSE_POINT_MAX_SIZE - 8]; 26 | 27 | struct { 28 | le16 substitute_name_offset; 29 | le16 substitute_name_nbytes; 30 | le16 print_name_offset; 31 | le16 print_name_nbytes; 32 | 33 | union { 34 | struct { 35 | u8 data[REPARSE_POINT_MAX_SIZE - 16]; 36 | } junction; 37 | 38 | struct { 39 | le32 flags; 40 | #define SYMBOLIC_LINK_RELATIVE 0x00000001 41 | u8 data[REPARSE_POINT_MAX_SIZE - 20]; 42 | } symlink; 43 | }; 44 | } link; 45 | }; 46 | }; 47 | 48 | #define REPARSE_DATA_OFFSET ((unsigned)offsetof(struct reparse_buffer_disk, rpdata)) 49 | 50 | #define REPARSE_DATA_MAX_SIZE (REPARSE_POINT_MAX_SIZE - REPARSE_DATA_OFFSET) 51 | 52 | static void __attribute__((unused)) 53 | check_reparse_buffer_disk(void) 54 | { 55 | STATIC_ASSERT(offsetof(struct reparse_buffer_disk, rpdata) == 8); 56 | STATIC_ASSERT(offsetof(struct reparse_buffer_disk, link.junction.data) == 16); 57 | STATIC_ASSERT(offsetof(struct reparse_buffer_disk, link.symlink.data) == 20); 58 | STATIC_ASSERT(sizeof(struct reparse_buffer_disk) == REPARSE_POINT_MAX_SIZE); 59 | } 60 | 61 | /* Wrapper around a symbolic link or junction reparse point 62 | * (WIM_IO_REPARSE_TAG_SYMLINK or WIM_IO_REPARSE_TAG_MOUNT_POINT) */ 63 | struct link_reparse_point { 64 | 65 | u32 rptag; 66 | u16 rpreserved; 67 | 68 | /* Flags, valid for symbolic links only */ 69 | u32 symlink_flags; 70 | 71 | /* Pointers to the substitute name and print name of the link, 72 | * potentially not null terminated */ 73 | utf16lechar *substitute_name; 74 | utf16lechar *print_name; 75 | 76 | /* Lengths of the substitute and print names in bytes, not including 77 | * their null terminators if present */ 78 | size_t substitute_name_nbytes; 79 | size_t print_name_nbytes; 80 | }; 81 | 82 | static inline bool 83 | link_is_relative_symlink(const struct link_reparse_point *link) 84 | { 85 | return link->rptag == WIM_IO_REPARSE_TAG_SYMLINK && 86 | (link->symlink_flags & SYMBOLIC_LINK_RELATIVE); 87 | } 88 | 89 | void 90 | complete_reparse_point(struct reparse_buffer_disk *rpbuf, 91 | const struct wim_inode *inode, u16 blob_size); 92 | 93 | int 94 | parse_link_reparse_point(const struct reparse_buffer_disk *rpbuf, u16 rpbuflen, 95 | struct link_reparse_point *link); 96 | 97 | int 98 | make_link_reparse_point(const struct link_reparse_point *link, 99 | struct reparse_buffer_disk *rpbuf, u16 *rpbuflen_ret); 100 | 101 | #ifndef _WIN32 102 | int 103 | wim_inode_readlink(const struct wim_inode *inode, char *buf, size_t bufsize, 104 | const struct blob_descriptor *blob, 105 | const char *altroot, size_t altroot_len); 106 | 107 | int 108 | wim_inode_set_symlink(struct wim_inode *inode, const char *target, 109 | struct blob_table *blob_table); 110 | #endif 111 | 112 | #endif /* _WIMLIB_REPARSE_H */ 113 | -------------------------------------------------------------------------------- /include/wimlib/scan.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_SCAN_H 2 | #define _WIMLIB_SCAN_H 3 | 4 | #include "wimlib.h" 5 | #include "wimlib/inode_table.h" 6 | #include "wimlib/list.h" 7 | #include "wimlib/progress.h" 8 | #include "wimlib/security.h" 9 | #include "wimlib/textfile.h" 10 | #include "wimlib/util.h" 11 | 12 | struct blob_table; 13 | struct wim_dentry; 14 | struct wim_inode; 15 | 16 | struct capture_config { 17 | 18 | /* List of path patterns to exclude */ 19 | struct string_list exclusion_pats; 20 | 21 | /* List of path patterns to include, overriding exclusion_pats */ 22 | struct string_list exclusion_exception_pats; 23 | 24 | void *buf; 25 | }; 26 | 27 | /* Scan parameters: common parameters to implementations of building an 28 | * in-memory dentry tree from an external directory structure. */ 29 | struct scan_params { 30 | 31 | /* The blob table within which any new blobs discovered during the scan 32 | * will be deduplicated. */ 33 | struct blob_table *blob_table; 34 | 35 | /* List of new blobs that have been discovered without their SHA-1 36 | * message digests having been calculated (as a shortcut). */ 37 | struct list_head *unhashed_blobs; 38 | 39 | /* Map from (inode number, device number) pair to inode for new inodes 40 | * that have been discovered so far. */ 41 | struct wim_inode_table *inode_table; 42 | 43 | /* The set of unique security descriptors to which each newly 44 | * discovered, unique security descriptor will be added. */ 45 | struct wim_sd_set *sd_set; 46 | 47 | /* The capture configuration in effect, or NULL if none. */ 48 | struct capture_config *config; 49 | 50 | /* Flags that affect the scan operation (WIMLIB_ADD_FLAG_*) */ 51 | int add_flags; 52 | 53 | /* If non-NULL, the user-supplied progress function. */ 54 | wimlib_progress_func_t progfunc; 55 | void *progctx; 56 | 57 | /* Progress data. */ 58 | union wimlib_progress_info progress; 59 | 60 | /* Path to the file or directory currently being scanned */ 61 | tchar *cur_path; 62 | size_t cur_path_nchars; 63 | size_t cur_path_alloc_nchars; 64 | 65 | /* Length of the prefix of 'cur_path' which names the root of the 66 | * directory tree currently being scanned */ 67 | size_t root_path_nchars; 68 | 69 | /* Can be used by the scan implementation. */ 70 | u64 capture_root_ino; 71 | u64 capture_root_dev; 72 | }; 73 | 74 | /* scan.c */ 75 | 76 | int 77 | do_scan_progress(struct scan_params *params, int status, 78 | const struct wim_inode *inode); 79 | 80 | int 81 | mangle_pat(tchar *pat, const tchar *path, unsigned long line_no); 82 | 83 | int 84 | read_capture_config(const tchar *config_file, const void *buf, 85 | size_t bufsize, struct capture_config *config); 86 | 87 | void 88 | destroy_capture_config(struct capture_config *config); 89 | 90 | bool 91 | match_pattern_list(const tchar *path, const struct string_list *list, 92 | int match_flags); 93 | 94 | int 95 | try_exclude(const struct scan_params *params); 96 | 97 | typedef int (*scan_tree_t)(struct wim_dentry **, const tchar *, 98 | struct scan_params *); 99 | 100 | #ifdef WITH_NTFS_3G 101 | /* ntfs-3g_capture.c */ 102 | int 103 | ntfs_3g_build_dentry_tree(struct wim_dentry **root_ret, 104 | const tchar *device, struct scan_params *params); 105 | #endif 106 | 107 | #ifdef _WIN32 108 | /* win32_capture.c */ 109 | int 110 | win32_build_dentry_tree(struct wim_dentry **root_ret, 111 | const tchar *root_disk_path, 112 | struct scan_params *params); 113 | #define platform_default_scan_tree win32_build_dentry_tree 114 | #else 115 | /* unix_capture.c */ 116 | int 117 | unix_build_dentry_tree(struct wim_dentry **root_ret, 118 | const tchar *root_disk_path, struct scan_params *params); 119 | #define platform_default_scan_tree unix_build_dentry_tree 120 | #endif 121 | 122 | #ifdef ENABLE_TEST_SUPPORT 123 | int 124 | generate_dentry_tree(struct wim_dentry **root_ret, 125 | const tchar *root_disk_path, struct scan_params *params); 126 | #endif 127 | 128 | #define WIMLIB_ADD_FLAG_ROOT 0x80000000 129 | 130 | static inline int 131 | report_scan_error(struct scan_params *params, int error_code) 132 | { 133 | return report_error(params->progfunc, params->progctx, error_code, 134 | params->cur_path); 135 | } 136 | 137 | bool 138 | should_ignore_filename(const tchar *name, int name_nchars); 139 | 140 | void 141 | attach_scanned_tree(struct wim_dentry *parent, struct wim_dentry *child, 142 | struct blob_table *blob_table); 143 | 144 | int 145 | pathbuf_init(struct scan_params *params, const tchar *root_path); 146 | 147 | const tchar * 148 | pathbuf_append_name(struct scan_params *params, const tchar *name, 149 | size_t name_nchars, size_t *orig_path_nchars_ret); 150 | 151 | void 152 | pathbuf_truncate(struct scan_params *params, size_t nchars); 153 | 154 | #endif /* _WIMLIB_SCAN_H */ 155 | -------------------------------------------------------------------------------- /include/wimlib/security.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_SECURITY_H 2 | #define _WIMLIB_SECURITY_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | struct wim_security_data; 7 | struct avl_tree_node; 8 | 9 | /* Map from SHA1 message digests of security descriptors to security IDs, which 10 | * are themselves indices into the table of security descriptors in the 'struct 11 | * wim_security_data'. */ 12 | struct wim_sd_set { 13 | struct wim_security_data *sd; 14 | struct avl_tree_node *root; 15 | s32 orig_num_entries; 16 | }; 17 | 18 | /* Table of security descriptors for a WIM image. */ 19 | struct wim_security_data { 20 | /* The total length of the security data, in bytes. If there are no 21 | * security descriptors, this field, when read from the on-disk metadata 22 | * resource, may be either 8 (which is correct) or 0 (which is 23 | * interpreted as 8). */ 24 | u32 total_length; 25 | 26 | /* The number of security descriptors in the array @descriptors. */ 27 | u32 num_entries; 28 | 29 | /* Array of sizes of the descriptors, in bytes, in the array 30 | * @descriptors. */ 31 | u64 *sizes; 32 | 33 | /* Array of pointers to the security descriptors in the 34 | * SECURITY_DESCRIPTOR_RELATIVE format. */ 35 | u8 **descriptors; 36 | }; 37 | 38 | void 39 | rollback_new_security_descriptors(struct wim_sd_set *sd_set); 40 | 41 | void 42 | destroy_sd_set(struct wim_sd_set *sd_set); 43 | 44 | s32 45 | sd_set_add_sd(struct wim_sd_set *sd_set, const char descriptor[], 46 | size_t size); 47 | 48 | int 49 | init_sd_set(struct wim_sd_set *sd_set, struct wim_security_data *sd); 50 | 51 | struct wim_security_data * 52 | new_wim_security_data(void); 53 | 54 | int 55 | read_wim_security_data(const u8 *buf, size_t buf_len, 56 | struct wim_security_data **sd_ret); 57 | 58 | u8 * 59 | write_wim_security_data(const struct wim_security_data * restrict sd, 60 | u8 * restrict p); 61 | 62 | void 63 | print_wim_security_data(const struct wim_security_data *sd); 64 | 65 | void 66 | free_wim_security_data(struct wim_security_data *sd); 67 | 68 | #endif /* _WIMLIB_SECURITY_H */ 69 | -------------------------------------------------------------------------------- /include/wimlib/sha1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sha1.h 3 | * 4 | * Copyright 2022-2023 Eric Biggers 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #ifndef _WIMLIB_SHA1_H 29 | #define _WIMLIB_SHA1_H 30 | 31 | #include 32 | 33 | #include "wimlib/types.h" 34 | #include "wimlib/util.h" 35 | 36 | #define SHA1_HASH_SIZE 20 37 | #define SHA1_BLOCK_SIZE 64 38 | 39 | struct sha1_ctx { 40 | u64 bytecount; 41 | u32 h[5]; 42 | u8 buffer[SHA1_BLOCK_SIZE]; 43 | }; 44 | 45 | void 46 | sha1_init(struct sha1_ctx *ctx); 47 | 48 | void 49 | sha1_update(struct sha1_ctx *ctx, const void *data, size_t len); 50 | 51 | void 52 | sha1_final(struct sha1_ctx *ctx, u8 hash[SHA1_HASH_SIZE]); 53 | 54 | void 55 | sha1(const void *data, size_t len, u8 hash[SHA1_HASH_SIZE]); 56 | 57 | extern const u8 zero_hash[SHA1_HASH_SIZE]; 58 | 59 | #define SHA1_HASH_STRING_LEN (2 * SHA1_HASH_SIZE + 1) 60 | void 61 | sprint_hash(const u8 hash[SHA1_HASH_SIZE], tchar strbuf[SHA1_HASH_STRING_LEN]); 62 | 63 | static inline void 64 | copy_hash(u8 dest[SHA1_HASH_SIZE], const u8 src[SHA1_HASH_SIZE]) 65 | { 66 | memcpy(dest, src, SHA1_HASH_SIZE); 67 | } 68 | 69 | static inline int 70 | hashes_cmp(const u8 h1[SHA1_HASH_SIZE], const u8 h2[SHA1_HASH_SIZE]) 71 | { 72 | return memcmp(h1, h2, SHA1_HASH_SIZE); 73 | } 74 | 75 | static inline bool 76 | hashes_equal(const u8 h1[SHA1_HASH_SIZE], const u8 h2[SHA1_HASH_SIZE]) 77 | { 78 | return !hashes_cmp(h1, h2); 79 | } 80 | 81 | static inline bool 82 | is_zero_hash(const u8 *hash) 83 | { 84 | return hash == zero_hash || hashes_equal(hash, zero_hash); 85 | } 86 | 87 | #endif /* _WIMLIB_SHA1_H */ 88 | -------------------------------------------------------------------------------- /include/wimlib/solid.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_SOLID_H 2 | #define _WIMLIB_SOLID_H 3 | 4 | struct list_head; 5 | 6 | int 7 | sort_blob_list_for_solid_compression(struct list_head *blob_list); 8 | 9 | #endif /* _WIMLIB_SOLID_H */ 10 | -------------------------------------------------------------------------------- /include/wimlib/tagged_items.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_TAGGED_ITEMS_H 2 | #define _WIMLIB_TAGGED_ITEMS_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | struct wim_inode; 7 | 8 | /* Windows-style object ID */ 9 | #define TAG_OBJECT_ID 0x00000001 10 | 11 | /* Extended attributes */ 12 | #define TAG_XATTRS 0x00000002 13 | 14 | /* [wimlib extension] Standard UNIX metadata: uid, gid, mode, and rdev */ 15 | #define TAG_WIMLIB_UNIX_DATA 0x337DD873 16 | 17 | /* 18 | * [wimlib extension] Linux-style extended attributes 19 | * (deprecated in favor of TAG_XATTRS) 20 | */ 21 | #define TAG_WIMLIB_LINUX_XATTRS 0x337DD874 22 | 23 | void * 24 | inode_get_tagged_item(const struct wim_inode *inode, u32 tag, u32 min_len, 25 | u32 *actual_len_ret); 26 | 27 | bool 28 | inode_set_tagged_item(struct wim_inode *inode, u32 tag, 29 | const void *data, u32 len); 30 | 31 | #endif /* _WIMLIB_TAGGED_ITEMS_H */ 32 | -------------------------------------------------------------------------------- /include/wimlib/test_support.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_TEST_SUPPORT_H 2 | #define _WIMLIB_TEST_SUPPORT_H 3 | 4 | #ifdef ENABLE_TEST_SUPPORT 5 | 6 | #include "wimlib.h" 7 | #include "wimlib/types.h" 8 | 9 | #define WIMLIB_ERR_IMAGES_ARE_DIFFERENT 200 10 | 11 | #define WIMLIB_ADD_FLAG_GENERATE_TEST_DATA 0x08000000 12 | 13 | #define WIMLIB_CMP_FLAG_UNIX_MODE 0x00000001 14 | #define WIMLIB_CMP_FLAG_NTFS_3G_MODE 0x00000002 15 | #define WIMLIB_CMP_FLAG_WINDOWS_MODE 0x00000004 16 | #define WIMLIB_CMP_FLAG_EXT4 0x00000008 17 | 18 | WIMLIBAPI void 19 | wimlib_seed_random(u64 seed); 20 | 21 | WIMLIBAPI int 22 | wimlib_compare_images(WIMStruct *wim1, int image1, 23 | WIMStruct *wim2, int image2, int cmp_flags); 24 | 25 | WIMLIBAPI int 26 | wimlib_parse_and_write_xml_doc(const tchar *in, tchar **out_ret); 27 | 28 | WIMLIBAPI int 29 | wimlib_utf8_to_utf16le(const char *in, size_t in_nbytes, 30 | utf16lechar **out_ret, size_t *out_nbytes_ret); 31 | 32 | WIMLIBAPI int 33 | wimlib_utf16le_to_utf8(const utf16lechar *in, size_t in_nbytes, 34 | char **out_ret, size_t *out_nbytes_ret); 35 | 36 | #endif /* ENABLE_TEST_SUPPORT */ 37 | 38 | #endif /* _WIMLIB_TEST_SUPPORT_H */ 39 | -------------------------------------------------------------------------------- /include/wimlib/textfile.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_TEXTFILE_H_ 2 | #define _WIMLIB_TEXTFILE_H_ 3 | 4 | #include "wimlib/types.h" 5 | 6 | struct string_list { 7 | tchar **strings; 8 | size_t num_strings; 9 | size_t num_alloc_strings; 10 | }; 11 | 12 | #define STRING_LIST_INITIALIZER \ 13 | { .strings = NULL, .num_strings = 0, .num_alloc_strings = 0, } 14 | 15 | #define STRING_LIST(_strings) \ 16 | struct string_list _strings = STRING_LIST_INITIALIZER 17 | 18 | typedef int (*line_mangle_t)(tchar *line, const tchar *filename, 19 | unsigned long line_no); 20 | 21 | struct text_file_section { 22 | const tchar *name; 23 | struct string_list *strings; 24 | }; 25 | 26 | #define LOAD_TEXT_FILE_REMOVE_QUOTES 0x00000001 27 | #define LOAD_TEXT_FILE_NO_WARNINGS 0x00000002 28 | #define LOAD_TEXT_FILE_ALLOW_STDIN 0x00000004 29 | 30 | int 31 | load_text_file(const tchar *path, const void *buf, size_t bufsize, 32 | void **mem_ret, 33 | const struct text_file_section *pos_sections, 34 | int num_pos_sections, 35 | int flags, line_mangle_t mangle_line); 36 | 37 | #endif /* _WIMLIB_TEXTFILE_H_ */ 38 | -------------------------------------------------------------------------------- /include/wimlib/threads.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_THREADS_H 2 | #define _WIMLIB_THREADS_H 3 | 4 | #include 5 | 6 | #ifdef _WIN32 7 | 8 | struct thread { 9 | void *win32_thread; 10 | void *(*thrproc)(void *); 11 | void *arg; 12 | }; 13 | 14 | struct mutex { void *win32_crit; }; 15 | #define MUTEX_INITIALIZER { NULL } 16 | 17 | struct condvar { void *win32_cond; }; 18 | 19 | #else /* _WIN32 */ 20 | 21 | #include 22 | 23 | struct thread { pthread_t pthread; }; 24 | 25 | struct mutex { pthread_mutex_t pthread_mutex; }; 26 | #define MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } 27 | 28 | struct condvar { pthread_cond_t pthread_cond; }; 29 | 30 | #endif /* !_WIN32 */ 31 | 32 | bool thread_create(struct thread *t, void *(*thrproc)(void *), void *arg); 33 | void thread_join(struct thread *t); 34 | bool mutex_init(struct mutex *m); 35 | void mutex_destroy(struct mutex *m); 36 | void mutex_lock(struct mutex *m); 37 | void mutex_unlock(struct mutex *m); 38 | bool condvar_init(struct condvar *c); 39 | void condvar_destroy(struct condvar *c); 40 | void condvar_wait(struct condvar *c, struct mutex *m); 41 | void condvar_signal(struct condvar *c); 42 | void condvar_broadcast(struct condvar *c); 43 | 44 | #endif /* _WIMLIB_THREADS_H */ 45 | -------------------------------------------------------------------------------- /include/wimlib/timestamp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * timestamp.h 3 | * 4 | * Conversion between Windows NT timestamps and UNIX timestamps. 5 | */ 6 | 7 | #ifndef _WIMLIB_TIMESTAMP_H 8 | #define _WIMLIB_TIMESTAMP_H 9 | 10 | #include 11 | #include 12 | 13 | #include "wimlib/types.h" 14 | 15 | struct wimlib_timespec; 16 | 17 | time_t 18 | wim_timestamp_to_time_t(u64 timestamp); 19 | 20 | void 21 | wim_timestamp_to_wimlib_timespec(u64 timestamp, struct wimlib_timespec *wts, 22 | s32 *high_part_ret); 23 | 24 | struct timeval 25 | wim_timestamp_to_timeval(u64 timestamp); 26 | 27 | struct timespec 28 | wim_timestamp_to_timespec(u64 timestamp); 29 | 30 | u64 31 | time_t_to_wim_timestamp(time_t t); 32 | 33 | u64 34 | timeval_to_wim_timestamp(const struct timeval *tv); 35 | 36 | u64 37 | timespec_to_wim_timestamp(const struct timespec *ts); 38 | 39 | u64 40 | now_as_wim_timestamp(void); 41 | 42 | void 43 | wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len); 44 | 45 | #endif /* _WIMLIB_TIMESTAMP_H */ 46 | -------------------------------------------------------------------------------- /include/wimlib/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_TYPES_H 2 | #define _WIMLIB_TYPES_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "wimlib_tchar.h" 9 | #include "wimlib/compiler.h" 10 | 11 | #ifndef _NTFS_TYPES_H 12 | /* Unsigned integer types of exact size in bits */ 13 | typedef uint8_t u8; 14 | typedef uint16_t u16; 15 | typedef uint32_t u32; 16 | typedef uint64_t u64; 17 | 18 | /* Signed integer types of exact size in bits */ 19 | typedef int8_t s8; 20 | typedef int16_t s16; 21 | typedef int32_t s32; 22 | typedef int64_t s64; 23 | 24 | /* Unsigned little endian types of exact size */ 25 | typedef uint16_t _bitwise_attr le16; 26 | typedef uint32_t _bitwise_attr le32; 27 | typedef uint64_t _bitwise_attr le64; 28 | 29 | /* Unsigned big endian types of exact size */ 30 | typedef uint16_t _bitwise_attr be16; 31 | typedef uint32_t _bitwise_attr be32; 32 | typedef uint64_t _bitwise_attr be64; 33 | #endif 34 | 35 | /* A pointer to 'utf16lechar' indicates a UTF-16LE encoded string */ 36 | typedef le16 utf16lechar; 37 | 38 | #ifndef WIMLIB_WIMSTRUCT_DECLARED 39 | typedef struct WIMStruct WIMStruct; 40 | # define WIMLIB_WIMSTRUCT_DECLARED 41 | #endif 42 | 43 | /* 44 | * Type of a machine word. 'unsigned long' would be logical, but that is only 45 | * 32 bits on x86_64 Windows. The same applies to 'uint_fast32_t'. So the best 46 | * we can do without a bunch of #ifdefs appears to be 'size_t'. 47 | */ 48 | typedef size_t machine_word_t; 49 | 50 | #define WORDBYTES sizeof(machine_word_t) 51 | #define WORDBITS (8 * WORDBYTES) 52 | 53 | #endif /* _WIMLIB_TYPES_H */ 54 | -------------------------------------------------------------------------------- /include/wimlib/unaligned.h: -------------------------------------------------------------------------------- 1 | /* 2 | * unaligned.h - inline functions for unaligned memory accesses 3 | * 4 | * Copyright 2022 Eric Biggers 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | */ 27 | 28 | #ifndef _WIMLIB_UNALIGNED_H 29 | #define _WIMLIB_UNALIGNED_H 30 | 31 | #include 32 | 33 | #include "wimlib/compiler.h" 34 | #include "wimlib/endianness.h" 35 | #include "wimlib/types.h" 36 | 37 | #define DEFINE_UNALIGNED_TYPE(type) \ 38 | static forceinline type \ 39 | load_##type##_unaligned(const void *p) \ 40 | { \ 41 | type v; \ 42 | memcpy(&v, p, sizeof(v)); \ 43 | return v; \ 44 | } \ 45 | \ 46 | static forceinline void \ 47 | store_##type##_unaligned(type v, void *p) \ 48 | { \ 49 | memcpy(p, &v, sizeof(v)); \ 50 | } 51 | 52 | DEFINE_UNALIGNED_TYPE(u16); 53 | DEFINE_UNALIGNED_TYPE(u32); 54 | DEFINE_UNALIGNED_TYPE(u64); 55 | DEFINE_UNALIGNED_TYPE(le16); 56 | DEFINE_UNALIGNED_TYPE(le32); 57 | DEFINE_UNALIGNED_TYPE(le64); 58 | DEFINE_UNALIGNED_TYPE(be16); 59 | DEFINE_UNALIGNED_TYPE(be32); 60 | DEFINE_UNALIGNED_TYPE(be64); 61 | DEFINE_UNALIGNED_TYPE(size_t); 62 | DEFINE_UNALIGNED_TYPE(machine_word_t); 63 | 64 | #define load_word_unaligned load_machine_word_t_unaligned 65 | #define store_word_unaligned store_machine_word_t_unaligned 66 | 67 | static forceinline u16 68 | get_unaligned_le16(const u8 *p) 69 | { 70 | if (UNALIGNED_ACCESS_IS_FAST) 71 | return le16_to_cpu(load_le16_unaligned(p)); 72 | else 73 | return ((u16)p[1] << 8) | p[0]; 74 | } 75 | 76 | static forceinline u32 77 | get_unaligned_le32(const u8 *p) 78 | { 79 | if (UNALIGNED_ACCESS_IS_FAST) 80 | return le32_to_cpu(load_le32_unaligned(p)); 81 | else 82 | return ((u32)p[3] << 24) | ((u32)p[2] << 16) | 83 | ((u32)p[1] << 8) | p[0]; 84 | } 85 | 86 | static forceinline u32 87 | get_unaligned_be32(const u8 *p) 88 | { 89 | if (UNALIGNED_ACCESS_IS_FAST) 90 | return be32_to_cpu(load_be32_unaligned(p)); 91 | else 92 | return ((u32)p[0] << 24) | ((u32)p[1] << 16) | 93 | ((u32)p[2] << 8) | p[3]; 94 | } 95 | 96 | static forceinline void 97 | put_unaligned_le16(u16 v, u8 *p) 98 | { 99 | if (UNALIGNED_ACCESS_IS_FAST) { 100 | store_le16_unaligned(cpu_to_le16(v), p); 101 | } else { 102 | p[0] = (u8)(v >> 0); 103 | p[1] = (u8)(v >> 8); 104 | } 105 | } 106 | 107 | static forceinline void 108 | put_unaligned_le32(u32 v, u8 *p) 109 | { 110 | if (UNALIGNED_ACCESS_IS_FAST) { 111 | store_le32_unaligned(cpu_to_le32(v), p); 112 | } else { 113 | p[0] = (u8)(v >> 0); 114 | p[1] = (u8)(v >> 8); 115 | p[2] = (u8)(v >> 16); 116 | p[3] = (u8)(v >> 24); 117 | } 118 | } 119 | 120 | static forceinline void 121 | put_unaligned_be32(u32 v, u8 *p) 122 | { 123 | if (UNALIGNED_ACCESS_IS_FAST) { 124 | store_be32_unaligned(cpu_to_be32(v), p); 125 | } else { 126 | p[0] = (u8)(v >> 24); 127 | p[1] = (u8)(v >> 16); 128 | p[2] = (u8)(v >> 8); 129 | p[3] = (u8)(v >> 0); 130 | } 131 | } 132 | 133 | #endif /* _WIMLIB_UNALIGNED_H */ 134 | -------------------------------------------------------------------------------- /include/wimlib/unix_data.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_UNIX_DATA_H 2 | #define _WIMLIB_UNIX_DATA_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | struct wimlib_unix_data { 7 | u32 uid; 8 | u32 gid; 9 | u32 mode; 10 | u32 rdev; 11 | }; 12 | 13 | struct wim_inode; 14 | 15 | bool 16 | inode_has_unix_data(const struct wim_inode *inode); 17 | 18 | bool 19 | inode_get_unix_data(const struct wim_inode *inode, 20 | struct wimlib_unix_data *unix_data); 21 | 22 | #define UNIX_DATA_UID 0x1 23 | #define UNIX_DATA_GID 0x2 24 | #define UNIX_DATA_MODE 0x4 25 | #define UNIX_DATA_RDEV 0x8 26 | 27 | #define UNIX_DATA_ALL 0xF 28 | 29 | bool 30 | inode_set_unix_data(struct wim_inode *inode, 31 | struct wimlib_unix_data *unix_data, int which); 32 | 33 | #endif /* _WIMLIB_UNIX_DATA_H */ 34 | -------------------------------------------------------------------------------- /include/wimlib/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * util.h - utility functions and macros 3 | */ 4 | #ifndef _WIMLIB_UTIL_H 5 | #define _WIMLIB_UTIL_H 6 | 7 | #include "wimlib/compiler.h" 8 | #include "wimlib/types.h" 9 | 10 | /**************** 11 | * General macros 12 | *****************/ 13 | 14 | /* Cast a pointer to a struct member to a pointer to the containing struct. */ 15 | #define container_of(ptr, type, member) \ 16 | ((type *)((char *)(ptr) - offsetof(type, member))) 17 | 18 | /* Calculate 'n / d', but round up instead of down. */ 19 | #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 20 | 21 | /* Calculate 'n % d', but return 'd' if the result would be 0. */ 22 | #define MODULO_NONZERO(n, d) (((n) % (d)) ? ((n) % (d)) : (d)) 23 | 24 | /* Get the number of elements of an array type. */ 25 | #define ARRAY_LEN(array) (sizeof(array) / sizeof((array)[0])) 26 | 27 | /* Round 'v' up to the next 'alignment'-byte aligned boundary. 'alignment' must 28 | * be a power of 2. */ 29 | #undef ALIGN /* NetBSD defines this already */ 30 | #define ALIGN(v, alignment) (((v) + ((alignment) - 1)) & ~((alignment) - 1)) 31 | 32 | /* Maximum number of bytes that can be allocated on the stack. 33 | * 34 | * Note: this isn't a hard bound on the stack space used, since this is just for 35 | * individual arrays. The full call stack could use more than this. */ 36 | #define STACK_MAX 32768 37 | 38 | /* Default size of file I/O buffer. Currently assumed to be <= STACK_MAX. */ 39 | #define BUFFER_SIZE 32768 40 | 41 | /******************* 42 | * Memory allocation 43 | *******************/ 44 | 45 | void * 46 | wimlib_malloc(size_t size); 47 | 48 | void 49 | wimlib_free_memory(void *p); 50 | 51 | void * 52 | wimlib_realloc(void *ptr, size_t size); 53 | 54 | void * 55 | wimlib_calloc(size_t nmemb, size_t size); 56 | 57 | char * 58 | wimlib_strdup(const char *str); 59 | 60 | #ifdef _WIN32 61 | wchar_t * 62 | wimlib_wcsdup(const wchar_t *str); 63 | #endif 64 | 65 | void * 66 | wimlib_aligned_malloc(size_t size, size_t alignment); 67 | 68 | void 69 | wimlib_aligned_free(void *ptr); 70 | 71 | void * 72 | memdup(const void *mem, size_t size); 73 | 74 | #define MALLOC wimlib_malloc 75 | #define FREE wimlib_free_memory 76 | #define REALLOC wimlib_realloc 77 | #define CALLOC wimlib_calloc 78 | #define STRDUP wimlib_strdup 79 | #define WCSDUP wimlib_wcsdup 80 | #define ALIGNED_MALLOC wimlib_aligned_malloc 81 | #define ALIGNED_FREE wimlib_aligned_free 82 | 83 | /******************* 84 | * String utilities 85 | *******************/ 86 | 87 | #ifndef HAVE_MEMPCPY 88 | void * 89 | mempcpy(void *dst, const void *src, size_t n); 90 | #endif 91 | 92 | /************************** 93 | * Random number generation 94 | **************************/ 95 | 96 | void 97 | get_random_bytes(void *p, size_t n); 98 | 99 | void 100 | get_random_alnum_chars(tchar *p, size_t n); 101 | 102 | /************************ 103 | * Hashing and comparison 104 | ************************/ 105 | 106 | static inline bool 107 | is_power_of_2(unsigned long n) 108 | { 109 | return (n != 0 && (n & (n - 1)) == 0); 110 | 111 | } 112 | 113 | static inline u64 114 | hash_u64(u64 n) 115 | { 116 | return n * 0x9e37fffffffc0001ULL; 117 | } 118 | 119 | static inline int 120 | cmp_u32(u32 n1, u32 n2) 121 | { 122 | if (n1 < n2) 123 | return -1; 124 | if (n1 > n2) 125 | return 1; 126 | return 0; 127 | } 128 | 129 | static inline int 130 | cmp_u64(u64 n1, u64 n2) 131 | { 132 | if (n1 < n2) 133 | return -1; 134 | if (n1 > n2) 135 | return 1; 136 | return 0; 137 | } 138 | 139 | /************************ 140 | * System information 141 | ************************/ 142 | 143 | unsigned 144 | get_available_cpus(void); 145 | 146 | u64 147 | get_available_memory(void); 148 | 149 | #endif /* _WIMLIB_UTIL_H */ 150 | -------------------------------------------------------------------------------- /include/wimlib/wimboot.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMBOOT_H_ 2 | #define _WIMBOOT_H_ 3 | 4 | #include "wimlib/header.h" 5 | #include "wimlib/sha1.h" 6 | #include "wimlib/types.h" 7 | #include "wimlib/win32_common.h" 8 | 9 | struct blob_descriptor; 10 | 11 | int 12 | wimboot_alloc_data_source_id(const wchar_t *wim_path, 13 | const u8 guid[GUID_SIZE], int image, 14 | const wchar_t *target, u64 *data_source_id_ret, 15 | bool *wof_running_ret); 16 | 17 | bool 18 | wimboot_set_pointer(HANDLE h, 19 | const struct blob_descriptor *blob, 20 | u64 data_source_id, 21 | const u8 blob_table_hash[SHA1_HASH_SIZE], 22 | bool wof_running); 23 | 24 | 25 | #endif /* _WIMBOOT_H_ */ 26 | -------------------------------------------------------------------------------- /include/wimlib/win32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * win32.h - Windows-specific declarations needed by non-Windows-specific files. 3 | */ 4 | 5 | #ifndef _WIMLIB_WIN32_H 6 | #define _WIMLIB_WIN32_H 7 | 8 | #ifdef _WIN32 9 | 10 | #include "wimlib/types.h" 11 | 12 | struct blob_descriptor; 13 | struct consume_chunk_callback; 14 | struct windows_file; 15 | 16 | struct windows_file * 17 | clone_windows_file(const struct windows_file *file); 18 | 19 | void 20 | free_windows_file(struct windows_file *file); 21 | 22 | int 23 | cmp_windows_files(const struct windows_file *file1, 24 | const struct windows_file *file2); 25 | 26 | int 27 | read_windows_file_prefix(const struct blob_descriptor *blob, u64 size, 28 | const struct consume_chunk_callback *cb, 29 | bool recover_data); 30 | 31 | int 32 | win32_global_init(int init_flags); 33 | 34 | void 35 | win32_global_cleanup(void); 36 | 37 | int 38 | fsync(int fd); 39 | 40 | tchar * 41 | realpath(const tchar *path, tchar *resolved_path); 42 | 43 | int 44 | win32_rename_replacement(const tchar *oldpath, const tchar *newpath); 45 | 46 | int 47 | win32_truncate_replacement(const tchar *path, off_t size); 48 | 49 | int 50 | win32_strerror_r_replacement(int errnum, tchar *buf, size_t buflen); 51 | 52 | FILE * 53 | win32_open_logfile(const wchar_t *path); 54 | 55 | ssize_t 56 | win32_read(int fd, void *buf, size_t count); 57 | 58 | ssize_t 59 | win32_write(int fd, const void *buf, size_t count); 60 | 61 | ssize_t 62 | win32_pread(int fd, void *buf, size_t count, off_t offset); 63 | 64 | ssize_t 65 | win32_pwrite(int fd, const void *buf, size_t count, off_t offset); 66 | 67 | #endif /* _WIN32 */ 68 | 69 | #endif /* _WIMLIB_WIN32_H */ 70 | -------------------------------------------------------------------------------- /include/wimlib/win32_vss.h: -------------------------------------------------------------------------------- 1 | /* 2 | * win32_vss.h - Declarations for managing VSS snapshots. This header should 3 | * only be included by Windows-specific files. 4 | */ 5 | 6 | #ifndef _WIMLIB_WIN32_VSS_H 7 | #define _WIMLIB_WIN32_VSS_H 8 | 9 | #include "wimlib/win32_common.h" 10 | 11 | /* A reference counter for a VSS snapshot. This is embedded in another data 12 | * structure only visible to win32_vss.c. */ 13 | struct vss_snapshot { 14 | size_t refcnt; 15 | }; 16 | 17 | void 18 | vss_delete_snapshot(struct vss_snapshot *snapshot); 19 | 20 | /* Acquire a reference to the specified VSS snapshot. */ 21 | static inline struct vss_snapshot * 22 | vss_get_snapshot(struct vss_snapshot *snapshot) 23 | { 24 | if (snapshot) 25 | snapshot->refcnt++; 26 | return snapshot; 27 | } 28 | 29 | /* Release a reference to the specified VSS snapshot. When the last reference 30 | * is released, the snapshot is deleted. */ 31 | static inline void 32 | vss_put_snapshot(struct vss_snapshot *snapshot) 33 | { 34 | if (snapshot && --snapshot->refcnt == 0) 35 | vss_delete_snapshot(snapshot); 36 | } 37 | 38 | int 39 | vss_create_snapshot(const wchar_t *source, UNICODE_STRING *vss_path_ret, 40 | struct vss_snapshot **snapshot_ret); 41 | 42 | void 43 | vss_global_cleanup(void); 44 | 45 | #endif /* _WIMLIB_WIN32_VSS_H */ 46 | -------------------------------------------------------------------------------- /include/wimlib/write.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_WRITE_H 2 | #define _WIMLIB_WRITE_H 3 | 4 | #include "wimlib.h" 5 | #include "wimlib/types.h" 6 | 7 | /* Internal use only */ 8 | #define WIMLIB_WRITE_FLAG_FILE_DESCRIPTOR 0x80000000 9 | #define WIMLIB_WRITE_FLAG_APPEND 0x40000000 10 | #define WIMLIB_WRITE_FLAG_NO_NEW_BLOBS 0x20000000 11 | #define WIMLIB_WRITE_FLAG_USE_EXISTING_TOTALBYTES 0x10000000 12 | #define WIMLIB_WRITE_FLAG_NO_METADATA 0x08000000 13 | 14 | /* Keep in sync with wimlib.h */ 15 | #define WIMLIB_WRITE_MASK_PUBLIC ( \ 16 | WIMLIB_WRITE_FLAG_CHECK_INTEGRITY | \ 17 | WIMLIB_WRITE_FLAG_NO_CHECK_INTEGRITY | \ 18 | WIMLIB_WRITE_FLAG_PIPABLE | \ 19 | WIMLIB_WRITE_FLAG_NOT_PIPABLE | \ 20 | WIMLIB_WRITE_FLAG_RECOMPRESS | \ 21 | WIMLIB_WRITE_FLAG_FSYNC | \ 22 | WIMLIB_WRITE_FLAG_REBUILD | \ 23 | WIMLIB_WRITE_FLAG_SOFT_DELETE | \ 24 | WIMLIB_WRITE_FLAG_IGNORE_READONLY_FLAG | \ 25 | WIMLIB_WRITE_FLAG_SKIP_EXTERNAL_WIMS | \ 26 | WIMLIB_WRITE_FLAG_STREAMS_OK | \ 27 | WIMLIB_WRITE_FLAG_RETAIN_GUID | \ 28 | WIMLIB_WRITE_FLAG_SOLID | \ 29 | WIMLIB_WRITE_FLAG_SEND_DONE_WITH_FILE_MESSAGES | \ 30 | WIMLIB_WRITE_FLAG_NO_SOLID_SORT | \ 31 | WIMLIB_WRITE_FLAG_UNSAFE_COMPACT) 32 | 33 | #if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) 34 | int 35 | lock_wim_for_append(WIMStruct *wim); 36 | void 37 | unlock_wim_for_append(WIMStruct *wim); 38 | #else 39 | static inline int 40 | lock_wim_for_append(WIMStruct *wim) 41 | { 42 | return 0; 43 | } 44 | static inline void 45 | unlock_wim_for_append(WIMStruct *wim) 46 | { 47 | } 48 | #endif 49 | 50 | struct filedes; 51 | struct list_head; 52 | struct wim_reshdr; 53 | 54 | int 55 | write_wim_part(WIMStruct *wim, 56 | const void *path_or_fd, 57 | int image, 58 | int write_flags, 59 | unsigned num_threads, 60 | unsigned part_number, 61 | unsigned total_parts, 62 | struct list_head *blob_list_override, 63 | const u8 *guid); 64 | 65 | int 66 | write_wim_resource_from_buffer(const void *buf, 67 | size_t buf_size, 68 | bool is_metadata, 69 | struct filedes *out_fd, 70 | int out_ctype, 71 | u32 out_chunk_size, 72 | struct wim_reshdr *out_reshdr, 73 | u8 *hash_ret, 74 | int write_resource_flags); 75 | 76 | #endif /* _WIMLIB_WRITE_H */ 77 | -------------------------------------------------------------------------------- /include/wimlib/xml.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_XML_H 2 | #define _WIMLIB_XML_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | /*****************************************************************************/ 7 | 8 | struct wim_xml_info; 9 | 10 | struct wim_xml_info * 11 | xml_new_info_struct(void); 12 | 13 | void 14 | xml_free_info_struct(struct wim_xml_info *info); 15 | 16 | /*****************************************************************************/ 17 | 18 | int 19 | xml_get_image_count(const struct wim_xml_info *info); 20 | 21 | u64 22 | xml_get_total_bytes(const struct wim_xml_info *info); 23 | 24 | u64 25 | xml_get_image_total_bytes(const struct wim_xml_info *info, int image); 26 | 27 | u64 28 | xml_get_image_hard_link_bytes(const struct wim_xml_info *info, int image); 29 | 30 | bool 31 | xml_get_wimboot(const struct wim_xml_info *info, int image); 32 | 33 | u64 34 | xml_get_windows_build_number(const struct wim_xml_info *info, int image); 35 | 36 | int 37 | xml_set_wimboot(struct wim_xml_info *info, int image); 38 | 39 | /*****************************************************************************/ 40 | 41 | int 42 | xml_update_image_info(WIMStruct *wim, int image); 43 | 44 | int 45 | xml_add_image(struct wim_xml_info *info, const tchar *name); 46 | 47 | int 48 | xml_export_image(const struct wim_xml_info *src_info, int src_image, 49 | struct wim_xml_info *dest_info, const tchar *dest_image_name, 50 | const tchar *dest_image_description, bool wimboot); 51 | 52 | void 53 | xml_delete_image(struct wim_xml_info *info, int image); 54 | 55 | 56 | void 57 | xml_print_image_info(struct wim_xml_info *info, int image); 58 | 59 | /*****************************************************************************/ 60 | 61 | struct wim_reshdr; 62 | 63 | #define WIM_TOTALBYTES_USE_EXISTING ((u64)(-1)) 64 | #define WIM_TOTALBYTES_OMIT ((u64)(-2)) 65 | 66 | int 67 | read_wim_xml_data(WIMStruct *wim); 68 | 69 | int 70 | write_wim_xml_data(WIMStruct *wim, int image, 71 | u64 total_bytes, struct wim_reshdr *out_reshdr, 72 | int write_resource_flags); 73 | 74 | #endif /* _WIMLIB_XML_H */ 75 | -------------------------------------------------------------------------------- /include/wimlib/xml_windows.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_XML_WINDOWS_H 2 | #define _WIMLIB_XML_WINDOWS_H 3 | 4 | #include "wimlib/types.h" 5 | 6 | int 7 | set_windows_specific_info(WIMStruct *wim); 8 | 9 | #endif /* _WIMLIB_XML_WINDOWS_H */ 10 | -------------------------------------------------------------------------------- /include/wimlib/xmlproc.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_XMLPROC_H 2 | #define _WIMLIB_XMLPROC_H 3 | 4 | #include "wimlib/list.h" 5 | #include "wimlib/types.h" 6 | 7 | /*****************************************************************************/ 8 | 9 | enum xml_node_type { 10 | XML_ELEMENT_NODE, 11 | XML_TEXT_NODE, 12 | XML_ATTRIBUTE_NODE, 13 | }; 14 | 15 | struct xml_node { 16 | enum xml_node_type type; /* type of node */ 17 | tchar *name; /* name of ELEMENT or ATTRIBUTE */ 18 | tchar *value; /* value of TEXT or ATTRIBUTE */ 19 | struct xml_node *parent; /* parent, or NULL if none */ 20 | struct list_head children; /* children; only used for ELEMENT */ 21 | struct list_head sibling_link; 22 | }; 23 | 24 | /* Iterate through the children of an xml_node. Does nothing if passed NULL. */ 25 | #define xml_node_for_each_child(parent, child) \ 26 | if (parent) list_for_each_entry(child, &(parent)->children, sibling_link) 27 | 28 | static inline bool 29 | xml_node_is_element(const struct xml_node *node, const tchar *name) 30 | { 31 | return node->type == XML_ELEMENT_NODE && !tstrcmp(node->name, name); 32 | } 33 | 34 | struct xml_node * 35 | xml_new_element(struct xml_node *parent, const tchar *name); 36 | 37 | struct xml_node * 38 | xml_new_element_with_text(struct xml_node *parent, const tchar *name, 39 | const tchar *text); 40 | 41 | void 42 | xml_add_child(struct xml_node *parent, struct xml_node *child); 43 | 44 | void 45 | xml_unlink_node(struct xml_node *node); 46 | 47 | void 48 | xml_free_node(struct xml_node *node); 49 | 50 | const tchar * 51 | xml_element_get_text(const struct xml_node *element); 52 | 53 | int 54 | xml_element_set_text(struct xml_node *element, const tchar *text); 55 | 56 | struct xml_node * 57 | xml_get_attrib(const struct xml_node *element, const tchar *name); 58 | 59 | int 60 | xml_set_attrib(struct xml_node *element, const tchar *name, const tchar *value); 61 | 62 | void 63 | xml_replace_child(struct xml_node *parent, struct xml_node *replacement); 64 | 65 | struct xml_node * 66 | xml_clone_tree(struct xml_node *orig); 67 | 68 | bool 69 | xml_legal_path(const tchar *name); 70 | 71 | bool 72 | xml_legal_value(const tchar *value); 73 | 74 | /*****************************************************************************/ 75 | 76 | int 77 | xml_parse_document(const tchar *raw_doc, struct xml_node **doc_ret); 78 | 79 | /*****************************************************************************/ 80 | 81 | struct xml_out_buf { 82 | tchar *buf; 83 | size_t count; 84 | size_t capacity; 85 | bool oom; 86 | }; 87 | 88 | int 89 | xml_write_document(struct xml_node *doc, struct xml_out_buf *buf); 90 | 91 | #endif /* _WIMLIB_XMLPROC_H */ 92 | -------------------------------------------------------------------------------- /include/wimlib/xpress_constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * xpress_constants.h 3 | * 4 | * Constants for the XPRESS compression format. 5 | */ 6 | 7 | #ifndef _XPRESS_CONSTANTS_H 8 | #define _XPRESS_CONSTANTS_H 9 | 10 | #define XPRESS_NUM_CHARS 256 11 | #define XPRESS_NUM_SYMBOLS 512 12 | #define XPRESS_MAX_CODEWORD_LEN 15 13 | 14 | #define XPRESS_END_OF_DATA 256 15 | 16 | #define XPRESS_MIN_OFFSET 1 17 | #define XPRESS_MAX_OFFSET 65535 18 | 19 | #define XPRESS_MIN_MATCH_LEN 3 20 | #define XPRESS_MAX_MATCH_LEN 65538 21 | 22 | #endif /* _XPRESS_CONSTANTS_H */ 23 | -------------------------------------------------------------------------------- /include/wimlib_tchar.h: -------------------------------------------------------------------------------- 1 | #ifndef _WIMLIB_TCHAR_H 2 | #define _WIMLIB_TCHAR_H 3 | 4 | /* Functions to act on "tchar" strings, which have a platform-dependent encoding 5 | * and character size. */ 6 | 7 | #ifdef _WIN32 8 | #include 9 | /* 10 | * For Windows builds, the "tchar" type will be 2 bytes and will be equivalent 11 | * to "wchar_t" and "utf16lechar". All indicate one coding unit of a string 12 | * encoded in UTF-16LE with the additional possibility of unpaired surrogates. 13 | */ 14 | typedef wchar_t tchar; 15 | # define TCHAR_IS_UTF16LE 1 16 | # define _T(text) L##text 17 | # define T(text) _T(text) /* Make a string literal into a wide string */ 18 | # define TS "ls" /* Format a string of "tchar" */ 19 | # define TC "lc" /* Format a "tchar" */ 20 | 21 | /* For Windows builds, the following definitions replace the "tchar" functions 22 | * with the "wide-character" functions. */ 23 | # define tmemchr wmemchr 24 | # define tmemcpy wmemcpy 25 | # define tmemmove wmemmove 26 | # define tmempcpy wmempcpy 27 | # define tstrcat wcscat 28 | # define tstrcpy wcscpy 29 | # define tprintf wprintf 30 | # define tsprintf swprintf 31 | # define tfprintf fwprintf 32 | # define tvfprintf vfwprintf 33 | # define tscanf swscanf 34 | # define istalpha(c) iswalpha((wchar_t)(c)) 35 | # define istspace(c) iswspace((wchar_t)(c)) 36 | # define totlower(c) towlower((wchar_t)(c)) 37 | # define tstrcmp wcscmp 38 | # define tstrncmp wcsncmp 39 | # define tstrchr wcschr 40 | # define tstrpbrk wcspbrk 41 | # define tstrrchr wcsrchr 42 | # define tstrstr wcsstr 43 | # define tstrlen wcslen 44 | # define tmemcmp wmemcmp 45 | # define tstrcasecmp _wcsicmp 46 | # define tstrftime wcsftime 47 | # define tputchar putwchar 48 | # define tputc putwc 49 | # define tputs _putws 50 | # define tfputs fputws 51 | # define tfopen _wfopen 52 | # define topen _wopen 53 | # define tstat _wstati64 54 | # define tstrtol wcstol 55 | # define tstrtod wcstod 56 | # define tstrtoul wcstoul 57 | # define tstrtoull wcstoull 58 | # define tunlink _wunlink 59 | # define tstrerror _wcserror 60 | # define taccess _waccess 61 | # define tstrdup wcsdup 62 | # define tgetenv _wgetenv 63 | /* The following "tchar" functions do not have exact wide-character equivalents 64 | * on Windows so require parameter rearrangement or redirection to a replacement 65 | * function defined ourselves. */ 66 | # define TSTRDUP WCSDUP 67 | # define tmkdir(path, mode) _wmkdir(path) 68 | # define tstrerror_r(errnum, buf, bufsize) \ 69 | _wcserror_s((buf), (bufsize), (errnum)) 70 | # define trename win32_rename_replacement 71 | # define tglob win32_wglob 72 | #else /* _WIN32 */ 73 | /* 74 | * For non-Windows builds, the "tchar" type will be one byte and will specify a 75 | * string encoded in UTF-8 with the additional possibility of surrogate 76 | * codepoints. 77 | */ 78 | typedef char tchar; 79 | # define TCHAR_IS_UTF16LE 0 80 | # define T(text) text /* In this case, strings of "tchar" are simply strings of 81 | char */ 82 | # define TS "s" /* Similarly, a string of "tchar" is printed just as a 83 | normal string. */ 84 | # define TC "c" /* Print a single character */ 85 | /* For non-Windows builds, replace the "tchar" functions with the regular old 86 | * string functions. */ 87 | # define tmemchr memchr 88 | # define tmemcpy memcpy 89 | # define tmemmove memmove 90 | # define tmempcpy mempcpy 91 | # define tstrcat strcat 92 | # define tstrcpy strcpy 93 | # define tprintf printf 94 | # define tsprintf sprintf 95 | # define tfprintf fprintf 96 | # define tvfprintf vfprintf 97 | # define tscanf sscanf 98 | # define istalpha(c) isalpha((unsigned char)(c)) 99 | # define istspace(c) isspace((unsigned char)(c)) 100 | # define totlower(c) tolower((unsigned char)(c)) 101 | # define tstrcmp strcmp 102 | # define tstrncmp strncmp 103 | # define tstrchr strchr 104 | # define tstrpbrk strpbrk 105 | # define tstrrchr strrchr 106 | # define tstrstr strstr 107 | # define tstrlen strlen 108 | # define tmemcmp memcmp 109 | # define tstrcasecmp strcasecmp 110 | # define tstrftime strftime 111 | # define tputchar putchar 112 | # define tputc putc 113 | # define tputs puts 114 | # define tfputs fputs 115 | # define tfopen fopen 116 | # define topen open 117 | # define tstat stat 118 | # define tunlink unlink 119 | # define tstrerror strerror 120 | # define tstrtol strtol 121 | # define tstrtod strtod 122 | # define tstrtoul strtoul 123 | # define tstrtoull strtoull 124 | # define tmkdir mkdir 125 | # define tstrdup strdup 126 | # define tgetenv getenv 127 | # define TSTRDUP STRDUP 128 | # define tstrerror_r strerror_r 129 | # define trename rename 130 | # define taccess access 131 | # define tglob glob 132 | #endif /* !_WIN32 */ 133 | 134 | #endif /* _WIMLIB_TCHAR_H */ 135 | -------------------------------------------------------------------------------- /programs/imagex-win32.c: -------------------------------------------------------------------------------- 1 | /* Windows-specific code for wimlib-imagex. */ 2 | 3 | #ifndef _WIN32 4 | # error "This file contains Windows code" 5 | #endif 6 | 7 | #include "imagex-win32.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* Set a file descriptor to binary mode. */ 14 | void set_fd_to_binary_mode(int fd) 15 | { 16 | _setmode(fd, _O_BINARY); 17 | } 18 | 19 | #include 20 | 21 | static wchar_t * 22 | get_security_descriptor_string(PSECURITY_DESCRIPTOR desc) 23 | { 24 | wchar_t *str = NULL; 25 | /* 52 characters!!! */ 26 | ConvertSecurityDescriptorToStringSecurityDescriptorW( 27 | desc, 28 | SDDL_REVISION_1, 29 | OWNER_SECURITY_INFORMATION | 30 | GROUP_SECURITY_INFORMATION | 31 | DACL_SECURITY_INFORMATION | 32 | SACL_SECURITY_INFORMATION, 33 | &str, 34 | NULL); 35 | return str; 36 | } 37 | 38 | void 39 | win32_print_security_descriptor(const uint8_t *sd, size_t size) 40 | { 41 | wchar_t *str; 42 | const wchar_t *printstr; 43 | 44 | /* 'size' is ignored here due to the crappy Windows APIs. Oh well, this 45 | * is just for debugging anyway. */ 46 | str = get_security_descriptor_string((PSECURITY_DESCRIPTOR)sd); 47 | if (str) 48 | printstr = str; 49 | else 50 | printstr = L"(invalid)"; 51 | 52 | wprintf(L"Security Descriptor = %ls\n", printstr); 53 | 54 | LocalFree(str); 55 | } 56 | -------------------------------------------------------------------------------- /programs/imagex-win32.h: -------------------------------------------------------------------------------- 1 | #ifndef _IMAGEX_WIN32_H 2 | #define _IMAGEX_WIN32_H 3 | 4 | #include 5 | #include 6 | 7 | void 8 | win32_print_security_descriptor(const uint8_t *sd, size_t size); 9 | 10 | void 11 | set_fd_to_binary_mode(int fd); 12 | 13 | #include "wgetopt.h" 14 | 15 | #define optarg woptarg 16 | #define optind woptind 17 | #define opterr wopterr 18 | #define optopt woptopt 19 | #define option woption 20 | 21 | #define getopt_long_only wgetopt_long_only 22 | #define getopt_long wgetopt_long 23 | #define getopt wgetopt 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /programs/wgetopt.h: -------------------------------------------------------------------------------- 1 | #ifndef _WGETOPT_H 2 | #define _WGETOPT_H 3 | 4 | #include 5 | 6 | extern wchar_t *woptarg; 7 | extern int woptind, wopterr, woptopt; 8 | 9 | struct woption { 10 | const wchar_t *name; 11 | int has_arg; 12 | int *flag; 13 | int val; 14 | }; 15 | 16 | #define no_argument 0 17 | #define required_argument 1 18 | #define optional_argument 2 19 | 20 | int 21 | wgetopt (int argc, wchar_t *const *argv, const wchar_t *optstring); 22 | 23 | int 24 | wgetopt_long(int argc, wchar_t * const *argv, const wchar_t *options, 25 | const struct woption *long_options, int *opt_index); 26 | 27 | int 28 | wgetopt_long_only(int argc, wchar_t *const *argv, const wchar_t *options, 29 | const struct woption *long_options, int *opt_index); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/compress_serial.c: -------------------------------------------------------------------------------- 1 | /* 2 | * compress_serial.c 3 | * 4 | * Compress chunks of data (serial version). 5 | */ 6 | 7 | /* 8 | * Copyright (C) 2013 Eric Biggers 9 | * 10 | * This file is free software; you can redistribute it and/or modify it under 11 | * the terms of the GNU Lesser General Public License as published by the Free 12 | * Software Foundation; either version 3 of the License, or (at your option) any 13 | * later version. 14 | * 15 | * This file is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 18 | * details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this file; if not, see https://www.gnu.org/licenses/. 22 | */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | # include "config.h" 26 | #endif 27 | 28 | #include 29 | 30 | #include "wimlib.h" 31 | #include "wimlib/assert.h" 32 | #include "wimlib/chunk_compressor.h" 33 | #include "wimlib/util.h" 34 | 35 | struct serial_chunk_compressor { 36 | struct chunk_compressor base; 37 | struct wimlib_compressor *compressor; 38 | u8 *udata; 39 | u8 *cdata; 40 | u32 usize; 41 | u8 *result_data; 42 | u32 result_size; 43 | }; 44 | 45 | static void 46 | serial_chunk_compressor_destroy(struct chunk_compressor *_ctx) 47 | { 48 | struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx; 49 | 50 | if (ctx == NULL) 51 | return; 52 | 53 | wimlib_free_compressor(ctx->compressor); 54 | FREE(ctx->udata); 55 | FREE(ctx->cdata); 56 | FREE(ctx); 57 | } 58 | 59 | static void * 60 | serial_chunk_compressor_get_chunk_buffer(struct chunk_compressor *_ctx) 61 | { 62 | struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx; 63 | 64 | if (ctx->result_data) 65 | return NULL; 66 | return ctx->udata; 67 | } 68 | 69 | static void 70 | serial_chunk_compressor_signal_chunk_filled(struct chunk_compressor *_ctx, u32 usize) 71 | { 72 | struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor*)_ctx; 73 | u32 csize; 74 | 75 | wimlib_assert(usize > 0); 76 | wimlib_assert(usize <= ctx->base.out_chunk_size); 77 | 78 | ctx->usize = usize; 79 | csize = wimlib_compress(ctx->udata, usize, ctx->cdata, usize - 1, 80 | ctx->compressor); 81 | if (csize) { 82 | ctx->result_data = ctx->cdata; 83 | ctx->result_size = csize; 84 | } else { 85 | ctx->result_data = ctx->udata; 86 | ctx->result_size = ctx->usize; 87 | } 88 | } 89 | 90 | static bool 91 | serial_chunk_compressor_get_compression_result(struct chunk_compressor *_ctx, 92 | const void **cdata_ret, u32 *csize_ret, 93 | u32 *usize_ret) 94 | { 95 | struct serial_chunk_compressor *ctx = (struct serial_chunk_compressor *)_ctx; 96 | 97 | if (!ctx->result_data) 98 | return false; 99 | 100 | *cdata_ret = ctx->result_data; 101 | *csize_ret = ctx->result_size; 102 | *usize_ret = ctx->usize; 103 | 104 | ctx->result_data = NULL; 105 | return true; 106 | } 107 | 108 | int 109 | new_serial_chunk_compressor(int out_ctype, u32 out_chunk_size, 110 | struct chunk_compressor **compressor_ret) 111 | { 112 | struct serial_chunk_compressor *ctx; 113 | int ret; 114 | 115 | wimlib_assert(out_chunk_size > 0); 116 | 117 | ctx = CALLOC(1, sizeof(*ctx)); 118 | if (ctx == NULL) 119 | return WIMLIB_ERR_NOMEM; 120 | 121 | ctx->base.out_ctype = out_ctype; 122 | ctx->base.out_chunk_size = out_chunk_size; 123 | ctx->base.num_threads = 1; 124 | ctx->base.destroy = serial_chunk_compressor_destroy; 125 | ctx->base.get_chunk_buffer = serial_chunk_compressor_get_chunk_buffer; 126 | ctx->base.signal_chunk_filled = serial_chunk_compressor_signal_chunk_filled; 127 | ctx->base.get_compression_result = serial_chunk_compressor_get_compression_result; 128 | 129 | ret = wimlib_create_compressor(out_ctype, out_chunk_size, 130 | WIMLIB_COMPRESSOR_FLAG_DESTRUCTIVE, 131 | &ctx->compressor); 132 | if (ret) 133 | goto err; 134 | 135 | ctx->udata = MALLOC(out_chunk_size); 136 | ctx->cdata = MALLOC(out_chunk_size - 1); 137 | if (ctx->udata == NULL || ctx->cdata == NULL) { 138 | ret = WIMLIB_ERR_NOMEM; 139 | goto err; 140 | } 141 | ctx->result_data = NULL; 142 | 143 | *compressor_ret = &ctx->base; 144 | return 0; 145 | 146 | err: 147 | serial_chunk_compressor_destroy(&ctx->base); 148 | return ret; 149 | } 150 | -------------------------------------------------------------------------------- /src/decompress.c: -------------------------------------------------------------------------------- 1 | /* 2 | * decompress.c 3 | * 4 | * Generic functions for decompression, wrapping around actual decompression 5 | * implementations. 6 | */ 7 | 8 | /* 9 | * Copyright (C) 2013, 2014 Eric Biggers 10 | * 11 | * This file is free software; you can redistribute it and/or modify it under 12 | * the terms of the GNU Lesser General Public License as published by the Free 13 | * Software Foundation; either version 3 of the License, or (at your option) any 14 | * later version. 15 | * 16 | * This file is distributed in the hope that it will be useful, but WITHOUT 17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 19 | * details. 20 | * 21 | * You should have received a copy of the GNU Lesser General Public License 22 | * along with this file; if not, see https://www.gnu.org/licenses/. 23 | */ 24 | 25 | #ifdef HAVE_CONFIG_H 26 | # include "config.h" 27 | #endif 28 | 29 | #include "wimlib.h" 30 | #include "wimlib/decompressor_ops.h" 31 | #include "wimlib/util.h" 32 | 33 | struct wimlib_decompressor { 34 | const struct decompressor_ops *ops; 35 | size_t max_block_size; 36 | void *private; 37 | }; 38 | 39 | static const struct decompressor_ops * const decompressor_ops[] = { 40 | [WIMLIB_COMPRESSION_TYPE_XPRESS] = &xpress_decompressor_ops, 41 | [WIMLIB_COMPRESSION_TYPE_LZX] = &lzx_decompressor_ops, 42 | [WIMLIB_COMPRESSION_TYPE_LZMS] = &lzms_decompressor_ops, 43 | }; 44 | 45 | static bool 46 | decompressor_ctype_valid(int ctype) 47 | { 48 | return (ctype >= 0 && 49 | ctype < ARRAY_LEN(decompressor_ops) && 50 | decompressor_ops[ctype] != NULL); 51 | } 52 | 53 | WIMLIBAPI int 54 | wimlib_create_decompressor(enum wimlib_compression_type ctype, 55 | size_t max_block_size, 56 | struct wimlib_decompressor **dec_ret) 57 | { 58 | struct wimlib_decompressor *dec; 59 | int ret; 60 | 61 | ret = wimlib_global_init(0); 62 | if (ret) 63 | return ret; 64 | 65 | if (!decompressor_ctype_valid(ctype)) 66 | return WIMLIB_ERR_INVALID_COMPRESSION_TYPE; 67 | 68 | if (dec_ret == NULL) 69 | return WIMLIB_ERR_INVALID_PARAM; 70 | 71 | if (max_block_size == 0) 72 | return WIMLIB_ERR_INVALID_PARAM; 73 | 74 | dec = MALLOC(sizeof(*dec)); 75 | if (dec == NULL) 76 | return WIMLIB_ERR_NOMEM; 77 | dec->ops = decompressor_ops[ctype]; 78 | dec->max_block_size = max_block_size; 79 | dec->private = NULL; 80 | if (dec->ops->create_decompressor) { 81 | ret = dec->ops->create_decompressor(max_block_size, 82 | &dec->private); 83 | if (ret) { 84 | FREE(dec); 85 | return ret; 86 | } 87 | } 88 | *dec_ret = dec; 89 | return 0; 90 | } 91 | 92 | WIMLIBAPI int 93 | wimlib_decompress(const void *compressed_data, size_t compressed_size, 94 | void *uncompressed_data, size_t uncompressed_size, 95 | struct wimlib_decompressor *dec) 96 | { 97 | if (unlikely(uncompressed_size > dec->max_block_size)) 98 | return -2; 99 | 100 | return dec->ops->decompress(compressed_data, compressed_size, 101 | uncompressed_data, uncompressed_size, 102 | dec->private); 103 | } 104 | 105 | WIMLIBAPI void 106 | wimlib_free_decompressor(struct wimlib_decompressor *dec) 107 | { 108 | if (dec) { 109 | if (dec->ops->free_decompressor) 110 | dec->ops->free_decompressor(dec->private); 111 | FREE(dec); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/delete_image.c: -------------------------------------------------------------------------------- 1 | /* 2 | * delete_image.c 3 | */ 4 | 5 | /* 6 | * Copyright (C) 2012-2016 Eric Biggers 7 | * 8 | * This file is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at your option) any 11 | * later version. 12 | * 13 | * This file is distributed in the hope that it will be useful, but WITHOUT 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 16 | * details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this file; if not, see https://www.gnu.org/licenses/. 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | # include "config.h" 24 | #endif 25 | 26 | #include 27 | 28 | #include "wimlib.h" 29 | #include "wimlib/dentry.h" 30 | #include "wimlib/metadata.h" 31 | #include "wimlib/wim.h" 32 | #include "wimlib/xml.h" 33 | 34 | /* Internal method for single-image deletion. This doesn't set the 35 | * image_deletion_occurred' flag on the WIMStruct. */ 36 | int 37 | delete_wim_image(WIMStruct *wim, int image) 38 | { 39 | int ret; 40 | struct wim_image_metadata *imd; 41 | 42 | /* Load the metadata for the image to be deleted. This is necessary 43 | * because blobs referenced by files in the image need to have their 44 | * reference counts decremented. */ 45 | ret = select_wim_image(wim, image); 46 | if (ret) 47 | return ret; 48 | 49 | /* Release the files and decrement the reference counts of the blobs 50 | * they reference. */ 51 | imd = wim->image_metadata[image - 1]; 52 | free_dentry_tree(imd->root_dentry, wim->blob_table); 53 | imd->root_dentry = NULL; 54 | 55 | /* Deselect the image and release its metadata. */ 56 | deselect_current_wim_image(wim); 57 | put_image_metadata(imd); 58 | 59 | /* Remove the empty slot from the image metadata array. */ 60 | memmove(&wim->image_metadata[image - 1], &wim->image_metadata[image], 61 | (wim->hdr.image_count - image) * 62 | sizeof(wim->image_metadata[0])); 63 | 64 | /* Decrement the image count. */ 65 | wim->hdr.image_count--; 66 | 67 | /* Remove the image from the XML information. */ 68 | xml_delete_image(wim->xml_info, image); 69 | 70 | /* Fix the boot index. */ 71 | if (wim->hdr.boot_idx == image) 72 | wim->hdr.boot_idx = 0; 73 | else if (wim->hdr.boot_idx > image) 74 | wim->hdr.boot_idx--; 75 | 76 | return 0; 77 | } 78 | 79 | /* API function documented in wimlib.h */ 80 | WIMLIBAPI int 81 | wimlib_delete_image(WIMStruct *wim, int image) 82 | { 83 | int ret; 84 | int first, last; 85 | 86 | if (image == WIMLIB_ALL_IMAGES) { 87 | /* Deleting all images */ 88 | last = wim->hdr.image_count; 89 | first = 1; 90 | } else { 91 | /* Deleting one image */ 92 | last = image; 93 | first = image; 94 | } 95 | 96 | for (image = last; image >= first; image--) { 97 | ret = delete_wim_image(wim, image); 98 | if (ret) 99 | return ret; 100 | wim->image_deletion_occurred = 1; 101 | } 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /src/join.c: -------------------------------------------------------------------------------- 1 | /* 2 | * join.c 3 | * 4 | * Join split WIMs (sometimes named as .swm files) together into one WIM. 5 | */ 6 | 7 | /* 8 | * Copyright (C) 2012-2016 Eric Biggers 9 | * 10 | * This file is free software; you can redistribute it and/or modify it under 11 | * the terms of the GNU Lesser General Public License as published by the Free 12 | * Software Foundation; either version 3 of the License, or (at your option) any 13 | * later version. 14 | * 15 | * This file is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 18 | * details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this file; if not, see https://www.gnu.org/licenses/. 22 | */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | # include "config.h" 26 | #endif 27 | 28 | #include 29 | 30 | #include "wimlib.h" 31 | #include "wimlib/error.h" 32 | #include "wimlib/types.h" 33 | #include "wimlib/util.h" 34 | #include "wimlib/wim.h" 35 | 36 | /* 37 | * Verify that a list of WIM files sorted by part number is a spanned set. 38 | * 39 | * Return: 0 on success; WIMLIB_ERR_SPLIT_INVALID if the set is not valid. 40 | */ 41 | static int 42 | verify_swm_set(WIMStruct * const *swms, unsigned num_swms) 43 | { 44 | for (unsigned i = 0; i < num_swms; i++) { 45 | if (!guids_equal(swms[i]->hdr.guid, swms[0]->hdr.guid)) { 46 | ERROR("The split WIM parts specified belong to " 47 | "different split WIMs!"); 48 | return WIMLIB_ERR_SPLIT_INVALID; 49 | } 50 | if (swms[i]->hdr.total_parts != num_swms) { 51 | ERROR("\"%"TS"\" says there are %u parts in the split " 52 | "WIM, but %s%u part%s provided", 53 | swms[i]->filename, swms[i]->hdr.total_parts, 54 | num_swms < swms[i]->hdr.total_parts ? "only ":"", 55 | num_swms, num_swms > 1 ? "s were" : " was"); 56 | return WIMLIB_ERR_SPLIT_INVALID; 57 | } 58 | if (swms[i]->hdr.part_number != i + 1) { 59 | ERROR("The parts of the split WIM are not numbered " 60 | "1..%u as expected. Did you specify duplicate " 61 | "parts?", num_swms); 62 | return WIMLIB_ERR_SPLIT_INVALID; 63 | } 64 | } 65 | return 0; 66 | } 67 | 68 | static int 69 | cmp_swms_by_part_number(const void *p1, const void *p2) 70 | { 71 | WIMStruct *swm1 = *(WIMStruct **)p1; 72 | WIMStruct *swm2 = *(WIMStruct **)p2; 73 | 74 | return (int)swm1->hdr.part_number - (int)swm2->hdr.part_number; 75 | } 76 | 77 | WIMLIBAPI int 78 | wimlib_join_with_progress(const tchar * const *swm_names, 79 | unsigned num_swms, 80 | const tchar *output_path, 81 | int swm_open_flags, 82 | int wim_write_flags, 83 | wimlib_progress_func_t progfunc, 84 | void *progctx) 85 | { 86 | WIMStruct **swms; 87 | unsigned i; 88 | int ret; 89 | 90 | if (num_swms < 1 || num_swms > 0xffff) 91 | return WIMLIB_ERR_INVALID_PARAM; 92 | 93 | swms = CALLOC(num_swms, sizeof(swms[0])); 94 | if (!swms) 95 | return WIMLIB_ERR_NOMEM; 96 | 97 | for (i = 0; i < num_swms; i++) { 98 | ret = wimlib_open_wim_with_progress(swm_names[i], 99 | swm_open_flags, 100 | &swms[i], 101 | progfunc, 102 | progctx); 103 | if (ret) 104 | goto out; 105 | } 106 | 107 | qsort(swms, num_swms, sizeof(swms[0]), cmp_swms_by_part_number); 108 | 109 | ret = verify_swm_set(swms, num_swms); 110 | if (ret) 111 | goto out; 112 | 113 | ret = wimlib_reference_resources(swms[0], swms + 1, num_swms - 1, 0); 114 | if (ret) 115 | goto out; 116 | 117 | /* It is reasonably safe to provide WIMLIB_WRITE_FLAG_STREAMS_OK, as we 118 | * have verified that the specified split WIM parts form a spanned set. 119 | */ 120 | ret = wimlib_write(swms[0], output_path, WIMLIB_ALL_IMAGES, 121 | wim_write_flags | 122 | WIMLIB_WRITE_FLAG_STREAMS_OK | 123 | WIMLIB_WRITE_FLAG_RETAIN_GUID, 124 | 1); 125 | out: 126 | for (i = 0; i < num_swms; i++) 127 | wimlib_free(swms[i]); 128 | FREE(swms); 129 | return ret; 130 | } 131 | 132 | /* API function documented in wimlib.h */ 133 | WIMLIBAPI int 134 | wimlib_join(const tchar * const *swm_names, 135 | unsigned num_swms, 136 | const tchar *output_path, 137 | int swm_open_flags, 138 | int wim_write_flags) 139 | { 140 | return wimlib_join_with_progress(swm_names, num_swms, output_path, 141 | swm_open_flags, wim_write_flags, 142 | NULL, NULL); 143 | } 144 | -------------------------------------------------------------------------------- /src/pathlist.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pathlist.c 3 | * 4 | * Utility function for reading path list files. 5 | */ 6 | 7 | /* 8 | * Copyright (C) 2013 Eric Biggers 9 | * 10 | * This file is free software; you can redistribute it and/or modify it under 11 | * the terms of the GNU Lesser General Public License as published by the Free 12 | * Software Foundation; either version 3 of the License, or (at your option) any 13 | * later version. 14 | * 15 | * This file is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 18 | * details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this file; if not, see https://www.gnu.org/licenses/. 22 | */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | # include "config.h" 26 | #endif 27 | 28 | #include "wimlib/pathlist.h" 29 | #include "wimlib/textfile.h" 30 | 31 | int 32 | read_path_list_file(const tchar *listfile, 33 | tchar ***paths_ret, size_t *num_paths_ret, 34 | void **mem_ret) 35 | { 36 | STRING_LIST(paths); 37 | struct text_file_section tmp = { 38 | .name = T(""), 39 | .strings = &paths, 40 | }; 41 | void *buf; 42 | int ret; 43 | 44 | ret = load_text_file(listfile, NULL, 0, &buf, &tmp, 1, 45 | LOAD_TEXT_FILE_REMOVE_QUOTES | 46 | LOAD_TEXT_FILE_ALLOW_STDIN, NULL); 47 | if (ret) 48 | return ret; 49 | 50 | *paths_ret = paths.strings; 51 | *num_paths_ret = paths.num_strings; 52 | *mem_ret = buf; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /src/paths.c: -------------------------------------------------------------------------------- 1 | /* 2 | * paths.c - Path manipulation routines 3 | */ 4 | 5 | /* 6 | * Copyright (C) 2012, 2013 Eric Biggers 7 | * 8 | * This file is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at your option) any 11 | * later version. 12 | * 13 | * This file is distributed in the hope that it will be useful, but WITHOUT 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 16 | * details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this file; if not, see https://www.gnu.org/licenses/. 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | # include "config.h" 24 | #endif 25 | 26 | #include 27 | 28 | #include "wimlib.h" 29 | #include "wimlib/paths.h" 30 | #include "wimlib/util.h" 31 | 32 | /* Like the basename() function, but does not modify @path; it just returns a 33 | * pointer to it. This assumes the path separator is the 34 | * OS_PREFERRED_PATH_SEPARATOR. */ 35 | const tchar * 36 | path_basename(const tchar *path) 37 | { 38 | return path_basename_with_len(path, tstrlen(path)); 39 | } 40 | 41 | /* Like path_basename(), but take an explicit string length. */ 42 | const tchar * 43 | path_basename_with_len(const tchar *path, size_t len) 44 | { 45 | const tchar *p = &path[len]; 46 | 47 | do { 48 | if (p == path) 49 | return &path[len]; 50 | } while (*--p == OS_PREFERRED_PATH_SEPARATOR); 51 | 52 | do { 53 | if (p == path) 54 | return &path[0]; 55 | } while (*--p != OS_PREFERRED_PATH_SEPARATOR); 56 | 57 | return ++p; 58 | } 59 | 60 | 61 | /* Returns a pointer to the part of @path following the first colon in the last 62 | * path component, or NULL if the last path component does not contain a colon 63 | * or has no characters following the first colon. */ 64 | const tchar * 65 | path_stream_name(const tchar *path) 66 | { 67 | const tchar *base = path_basename(path); 68 | const tchar *stream_name = tstrchr(base, T(':')); 69 | if (stream_name == NULL || *(stream_name + 1) == T('\0')) 70 | return NULL; 71 | else 72 | return stream_name + 1; 73 | } 74 | 75 | /* Collapse and translate path separators, and strip trailing slashes. Doesn't 76 | * add or delete a leading slash. 77 | * 78 | * @in may alias @out. 79 | */ 80 | void 81 | do_canonicalize_path(const tchar *in, tchar *out) 82 | { 83 | tchar *orig_out = out; 84 | 85 | while (*in) { 86 | if (is_any_path_separator(*in)) { 87 | /* Collapse multiple path separators into one */ 88 | *out++ = WIM_PATH_SEPARATOR; 89 | do { 90 | in++; 91 | } while (is_any_path_separator(*in)); 92 | } else { 93 | /* Copy non-path-separator character */ 94 | *out++ = *in++; 95 | } 96 | } 97 | 98 | /* Remove trailing slash if existent */ 99 | if (out - orig_out > 1 && *(out - 1) == WIM_PATH_SEPARATOR) 100 | --out; 101 | 102 | *out = T('\0'); 103 | } 104 | 105 | /* 106 | * canonicalize_wim_path() - Given a user-provided path to a file within a WIM 107 | * image, translate it into a "canonical" path. 108 | * 109 | * - Translate both types of slash into a consistent type (WIM_PATH_SEPARATOR). 110 | * - Collapse path separators. 111 | * - Add leading slash if missing. 112 | * - Strip trailing slashes. 113 | * 114 | * Examples (with WIM_PATH_SEPARATOR == '/'): 115 | * 116 | * => / [ either NULL or empty string ] 117 | * / => / 118 | * \ => / 119 | * hello => /hello 120 | * \hello => /hello 121 | * \hello => /hello 122 | * /hello/ => /hello 123 | * \hello/ => /hello 124 | * /hello//1 => /hello/1 125 | * \\hello\\1\\ => /hello/1 126 | */ 127 | tchar * 128 | canonicalize_wim_path(const tchar *wim_path) 129 | { 130 | const tchar *in; 131 | tchar *out; 132 | tchar *result; 133 | 134 | in = wim_path; 135 | if (!in) 136 | in = T(""); 137 | 138 | result = MALLOC((1 + tstrlen(in) + 1) * sizeof(result[0])); 139 | if (!result) 140 | return NULL; 141 | 142 | out = result; 143 | 144 | /* Add leading slash if missing */ 145 | if (!is_any_path_separator(*in)) 146 | *out++ = WIM_PATH_SEPARATOR; 147 | 148 | do_canonicalize_path(in, out); 149 | 150 | return result; 151 | } 152 | -------------------------------------------------------------------------------- /src/progress.c: -------------------------------------------------------------------------------- 1 | /* 2 | * progress.c 3 | */ 4 | 5 | /* 6 | * Copyright (C) 2014 Eric Biggers 7 | * 8 | * This file is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at your option) any 11 | * later version. 12 | * 13 | * This file is distributed in the hope that it will be useful, but WITHOUT 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 16 | * details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public License 19 | * along with this file; if not, see https://www.gnu.org/licenses/. 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | # include "config.h" 24 | #endif 25 | 26 | #include "wimlib/progress.h" 27 | 28 | int 29 | report_error(wimlib_progress_func_t progfunc, 30 | void *progctx, int error_code, const tchar *path) 31 | { 32 | int ret; 33 | union wimlib_progress_info progress; 34 | tchar *cookie; 35 | 36 | if (error_code == WIMLIB_ERR_SUCCESS || 37 | error_code == WIMLIB_ERR_ABORTED_BY_PROGRESS || 38 | error_code == WIMLIB_ERR_UNKNOWN_PROGRESS_STATUS) 39 | return error_code; 40 | 41 | progress.handle_error.path = path; 42 | progress.handle_error.error_code = error_code; 43 | progress.handle_error.will_ignore = false; 44 | 45 | cookie = progress_get_win32_path(path); 46 | 47 | ret = call_progress(progfunc, WIMLIB_PROGRESS_MSG_HANDLE_ERROR, 48 | &progress, progctx); 49 | 50 | progress_put_win32_path(cookie); 51 | 52 | if (ret) 53 | return ret; 54 | 55 | if (!progress.handle_error.will_ignore) 56 | return error_code; 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /src/timestamp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * timestamp.c 3 | * 4 | * Conversion between Windows NT timestamps and UNIX timestamps. 5 | */ 6 | 7 | /* 8 | * Copyright (C) 2012-2017 Eric Biggers 9 | * 10 | * This file is free software; you can redistribute it and/or modify it under 11 | * the terms of the GNU Lesser General Public License as published by the Free 12 | * Software Foundation; either version 3 of the License, or (at your option) any 13 | * later version. 14 | * 15 | * This file is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 18 | * details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this file; if not, see https://www.gnu.org/licenses/. 22 | */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | # include "config.h" 26 | #endif 27 | 28 | #include "wimlib.h" /* for struct wimlib_timespec */ 29 | #include "wimlib/timestamp.h" 30 | 31 | /* 32 | * Timestamps in WIM files are Windows NT timestamps, or FILETIMEs: 64-bit 33 | * values storing the number of 100-nanosecond ticks since January 1, 1601. 34 | * 35 | * Note: UNIX timestamps are signed; Windows timestamps are not. Negative UNIX 36 | * timestamps represent times before 1970-01-01. When such a timestamp is 37 | * converted to a Windows timestamp, we can preserve the correct date provided 38 | * that it is not also before 1601-01-01. 39 | */ 40 | 41 | #define NANOSECONDS_PER_TICK 100 42 | #define TICKS_PER_SECOND (1000000000 / NANOSECONDS_PER_TICK) 43 | #define TICKS_PER_MICROSECOND (TICKS_PER_SECOND / 1000000) 44 | 45 | /* 46 | * EPOCH_DISTANCE is the number of seconds separating the Windows NT and UNIX 47 | * epochs. This is equal to ((1970-1601)*365+89)*24*60*60. 89 is the number 48 | * of leap years between 1970 and 1601. 49 | */ 50 | #define EPOCH_DISTANCE 11644473600 51 | 52 | /* Windows NT timestamps to UNIX timestamps */ 53 | 54 | time_t 55 | wim_timestamp_to_time_t(u64 timestamp) 56 | { 57 | return (timestamp / TICKS_PER_SECOND) - EPOCH_DISTANCE; 58 | } 59 | 60 | void 61 | wim_timestamp_to_wimlib_timespec(u64 timestamp, struct wimlib_timespec *wts, 62 | s32 *high_part_ret) 63 | { 64 | s64 sec = (timestamp / TICKS_PER_SECOND) - EPOCH_DISTANCE; 65 | 66 | wts->tv_sec = sec; 67 | wts->tv_nsec = (timestamp % TICKS_PER_SECOND) * NANOSECONDS_PER_TICK; 68 | 69 | if (sizeof(wts->tv_sec) == 4) 70 | *high_part_ret = sec >> 32; 71 | } 72 | 73 | #ifdef _WIN32 74 | static void __attribute__((unused)) 75 | check_sizeof_time_t(void) 76 | { 77 | /* Windows builds should always be using 64-bit time_t now. */ 78 | STATIC_ASSERT(sizeof(time_t) == 8); 79 | } 80 | #else 81 | struct timeval 82 | wim_timestamp_to_timeval(u64 timestamp) 83 | { 84 | return (struct timeval) { 85 | .tv_sec = wim_timestamp_to_time_t(timestamp), 86 | .tv_usec = (timestamp % TICKS_PER_SECOND) / TICKS_PER_MICROSECOND, 87 | }; 88 | } 89 | 90 | struct timespec 91 | wim_timestamp_to_timespec(u64 timestamp) 92 | { 93 | return (struct timespec) { 94 | .tv_sec = wim_timestamp_to_time_t(timestamp), 95 | .tv_nsec = (timestamp % TICKS_PER_SECOND) * NANOSECONDS_PER_TICK, 96 | }; 97 | } 98 | #endif /* !_WIN32 */ 99 | 100 | /* UNIX timestamps to Windows NT timestamps */ 101 | 102 | u64 103 | time_t_to_wim_timestamp(time_t t) 104 | { 105 | return ((u64)t + EPOCH_DISTANCE) * TICKS_PER_SECOND; 106 | } 107 | 108 | #ifndef _WIN32 109 | u64 110 | timeval_to_wim_timestamp(const struct timeval *tv) 111 | { 112 | return time_t_to_wim_timestamp(tv->tv_sec) + 113 | (u32)tv->tv_usec * TICKS_PER_MICROSECOND; 114 | } 115 | 116 | u64 117 | timespec_to_wim_timestamp(const struct timespec *ts) 118 | { 119 | return time_t_to_wim_timestamp(ts->tv_sec) + 120 | (u32)ts->tv_nsec / NANOSECONDS_PER_TICK; 121 | } 122 | 123 | /* Retrieve the current time as a WIM timestamp. */ 124 | u64 125 | now_as_wim_timestamp(void) 126 | { 127 | struct timeval tv; 128 | 129 | gettimeofday(&tv, NULL); 130 | return timeval_to_wim_timestamp(&tv); 131 | } 132 | #endif /* !_WIN32 */ 133 | 134 | /* Translate a WIM timestamp into a human-readable string. */ 135 | void 136 | wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len) 137 | { 138 | struct tm tm; 139 | time_t t = wim_timestamp_to_time_t(timestamp); 140 | 141 | gmtime_r(&t, &tm); 142 | tstrftime(buf, len, T("%a %b %d %H:%M:%S %Y UTC"), &tm); 143 | } 144 | -------------------------------------------------------------------------------- /tests/common_tests.sh: -------------------------------------------------------------------------------- 1 | 2 | msg "nothing" 3 | do_test "" 4 | 5 | msg "a single file" 6 | do_test "echo 1 > file" 7 | 8 | msg "a single directory" 9 | do_test "mkdir dir" 10 | 11 | msg "subdirectory with file" 12 | do_test "mkdir dir; echo 1 > dir/file" 13 | 14 | msg "empty file" 15 | do_test "echo -n > empty_file" 16 | 17 | msg "two empty files" 18 | do_test "echo -n > empty_file_1; echo -n > empty_file_2" 19 | 20 | msg "hard link in same directory" 21 | do_test "echo 1 > file; ln file link" 22 | 23 | msg "hard link between empty files" 24 | do_test "echo -n > empty_file; ln empty_file link" 25 | 26 | msg "relative symbolic link" 27 | do_test "echo 1 > file; ln -s file symlink" 28 | 29 | msg "absolute symbolic link" 30 | do_test "echo 1 > file; ln -s /some/absolute/target symlink" 31 | 32 | msg "large file" 33 | do_test "dd if=/dev/zero of=file bs=4096 count=10 &> /dev/null" 34 | 35 | msg "many nested directories" 36 | do_test 'mkdir dir; mkdir dir/subdir; mkdir dir/subdir/subdir2; mkdir dir/subdir/subdir3' 37 | 38 | msg "identical files and symlinks in subdirectory" 39 | do_test 'mkdir dir; 40 | echo 888 > dir/file; 41 | echo 888 > dir/idfile2; 42 | ln -s ../dir dir/circle; ln -s file dir/filelink' 43 | 44 | msg "hard link group and identical files not hard linked" 45 | do_test 'echo 888 > file; 46 | echo 888 > file2; 47 | ln file link; 48 | ln file link2; 49 | echo 888 > file3' 50 | 51 | msg "C source code of wimlib" 52 | do_test 'cp $srcdir/src/*.c .' 53 | 54 | msg "tons of random stuff" 55 | do_test 'echo -n 8 > file; 56 | ln file hardlink; 57 | ln -s hardlink symlink; 58 | echo -n 8 > identical file; 59 | dd if=/dev/urandom of=randomfile bs=4096 count=10 &>/dev/null; 60 | mkdir dir; 61 | mkdir anotherdir; 62 | cp file anotherdir; 63 | ln file anotherdir/anotherhardlink; 64 | ln -s .. anotherdir/anothersymlink; 65 | ln -s anothersymlink anotherdir/symlinktosymlink; 66 | echo -n 33 > anotherfile; 67 | echo -n > emptyfile; 68 | mkdir dir/subdir; 69 | ln file dir/subdir/file; 70 | echo -n 8 > dir/subdir/file2; 71 | ln dir/subdir/file dir/subdir/link;' 72 | 73 | msg "timestamp before 1970 (before start of UNIX epoch)" 74 | do_test 'touch -t 196901231234.56 file' 75 | -------------------------------------------------------------------------------- /tests/exclusionlists/anchored_exception_in_excluded_dir: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | /dir 3 | 4 | [ExclusionException] 5 | /dir/include* 6 | 7 | @@@ 8 | 9 | dir/ 10 | - dir/exclude.txt 11 | dir/include.txt 12 | -------------------------------------------------------------------------------- /tests/exclusionlists/anchored_prefix_match: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | /foo* 3 | 4 | @@@ 5 | 6 | - foo 7 | - foobar 8 | goo/ 9 | goo/foo 10 | goo/foobar 11 | -------------------------------------------------------------------------------- /tests/exclusionlists/anchored_simple: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | /foo 3 | 4 | @@@ 5 | 6 | - foo 7 | foobar 8 | goo/ 9 | goo/foo 10 | goo/foobar 11 | -------------------------------------------------------------------------------- /tests/exclusionlists/case_insensitive: -------------------------------------------------------------------------------- 1 | # case insensitive 2 | [ExclusionList] 3 | foo 4 | 5 | @@@ 6 | 7 | - FOO 8 | - foo 9 | BOO 10 | boo 11 | -------------------------------------------------------------------------------- /tests/exclusionlists/case_sensitive: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | foo 3 | 4 | @@@ 5 | 6 | - foo 7 | FOO 8 | -------------------------------------------------------------------------------- /tests/exclusionlists/inner_star: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | foo*bar 3 | 4 | @@@ 5 | 6 | bar 7 | foo 8 | - foobar 9 | - fooXYZbar 10 | -------------------------------------------------------------------------------- /tests/exclusionlists/multiple_stars: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | foo*bar*baz 3 | 4 | @@@ 5 | 6 | bar 7 | barbaz 8 | baz 9 | foo 10 | foobar 11 | - foobarbaz 12 | - fooXYZbarXYZbaz 13 | -------------------------------------------------------------------------------- /tests/exclusionlists/prefix_match: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | foo* 3 | 4 | @@@ 5 | 6 | boo 7 | boofoo 8 | - foo 9 | - foobar 10 | goo/ 11 | - goo/foo 12 | - goo/foobar 13 | -------------------------------------------------------------------------------- /tests/exclusionlists/question_mark: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | te?t 3 | 4 | @@@ 5 | 6 | - test 7 | - text 8 | - te?t 9 | best 10 | testing 11 | Xtest 12 | -------------------------------------------------------------------------------- /tests/exclusionlists/recursive_match: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | dir 3 | 4 | @@@ 5 | 6 | - dir/ 7 | - dir/a 8 | - dir/b 9 | foo 10 | goo 11 | subdir/ 12 | - subdir/dir/ 13 | - subdir/dir/abcd 14 | -------------------------------------------------------------------------------- /tests/exclusionlists/simple_exception: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | *.jpg 3 | 4 | [ExclusionException] 5 | test.jpg 6 | 7 | @@@ 8 | 9 | - a.jpg 10 | - abcd.jpg 11 | abcd.png 12 | test.jpg 13 | -------------------------------------------------------------------------------- /tests/exclusionlists/suffix_match: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | *.jpg 3 | 4 | @@@ 5 | 6 | a.png 7 | - a.jpg 8 | dir/ 9 | dir/a.png 10 | - dir/a.jpg 11 | -------------------------------------------------------------------------------- /tests/exclusionlists/wildcard_exception: -------------------------------------------------------------------------------- 1 | [ExclusionList] 2 | *.jpg 3 | 4 | [ExclusionException] 5 | ?oo.jpg 6 | 7 | @@@ 8 | 9 | - a.jpg 10 | - abcd.jpg 11 | boo.jpg 12 | foo.jpg 13 | foo.png 14 | -------------------------------------------------------------------------------- /tests/security_descriptor_1.base64: -------------------------------------------------------------------------------- 1 | AQAEoLgAAADEAAAAAAAAABQAAAACAKQABwAAAAAAFAD/AR8AAQEAAAAAAAUSAAAAABMYAP8BHwABAgAAAAAABSAAAAAgAgAAABMUAP8BHwABAQAAAAAABRIAAAAAGxQAAAAAEAEBAAAAAAADAAAAAAATGACpABIAAQIAAAAAAAUgAAAAIQIAAAASGAAEAAAAAQIAAAAAAAUgAAAAIQIAAAASGAACAAAAAQIAAAAAAAUgAAAAIQIAAAEBAAAAAAAFEgAAAAEBAAAAAAAFEgAAAA== -------------------------------------------------------------------------------- /tests/security_descriptor_1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/security_descriptor_1.bin -------------------------------------------------------------------------------- /tests/security_descriptor_2.base64: -------------------------------------------------------------------------------- 1 | AQAEoHQAAACAAAAAAAAAABQAAAACAGAABAAAAAAAFAD/AR8AAQEAAAAAAAUSAAAAABAYAP8BHwABAgAAAAAABSAAAAAgAgAAABAUAP8BHwABAQAAAAAABRIAAAAAEBgAqQASAAECAAAAAAAFIAAAACECAAABAQAAAAAABRIAAAABAQAAAAAABRIAAAA= -------------------------------------------------------------------------------- /tests/security_descriptor_2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/security_descriptor_2.bin -------------------------------------------------------------------------------- /tests/set_reparse_point.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static const wchar_t * 7 | win32_error_string(DWORD err) 8 | { 9 | static wchar_t buf[1024]; 10 | buf[0] = L'\0'; 11 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, 1024, NULL); 12 | return buf; 13 | } 14 | 15 | static void 16 | fail(const char *func) 17 | { 18 | DWORD err = GetLastError(); 19 | fprintf(stderr, "%s (err 0x%08x: %ls)\n", func, 20 | (uint32_t)err, win32_error_string(err)); 21 | exit(1); 22 | } 23 | 24 | int 25 | wmain(int argc, wchar_t **argv) 26 | { 27 | uint16_t rpdatalen = 80; 28 | 29 | if (argc < 2 || argc > 3) { 30 | fprintf(stderr, "Usage: %ls FILE [rpdatalen]\n", argv[0]); 31 | return 1; 32 | } 33 | 34 | if (argc == 3) 35 | rpdatalen = wcstol(argv[2], NULL, 10); 36 | 37 | HANDLE h = CreateFile(argv[1], 38 | GENERIC_WRITE, 39 | FILE_SHARE_VALID_FLAGS, 40 | NULL, 41 | OPEN_EXISTING, 42 | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 43 | NULL); 44 | if (h == INVALID_HANDLE_VALUE) 45 | fail("CreateFile"); 46 | 47 | uint8_t in[8 + rpdatalen]; 48 | uint8_t *p = in; 49 | *(uint32_t *)p = 0x80000000; /* rptag */ 50 | p += 4; 51 | *(uint16_t *)p = rpdatalen; /* rpdatalen */ 52 | p += 2; 53 | *(uint16_t *)p = 0x1234; /* rpreserved */ 54 | p += 2; 55 | memset(p, 0, rpdatalen); /* rpdata */ 56 | p += rpdatalen; 57 | 58 | DWORD bytes_returned; 59 | 60 | if (!DeviceIoControl(h, FSCTL_SET_REPARSE_POINT, in, p - in, 61 | NULL, 0, &bytes_returned, NULL)) 62 | fail("DeviceIoControl"); 63 | 64 | CloseHandle(h); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /tests/test_utils.sh: -------------------------------------------------------------------------------- 1 | if stat -c %i . &> /dev/null ; then 2 | BSD_STAT=0 3 | else 4 | BSD_STAT=1 5 | fi 6 | 7 | get_inode_number() 8 | { 9 | if [ "$BSD_STAT" -eq 1 ]; then 10 | stat -f %i "$1" 11 | else 12 | stat -c %i "$1" 13 | fi 14 | } 15 | 16 | get_link_count() 17 | { 18 | if [ "$BSD_STAT" -eq 1 ]; then 19 | stat -f %l "$1" 20 | else 21 | stat -c %h "$1" 22 | fi 23 | } 24 | 25 | get_file_size() 26 | { 27 | if [ "$BSD_STAT" -eq 1 ]; then 28 | stat -f %z "$1" 29 | else 30 | stat -c %s "$1" 31 | fi 32 | } 33 | 34 | wimlib_imagex() 35 | { 36 | ../../wimlib-imagex "$@" 37 | } 38 | 39 | wimappend() 40 | { 41 | wimlib_imagex append "$@" > /dev/null 42 | } 43 | 44 | wimapply() 45 | { 46 | wimlib_imagex apply "$@" > /dev/null 47 | } 48 | 49 | wimcapture() 50 | { 51 | wimlib_imagex capture "$@" > /dev/null 52 | } 53 | 54 | wimdelete() 55 | { 56 | wimlib_imagex delete "$@" > /dev/null 57 | } 58 | 59 | wimdir() 60 | { 61 | wimlib_imagex dir "$@" 62 | } 63 | 64 | wimexport() 65 | { 66 | wimlib_imagex export "$@" > /dev/null 67 | } 68 | 69 | wimextract() 70 | { 71 | wimlib_imagex extract "$@" > /dev/null 72 | } 73 | 74 | wiminfo() 75 | { 76 | wimlib_imagex info "$@" 77 | } 78 | 79 | wimjoin() 80 | { 81 | wimlib_imagex join "$@" > /dev/null 82 | } 83 | 84 | wimmount() 85 | { 86 | wimlib_imagex mount "$@" > /dev/null 87 | } 88 | 89 | wimmountrw() 90 | { 91 | wimlib_imagex mountrw "$@" > /dev/null 92 | } 93 | 94 | wimoptimize() 95 | { 96 | wimlib_imagex optimize "$@" > /dev/null 97 | } 98 | 99 | wimsplit() 100 | { 101 | wimlib_imagex split "$@" > /dev/null 102 | } 103 | 104 | wimunmount() 105 | { 106 | wimlib_imagex unmount "$@" > /dev/null 107 | } 108 | 109 | wimupdate() 110 | { 111 | wimlib_imagex update "$@" > /dev/null 112 | } 113 | 114 | wimverify() 115 | { 116 | wimlib_imagex verify "$@" > /dev/null 117 | } 118 | 119 | wim_ctype() 120 | { 121 | wiminfo $1 | grep Compression | awk '{print $2}' 122 | } 123 | 124 | default_cleanup() 125 | { 126 | rm -rf $TEST_SUBDIR 127 | } 128 | 129 | error() 130 | { 131 | echo "****************************************************************" 132 | echo " Test failure " 133 | echo $* 134 | echo "****************************************************************" 135 | exit 1 136 | } 137 | -------------------------------------------------------------------------------- /tests/wims/README: -------------------------------------------------------------------------------- 1 | Some fun files: 2 | 3 | corrupted_file_1.wim: This WIM contains a file whose SHA-1 digest doesn't match. 4 | 5 | corrupted_file_2.wim: This WIM contains a file that fails to decompress. 6 | 7 | cyclic.wim: This WIM has an image with a cyclic directory structure and should be 8 | detected as invalid. 9 | 10 | duplicate_names.wim: This WIM has an image with multiple files with the same 11 | name in the same directory, and should be detected as invalid. 12 | 13 | dotdot.wim: This WIM has an image with the path 14 | /../../../../../../../../../../../../../../../../etc/passwd, and should be 15 | detected as invalid. (Fun fact: WIMGAPI is dumb and will extract .. files, and 16 | requires running with Admin rights, so given a malicious WIM file it will 17 | overwrite arbitrary files on the target drive.) 18 | 19 | longpaths.wim: This WIM has an image with a path longer than MAX_PATH on Windows. 20 | This should still be extracted successfully. 21 | 22 | empty_dacl.wim: This WIM has an image containing file with a security 23 | descriptor having an empty DACL. This is valid and should be extracted 24 | successfully. 25 | 26 | linux_xattrs_old.wim: Includes Linux xattrs in old format 27 | (TAG_WIMLIB_LINUX_XATTRS) 28 | -------------------------------------------------------------------------------- /tests/wims/corrupted_file_1.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/corrupted_file_1.wim -------------------------------------------------------------------------------- /tests/wims/corrupted_file_2.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/corrupted_file_2.wim -------------------------------------------------------------------------------- /tests/wims/cyclic.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/cyclic.wim -------------------------------------------------------------------------------- /tests/wims/dotdot.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/dotdot.wim -------------------------------------------------------------------------------- /tests/wims/duplicate_names.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/duplicate_names.wim -------------------------------------------------------------------------------- /tests/wims/empty_dacl.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/empty_dacl.wim -------------------------------------------------------------------------------- /tests/wims/linux_xattrs_old.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/linux_xattrs_old.wim -------------------------------------------------------------------------------- /tests/wims/longpaths.wim: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tests/wims/longpaths.wim -------------------------------------------------------------------------------- /tests/win32-test-imagex-capture_and_apply.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e -u -v 4 | 5 | ./tools/windows-build.sh 6 | bindir=$(find . -name 'wimlib-*-bin' | tail -1) 7 | for helper in win32-tree-cmp set_reparse_point; do 8 | cc -O2 -municode -Wall -Werror ./tests/$helper.c -o "$bindir"/$helper.exe 9 | chmod 700 "$bindir"/$helper.exe 10 | done 11 | cd "$bindir" 12 | ../tests/win32-test-imagex-capture_and_apply.bat 13 | -------------------------------------------------------------------------------- /tools/compress_upcase_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | * compress_upcase_table.c 3 | * 4 | * Compress a table that maps each UCS-2 character to its upper case equivalent. 5 | * 6 | * ---------------------------------------------------------------------------- 7 | * 8 | * Copyright (C) 2015 Eric Biggers 9 | * 10 | * This file is free software; you can redistribute it and/or modify it under 11 | * the terms of the GNU Lesser General Public License as published by the Free 12 | * Software Foundation; either version 3 of the License, or (at your option) any 13 | * later version. 14 | * 15 | * This file is distributed in the hope that it will be useful, but WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 18 | * details. 19 | * 20 | * You should have received a copy of the GNU Lesser General Public License 21 | * along with this file; if not, see https://www.gnu.org/licenses/. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define LEN 65536 31 | #define SIZE (65536 * sizeof(uint16_t)) 32 | 33 | static uint16_t 34 | match_length(const uint16_t *p1, const uint16_t *p2, uint16_t max_len) 35 | { 36 | uint16_t len = 0; 37 | 38 | while (len < max_len && p1[len] == p2[len]) 39 | len++; 40 | 41 | return len; 42 | } 43 | 44 | static void 45 | longest_match(const uint16_t *tab, uint16_t cur_pos, 46 | uint16_t *len_ret, uint16_t *src_pos_ret) 47 | { 48 | uint16_t max_len = LEN - cur_pos; 49 | uint16_t src_pos; 50 | *len_ret = 0; 51 | *src_pos_ret = 0; 52 | for (src_pos = 0; src_pos < cur_pos; src_pos++) { 53 | /* check for match at this pos */ 54 | uint16_t len = match_length(&tab[cur_pos], &tab[src_pos], max_len); 55 | if (len > *len_ret) { 56 | *len_ret = len; 57 | *src_pos_ret = src_pos; 58 | } 59 | } 60 | } 61 | 62 | static void 63 | output(uint16_t v) 64 | { 65 | printf("0x%04x, ", v); 66 | } 67 | 68 | int main() 69 | { 70 | int fd = open("upcase.tab", O_RDONLY); 71 | if (fd < 0) { 72 | fprintf(stderr, "ERROR: upcase.tab not found\n"); 73 | return 1; 74 | } 75 | uint16_t *tab = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); 76 | uint32_t i; 77 | 78 | /* Delta filter */ 79 | for (i = 0; i < LEN; i++) 80 | tab[i] -= i; 81 | 82 | /* Simple LZ encoder */ 83 | for (i = 0; i < LEN; ) { 84 | uint16_t len, src_pos; 85 | longest_match(tab, i, &len, &src_pos); 86 | if (len <= 1) { 87 | /* Literal */ 88 | output(0); 89 | output(tab[i]); 90 | i++; 91 | } else { 92 | /* Match */ 93 | output(len); 94 | output(src_pos); 95 | i += len; 96 | } 97 | } 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /tools/generate_language_id_map.c: -------------------------------------------------------------------------------- 1 | /* 2 | * generate_language_id_map.c 3 | * 4 | * Generate a memory-efficient map from Windows language IDs to names. This 5 | * program runs on Windows and uses LCIDToLocaleName() to enumerate all 6 | * languages recognized by Windows. 7 | * 8 | * ---------------------------------------------------------------------------- 9 | * 10 | * Copyright (C) 2016 Eric Biggers 11 | * 12 | * This file is free software; you can redistribute it and/or modify it under 13 | * the terms of the GNU Lesser General Public License as published by the Free 14 | * Software Foundation; either version 3 of the License, or (at your option) any 15 | * later version. 16 | * 17 | * This file is distributed in the hope that it will be useful, but WITHOUT 18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 19 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 20 | * details. 21 | * 22 | * You should have received a copy of the GNU Lesser General Public License 23 | * along with this file; if not, see https://www.gnu.org/licenses/. 24 | */ 25 | 26 | #define WINVER 0x6000 /* Needed for LCIDToLocaleName() declaration */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | static struct { 34 | uint16_t id; 35 | char name[LOCALE_NAME_MAX_LENGTH]; 36 | } map[65536]; 37 | 38 | int main(void) 39 | { 40 | uint32_t num_languages = 0; 41 | uint32_t name_start_offset = 0; 42 | uint32_t num_chars; 43 | bool need_new_line = true; 44 | 45 | for (uint32_t lcid = 0; lcid < 65536; lcid++) { 46 | wchar_t locale_name[LOCALE_NAME_MAX_LENGTH]; 47 | 48 | if (LCIDToLocaleName(lcid, locale_name, LOCALE_NAME_MAX_LENGTH, 0)) { 49 | size_t len = wcslen(locale_name); 50 | for (size_t j = 0; j <= len; j++) { 51 | if (locale_name[j] > 127) { 52 | fprintf(stderr, 53 | "ERROR: locale name \"%ls\" " 54 | "includes non-ASCII characters", 55 | locale_name); 56 | return 1; 57 | } 58 | map[num_languages].name[j] = locale_name[j]; 59 | } 60 | map[num_languages++].id = lcid; 61 | } else if (GetLastError() != ERROR_INVALID_PARAMETER) { 62 | fprintf(stderr, 63 | "ERROR: LCIDToLocaleName(%"PRIx32"): %u\n", 64 | lcid, (unsigned)GetLastError()); 65 | return 1; 66 | } 67 | } 68 | 69 | printf("static const struct {\n"); 70 | printf("\tu16 id;\n"); 71 | printf("\tu16 name_start_offset;\n"); 72 | printf("} language_id_map[%"PRIu32"] = {", num_languages); 73 | for (uint32_t i = 0; i < num_languages; i++) { 74 | if (need_new_line) 75 | printf("\n\t"); 76 | printf("{0x%04x, %4"PRIu32"},", map[i].id, name_start_offset); 77 | need_new_line = (i % 4 == 3); 78 | if (!need_new_line) 79 | putchar(' '); 80 | name_start_offset += strlen(map[i].name) + 1; 81 | if (name_start_offset > 65536) { 82 | fprintf(stderr, "ERROR: total length of " 83 | "language names is too long!"); 84 | return 1; 85 | } 86 | } 87 | printf("\n};\n"); 88 | printf("\n"); 89 | 90 | printf("static const char language_names[%"PRIu32"] =\n", 91 | name_start_offset); 92 | printf("\t\""); 93 | num_chars = 8; 94 | for (uint32_t i = 0; i < num_languages; i++) { 95 | size_t len = strlen(map[i].name); 96 | need_new_line = (num_chars + len + 3 > 80); 97 | if (need_new_line) { 98 | printf("\"\n"); 99 | printf("\t\""); 100 | num_chars = 9; 101 | } 102 | printf("%s\\0", map[i].name); 103 | num_chars += len + 2; 104 | } 105 | printf("\";\n"); 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /tools/get-version-number.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Get the version number of the project to use in the release filenames 4 | # and in the --version output. 5 | 6 | vers=$(git describe --abbrev=8 --dirty --always 2>/dev/null | \ 7 | sed 's/^v//') 8 | if [ -z "$vers" ]; then 9 | # Fallback for people who use autoreconf on tarball releases 10 | vers="1.14.4" 11 | fi 12 | echo "$vers" 13 | -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/lzms20: -------------------------------------------------------------------------------- 1 | CHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/lzms50: -------------------------------------------------------------------------------- 1 | 2CHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/lzms80: -------------------------------------------------------------------------------- 1 | PCHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/lzx20: -------------------------------------------------------------------------------- 1 | CHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/lzx50: -------------------------------------------------------------------------------- 1 | 2CHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/lzx80: -------------------------------------------------------------------------------- 1 | PCHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/xpress20: -------------------------------------------------------------------------------- 1 | CHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/xpress50: -------------------------------------------------------------------------------- 1 | 2CHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/corpus/xpress80: -------------------------------------------------------------------------------- 1 | PCHAPTER 1. Loomings. 2 | 3 | Call me Ishmael. Some years ago—never mind how long precisely—having 4 | little or no money in my purse, and nothing particular to interest me 5 | on shore, I thought I would sail about a little and see the watery part 6 | of the world. It is a way I have of driving off the spleen and 7 | regulating the circulation. Whenever I find myself growing grim about 8 | the mouth; whenever it is a damp, drizzly November in my soul; whenever 9 | I find myself involuntarily pausing before coffin warehouses, and 10 | bringing up the rear of every funeral I meet; and especially whenever 11 | my hypos get such an upper hand of me, that it requires a strong moral 12 | principle to prevent me from deliberately stepping into the street, and 13 | methodically knocking people’s hats off—then, I account it high time to 14 | get to sea as soon as I can. This is my substitute for pistol and ball. 15 | With a philosophical flourish Cato throws himself upon his sword; I 16 | quietly take to the ship. There is nothing su -------------------------------------------------------------------------------- /tools/libFuzzer/compress/fuzz.c: -------------------------------------------------------------------------------- 1 | #include "../fuzzer.h" 2 | 3 | /* Fuzz the compression and decompression round trip. */ 4 | int LLVMFuzzerTestOneInput(const uint8_t *in, size_t insize) 5 | { 6 | int ctype; 7 | int level; 8 | struct wimlib_compressor *c; 9 | struct wimlib_decompressor *d; 10 | size_t csize_avail = insize; 11 | uint8_t *cbuf; 12 | uint8_t *decompressed; 13 | size_t csize; 14 | int ret; 15 | 16 | if (insize < 2) 17 | return 0; 18 | ctype = 1 + ((uint8_t)(in[0] - 1) % 3); /* 1-3 */ 19 | level = 1 + (in[1] % 100); /* 1-100 */ 20 | in += 2; 21 | insize -= 2; 22 | 23 | cbuf = malloc(csize_avail); 24 | decompressed = malloc(insize); 25 | 26 | ret = wimlib_create_compressor(ctype, insize, level, &c); 27 | if (ret == 0) { 28 | ret = wimlib_create_decompressor(ctype, insize, &d); 29 | assert(ret == 0); 30 | 31 | csize = wimlib_compress(in, insize, cbuf, csize_avail, c); 32 | if (csize) { 33 | ret = wimlib_decompress(cbuf, csize, 34 | decompressed, insize, d); 35 | assert(ret == 0); 36 | assert(memcmp(in, decompressed, insize) == 0); 37 | } 38 | wimlib_free_compressor(c); 39 | wimlib_free_decompressor(d); 40 | } 41 | free(cbuf); 42 | free(decompressed); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tools/libFuzzer/decompress/corpus/lzms: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tools/libFuzzer/decompress/corpus/lzms -------------------------------------------------------------------------------- /tools/libFuzzer/decompress/corpus/lzx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tools/libFuzzer/decompress/corpus/lzx -------------------------------------------------------------------------------- /tools/libFuzzer/decompress/corpus/xpress: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tools/libFuzzer/decompress/corpus/xpress -------------------------------------------------------------------------------- /tools/libFuzzer/decompress/fuzz.c: -------------------------------------------------------------------------------- 1 | #include "../fuzzer.h" 2 | 3 | /* Fuzz decompression. */ 4 | int LLVMFuzzerTestOneInput(const uint8_t *in, size_t insize) 5 | { 6 | int ctype; 7 | struct wimlib_decompressor *d; 8 | const size_t outsize_avail = 3 * insize; 9 | uint8_t *out; 10 | int ret; 11 | 12 | if (insize < 1) 13 | return 0; 14 | ctype = 1 + ((uint8_t)(in[0] - 1) % 3); /* 1-3 */ 15 | in++; 16 | insize--; 17 | 18 | ret = wimlib_create_decompressor(ctype, insize, &d); 19 | if (ret == 0) { 20 | out = malloc(outsize_avail); 21 | wimlib_decompress(in, insize, out, outsize_avail, d); 22 | wimlib_free_decompressor(d); 23 | free(out); 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /tools/libFuzzer/encoding/corpus/0: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /tools/libFuzzer/encoding/corpus/1: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /tools/libFuzzer/encoding/fuzz.c: -------------------------------------------------------------------------------- 1 | #include "../fuzzer.h" 2 | 3 | /* 4 | * "UTF-8" (actually "WTF-8") to UTF-16LE (actually "arbitrary sequence of 5 | * 16-bit wchars") and back again should be lossless, unless the initial string 6 | * isn't valid WTF-8, in which case WIMLIB_ERR_INVALID_UTF8_STRING is expected. 7 | */ 8 | static void 9 | fuzz_utf8_roundtrip(const u8 *in, size_t insize) 10 | { 11 | utf16lechar *utf16; 12 | size_t utf16_size; 13 | int ret; 14 | char *result; 15 | size_t result_size; 16 | 17 | ret = wimlib_utf8_to_utf16le((const char *)in, insize, 18 | &utf16, &utf16_size); 19 | if (ret) { 20 | assert(ret == WIMLIB_ERR_INVALID_UTF8_STRING); 21 | return; 22 | } 23 | assert(ret == 0); 24 | ret = wimlib_utf16le_to_utf8(utf16, utf16_size, &result, &result_size); 25 | assert(ret == 0); 26 | assert(result_size == insize); 27 | assert(memcmp(result, in, insize) == 0); 28 | free(result); 29 | free(utf16); 30 | } 31 | 32 | /* 33 | * "UTF-16LE" (actually "arbitrary sequence of 16-bit wchars") to UTF-8 34 | * (actually "WTF-8") and back again should be lossless, unless the initial 35 | * length isn't a multiple of 2 bytes, in which case 36 | * WIMLIB_ERR_INVALID_UTF16_STRING is expected. 37 | */ 38 | static void 39 | fuzz_utf16_roundtrip(const u8 *in, size_t insize) 40 | { 41 | utf16lechar *in_aligned = malloc(insize); 42 | char *utf8; 43 | size_t utf8_size; 44 | int ret; 45 | utf16lechar *result; 46 | size_t result_size; 47 | 48 | memcpy(in_aligned, in, insize); 49 | ret = wimlib_utf16le_to_utf8(in_aligned, insize, &utf8, &utf8_size); 50 | if (insize % 2) { 51 | assert(ret == WIMLIB_ERR_INVALID_UTF16_STRING); 52 | free(in_aligned); 53 | return; 54 | } 55 | assert(ret == 0); 56 | ret = wimlib_utf8_to_utf16le(utf8, utf8_size, &result, &result_size); 57 | assert(ret == 0); 58 | assert(result_size == insize); 59 | assert(memcmp(result, in, insize) == 0); 60 | free(result); 61 | free(utf8); 62 | free(in_aligned); 63 | } 64 | 65 | /* Fuzz character encoding conversion. */ 66 | int LLVMFuzzerTestOneInput(const u8 *in, size_t insize) 67 | { 68 | int which; 69 | 70 | if (insize < 1) 71 | return 0; 72 | which = *in++; 73 | insize--; 74 | switch (which) { 75 | case 0: 76 | fuzz_utf8_roundtrip(in, insize); 77 | break; 78 | case 1: 79 | fuzz_utf16_roundtrip(in, insize); 80 | break; 81 | } 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /tools/libFuzzer/fault-injection.c: -------------------------------------------------------------------------------- 1 | #include "fuzzer.h" 2 | 3 | static int64_t num_allocs_remaining; 4 | 5 | static void * 6 | faultinject_malloc(size_t size) 7 | { 8 | if (__atomic_sub_fetch(&num_allocs_remaining, 1, __ATOMIC_RELAXED) <= 0) 9 | return NULL; 10 | return malloc(size); 11 | } 12 | 13 | static void 14 | faultinject_free(void *p) 15 | { 16 | free(p); 17 | } 18 | 19 | static void * 20 | faultinject_realloc(void *p, size_t size) 21 | { 22 | if (__atomic_sub_fetch(&num_allocs_remaining, 1, __ATOMIC_RELAXED) <= 0) 23 | return NULL; 24 | return realloc(p, size); 25 | } 26 | 27 | bool 28 | setup_fault_nth(const uint8_t **in, size_t *insize, uint16_t *fault_nth) 29 | { 30 | uint16_t n; 31 | 32 | if (*insize < 2) 33 | return false; 34 | memcpy(&n, *in, 2); 35 | wimlib_set_memory_allocator(faultinject_malloc, faultinject_free, 36 | faultinject_realloc); 37 | num_allocs_remaining = n ?: INT64_MAX; 38 | *in += 2; 39 | *insize -= 2; 40 | *fault_nth = n; 41 | return true; 42 | } 43 | -------------------------------------------------------------------------------- /tools/libFuzzer/fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e -u -o pipefail 4 | 5 | cd "$(dirname "$0")" 6 | TOPDIR=../.. 7 | SCRIPTDIR=$PWD 8 | 9 | read -r -a AVAILABLE_TARGETS < <(echo */fuzz.c | sed 's@/fuzz.c@@g') 10 | 11 | usage() 12 | { 13 | cat << EOF 14 | Usage: $0 [OPTION]... FUZZ_TARGET 15 | 16 | Fuzz wimlib with LLVM's libFuzzer. 17 | 18 | Options: 19 | --asan Enable AddressSanitizer 20 | --input=INPUT Test a single input file only 21 | --max-len=LEN Maximum length of generated inputs (default: $MAX_LEN) 22 | --msan Enable MemorySanitizer 23 | --time=SECONDS Stop after the given time has passed 24 | --ubsan Enable UndefinedBehaviorSanitizer 25 | 26 | Available fuzz targets: ${AVAILABLE_TARGETS[*]} 27 | EOF 28 | } 29 | 30 | die() 31 | { 32 | echo "$*" 1>&2 33 | exit 1 34 | } 35 | 36 | run_cmd() 37 | { 38 | echo "$*" 39 | "$@" 40 | } 41 | 42 | EXTRA_SANITIZERS= 43 | EXTRA_FUZZER_ARGS=() 44 | INPUT= 45 | MAX_LEN=32768 46 | 47 | longopts_array=( 48 | asan 49 | help 50 | input: 51 | max-len: 52 | msan 53 | time: 54 | ubsan 55 | ) 56 | longopts=$(echo "${longopts_array[@]}" | tr ' ' ',') 57 | 58 | if ! options=$(getopt -o "" -l "$longopts" -- "$@"); then 59 | usage 1>&2 60 | exit 1 61 | fi 62 | eval set -- "$options" 63 | while true; do 64 | case "$1" in 65 | --asan) 66 | EXTRA_SANITIZERS+=",address" 67 | ;; 68 | --help) 69 | usage 70 | exit 0 71 | ;; 72 | --input) 73 | INPUT=$2 74 | shift 75 | ;; 76 | --max-len) 77 | MAX_LEN=$2 78 | shift 79 | ;; 80 | --msan) 81 | EXTRA_SANITIZERS+=",memory" 82 | ;; 83 | --time) 84 | EXTRA_FUZZER_ARGS+=("-max_total_time=$2") 85 | shift 86 | ;; 87 | --ubsan) 88 | EXTRA_SANITIZERS+=",undefined" 89 | ;; 90 | --) 91 | shift 92 | break 93 | ;; 94 | *) 95 | echo 1>&2 "Invalid option '$1'" 96 | usage 1>&2 97 | exit 1 98 | esac 99 | shift 100 | done 101 | EXTRA_FUZZER_ARGS+=("-max_len=$MAX_LEN") 102 | 103 | if (( $# != 1 )); then 104 | echo 1>&2 "No fuzz target specified!" 105 | usage 1>&2 106 | exit 1 107 | fi 108 | TARGET=$1 109 | if [ ! -e "$TARGET/fuzz.c" ]; then 110 | echo 1>&2 "'$TARGET' is not a valid fuzz target!" 111 | usage 1>&2 112 | exit 1 113 | fi 114 | cd "$TOPDIR" 115 | cflags="-g -O1 -Wall -Werror" 116 | cflags+=" -fsanitize=fuzzer-no-link$EXTRA_SANITIZERS" 117 | if [ -n "$EXTRA_SANITIZERS" ]; then 118 | cflags+=" -fno-sanitize-recover=${EXTRA_SANITIZERS#,}" 119 | fi 120 | if ! [ -e config.log ] || ! grep -q -- "'CFLAGS=$cflags'" config.log; then 121 | run_cmd ./configure --enable-test-support --without-fuse --without-ntfs-3g \ 122 | CC=clang CFLAGS="$cflags" 123 | fi 124 | run_cmd make "-j$(getconf _NPROCESSORS_ONLN)" 125 | cd "$SCRIPTDIR" 126 | if [ -n "$INPUT" ]; then 127 | run_cmd clang -g -O1 -fsanitize=fuzzer-no-link$EXTRA_SANITIZERS -Wall -Werror \ 128 | -I "$TOPDIR/include" "$TARGET/fuzz.c" test-one-input.c fault-injection.c \ 129 | "$TOPDIR/.libs/libwim.a" -o test-one-input 130 | run_cmd ./test-one-input "$INPUT" 131 | else 132 | run_cmd clang -g -O1 -fsanitize=fuzzer$EXTRA_SANITIZERS -Wall -Werror \ 133 | -I "$TOPDIR/include" "$TARGET/fuzz.c" fault-injection.c \ 134 | "$TOPDIR/.libs/libwim.a" -o "$TARGET/fuzz" 135 | run_cmd "$TARGET/fuzz" "${EXTRA_FUZZER_ARGS[@]}" "$TARGET/corpus" 136 | fi 137 | -------------------------------------------------------------------------------- /tools/libFuzzer/fuzzer.h: -------------------------------------------------------------------------------- 1 | #define ENABLE_TEST_SUPPORT 1 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | bool 13 | setup_fault_nth(const uint8_t **in, size_t *insize, uint16_t *fault_nth); 14 | -------------------------------------------------------------------------------- /tools/libFuzzer/test-one-input.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int LLVMFuzzerTestOneInput(const uint8_t *in, size_t insize); 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | int fd; 13 | struct stat stbuf; 14 | uint8_t *in; 15 | 16 | fd = open(argv[1], O_RDONLY); 17 | if (fd < 0) { 18 | perror(argv[1]); 19 | return 1; 20 | } 21 | if (fstat(fd, &stbuf) != 0) { 22 | perror("fstat"); 23 | return 1; 24 | } 25 | in = malloc(stbuf.st_size); 26 | if (read(fd, in, stbuf.st_size) != stbuf.st_size) { 27 | perror("read"); 28 | return 1; 29 | } 30 | LLVMFuzzerTestOneInput(in, stbuf.st_size); 31 | close(fd); 32 | free(in); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /tools/libFuzzer/wim/corpus/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tools/libFuzzer/wim/corpus/0 -------------------------------------------------------------------------------- /tools/libFuzzer/wim/fuzz.c: -------------------------------------------------------------------------------- 1 | #include "../fuzzer.h" 2 | 3 | /* Fuzz WIM file reading. */ 4 | int LLVMFuzzerTestOneInput(const uint8_t *in, size_t insize) 5 | { 6 | uint16_t fault_nth; 7 | char tmp_wim[128]; 8 | char tmp_dir[128]; 9 | int fd; 10 | WIMStruct *wim; 11 | int ret; 12 | 13 | if (!setup_fault_nth(&in, &insize, &fault_nth)) 14 | return 0; 15 | 16 | sprintf(tmp_wim, "/tmp/wim-fuzz-%d.wim", getpid()); 17 | sprintf(tmp_dir, "/tmp/wim-fuzz-%d", getpid()); 18 | 19 | fd = open(tmp_wim, O_WRONLY|O_CREAT|O_TRUNC, 0600); 20 | assert(fd >= 0); 21 | ret = write(fd, in, insize); 22 | assert(ret == insize); 23 | close(fd); 24 | 25 | ret = wimlib_open_wim(tmp_wim, 0, &wim); 26 | if (ret == 0) { 27 | wimlib_extract_image(wim, 1, tmp_dir, 0); 28 | wimlib_add_image(wim, tmp_dir, "name", NULL, 0); 29 | wimlib_free(wim); 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tools/libFuzzer/xml_windows/corpus/dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tools/libFuzzer/xml_windows/corpus/dll -------------------------------------------------------------------------------- /tools/libFuzzer/xml_windows/corpus/registry: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ebiggers/wimlib/e59d1de0f439d91065df7c47f647f546728e6a24/tools/libFuzzer/xml_windows/corpus/registry -------------------------------------------------------------------------------- /tools/libFuzzer/xml_windows/fuzz.c: -------------------------------------------------------------------------------- 1 | #include "../fuzzer.h" 2 | 3 | #include 4 | 5 | #define TMPDIR "/tmp/fuzz-xml-windows/" 6 | 7 | static void 8 | write_file(const char *path, const void *data, size_t size) 9 | { 10 | int fd; 11 | ssize_t res; 12 | 13 | fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0600); 14 | assert(fd >= 0); 15 | res = write(fd, data, size); 16 | assert(res == size); 17 | close(fd); 18 | } 19 | 20 | /* Fuzz set_windows_specific_info() in xml_windows.c. */ 21 | int LLVMFuzzerTestOneInput(const uint8_t *in, size_t insize) 22 | { 23 | WIMStruct *wim; 24 | int ret; 25 | 26 | mkdir(TMPDIR, 0700); 27 | mkdir(TMPDIR "Windows", 0700); 28 | mkdir(TMPDIR "Windows", 0700); 29 | mkdir(TMPDIR "Windows/System32", 0700); 30 | mkdir(TMPDIR "Windows/System32/config", 0700); 31 | write_file(TMPDIR "Windows/System32/kernel32.dll", in, insize); 32 | write_file(TMPDIR "Windows/System32/config/SYSTEM", in, insize); 33 | write_file(TMPDIR "Windows/System32/config/SOFTWARE", in, insize); 34 | 35 | ret = wimlib_create_new_wim(WIMLIB_COMPRESSION_TYPE_NONE, &wim); 36 | assert(!ret); 37 | 38 | ret = wimlib_add_image(wim, TMPDIR, NULL, NULL, 0); 39 | assert(!ret); 40 | 41 | wimlib_free(wim); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tools/libFuzzer/xmlproc/corpus/0: -------------------------------------------------------------------------------- 1 | 206812822262067609200x01D009F00x19E44A6E0x01D009F00x19E573C6testdata 2 | -------------------------------------------------------------------------------- /tools/libFuzzer/xmlproc/fuzz.c: -------------------------------------------------------------------------------- 1 | #include "../fuzzer.h" 2 | 3 | /* Fuzz XML parsing and writing. */ 4 | int LLVMFuzzerTestOneInput(const uint8_t *in, size_t insize) 5 | { 6 | uint16_t fault_nth; 7 | char *in_str; 8 | char *out_str = NULL; 9 | int ret; 10 | 11 | if (!setup_fault_nth(&in, &insize, &fault_nth)) 12 | return 0; 13 | 14 | in_str = malloc(insize + 1); 15 | memcpy(in_str, in, insize); 16 | in_str[insize] = '\0'; 17 | ret = wimlib_parse_and_write_xml_doc(in_str, &out_str); 18 | if (ret == 0) { 19 | char *out2_str = NULL; 20 | 21 | /* 22 | * If the first parse+write succeeded, we now should be able to 23 | * parse+write the result without changing it further. 24 | */ 25 | ret = wimlib_parse_and_write_xml_doc(out_str, &out2_str); 26 | if (ret != 0) 27 | assert(ret == WIMLIB_ERR_NOMEM && fault_nth); 28 | else 29 | assert(strcmp(out_str, out2_str) == 0); 30 | free(out2_str); 31 | } else { 32 | assert(ret == WIMLIB_ERR_XML || 33 | (fault_nth && ret == WIMLIB_ERR_NOMEM)); 34 | } 35 | free(in_str); 36 | free(out_str); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /tools/log2_interpolation.r: -------------------------------------------------------------------------------- 1 | # 2 | # This R language script finds a degree 2 interpolating polynomial for f = 3 | # log2(x) over the interval [1, 2). 4 | # 5 | 6 | f = function(x) { log2(x) } 7 | 8 | get.chebyshev.points = function(a, b, n) 9 | { 10 | (a+b)/2 + (b-a)/2 * cos(((2*(1:n)-1)*pi)/(2*n)) 11 | } 12 | 13 | build.vandermonde.matrix = function(x) 14 | { 15 | n = length(x) 16 | V = matrix(nrow=n, ncol=n) 17 | for (j in 1:n) 18 | V[,j] = x^(j-1) 19 | return(V) 20 | } 21 | 22 | evaluate.polynomial = function(coeffs, x) 23 | { 24 | y = coeffs[length(coeffs)] 25 | for (i in (length(coeffs)-1):1) 26 | y = y*x + coeffs[i] 27 | return(y) 28 | } 29 | 30 | x.plot = seq(1, 2, length=1000) 31 | x.chebychev = get.chebyshev.points(1, 2, 3) 32 | V = build.vandermonde.matrix(x.chebychev) 33 | coeffs.a = solve(V, f(x.chebychev)) 34 | coeffs.a = c(coeffs.a) 35 | polynomial.interp = function(x) { evaluate.polynomial(coeffs.a, x) } 36 | cat("Coefficients of degree 2 interpolating polynomial:\n") 37 | options(digits=10) 38 | cat(coeffs.a, "\n") 39 | pdf("polynomial-interp.pdf") 40 | plot(x.plot, f(x.plot), col="black", type="l", xlab="x", ylab="y", 41 | main="f(x) and interpolating polynomial approximation") 42 | points(x.chebychev, f(x.chebychev), pch=19, col="red") 43 | lines(x.plot, polynomial.interp(x.plot), col="blue") 44 | legend("topleft", pch=c(NA, NA, 19), 45 | col=c("black", "blue", "red"), lty=c(1,1,0), 46 | legend=c("f(x)", "Interpolating polynomial", "Chebychev points"), 47 | inset=0.07) 48 | -------------------------------------------------------------------------------- /tools/make-releases.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | MAKE="make -j$(grep -c processor /proc/cpuinfo)" 6 | 7 | export CFLAGS="-O2 -Wall -Werror" 8 | 9 | autoreconf -i -f # make sure the version number gets updated 10 | 11 | ./configure && $MAKE distcheck 12 | 13 | # Recompress with libdeflate 14 | gzfile=$(find . -name 'wimlib-*.tar.gz' | tail -1) 15 | tarfile=${gzfile%.gz} 16 | libdeflate-gunzip "$gzfile" 17 | libdeflate-gzip -12 "$tarfile" 18 | 19 | for arch in i686 x86_64; do 20 | ./tools/windows-build.sh --arch=$arch --include-docs --zip 21 | done 22 | -------------------------------------------------------------------------------- /tools/msvc-test-examples.bat: -------------------------------------------------------------------------------- 1 | REM 2 | REM Try building and running the example programs on Windows with Visual Studio. 3 | REM 4 | 5 | @echo off 6 | setlocal EnableDelayedExpansion 7 | 8 | copy .libs\libwim.dll.a libwim.lib 9 | copy .libs\libwim-15.dll libwim-15.dll 10 | for %%a in (examples\*.c) do ( 11 | cl %%a libwim.lib /Iinclude /link /opt:noref 12 | if errorlevel 1 exit /b 13 | ) 14 | call :do_test 15 | 16 | 17 | cd examples 18 | rename *.c *.cc 19 | cd .. 20 | for %%a in (examples\*.cc) do ( 21 | cl %%a libwim.lib /Iinclude /link /opt:noref 22 | if errorlevel 1 exit /b 23 | ) 24 | call :do_test 25 | cd examples 26 | rename *.cc *.c 27 | cd .. 28 | 29 | del *.exe *.obj *.dll *.lib 30 | 31 | exit /b 0 32 | 33 | :do_test 34 | .\applywim.exe j:\test.wim e:\tmp1 35 | if errorlevel 1 exit /b 36 | .\capturewim.exe e:\tmp1 e:\tmp1.wim 37 | if errorlevel 1 exit /b 38 | REM Windows likes to give UAC prompts for programs with "update" in their name. 39 | move /y updatewim.exe updat3wim.exe 40 | .\updat3wim.exe e:\tmp1.wim examples examples 41 | if errorlevel 1 exit /b 42 | 43 | .\compressfile.exe j:\testdata e:\testdata.lzx 44 | if errorlevel 1 exit /b 45 | .\decompressfile.exe e:\testdata.lzx e:\testdata.orig 46 | if errorlevel 1 exit /b 47 | fc /b j:\testdata e:\testdata.orig 48 | if errorlevel 1 exit /b 49 | 50 | .\compressfile.exe j:\testdata e:\testdata.lzx XPRESS 16384 51 | if errorlevel 1 exit /b 52 | .\decompressfile.exe e:\testdata.lzx e:\testdata.orig 53 | if errorlevel 1 exit /b 54 | fc /b j:\testdata e:\testdata.orig 55 | if errorlevel 1 exit /b 56 | goto :eof 57 | -------------------------------------------------------------------------------- /tools/repack-windows-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script takes in the path to a windows-CLANGARM64-bin artifact downloaded 4 | # from GitHub Actions, which lacks the PDF documentation and has the wrong file 5 | # layout, and packs it up into a releasable zip file. Assumes that an x86_64 6 | # zip built from the same commit already exists locally. 7 | 8 | set -e -u 9 | 10 | usage() 11 | { 12 | echo 1>&2 "Usage: $0 windows-CLANGARM64-bin.zip" 13 | exit 1 14 | } 15 | 16 | [ $# -eq 1 ] || usage 17 | 18 | tmpdir=$(mktemp -d) 19 | trap 'rm -rf "$tmpdir"' EXIT 20 | 21 | ZIP_FROM_GITHUB=$1 22 | unzip -q -d "$tmpdir" "$ZIP_FROM_GITHUB" 23 | DESTDIR=$(basename "$(echo "$tmpdir"/*)") 24 | rm -rf "$DESTDIR" "$DESTDIR.zip" 25 | cp -a "$tmpdir/$DESTDIR" "$DESTDIR" 26 | prefix=$(echo "$DESTDIR" | grep -o 'wimlib.*windows') 27 | cp -a "${prefix}-x86_64-bin/doc" "$DESTDIR/doc" 28 | chmod +x "$DESTDIR"/*.{dll,exe,cmd} 29 | cd "$DESTDIR" 30 | 7z -mx9 a ../"$DESTDIR.zip" . > /dev/null 31 | cd .. 32 | echo "Success! Output is in $DESTDIR.zip" 33 | -------------------------------------------------------------------------------- /tools/run-sparse.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | for fil in src/*.c programs/imagex.c; do 4 | sparse "$fil" -gcc-base-dir "$(gcc --print-file-name=)" \ 5 | -D_FILE_OFFSET_BITS=64 -DHAVE_CONFIG_H -D_GNU_SOURCE \ 6 | -I. -Iinclude -Wbitwise -Wpointer-subtraction-blows 7 | done 8 | -------------------------------------------------------------------------------- /tools/test-examples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Try building the example programs: in 32-bit and 64-bit mode, in C and C++ 4 | # mode, and for Linux and for Windows. Also run the Linux versions to make sure 5 | # they work. 6 | # 7 | 8 | set -eu 9 | 10 | cd examples 11 | make clean 12 | 13 | COMMON_FLAGS="-Wall -Wextra -Werror -Wundef -Wno-unused-parameter -Wvla" 14 | COMMON_CFLAGS="$COMMON_FLAGS -std=gnu99 -Wdeclaration-after-statement -Wstrict-prototypes" 15 | COMMON_CXXFLAGS="$COMMON_FLAGS" 16 | 17 | TEST_WIM="$HOME/data/test.wim" 18 | TESTDATA="$HOME/data/testdata" 19 | 20 | tmpdir="$(mktemp -d)" 21 | tmpfile="$(mktemp)" 22 | tmpfile2="$(mktemp)" 23 | 24 | trap 'rm -rf "$tmpdir" "$tmpfile" "$tmpfile2"' EXIT 25 | 26 | do_test() { 27 | rm -rf "$tmpdir" 28 | 29 | ./applywim "$TEST_WIM" "$tmpdir" 30 | ./capturewim "$tmpdir" "$tmpfile" 31 | ./updatewim "$tmpfile" "examples" . 32 | 33 | ./compressfile "$TESTDATA" "$tmpfile" 34 | ./decompressfile "$tmpfile" "$tmpfile2" 35 | cmp "$tmpfile2" "$TESTDATA" 36 | 37 | ./compressfile "$TESTDATA" "$tmpfile" XPRESS 16384 38 | ./decompressfile "$tmpfile" "$tmpfile2" 39 | cmp "$tmpfile2" "$TESTDATA" 40 | } 41 | 42 | make CC=gcc CFLAGS="$COMMON_CFLAGS" 43 | do_test 44 | make clean 45 | make CC=g++ CFLAGS="$COMMON_CXXFLAGS" 46 | do_test 47 | make clean 48 | 49 | make CC=i686-w64-mingw32-gcc CFLAGS="$COMMON_CFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/wimlib" 50 | make clean 51 | make CC=i686-w64-mingw32-g++ CFLAGS="$COMMON_CXXFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/wimlib" 52 | make clean 53 | 54 | make CC=x86_64-w64-mingw32-gcc CFLAGS="$COMMON_CFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/x64" 55 | make clean 56 | make CC=x86_64-w64-mingw32-g++ CFLAGS="$COMMON_CXXFLAGS -I../include -municode" LDLIBS="-lwim-15" LDFLAGS="-L/j/x64" 57 | make clean 58 | -------------------------------------------------------------------------------- /tools/update-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | 5 | if [ $# -ne 1 ]; then 6 | echo "Usage: $0 NEW_VERS" 1>&2 7 | exit 1 8 | fi 9 | 10 | oldmonth=$(head -1 doc/man1/wimcapture.1 | cut -d' ' -f4 | tr -d '"') 11 | oldyear=$(head -1 doc/man1/wimcapture.1 | cut -d' ' -f5 | tr -d '"') 12 | oldver=$(grep 'the library interface of wimlib' include/wimlib.h \ 13 | | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+') 14 | 15 | newver=$1 16 | newmajor=$(echo "$newver" | cut -d'.' -f1) 17 | newminor=$(echo "$newver" | cut -d'.' -f2) 18 | newpatch=$(echo "$newver" | cut -d'.' -f3) 19 | newmonth=$(date +%B) 20 | newyear=$(date +%Y) 21 | 22 | newver="${newmajor}.${newminor}.${newpatch}" 23 | pat='This is wimlib version [^[:space:]]\+ ([^[:space:]]\+ [^[:space:]]\+)' 24 | sed -i "s/$pat/This is wimlib version $newver ($newmonth $newyear)/" README.md 25 | 26 | sed -i "s/$oldver/$newver/" tools/get-version-number.sh README.WINDOWS.md 27 | 28 | sed -i -e 's/\(#define WIMLIB_MAJOR_VERSION[[:space:]]\+\)[[:digit:]]\+/\1'"$newmajor"'/' \ 29 | -e 's/\(#define WIMLIB_MINOR_VERSION[[:space:]]\+\)[[:digit:]]\+/\1'"$newminor"'/' \ 30 | -e 's/\(#define WIMLIB_PATCH_VERSION[[:space:]]\+\)[[:digit:]]\+/\1'"$newpatch"'/' \ 31 | -e 's/\(the library interface of wimlib \)'"$oldver"'/\1'"$newver"'/' \ 32 | include/wimlib.h 33 | 34 | sed -i -e "1s/$oldmonth $oldyear/$newmonth $newyear/;1s/wimlib $oldver/wimlib $newver/" \ 35 | doc/man[1-9]/*.[1-9] 36 | -------------------------------------------------------------------------------- /tools/wimgapi_wrapper.h: -------------------------------------------------------------------------------- 1 | #define _In_ 2 | #define __in 3 | #define __out 4 | #define __in_opt 5 | #define __out_opt 6 | #define __inout 7 | #define __out_bcount(x) 8 | #define __in_bcount(x) 9 | #define __out_bcount_opt(x) 10 | #define _Out_opt_ 11 | #define _Out_ 12 | #define _Out_writes_bytes_to_(x, y) 13 | #define _Inout_ 14 | #define _In_opt_ 15 | #define _Out_writes_bytes_opt_(x) 16 | #define _Out_writes_bytes_(x) 17 | #define __typefix(x) 18 | #define __deref_out_ecount_z(x) 19 | #define _In_reads_bytes_(x) 20 | 21 | #include 22 | #include 23 | #include "wimgapi.h" 24 | 25 | #define WIM_FLAG_SOLID 0x20000000 /* undocumented */ 26 | -------------------------------------------------------------------------------- /wimlib.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: wimlib 7 | Description: Library to extract, create, modify, and mount Windows Imaging (WIM) files 8 | URL: https://wimlib.net 9 | Version: @VERSION@ 10 | Libs: -L${libdir} -lwim 11 | Requires.private: @PKGCONFIG_PRIVATE_REQUIRES@ 12 | Libs.private: @PKGCONFIG_PRIVATE_LIBS@ 13 | Cflags: -I${includedir} 14 | --------------------------------------------------------------------------------