From e8c3ca2d1d0cac3d64985b45a9f654d2029a7518 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 14 May 2013 19:03:46 -0500 Subject: [PATCH] Refactor headers --- Makefile.am | 98 ++- README | 6 +- configure.ac | 6 +- configure.windows | 1 + doc/Doxyfile.in | 2 +- {src => include}/wimlib.h | 5 +- include/wimlib/apply.h | 86 +++ include/wimlib/assert.h | 17 + {src => include/wimlib}/buffer_io.h | 3 +- include/wimlib/callback.h | 8 + include/wimlib/capture.h | 129 ++++ include/wimlib/compiler.h | 27 + {src => include/wimlib}/compress.h | 4 +- {src => include/wimlib}/decompress.h | 61 +- {src => include/wimlib}/dentry.h | 27 +- include/wimlib/encoding.h | 39 + {src => include/wimlib}/endianness.h | 67 +- include/wimlib/error.h | 75 ++ include/wimlib/file_io.h | 39 + include/wimlib/header.h | 126 ++++ include/wimlib/integrity.h | 23 + {src => include/wimlib}/list.h | 2 +- {src => include/wimlib}/lookup_table.h | 37 +- {src => include/wimlib}/lzx.h | 3 +- include/wimlib/metadata.h | 111 +++ include/wimlib/ntfs_3g.h | 24 + include/wimlib/paths.h | 24 + {src => include/wimlib}/rbtree.h | 2 +- include/wimlib/reparse.h | 77 ++ include/wimlib/resource.h | 127 ++++ include/wimlib/security.h | 65 ++ {src => include/wimlib}/sha1.h | 7 +- include/wimlib/swm.h | 17 + {src => include/wimlib}/timestamp.h | 4 +- include/wimlib/types.h | 32 + include/wimlib/util.h | 111 +++ include/wimlib/version.h | 22 + include/wimlib/wim.h | 86 +++ {src => include/wimlib}/win32.h | 57 +- {src => include/wimlib}/win32_common.h | 6 +- include/wimlib/write.h | 34 + {src => include/wimlib}/xml.h | 16 +- {src => include/wimlib}/xpress.h | 2 - wimlib_tchar.h => include/wimlib_tchar.h | 0 programs/imagex-win32.c | 8 +- programs/imagex-win32.h | 8 +- programs/imagex.c | 13 +- programs/wgetopt.c | 2 +- src/add_image.c | 13 +- src/capture_common.c | 13 +- src/compress.c | 10 +- src/decompress.c | 8 +- src/delete_image.c | 13 +- src/dentry.c | 23 +- src/encoding.c | 12 +- src/export_image.c | 15 +- src/{extract_image.c => extract.c} | 36 +- src/file_io.c | 168 +++++ src/hardlink.c | 12 +- src/header.c | 15 +- src/integrity.c | 15 +- src/join.c | 18 +- src/lookup_table.c | 37 +- src/lz77.c | 8 +- src/lzx-common.c | 29 +- src/lzx-compress.c | 16 +- src/lzx-decompress.c | 17 +- src/metadata_resource.c | 14 +- src/mount_image.c | 32 +- src/{ntfs-apply.c => ntfs-3g_apply.c} | 44 +- src/{ntfs-capture.c => ntfs-3g_capture.c} | 52 +- src/paths.c | 131 ++++ src/rbtree.c | 7 +- src/reparse.c | 30 +- src/resource.c | 34 +- src/security.c | 30 +- src/security.h | 29 - src/sha1.c | 10 +- src/split.c | 22 +- src/timestamp.c | 50 ++ src/unix_apply.c | 20 +- src/unix_capture.c | 15 +- src/update_image.c | 25 +- src/util.c | 296 +------- src/util.h | 325 --------- src/verify.c | 13 +- src/wim.c | 45 +- src/wimlib_internal.h | 850 ---------------------- src/win32_apply.c | 19 +- src/win32_capture.c | 53 +- src/win32_common.c | 239 +----- src/win32_replacements.c | 292 ++++++++ src/write.c | 28 +- src/xml.c | 28 +- src/xpress-compress.c | 10 +- src/xpress-decompress.c | 12 +- tests/common_tests.sh | 2 +- tests/test-imagex | 2 +- tests/test-imagex-mount | 2 +- tests/test-imagex-ntfs | 2 +- 100 files changed, 2802 insertions(+), 2185 deletions(-) create mode 100644 configure.windows rename {src => include}/wimlib.h (99%) create mode 100644 include/wimlib/apply.h create mode 100644 include/wimlib/assert.h rename {src => include/wimlib}/buffer_io.h (99%) create mode 100644 include/wimlib/callback.h create mode 100644 include/wimlib/capture.h create mode 100644 include/wimlib/compiler.h rename {src => include/wimlib}/compress.h (97%) rename {src => include/wimlib}/decompress.h (87%) rename {src => include/wimlib}/dentry.h (97%) create mode 100644 include/wimlib/encoding.h rename {src => include/wimlib}/endianness.h (50%) create mode 100644 include/wimlib/error.h create mode 100644 include/wimlib/file_io.h create mode 100644 include/wimlib/header.h create mode 100644 include/wimlib/integrity.h rename {src => include/wimlib}/list.h (99%) rename {src => include/wimlib}/lookup_table.h (96%) rename {src => include/wimlib}/lzx.h (98%) create mode 100644 include/wimlib/metadata.h create mode 100644 include/wimlib/ntfs_3g.h create mode 100644 include/wimlib/paths.h rename {src => include/wimlib}/rbtree.h (98%) create mode 100644 include/wimlib/reparse.h create mode 100644 include/wimlib/resource.h create mode 100644 include/wimlib/security.h rename {src => include/wimlib}/sha1.h (95%) create mode 100644 include/wimlib/swm.h rename {src => include/wimlib}/timestamp.h (97%) create mode 100644 include/wimlib/types.h create mode 100644 include/wimlib/util.h create mode 100644 include/wimlib/version.h create mode 100644 include/wimlib/wim.h rename {src => include/wimlib}/win32.h (58%) rename {src => include/wimlib}/win32_common.h (93%) create mode 100644 include/wimlib/write.h rename {src => include/wimlib}/xml.h (81%) rename {src => include/wimlib}/xpress.h (96%) rename wimlib_tchar.h => include/wimlib_tchar.h (100%) rename src/{extract_image.c => extract.c} (98%) create mode 100644 src/file_io.c rename src/{ntfs-apply.c => ntfs-3g_apply.c} (96%) rename src/{ntfs-capture.c => ntfs-3g_capture.c} (96%) create mode 100644 src/paths.c delete mode 100644 src/security.h create mode 100644 src/timestamp.c delete mode 100644 src/util.h delete mode 100644 src/wimlib_internal.h create mode 100644 src/win32_replacements.c diff --git a/Makefile.am b/Makefile.am index 0aede591..babc014f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,8 +1,9 @@ ACLOCAL_AMFLAGS = -I m4 -AM_CPPFLAGS = -I$(top_srcdir)/src $(WINDOWS_CPPFLAGS) \ +AM_CPPFLAGS = -I$(top_srcdir)/include $(WINDOWS_CPPFLAGS) \ -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -AM_CFLAGS = -std=gnu99 -fno-strict-aliasing +AM_CFLAGS = -std=gnu99 -fno-strict-aliasing \ + -Wmissing-prototypes -Wstrict-prototypes lib_LTLIBRARIES = libwim.la @@ -10,64 +11,98 @@ libwim_la_LDFLAGS = -version-info 7:0:0 $(WINDOWS_LDFLAGS) libwim_la_SOURCES = \ src/add_image.c \ - src/buffer_io.h \ src/capture_common.c \ src/compress.c \ - src/compress.h \ src/decompress.c \ - src/decompress.h \ src/delete_image.c \ src/dentry.c \ - src/dentry.h \ src/encoding.c \ - src/endianness.h \ src/export_image.c \ - src/extract_image.c \ + src/extract.c \ + src/file_io.c \ src/hardlink.c \ src/header.c \ src/integrity.c \ src/join.c \ - src/list.h \ src/lookup_table.c \ - src/lookup_table.h \ src/lz77.c \ src/lzx-common.c \ src/lzx-compress.c \ src/lzx-decompress.c \ - src/lzx.h \ src/metadata_resource.c \ src/mount_image.c \ + src/paths.c \ src/resource.c \ src/rbtree.c \ - src/rbtree.h \ src/security.c \ - src/security.h \ src/sha1.c \ - src/sha1.h \ src/split.c \ src/reparse.c \ - src/timestamp.h \ + src/timestamp.c \ src/update_image.c \ src/util.c \ - src/util.h \ src/verify.c \ src/wim.c \ - src/wimlib.h \ - wimlib_tchar.h \ - src/wimlib_internal.h \ src/write.c \ src/xml.c \ - src/xml.h \ src/xpress-compress.c \ - src/xpress-decompress.c \ - src/xpress.h + src/xpress-decompress.c \ + include/wimlib/apply.h \ + include/wimlib/assert.h \ + include/wimlib/buffer_io.h \ + include/wimlib/callback.h \ + include/wimlib/capture.h \ + include/wimlib/compiler.h \ + include/wimlib/compress.h \ + include/wimlib/decompress.h \ + include/wimlib/dentry.h \ + include/wimlib/encoding.h \ + include/wimlib/endianness.h \ + include/wimlib/error.h \ + include/wimlib/file_io.h \ + include/wimlib/header.h \ + include/wimlib/integrity.h \ + include/wimlib/list.h \ + include/wimlib/lookup_table.h \ + include/wimlib/lzx.h \ + include/wimlib/metadata.h \ + include/wimlib/ntfs_3g.h \ + include/wimlib/paths.h \ + include/wimlib/rbtree.h \ + include/wimlib/reparse.h \ + include/wimlib/resource.h \ + include/wimlib/security.h \ + include/wimlib/sha1.h \ + include/wimlib/swm.h \ + include/wimlib/timestamp.h \ + include/wimlib/types.h \ + include/wimlib/util.h \ + include/wimlib/version.h \ + include/wimlib/wim.h \ + include/wimlib/write.h \ + include/wimlib/xml.h \ + include/wimlib/xpress.h if WITH_NTFS_3G -libwim_la_SOURCES += src/ntfs-apply.c \ - src/ntfs-capture.c +libwim_la_SOURCES += src/ntfs-3g_apply.c \ + src/ntfs-3g_capture.c \ + include/wimlib/ntfs_3g.h +endif + +if WINDOWS_NATIVE_BUILD +libwim_la_SOURCES += src/win32_common.c \ + src/win32_apply.c \ + src/win32_capture.c \ + src/win32_replacements.c \ + include/wimlib/win32_common.h \ + include/wimlib/win32.h +else +libwim_la_SOURCES += src/unix_apply.c \ + src/unix_capture.c endif + EXTRA_libwim_la_SOURCES = src/sha1-ssse3.asm libwim_la_DEPENDENCIES = $(SSSE3_SHA1_OBJ) STRIP_FPIC = sh $(top_srcdir)/build-aux/strip_fPIC.sh @@ -97,7 +132,9 @@ libwim_la_CFLAGS = \ bin_PROGRAMS = imagex -imagex_SOURCES = programs/imagex.c wimlib_tchar.h +imagex_SOURCES = programs/imagex.c \ + include/wimlib.h \ + include/wimlib_tchar.h imagex_LDADD = $(top_builddir)/libwim.la imagex_CFLAGS = $(AM_CFLAGS) $(WINDOWS_CFLAGS) @@ -106,15 +143,6 @@ imagex_SOURCES += programs/imagex-win32.c \ programs/imagex-win32.h \ programs/wgetopt.c \ programs/wgetopt.h - -libwim_la_SOURCES += src/win32_common.c \ - src/win32_apply.c \ - src/win32_capture.c \ - src/win32.h \ - src/win32_common.h -else -libwim_la_SOURCES += src/unix_apply.c \ - src/unix_capture.c endif install-exec-hook: @@ -129,7 +157,7 @@ uninstall-hook: dist_bin_SCRIPTS = programs/mkwinpeimg -include_HEADERS = src/wimlib.h +include_HEADERS = include/wimlib.h EXTRA_DIST = \ build-aux/strip_fPIC.sh \ diff --git a/README b/README index 3de7c61d..86eec9b2 100644 --- a/README +++ b/README @@ -243,9 +243,9 @@ see the code and/or ask me if you have any questions about the WIM file format as it exists in reality and not as it exists in Microsoft's poorly written documentation. -The code in ntfs-apply.c and ntfs-capture.c uses the NTFS-3g library, which is a -library for reading and writing to NTFS filesystems (the filesystem used by -recent versions of Windows). See +The code in ntfs-3g_apply.c and ntfs-3g_capture.c uses the NTFS-3g library, +which is a library for reading and writing to NTFS filesystems (the filesystem +used by recent versions of Windows). See http://www.tuxera.com/community/ntfs-3g-download/ for more information. lzx-decompress.c, the code to decompress WIM file resources that are compressed diff --git a/configure.ac b/configure.ac index aa2f34e4..b593c43c 100644 --- a/configure.ac +++ b/configure.ac @@ -221,7 +221,7 @@ AM_CONDITIONAL([WINDOWS_NATIVE_BUILD], [test "x$WINDOWS_NATIVE_BUILD" = "xyes"]) AC_MSG_CHECKING([whether to include support for ntfs-3g]) AC_ARG_WITH([ntfs-3g], AS_HELP_STRING([--without-ntfs-3g], [build without NTFS-3g. - This will disable the ability to use NTFS-specific + On UNIX, this will disable the ability to use NTFS-specific information when capturing or applying WIMs to a NTFS filesystem.]), [WITH_NTFS_3G=$withval], @@ -229,8 +229,8 @@ AC_ARG_WITH([ntfs-3g], ) AC_MSG_RESULT([$WITH_NTFS_3G]) if test "x$WITH_NTFS_3G" = "xyes"; then - AC_DEFINE([WITH_NTFS_3G], [1], [Define to 1 to enable support for - NTFS-specific information]) + AC_DEFINE([WITH_NTFS_3G], [1], [On UNIX, define to 1 to enable support + for NTFS-specific information]) dnl This effectively checks for NTFS-3g 2011.4.12 or later AC_CHECK_LIB([ntfs-3g], [ntfs_xattr_system_setxattr], [], diff --git a/configure.windows b/configure.windows new file mode 100644 index 00000000..5c78a8e3 --- /dev/null +++ b/configure.windows @@ -0,0 +1 @@ +./configure --host=i686-w64-mingw32 "$@" diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index b8b08b5e..3e860edb 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -7,7 +7,7 @@ SHOW_INCLUDE_FILES = YES JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES SHOW_USED_FILES = YES -INPUT = @top_srcdir@/src/wimlib.h +INPUT = @top_srcdir@/include/wimlib.h FULL_PATH_NAMES = NO OPTIMIZE_FOR_C = YES GENERATE_HTML = YES diff --git a/src/wimlib.h b/include/wimlib.h similarity index 99% rename from src/wimlib.h rename to include/wimlib.h index ab0d43ba..16f4ba9c 100644 --- a/src/wimlib.h +++ b/include/wimlib.h @@ -179,7 +179,10 @@ * Use wimlib_write() or wimlib_overwrite() to actually write an on-disk WIM * file from a ::WIMStruct. */ +#ifndef WIMLIB_WIMSTRUCT_DECLARED typedef struct WIMStruct WIMStruct; +#define WIMLIB_WIMSTRUCT_DECLARED +#endif #ifdef __WIN32__ typedef wchar_t wimlib_tchar; @@ -1637,7 +1640,7 @@ wimlib_global_init(int init_flags); * memory allocated by the library. */ extern void -wimlib_global_cleanup(); +wimlib_global_cleanup(void); /** * Returns true if the WIM has an integrity table. diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h new file mode 100644 index 00000000..44773bd1 --- /dev/null +++ b/include/wimlib/apply.h @@ -0,0 +1,86 @@ +#ifndef _WIMLIB_APPLY_H +#define _WIMLIB_APPLY_H + +#include "wimlib.h" +#include "wimlib/types.h" + +#ifdef WITH_NTFS_3G +struct _ntfs_volume; +#endif + +struct apply_args { + WIMStruct *w; + const tchar *target; + unsigned target_nchars; + unsigned wim_source_path_nchars; + struct wim_dentry *extract_root; + tchar *target_realpath; + unsigned target_realpath_len; + int extract_flags; + union wimlib_progress_info progress; + wimlib_progress_func_t progress_func; + int (*apply_dentry)(struct wim_dentry *, void *); + union { + #ifdef WITH_NTFS_3G + struct { + /* NTFS apply only */ + struct _ntfs_volume *vol; + }; + #endif + #ifdef __WIN32__ + struct { + /* Normal apply only (Win32) */ + unsigned long num_set_sacl_priv_notheld; + unsigned long num_set_sd_access_denied; + unsigned vol_flags; + unsigned long num_hard_links_failed; + unsigned long num_soft_links_failed; + bool have_vol_flags; + }; + #else + struct { + /* Normal apply only (UNIX) */ + unsigned long num_utime_warnings; + }; + #endif + }; +}; + +#ifdef WITH_NTFS_3G +extern int +apply_dentry_ntfs(struct wim_dentry *dentry, void *arg); + +extern int +apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg); +#endif + +#ifdef __WIN32__ +extern int +win32_do_apply_dentry(const tchar *output_path, + size_t output_path_nbytes, + struct wim_dentry *dentry, + struct apply_args *args); + +extern int +win32_do_apply_dentry_timestamps(const tchar *output_path, + size_t output_path_nbytes, + struct wim_dentry *dentry, + struct apply_args *args); +#else /* __WIN32__ */ +extern int +unix_do_apply_dentry(const tchar *output_path, size_t output_path_nbytes, + struct wim_dentry *dentry, struct apply_args *args); +extern int +unix_do_apply_dentry_timestamps(const tchar *output_path, + size_t output_path_nbytes, + struct wim_dentry *dentry, + struct apply_args *args); +#endif /* !__WIN32__ */ + +/* Internal use only */ +#define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000 +#define WIMLIB_EXTRACT_FLAG_NO_STREAMS 0x40000000 +#define WIMLIB_EXTRACT_MASK_PUBLIC 0x3fffffff + + +#endif /* _WIMLIB_APPLY_H */ diff --git a/include/wimlib/assert.h b/include/wimlib/assert.h new file mode 100644 index 00000000..d0ed314c --- /dev/null +++ b/include/wimlib/assert.h @@ -0,0 +1,17 @@ +#ifndef _WIMLIB_ASSERT_H +#define _WIMLIB_ASSERT_H + +#ifdef ENABLE_ASSERTIONS +#include +# define wimlib_assert(expr) assert(expr) +#else +# define wimlib_assert(expr) +#endif + +#ifdef ENABLE_MORE_ASSERTIONS +# define wimlib_assert2(expr) wimlib_assert(expr) +#else +# define wimlib_assert2(expr) +#endif + +#endif /* _WIMLIB_ASSERT_H */ diff --git a/src/buffer_io.h b/include/wimlib/buffer_io.h similarity index 99% rename from src/buffer_io.h rename to include/wimlib/buffer_io.h index 4a247ba5..43e497ba 100644 --- a/src/buffer_io.h +++ b/include/wimlib/buffer_io.h @@ -8,7 +8,7 @@ #ifndef _WIMLIB_BUFFER_IO_H #define _WIMLIB_BUFFER_IO_H -#include "util.h" +#include "wimlib/types.h" #include "endianness.h" #include @@ -129,4 +129,5 @@ put_bytes(void *p, size_t num_bytes, const void *input) { return memcpy(p, input, num_bytes) + num_bytes; } + #endif /* _WIMLIB_BUFFER_IO_H */ diff --git a/include/wimlib/callback.h b/include/wimlib/callback.h new file mode 100644 index 00000000..a805f551 --- /dev/null +++ b/include/wimlib/callback.h @@ -0,0 +1,8 @@ +#ifndef _WIMLIB_CALLBACK_H +#define _WIMLIB_CALLBACK_H + +#include + +typedef int (*consume_data_callback_t)(const void *buf, size_t len, void *ctx); + +#endif diff --git a/include/wimlib/capture.h b/include/wimlib/capture.h new file mode 100644 index 00000000..b60c5c85 --- /dev/null +++ b/include/wimlib/capture.h @@ -0,0 +1,129 @@ +#ifndef _WIMLIB_CAPTURE_H +#define _WIMLIB_CAPTURE_H + +#include "wimlib.h" +#include "wimlib/list.h" +#include "wimlib/security.h" +#include "wimlib/util.h" + +struct wim_lookup_table; +struct wim_dentry; + +/* Hash table to find inodes, given an inode number (in the case of reading + * a WIM images), or both an inode number and a device number (in the case of + * capturing a WIM image). */ +struct wim_inode_table { + /* Fields for the hash table */ + struct hlist_head *array; + u64 num_entries; + u64 capacity; + + /* + * Linked list of "extra" inodes. These may be: + * + * - inodes with link count 1, which are all allowed to have 0 for their + * inode number, meaning we cannot insert them into the hash table. + * + * - Groups we create ourselves by splitting a nominal inode due to + * inconsistencies in the dentries. These inodes will share an inode + * number with some other inode until assign_inode_numbers() is + * called. + */ + struct list_head extra_inodes; +}; + +/* Common parameters to implementations of building an in-memory dentry tree + * from an on-disk directory structure. */ +struct add_image_params { + /* Pointer to the lookup table of the WIM. */ + struct wim_lookup_table *lookup_table; + + /* Hash table of inodes that have been captured for this tree so far. */ + struct wim_inode_table inode_table; + + /* The set of security descriptors that have been captured for this + * image so far. */ + struct wim_sd_set sd_set; + + /* Pointer to the capture configuration, which indicates whether any + * files should be excluded from capture or not. */ + const struct wimlib_capture_config *config; + + /* Flags that affect the capture operation (WIMLIB_ADD_FLAG_*) */ + int add_flags; + + /* If non-NULL, the user-supplied progress function. */ + wimlib_progress_func_t progress_func; + + /* Extra argument; set to point to a pointer to the ntfs_volume for + * libntfs-3g capture. */ + void *extra_arg; + + u64 capture_root_ino; + u64 capture_root_dev; +}; + + +/* capture_common.c */ + +extern bool +exclude_path(const tchar *path, size_t path_len, + const struct wimlib_capture_config *config, + bool exclude_prefix); + +extern struct wimlib_capture_config * +copy_capture_config(const struct wimlib_capture_config *config); + +extern int +copy_and_canonicalize_capture_config(const struct wimlib_capture_config *config, + struct wimlib_capture_config **config_copy_ret); + +extern void +free_capture_config(struct wimlib_capture_config *config); + +/* hardlink.c */ + +extern int +init_inode_table(struct wim_inode_table *table, size_t capacity); + +extern int +inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, + u64 ino, u64 devno, bool noshare, + struct wim_dentry **dentry_ret); + +extern void +inode_table_prepare_inode_list(struct wim_inode_table *table, + struct list_head *head); + +static inline void +destroy_inode_table(struct wim_inode_table *table) +{ + FREE(table->array); +} + + +#ifdef WITH_NTFS_3G +/* ntfs-3g_capture.c */ +extern int +build_dentry_tree_ntfs(struct wim_dentry **root_p, + const tchar *device, + struct add_image_params *params); +#endif + +#ifdef __WIN32__ +/* win32_capture.c */ +extern int +win32_build_dentry_tree(struct wim_dentry **root_ret, + const tchar *root_disk_path, + struct add_image_params *params); +#else +/* unix_capture.c */ +extern int +unix_build_dentry_tree(struct wim_dentry **root_ret, + const tchar *root_disk_path, + struct add_image_params *params); +#endif + +#define WIMLIB_ADD_FLAG_ROOT 0x80000000 + +#endif /* _WIMLIB_CAPTURE_H */ diff --git a/include/wimlib/compiler.h b/include/wimlib/compiler.h new file mode 100644 index 00000000..3134b119 --- /dev/null +++ b/include/wimlib/compiler.h @@ -0,0 +1,27 @@ +#ifndef _WIMLIB_COMPILER_H +#define _WIMLIB_COMPILER_H + +#ifdef __GNUC__ +# if defined(__CYGWIN__) || defined(__WIN32__) +# define WIMLIBAPI __declspec(dllexport) +# else +# define WIMLIBAPI __attribute__((visibility("default"))) +# endif +# define ALWAYS_INLINE inline __attribute__((always_inline)) +# define PACKED __attribute__((packed)) +# define FORMAT(type, format_str, args_start) \ + /*__attribute__((format(type, format_str, args_start))) */ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +# define COLD __attribute__((cold)) +# else +# define COLD +# endif +#else +# define WIMLIBAPI +# define ALWAYS_INLINE inline +# define FORMAT(type, format_str, args_start) +# define COLD +# define PACKED +#endif /* __GNUC__ */ + +#endif /* _WIMLIB_COMPILER_H */ diff --git a/src/compress.h b/include/wimlib/compress.h similarity index 97% rename from src/compress.h rename to include/wimlib/compress.h index 88c55f26..764eee72 100644 --- a/src/compress.h +++ b/include/wimlib/compress.h @@ -7,8 +7,8 @@ #ifndef _WIMLIB_COMPRESS_H #define _WIMLIB_COMPRESS_H -#include "util.h" -#include "endianness.h" +#include "wimlib/endianness.h" +#include "wimlib/types.h" typedef u16 output_bitbuf_t; diff --git a/src/decompress.h b/include/wimlib/decompress.h similarity index 87% rename from src/decompress.h rename to include/wimlib/decompress.h index a2466456..c020cbad 100644 --- a/src/decompress.h +++ b/include/wimlib/decompress.h @@ -4,11 +4,13 @@ * Functions useful for decompression, mainly bitstreams. */ -#ifndef _WIMLIB_DECOMP_H -#define _WIMLIB_DECOMP_H +#ifndef _WIMLIB_DECOMPRESS_H +#define _WIMLIB_DECOMPRESS_H -#include "util.h" -#include "endianness.h" +#include "wimlib/assert.h" +#include "wimlib/endianness.h" +#include "wimlib/error.h" +#include "wimlib/types.h" /* Must be at least 32 bits. */ typedef unsigned long input_bitbuf_t; @@ -36,8 +38,9 @@ struct input_bitstream { }; /* Initializes a bitstream to receive its input from @data. */ -static inline void init_input_bitstream(struct input_bitstream *istream, - const void *data, unsigned num_data_bytes) +static inline void +init_input_bitstream(struct input_bitstream *istream, + const void *data, unsigned num_data_bytes) { istream->bitbuf = 0; istream->bitsleft = 0; @@ -50,8 +53,8 @@ static inline void init_input_bitstream(struct input_bitstream *istream, * * If there are at least @num_bits bits remaining in the bitstream, 0 is * returned. Otherwise, -1 is returned. */ -static inline int bitstream_ensure_bits(struct input_bitstream *istream, - unsigned num_bits) +static inline int +bitstream_ensure_bits(struct input_bitstream *istream, unsigned num_bits) { wimlib_assert2(num_bits <= 16); @@ -101,8 +104,8 @@ bitstream_peek_bits(const struct input_bitstream *istream, unsigned num_bits) /* Removes @num_bits bits from the buffer variable, which must contain at least * @num_bits bits, for the bitstream. */ -static inline void bitstream_remove_bits(struct input_bitstream *istream, - unsigned num_bits) +static inline void +bitstream_remove_bits(struct input_bitstream *istream, unsigned num_bits) { wimlib_assert2(istream->bitsleft >= num_bits); istream->bitbuf <<= num_bits; @@ -112,8 +115,9 @@ static inline void bitstream_remove_bits(struct input_bitstream *istream, /* Reads @num_bits bits from the input bitstream. @num_bits must be 16 or fewer. * On success, returns 0 and returns the requested bits in @n. If there are * fewer than @num_bits remaining in the bitstream, -1 is returned. */ -static inline int bitstream_read_bits(struct input_bitstream *istream, - unsigned num_bits, unsigned *n) +static inline int +bitstream_read_bits(struct input_bitstream *istream, + unsigned num_bits, unsigned *n) { wimlib_assert2(num_bits <= 16); int ret = bitstream_ensure_bits(istream, num_bits); @@ -133,7 +137,8 @@ static inline int bitstream_read_bits(struct input_bitstream *istream, * * This function returns the next such literal byte, or -1 if there are no more. */ -static inline int bitstream_read_byte(struct input_bitstream *istream) +static inline int +bitstream_read_byte(struct input_bitstream *istream) { wimlib_assert2(istream->bitsleft < 32); int ret; @@ -158,12 +163,13 @@ bitstream_read_bits_nocheck(struct input_bitstream *istream, unsigned num_bits) return n; } -extern int read_huffsym_near_end_of_input(struct input_bitstream *istream, - const u16 decode_table[], - const u8 lens[], - unsigned num_syms, - unsigned table_bits, - unsigned *n); +extern int +read_huffsym_near_end_of_input(struct input_bitstream *istream, + const u16 decode_table[], + const u8 lens[], + unsigned num_syms, + unsigned table_bits, + unsigned *n); /* * Reads a Huffman-encoded symbol from a bitstream. @@ -183,13 +189,14 @@ extern int read_huffsym_near_end_of_input(struct input_bitstream *istream, * directory in the decode_table, as the * decode_table contains 2**table_bits entries. */ -static inline int read_huffsym(struct input_bitstream *istream, - const u16 decode_table[], - const u8 lens[], - unsigned num_syms, - unsigned table_bits, - unsigned *n, - unsigned max_codeword_len) +static inline int +read_huffsym(struct input_bitstream *istream, + const u16 decode_table[], + const u8 lens[], + unsigned num_syms, + unsigned table_bits, + unsigned *n, + unsigned max_codeword_len) { int ret; @@ -234,4 +241,4 @@ extern int make_huffman_decode_table(u16 decode_table[], unsigned num_syms, unsigned num_bits, const u8 lengths[], unsigned max_codeword_len); -#endif /* _WIMLIB_DECOMP_H */ +#endif /* _WIMLIB_DECOMPRESS_H */ diff --git a/src/dentry.h b/include/wimlib/dentry.h similarity index 97% rename from src/dentry.h rename to include/wimlib/dentry.h index a613db42..e67eb5b5 100644 --- a/src/dentry.h +++ b/include/wimlib/dentry.h @@ -1,24 +1,22 @@ #ifndef _WIMLIB_DENTRY_H #define _WIMLIB_DENTRY_H -#include "util.h" -#include "config.h" -#include "list.h" -#include "sha1.h" -#include "rbtree.h" +#include "wimlib/list.h" +#include "wimlib/rbtree.h" +#include "wimlib/sha1.h" +#include "wimlib/types.h" + #include +#include /* uid_t, gid_t */ #ifdef WITH_FUSE -#include +# include #endif -struct stat; struct wim_lookup_table; -struct WIMStruct; struct wim_lookup_table_entry; struct wimfs_fd; struct wim_inode; -struct wim_dentry; /* Size of the struct wim_dentry up to and including the file_name_len. */ #define WIM_DENTRY_DISK_SIZE 102 @@ -391,7 +389,7 @@ extern tchar * dentry_full_path(struct wim_dentry *dentry); extern struct wim_inode * -new_timeless_inode(); +new_timeless_inode(void); extern int new_dentry(const tchar *name, struct wim_dentry **dentry_ret); @@ -562,4 +560,13 @@ dentry_has_long_name(const struct wim_dentry *dentry) return dentry->file_name_nbytes != 0; } +extern void +inode_ref_streams(struct wim_inode *inode); + +extern int +dentry_tree_fix_inodes(struct wim_dentry *root, struct list_head *inode_list); + +extern int +verify_dentry(struct wim_dentry *dentry, void *wim); + #endif diff --git a/include/wimlib/encoding.h b/include/wimlib/encoding.h new file mode 100644 index 00000000..ff3c2ae6 --- /dev/null +++ b/include/wimlib/encoding.h @@ -0,0 +1,39 @@ +#ifndef _WIMLIB_ENCODING_H +#define _WIMLIB_ENCODING_H + +#include "wimlib/types.h" + +extern void +iconv_global_cleanup(void); + +extern bool wimlib_mbs_is_utf8; + +#define DECLARE_CHAR_CONVERSION_FUNCTIONS(varname1, varname2, \ + chartype1, chartype2) \ + \ +extern int \ +varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes, \ + chartype2 **out_ret, \ + size_t *out_nbytes_ret); \ + \ +extern int \ +varname1##_to_##varname2##_nbytes(const chartype1 *in, size_t in_nbytes,\ + size_t *out_nbytes_ret); \ + \ +extern int \ +varname1##_to_##varname2##_buf(const chartype1 *in, size_t in_nbytes, \ + chartype2 *out); + + +#if !TCHAR_IS_UTF16LE +DECLARE_CHAR_CONVERSION_FUNCTIONS(utf16le, tstr, utf16lechar, tchar); +DECLARE_CHAR_CONVERSION_FUNCTIONS(tstr, utf16le, tchar, utf16lechar); +#endif + +extern int +utf8_to_tstr_simple(const char *utf8str, tchar **out); + +extern int +tstr_to_utf8_simple(const tchar *tstr, char **out); + +#endif /* _WIMLIB_ENCODING_H */ diff --git a/src/endianness.h b/include/wimlib/endianness.h similarity index 50% rename from src/endianness.h rename to include/wimlib/endianness.h index 3de872ac..2d1e9a67 100644 --- a/src/endianness.h +++ b/include/wimlib/endianness.h @@ -1,23 +1,20 @@ #ifndef _WIMLIB_ENDIANNESS_H #define _WIMLIB_ENDIANNESS_H +#include "wimlib/types.h" -#include "config.h" -#include +/* Watch out for conflict with ntfs-3g/endian.h ... */ -/* Watch out for conflicts with ntfs-3g headers... */ +#ifndef _NTFS_ENDIANS_H -#ifndef bswap16 -static inline uint16_t -bswap16(uint16_t n) +static inline u16 +bswap16(u16 n) { return (n << 8) | (n >> 8); } -#endif /* ifndef bswap16 */ -#ifndef bswap32 -static inline uint32_t -bswap32(uint32_t n) +static inline u32 +bswap32(u32 n) { #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) return __builtin_bswap32(n); @@ -26,11 +23,9 @@ bswap32(uint32_t n) (n >> 24); #endif } -#endif /* ifndef bswap32 */ -#ifndef bswap64 -static inline uint64_t -bswap64(uint64_t n) +static inline u64 +bswap64(u64 n) { #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) return __builtin_bswap64(n); @@ -41,54 +36,50 @@ bswap64(uint64_t n) ((n & 0xff000000000000) >> 40) | (n >> 56); #endif } -#endif /* ifndef bswap64 */ - -#ifndef _NTFS_ENDIANS_H -# ifdef WORDS_BIGENDIAN -# define le16_to_cpu(n) bswap16(n) -# define le32_to_cpu(n) bswap32(n) -# define le64_to_cpu(n) bswap64(n) -# define cpu_to_le16(n) bswap16(n) -# define cpu_to_le32(n) bswap32(n) -# define cpu_to_le64(n) bswap64(n) -# else -# define cpu_to_le16(n) (n) -# define cpu_to_le32(n) (n) -# define cpu_to_le64(n) (n) -# define le16_to_cpu(n) (n) -# define le32_to_cpu(n) (n) -# define le64_to_cpu(n) (n) -# endif -#endif +# ifdef WORDS_BIGENDIAN +# define le16_to_cpu(n) bswap16(n) +# define le32_to_cpu(n) bswap32(n) +# define le64_to_cpu(n) bswap64(n) +# define cpu_to_le16(n) bswap16(n) +# define cpu_to_le32(n) bswap32(n) +# define cpu_to_le64(n) bswap64(n) +# else +# define cpu_to_le16(n) (n) +# define cpu_to_le32(n) (n) +# define cpu_to_le64(n) (n) +# define le16_to_cpu(n) (n) +# define le32_to_cpu(n) (n) +# define le64_to_cpu(n) (n) +# endif +#endif /* _NTFS_ENDIANS_H */ static inline void -array_cpu_to_le32(uint32_t *p, size_t n) +array_cpu_to_le32(u32 *p, size_t n) { for (size_t i = 0; i < n; i++) p[i] = cpu_to_le32(p[i]); } static inline void -array_le32_to_cpu(uint32_t *p, size_t n) +array_le32_to_cpu(u32 *p, size_t n) { for (size_t i = 0; i < n; i++) p[i] = le32_to_cpu(p[i]); } static inline void -array_cpu_to_le64(uint64_t *p, size_t n) +array_cpu_to_le64(u64 *p, size_t n) { for (size_t i = 0; i < n; i++) p[i] = cpu_to_le64(p[i]); } static inline void -array_le64_to_cpu(uint64_t *p, size_t n) +array_le64_to_cpu(u64 *p, size_t n) { for (size_t i = 0; i < n; i++) p[i] = le64_to_cpu(p[i]); } - #endif /* _WIMLIB_ENDIANNESS_H */ diff --git a/include/wimlib/error.h b/include/wimlib/error.h new file mode 100644 index 00000000..7de749d3 --- /dev/null +++ b/include/wimlib/error.h @@ -0,0 +1,75 @@ +#ifndef _WIMLIB_ERROR_H +#define _WIMLIB_ERROR_H + +#include "wimlib.h" /* Get error code definitions */ +#include "wimlib/compiler.h" +#include "wimlib/types.h" + +#include + +#ifdef __WIN32__ +# define wimlib_fprintf fwprintf +# define wimlib_printf wprintf +#else /* __WIN32__ */ +extern int +wimlib_fprintf(FILE *fp, const tchar *format, ...) FORMAT(printf, 2, 3); + +extern int +wimlib_printf(const tchar *format, ...) FORMAT(printf, 1, 2); +#endif /* !__WIN32__ */ + + +static inline int dummy_tprintf(const tchar *format, ...) +{ + return 0; +} + +#ifdef ENABLE_ERROR_MESSAGES +extern void +wimlib_error(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; + +extern void +wimlib_error_with_errno(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; + +extern void +wimlib_warning(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; + +extern void +wimlib_warning_with_errno(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; +# define ERROR(format, ...) wimlib_error(T(format), ## __VA_ARGS__) +# define ERROR_WITH_ERRNO(format, ...) wimlib_error_with_errno(T(format), ## __VA_ARGS__) +# define WARNING(format, ...) wimlib_warning(T(format), ## __VA_ARGS__) +# define WARNING_WITH_ERRNO(format, ...) wimlib_warning_with_errno(T(format), ## __VA_ARGS__) +#else /* ENABLE_ERROR_MESSAGES */ +# define ERROR(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) +# define ERROR_WITH_ERRNO(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) +# define WARNING(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) +# define WARNING_WITH_ERRNO(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) +#endif /* !ENABLE_ERROR_MESSAGES */ + +#if defined(ENABLE_MORE_DEBUG) && !defined(ENABLE_DEBUG) +# define ENABLE_DEBUG 1 +#endif + +#if defined(ENABLE_MORE_ASSERTIONS) && !defined(ENABLE_ASSERTIONS) +# define ENABLE_ASSERTIONS 1 +#endif + +#ifdef ENABLE_DEBUG +extern void +wimlib_debug(const tchar *file, int line, const char *func, + const tchar *format, ...); +# define DEBUG(format, ...) \ + wimlib_debug(T(__FILE__), __LINE__, __func__, T(format), ## __VA_ARGS__) + +#else +# define DEBUG(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) +#endif /* !ENABLE_DEBUG */ + +#ifdef ENABLE_MORE_DEBUG +# define DEBUG2(format, ...) DEBUG(format, ## __VA_ARGS__) +#else +# define DEBUG2(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) +#endif /* !ENABLE_MORE_DEBUG */ + +#endif /* _WIMLIB_ERROR_H */ diff --git a/include/wimlib/file_io.h b/include/wimlib/file_io.h new file mode 100644 index 00000000..1d258983 --- /dev/null +++ b/include/wimlib/file_io.h @@ -0,0 +1,39 @@ +#ifndef _WIMLIB_FILE_IO_H +#define _WIMLIB_FILE_IO_H + +#include +#include + +extern size_t +full_read(int fd, void *buf, size_t n); + +extern size_t +full_write(int fd, const void *buf, size_t n); + +extern size_t +full_pread(int fd, void *buf, size_t nbyte, off_t offset); + +extern size_t +full_pwrite(int fd, const void *buf, size_t count, off_t offset); + + +#ifdef __WIN32__ +struct iovec { + void *iov_base; + size_t iov_len; +}; +#else +struct iovec; +#endif + +extern size_t +full_writev(int fd, struct iovec *iov, int iovcnt); + +extern off_t +filedes_offset(int fd); + +#ifndef __WIN32__ +# define O_BINARY 0 +#endif + +#endif /* _WIMLIB_FILE_IO_H */ diff --git a/include/wimlib/header.h b/include/wimlib/header.h new file mode 100644 index 00000000..151d6c78 --- /dev/null +++ b/include/wimlib/header.h @@ -0,0 +1,126 @@ +#ifndef _WIMLIB_HEADER_H +#define _WIMLIB_HEADER_H + +#include "wimlib/resource.h" +#include "wimlib/types.h" + +#define WIM_MAGIC_LEN 8 +#define WIM_GID_LEN 16 +#define WIM_UNUSED_LEN 60 + +/* Length of the WIM header on disk. */ +#define WIM_HEADER_DISK_SIZE (148 + WIM_UNUSED_LEN) + +/* Compressed resources in the WIM are divided into separated compressed chunks + * of this size. */ +#define WIM_CHUNK_SIZE 32768 + +/* Version of the WIM file. There is an older version, but we don't support it + * yet. The differences between the versions are undocumented. */ +#define WIM_VERSION 0x10d00 + +/* Header at the very beginning of the WIM file. */ +struct wim_header { + /* Identifies the file as WIM file. Must be exactly + * {'M', 'S', 'W', 'I', 'M', 0, 0, 0} */ + //u8 magic[WIM_MAGIC_LEN]; + + /* size of WIM header in bytes. */ + //u32 hdr_size; + + /* Version of the WIM file. Microsoft provides no documentation about + * exactly what this field affects about the file format, other than the + * fact that more recent versions have a higher value. */ + //u32 version; + + /* Bitwise OR of one or more of the WIM_HDR_FLAG_* defined below. */ + u32 flags; + + /* The size of the pieces that the uncompressed files were split up into + * when they were compressed. This should be the same as + * WIM_CHUNK_SIZE. Microsoft incorrectly documents this as "the size of + * the compressed .wim file in bytes".*/ + //u32 chunk_size; + + /* A unique identifier for the WIM file. */ + u8 guid[WIM_GID_LEN]; + + /* Part number of the WIM file in a spanned set. */ + u16 part_number; + + /* Total number of parts in a spanned set. */ + u16 total_parts; + + /* Number of images in the WIM file. */ + u32 image_count; + + /* Location, size, and flags of the lookup table of the WIM. */ + struct resource_entry lookup_table_res_entry; + + /* Location, size, and flags for the XML data of the WIM. */ + struct resource_entry xml_res_entry; + + /* Location, size, and flags for the boot metadata. This means the + * metadata resource for the image specified by boot_idx below. Should + * be zeroed out if boot_idx is 0. */ + struct resource_entry boot_metadata_res_entry; + + /* The index of the bootable image in the WIM file. If 0, there are no + * bootable images available. */ + u32 boot_idx; + + /* The location of the optional integrity table used to verify the + * integrity WIM. Zeroed out if there is no integrity table.*/ + struct resource_entry integrity; + + /* Reserved for future disuse */ + //u8 unused[WIM_UNUSED_LEN]; +}; + +/* Flags for the `flags' field of the struct wim_header: */ + +/* Reserved for future use */ +#define WIM_HDR_FLAG_RESERVED 0x00000001 + +/* Files and metadata in the WIM are compressed. */ +#define WIM_HDR_FLAG_COMPRESSION 0x00000002 + +/* WIM is read-only (wimlib ignores this because it's pretty much pointless) */ +#define WIM_HDR_FLAG_READONLY 0x00000004 + +/* Resource data specified by images in this WIM may be contained in a different + * WIM. Or in other words, this WIM is part of a split WIM. */ +#define WIM_HDR_FLAG_SPANNED 0x00000008 + +/* The WIM contains resources only; no filesystem metadata. wimlib ignores this + * flag, as it looks for resources in all the WIMs anyway. */ +#define WIM_HDR_FLAG_RESOURCE_ONLY 0x00000010 + +/* The WIM contains metadata only. wimlib ignores this flag. Note that all the + * metadata resources for a split WIM should be in the first part. */ +#define WIM_HDR_FLAG_METADATA_ONLY 0x00000020 + +/* Lock field to prevent multiple writers from writing the WIM concurrently. + * wimlib ignores this flag as it uses flock() to acquire a real lock on the + * file (if supported by the underlying filesystem). */ +#define WIM_HDR_FLAG_WRITE_IN_PROGRESS 0x00000040 + +/* Reparse point fixup flag. See docs for --rpfix and --norpfix in imagex, or + * WIMLIB_ADD_FLAG_{RPFIX,NORPFIX} in wimlib.h. Note that + * WIM_HDR_FLAG_RP_FIX is a header flag and just sets the default behavior for + * the WIM; it can still be overridder on a per-image basis. But there is no + * flag to set the default behavior for a specific image. */ +#define WIM_HDR_FLAG_RP_FIX 0x00000080 + +/* Unused, reserved flag for another compression type */ +#define WIM_HDR_FLAG_COMPRESS_RESERVED 0x00010000 + +/* Resources within the WIM are compressed using "XPRESS" compression, which is + * a LZ77-based compression algorithm. */ +#define WIM_HDR_FLAG_COMPRESS_XPRESS 0x00020000 + +/* Resources within the WIM are compressed using "LZX" compression. This is also + * a LZ77-based algorithm. */ +#define WIM_HDR_FLAG_COMPRESS_LZX 0x00040000 + +#endif /* _WIMLIB_HEADER_H */ diff --git a/include/wimlib/integrity.h b/include/wimlib/integrity.h new file mode 100644 index 00000000..6d5a16b5 --- /dev/null +++ b/include/wimlib/integrity.h @@ -0,0 +1,23 @@ +#ifndef _WIMLIB_INTEGRITY_H +#define _WIMLIB_INTEGRITY_H + +#include "wimlib.h" +#include + +#define WIM_INTEGRITY_OK 0 +#define WIM_INTEGRITY_NOT_OK -1 +#define WIM_INTEGRITY_NONEXISTENT -2 + +struct resource_entry; + +extern int +write_integrity_table(int fd, + struct resource_entry *integrity_res_entry, + off_t new_lookup_table_end, + off_t old_lookup_table_end, + wimlib_progress_func_t progress_func); + +extern int +check_wim_integrity(WIMStruct *w, wimlib_progress_func_t progress_func); + +#endif /* _WIMLIB_INTEGRITY_H */ diff --git a/src/list.h b/include/wimlib/list.h similarity index 99% rename from src/list.h rename to include/wimlib/list.h index 2991f46a..ff407428 100644 --- a/src/list.h +++ b/include/wimlib/list.h @@ -32,7 +32,7 @@ struct hlist_node { #define LIST_HEAD_INIT(name) { &(name), &(name) } #ifdef LIST_HEAD /* BSD sys/queue.h defines this... */ -#undef LIST_HEAD +# undef LIST_HEAD #endif #define LIST_HEAD(name) \ diff --git a/src/lookup_table.h b/include/wimlib/lookup_table.h similarity index 96% rename from src/lookup_table.h rename to include/wimlib/lookup_table.h index 91c42571..a01598c2 100644 --- a/src/lookup_table.h +++ b/include/wimlib/lookup_table.h @@ -1,20 +1,16 @@ #ifndef _WIMLIB_LOOKUP_TABLE_H #define _WIMLIB_LOOKUP_TABLE_H -#include "wimlib_internal.h" -#include "dentry.h" -#include "sha1.h" -#include -/* Size of each lookup table entry in the WIM file. */ -#define WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE 50 +#include "wimlib/assert.h" +#include "wimlib/dentry.h" +#include "wimlib/list.h" +#include "wimlib/sha1.h" +#include "wimlib/types.h" +#include "wimlib/wim.h" #define LOOKUP_FLAG_ADS_OK 0x00000001 #define LOOKUP_FLAG_DIRECTORY_OK 0x00000002 -#ifdef __WIN32__ -#include -#endif - /* The lookup table of a WIM file maps SHA1 message digests to streams of data. * Here, the in-memory structure is implemented as a hash table. @@ -36,6 +32,9 @@ struct wim_lookup_table { }; #ifdef WITH_NTFS_3G + +struct _ntfs_volume; + struct ntfs_location { tchar *path; utf16lechar *stream_name; @@ -269,18 +268,8 @@ wim_resource_compressed_size(const struct wim_lookup_table_entry *lte) return lte->resource_entry.size; } -/* - * XXX Probably should store the compression type directly in the lookup table - * entry - */ -static inline int -wim_resource_compression_type(const struct wim_lookup_table_entry *lte) -{ - if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) - || lte->resource_location != RESOURCE_IN_WIM) - return WIMLIB_COMPRESSION_TYPE_NONE; - return wimlib_get_compression_type(lte->wim); -} +extern int +wim_resource_compression_type(const struct wim_lookup_table_entry *lte); static inline bool lte_filename_valid(const struct wim_lookup_table_entry *lte) @@ -329,7 +318,7 @@ lookup_table_unlink(struct wim_lookup_table *table, struct wim_lookup_table_entr } extern struct wim_lookup_table_entry * -new_lookup_table_entry(); +new_lookup_table_entry(void); extern struct wim_lookup_table_entry * clone_lookup_table_entry(const struct wim_lookup_table_entry *lte); @@ -500,4 +489,4 @@ hash_unhashed_stream(struct wim_lookup_table_entry *lte, extern struct wim_lookup_table_entry ** retrieve_lte_pointer(struct wim_lookup_table_entry *lte); -#endif +#endif /* _WIMLIB_LOOKUP_TABLE_H */ diff --git a/src/lzx.h b/include/wimlib/lzx.h similarity index 98% rename from src/lzx.h rename to include/wimlib/lzx.h index 5f87076e..a3db788a 100644 --- a/src/lzx.h +++ b/include/wimlib/lzx.h @@ -1,7 +1,8 @@ #ifndef _WIMLIB_LZX_H #define _WIMLIB_LZX_H -#include "util.h" +#include "wimlib/assert.h" +#include "wimlib/types.h" //#define ENABLE_LZX_DEBUG #ifdef ENABLE_LZX_DEBUG diff --git a/include/wimlib/metadata.h b/include/wimlib/metadata.h new file mode 100644 index 00000000..178c4232 --- /dev/null +++ b/include/wimlib/metadata.h @@ -0,0 +1,111 @@ +#ifndef _WIMLIB_METADATA_H +#define _WIMLIB_METADATA_H + +#include "wimlib/list.h" +#include "wimlib/types.h" +#include "wimlib/wim.h" + +#ifdef WITH_NTFS_3G +struct _ntfs_volume; +#endif + +/* Metadata for a WIM image */ +struct wim_image_metadata { + + /* Number of WIMStruct's that are sharing this image metadata (from + * calls to wimlib_export_image().) */ + unsigned long refcnt; + + /* Pointer to the root dentry of the image. */ + struct wim_dentry *root_dentry; + + /* Pointer to the security data of the image. */ + struct wim_security_data *security_data; + + /* Pointer to the lookup table entry for this image's metadata resource + */ + struct wim_lookup_table_entry *metadata_lte; + + /* Linked list of 'struct wim_inode's for this image. */ + struct list_head inode_list; + + /* Linked list of 'struct wim_lookup_table_entry's for this image that + * are referred to in the dentry tree, but have not had a SHA1 message + * digest calculated yet and therefore have not been inserted into the + * WIM's lookup table. This list is added to during wimlib_add_image() + * and wimlib_mount_image() (read-write only). */ + struct list_head unhashed_streams; + + /* 1 iff the dentry tree has been modified. If this is the case, the + * memory for the dentry tree should not be freed when switching to a + * different WIM image. */ + u8 modified : 1; + +#ifdef WITH_NTFS_3G + struct _ntfs_volume *ntfs_vol; +#endif +}; + +static inline struct wim_image_metadata * +wim_get_current_image_metadata(WIMStruct *w) +{ + return w->image_metadata[w->current_image - 1]; +} + +static inline const struct wim_image_metadata * +wim_get_const_current_image_metadata(const WIMStruct *w) +{ + return w->image_metadata[w->current_image - 1]; +} + +static inline struct wim_dentry * +wim_root_dentry(WIMStruct *w) +{ + return wim_get_current_image_metadata(w)->root_dentry; +} + +static inline struct wim_security_data * +wim_security_data(WIMStruct *w) +{ + return wim_get_current_image_metadata(w)->security_data; +} + +static inline const struct wim_security_data * +wim_const_security_data(const WIMStruct *w) +{ + return wim_get_const_current_image_metadata(w)->security_data; +} + +/* Iterate over each inode in a WIM image that has not yet been hashed */ +#define image_for_each_inode(inode, imd) \ + list_for_each_entry(inode, &imd->inode_list, i_list) + +/* Iterate over each stream in a WIM image that has not yet been hashed */ +#define image_for_each_unhashed_stream(lte, imd) \ + list_for_each_entry(lte, &imd->unhashed_streams, unhashed_list) + +/* Iterate over each stream in a WIM image that has not yet been hashed (safe + * against stream removal) */ +#define image_for_each_unhashed_stream_safe(lte, tmp, imd) \ + list_for_each_entry_safe(lte, tmp, &imd->unhashed_streams, unhashed_list) + +extern void +destroy_image_metadata(struct wim_image_metadata *imd, + struct wim_lookup_table *table, + bool free_metadata_lte); + +extern void +put_image_metadata(struct wim_image_metadata *imd, + struct wim_lookup_table *table); + +extern int +append_image_metadata(WIMStruct *w, struct wim_image_metadata *imd); + +extern struct wim_image_metadata * +new_image_metadata(void); + +extern struct wim_image_metadata ** +new_image_metadata_array(unsigned num_images); + + +#endif /* _WIMLIB_METADATA_H */ diff --git a/include/wimlib/ntfs_3g.h b/include/wimlib/ntfs_3g.h new file mode 100644 index 00000000..425d9dfd --- /dev/null +++ b/include/wimlib/ntfs_3g.h @@ -0,0 +1,24 @@ +#ifndef _WIMLIB_NTFS_3G_H +#define _WIMLIB_NTFS_3G_H + +#include "wimlib/callback.h" +#include "wimlib/types.h" + +struct wim_lookup_table_entry; +struct _ntfs_volume; + +extern void +libntfs3g_global_init(void); + +extern int +read_ntfs_file_prefix(const struct wim_lookup_table_entry *lte, + u64 size, + consume_data_callback_t cb, + void *ctx_or_buf, + int _ignored_flags); + + +extern int +do_ntfs_umount(struct _ntfs_volume *vol); + +#endif diff --git a/include/wimlib/paths.h b/include/wimlib/paths.h new file mode 100644 index 00000000..944fbf45 --- /dev/null +++ b/include/wimlib/paths.h @@ -0,0 +1,24 @@ +#ifndef _WIMLIB_PATHS_H +#define _WIMLIB_PATHS_H + +#include "wimlib/types.h" + +const tchar * +path_basename(const tchar *path); + +const tchar * +path_basename_with_len(const tchar *path, size_t len); + +extern const tchar * +path_stream_name(const tchar *path); + +extern void +zap_backslashes(tchar *s); + +extern tchar * +canonicalize_wim_path(const tchar *wim_path); + +extern tchar * +canonicalize_fs_path(const tchar *fs_path); + +#endif /* _WIMLIB_PATHS_H */ diff --git a/src/rbtree.h b/include/wimlib/rbtree.h similarity index 98% rename from src/rbtree.h rename to include/wimlib/rbtree.h index c9321a68..bdb209dc 100644 --- a/src/rbtree.h +++ b/include/wimlib/rbtree.h @@ -29,8 +29,8 @@ #ifndef _LINUX_RBTREE_H #define _LINUX_RBTREE_H -#include "util.h" #include +#include struct rb_node { uintptr_t __rb_parent_color; diff --git a/include/wimlib/reparse.h b/include/wimlib/reparse.h new file mode 100644 index 00000000..8628d694 --- /dev/null +++ b/include/wimlib/reparse.h @@ -0,0 +1,77 @@ +#ifndef _WIMLIB_REPARSE_H +#define _WIMLIB_REPARSE_H + +#include "wimlib/types.h" + +struct wim_inode; +struct wim_lookup_table; + +#define REPARSE_POINT_MAX_SIZE (16 * 1024) + +/* Structured format for symbolic link, junction point, or mount point reparse + * data. */ +struct reparse_data { + /* Reparse point tag (see WIM_IO_REPARSE_TAG_* values) */ + u32 rptag; + + /* Length of reparse data, not including the 8-byte header (ReparseTag, + * ReparseDataLength, ReparseReserved) */ + u16 rpdatalen; + + /* ReparseReserved */ + u16 rpreserved; + + /* Flags (only for WIM_IO_REPARSE_TAG_SYMLINK reparse points). + * SYMBOLIC_LINK_RELATIVE means this is a relative symbolic link; + * otherwise should be set to 0. */ +#define SYMBOLIC_LINK_RELATIVE 0x00000001 + u32 rpflags; + + /* Pointer to the substitute name of the link (UTF-16LE). */ + utf16lechar *substitute_name; + + /* Pointer to the print name of the link (UTF-16LE). */ + utf16lechar *print_name; + + /* Number of bytes of the substitute name, not including null terminator + * if present */ + u16 substitute_name_nbytes; + + /* Number of bytes of the print name, not including null terminator if + * present */ + u16 print_name_nbytes; +}; + +enum { + SUBST_NAME_IS_RELATIVE_LINK = -1, + SUBST_NAME_IS_VOLUME_JUNCTION = -2, + SUBST_NAME_IS_UNKNOWN = -3, +}; +extern int +parse_substitute_name(const utf16lechar *substitute_name, + u16 substitute_name_nbytes, + u32 rptag); + +extern int +parse_reparse_data(const u8 *rpbuf, u16 rpbuflen, struct reparse_data *rpdata); + +extern int +make_reparse_buffer(const struct reparse_data *rpdata, u8 *buf); + +extern int +wim_inode_get_reparse_data(const struct wim_inode *inode, u8 *rpbuf); + +#ifndef __WIN32__ +ssize_t +wim_inode_readlink(const struct wim_inode *inode, char *buf, size_t buf_len); + +extern int +wim_inode_set_symlink(struct wim_inode *inode, const char *target, + struct wim_lookup_table *lookup_table); +#endif + +extern tchar * +capture_fixup_absolute_symlink(tchar *dest, + u64 capture_root_ino, u64 capture_root_dev); + +#endif /* _WIMLIB_REPARSE_H */ diff --git a/include/wimlib/resource.h b/include/wimlib/resource.h new file mode 100644 index 00000000..757531c9 --- /dev/null +++ b/include/wimlib/resource.h @@ -0,0 +1,127 @@ +#ifndef _WIMLIB_RESOURCE_H +#define _WIMLIB_RESOURCE_H + +#include "wimlib/types.h" +#include "wimlib/callback.h" + +struct wim_lookup_table_entry; +struct wim_image_metadata; + +/* Metadata for a resource in a WIM file. */ +struct resource_entry { + /* Size, in bytes, of the resource in the WIM file. */ + u64 size : 56; + + /* Bitwise or of one or more of the WIM_RESHDR_FLAG_* flags. */ + u64 flags : 8; + + /* Offset, in bytes, of the resource in the WIM file. */ + u64 offset; + + /* Uncompressed size of the resource in the WIM file. Is the same as + * @size if the resource is uncompressed. */ + u64 original_size; +}; + + +/* Flags for the `flags' field of the struct resource_entry structure. */ + +/* I haven't seen this flag used in any of the WIMs I have examined. I assume + * it means that there are no references to the stream, so the space is free. + * However, even after deleting files from a WIM mounted with `imagex.exe + * /mountrw', I could not see this flag being used. Either way, we don't + * actually use this flag for anything. */ +#define WIM_RESHDR_FLAG_FREE 0x01 + +/* Indicates that the stream is a metadata resource for a WIM image. */ +#define WIM_RESHDR_FLAG_METADATA 0x02 + +/* Indicates that the stream is compressed. */ +#define WIM_RESHDR_FLAG_COMPRESSED 0x04 + +/* I haven't seen this flag used in any of the WIMs I have examined. Perhaps it + * means that a stream could possibly be split among multiple split WIM parts. + * However, `imagex.exe /split' does not seem to create any WIMs like this. + * Either way, we don't actually use this flag for anything. */ +#define WIM_RESHDR_FLAG_SPANNED 0x08 + +/* Nonzero if a struct resource_entry indicates a compressed resource. */ +static inline int +resource_is_compressed(const struct resource_entry *entry) +{ + return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED); +} + +#if 1 +# define copy_resource_entry(dst, src) memcpy(dst, src, sizeof(struct resource_entry)) +# define zero_resource_entry(entry) memset(entry, 0, sizeof(struct resource_entry)) +#else +static inline void +copy_resource_entry(struct resource_entry *dst, + const struct resource_entry *src) +{ + BUILD_BUG_ON(sizeof(struct resource_entry) != 24); + ((u64*)dst)[0] = ((u64*)src)[0]; + ((u64*)dst)[1] = ((u64*)src)[1]; + ((u64*)dst)[2] = ((u64*)src)[2]; +} + +static inline void +zero_resource_entry(struct resource_entry *entry) +{ + BUILD_BUG_ON(sizeof(struct resource_entry) != 24); + ((u64*)entry)[0] = 0; + ((u64*)entry)[1] = 0; + ((u64*)entry)[2] = 0; +} +#endif + +#define WIMLIB_RESOURCE_FLAG_RAW 0x1 +#define WIMLIB_RESOURCE_FLAG_RECOMPRESS 0x2 + +extern int +read_resource_prefix(const struct wim_lookup_table_entry *lte, + u64 size, consume_data_callback_t cb, void *ctx_or_buf, + int flags); + +extern const void * +get_resource_entry(const void *p, struct resource_entry *entry); + +extern void * +put_resource_entry(void *p, const struct resource_entry *entry); + +extern int +read_partial_wim_resource_into_buf(const struct wim_lookup_table_entry *lte, + size_t size, u64 offset, void *buf); +extern int +read_full_resource_into_buf(const struct wim_lookup_table_entry *lte, void *buf); + +extern int +write_wim_resource(struct wim_lookup_table_entry *lte, int out_fd, + int out_ctype, struct resource_entry *out_res_entry, + int flags); + +extern int +extract_wim_resource(const struct wim_lookup_table_entry *lte, + u64 size, + consume_data_callback_t extract_chunk, + void *extract_chunk_arg); + +extern int +extract_wim_resource_to_fd(const struct wim_lookup_table_entry *lte, + int fd, u64 size); + +extern int +sha1_resource(struct wim_lookup_table_entry *lte); + +extern int +copy_resource(struct wim_lookup_table_entry *lte, void *w); + +extern int +read_metadata_resource(WIMStruct *w, + struct wim_image_metadata *image_metadata); + +extern int +write_metadata_resource(WIMStruct *w); + +#endif /* _WIMLIB_RESOURCE_H */ diff --git a/include/wimlib/security.h b/include/wimlib/security.h new file mode 100644 index 00000000..7fa122ee --- /dev/null +++ b/include/wimlib/security.h @@ -0,0 +1,65 @@ +#ifndef _WIMLIB_SECURITY_H +#define _WIMLIB_SECURITY_H + +#include "wimlib/rbtree.h" +#include "wimlib/types.h" + +/* Red-black tree that maps SHA1 message digests of security descriptors to + * security IDs, which are themselves indices into the table of security + * descriptors in the 'struct wim_security_data'. */ +struct wim_sd_set { + struct wim_security_data *sd; + struct rb_root rb_root; + int32_t orig_num_entries; +}; + +/* Table of security descriptors for a WIM image. */ +struct wim_security_data { + /* The total length of the security data, in bytes. If there are no + * security descriptors, this field, when read from the on-disk metadata + * resource, may be either 8 (which is correct) or 0 (which is + * interpreted as 0). */ + u32 total_length; + + /* The number of security descriptors in the array @descriptors, below. + * It is really an unsigned int on-disk, but it must fit into an int + * because the security ID's are signed. (Not like you would ever have + * more than a few hundred security descriptors anyway.) */ + int32_t num_entries; + + /* Array of sizes of the descriptors in the array @descriptors. */ + u64 *sizes; + + /* Array of descriptors. */ + u8 **descriptors; +}; + +extern void +destroy_sd_set(struct wim_sd_set *sd_set, bool rollback); + +extern int +lookup_sd(struct wim_sd_set *set, const u8 hash[]); + +extern int +sd_set_add_sd(struct wim_sd_set *sd_set, const char descriptor[], + size_t size); + +extern int +init_sd_set(struct wim_sd_set *sd_set, struct wim_security_data *sd); + +extern struct wim_security_data * +new_wim_security_data(void); + +extern int +read_security_data(const u8 metadata_resource[], + u64 metadata_resource_len, struct wim_security_data **sd_p); +extern void +print_security_data(const struct wim_security_data *sd); + +extern u8 * +write_security_data(const struct wim_security_data *sd, u8 *p); + +extern void +free_security_data(struct wim_security_data *sd); + +#endif /* _WIMLIB_SECURITY_H */ diff --git a/src/sha1.h b/include/wimlib/sha1.h similarity index 95% rename from src/sha1.h rename to include/wimlib/sha1.h index 3f500b23..1f7c50f7 100644 --- a/src/sha1.h +++ b/include/wimlib/sha1.h @@ -1,11 +1,10 @@ #ifndef _WIMLIB_SHA1_H #define _WIMLIB_SHA1_H -#include "config.h" -#include -#include +#include "wimlib/types.h" +#include "wimlib/util.h" + #include -#include "util.h" #define SHA1_HASH_SIZE 20 diff --git a/include/wimlib/swm.h b/include/wimlib/swm.h new file mode 100644 index 00000000..73281651 --- /dev/null +++ b/include/wimlib/swm.h @@ -0,0 +1,17 @@ +#ifndef _WIMLIB_SWM_H +#define _WIMLIB_SWM_H + +#include "wimlib/types.h" + +extern int +verify_swm_set(WIMStruct *w, + WIMStruct **additional_swms, unsigned num_additional_swms); + +extern void +merge_lookup_tables(WIMStruct *w, + WIMStruct **additional_swms, unsigned num_additional_swms); + +extern void +unmerge_lookup_table(WIMStruct *wim); + +#endif diff --git a/src/timestamp.h b/include/wimlib/timestamp.h similarity index 97% rename from src/timestamp.h rename to include/wimlib/timestamp.h index 91006fc0..14a2eb16 100644 --- a/src/timestamp.h +++ b/include/wimlib/timestamp.h @@ -1,7 +1,7 @@ #ifndef _WIMLIB_TIMESTAMP_H #define _WIMLIB_TIMESTAMP_H -#include "util.h" +#include "wimlib/types.h" #include #include #include @@ -69,7 +69,7 @@ wim_timestamp_to_timespec(u64 timestamp) } extern u64 -get_wim_timestamp(); +get_wim_timestamp(void); extern void wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len); diff --git a/include/wimlib/types.h b/include/wimlib/types.h new file mode 100644 index 00000000..faf290c9 --- /dev/null +++ b/include/wimlib/types.h @@ -0,0 +1,32 @@ +#ifndef _WIMLIB_TYPES_H +#define _WIMLIB_TYPES_H + +#include "wimlib_tchar.h" + +#include +#include +#include + +#ifndef _NTFS_TYPES_H +/* Unsigned integer types of exact size in bits */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +/* Signed integer types of exact size in bits */ +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +#endif + +/* A pointer to 'utf16lechar' indicates a UTF-16LE encoded string */ +typedef u16 utf16lechar; + +#ifndef WIMLIB_WIMSTRUCT_DECLARED +typedef struct WIMStruct WIMStruct; +# define WIMLIB_WIMSTRUCT_DECLARED +#endif + +#endif diff --git a/include/wimlib/util.h b/include/wimlib/util.h new file mode 100644 index 00000000..177e1190 --- /dev/null +++ b/include/wimlib/util.h @@ -0,0 +1,111 @@ +#ifndef _WIMLIB_UTIL_H +#define _WIMLIB_UTIL_H + +#include "wimlib/types.h" +#include "wimlib/compiler.h" + +#include +#include + +#ifndef min +#define min(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \ + (__a < __b) ? __a : __b; }) +#endif + +#ifndef max +#define max(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \ + (__a > __b) ? __a : __b; }) +#endif + +#ifndef swap +#define swap(a, b) ({typeof(a) _a = a; (a) = (b); (b) = _a;}) +#endif + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#define DIV_ROUND_UP(numerator, denominator) \ + (((numerator) + (denominator) - 1) / (denominator)) + +#define MODULO_NONZERO(numerator, denominator) \ + (((numerator) % (denominator)) ? ((numerator) % (denominator)) : (denominator)) + +#define ARRAY_LEN(array) (sizeof(array) / sizeof((array)[0])) + +#define ZERO_ARRAY(array) memset(array, 0, sizeof(array)) + +/* Used for buffering FILE IO in a few places */ +#define BUFFER_SIZE 32768 + +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) + +#ifdef ENABLE_CUSTOM_MEMORY_ALLOCATOR +extern void *(*wimlib_malloc_func)(size_t); +extern void (*wimlib_free_func)(void *); +extern void *(*wimlib_realloc_func)(void *, size_t); +extern void *wimlib_calloc(size_t nmemb, size_t size); +#ifdef __WIN32__ +extern wchar_t *wimlib_wcsdup(const wchar_t *str); +#endif +extern char *wimlib_strdup(const char *str); +# define MALLOC wimlib_malloc_func +# define FREE wimlib_free_func +# define REALLOC wimlib_realloc_func +# define CALLOC wimlib_calloc +# define STRDUP wimlib_strdup +# define WSTRDUP wimlib_wcsdup +#else /* ENABLE_CUSTOM_MEMORY_ALLOCATOR */ +# include +# include +# define MALLOC malloc +# define FREE free +# define REALLOC realloc +# define CALLOC calloc +# define STRDUP strdup +# define WSTRDUP wcsdup +#endif /* !ENABLE_CUSTOM_MEMORY_ALLOCATOR */ + + +/* util.c */ +extern void +randomize_byte_array(u8 *p, size_t n); + +extern void +randomize_char_array_with_alnum(tchar p[], size_t n); + +extern void +print_byte_field(const u8 field[], size_t len, FILE *out); + +static inline u32 +bsr32(u32 n) +{ +#if defined(__x86__) || defined(__x86_64__) + asm("bsrl %0, %0;" + : "=r"(n) + : "0" (n)); + return n; +#else + u32 pow = 0; + while ((n >>= 1) != 0) + pow++; + return pow; +#endif +} + +static inline u64 +hash_u64(u64 n) +{ + return n * 0x9e37fffffffc0001ULL; +} + +#endif /* _WIMLIB_UTIL_H */ diff --git a/include/wimlib/version.h b/include/wimlib/version.h new file mode 100644 index 00000000..42deaa69 --- /dev/null +++ b/include/wimlib/version.h @@ -0,0 +1,22 @@ +#ifndef _WIMLIB_VERSION_H +#define _WIMLIB_VERSION_H + +#include "wimlib.h" + +#define WIMLIB_MAKEVERSION(major, minor, patch) \ + ((major << 20) | (minor << 10) | patch) + + +#define WIMLIB_VERSION_CODE \ + WIMLIB_MAKEVERSION(WIMLIB_MAJOR_VERSION,\ + WIMLIB_MINOR_VERSION,\ + WIMLIB_PATCH_VERSION) + +#define WIMLIB_GET_PATCH_VERSION(version) \ + ((version >> 0) & ((1 << 10) - 1)) +#define WIMLIB_GET_MINOR_VERSION(version) \ + ((version >> 10) & ((1 << 10) - 1)) +#define WIMLIB_GET_MAJOR_VERSION(version) \ + ((version >> 20) & ((1 << 10) - 1)) + +#endif /* _WIMLIB_VERSION_H */ diff --git a/include/wimlib/wim.h b/include/wimlib/wim.h new file mode 100644 index 00000000..946eee1f --- /dev/null +++ b/include/wimlib/wim.h @@ -0,0 +1,86 @@ +#ifndef _WIMLIB_WIM_H +#define _WIMLIB_WIM_H + +#include "wimlib/header.h" +#include "wimlib/types.h" + +struct wim_info; +struct wim_lookup_table; +struct wim_image_metadata; + +/* The opaque structure exposed to the wimlib API. */ +struct WIMStruct { + + /* File descriptor for the WIM file, opened for reading, or -1 if it has + * not been opened or there is no associated file backing it yet. */ + int in_fd; + + /* File descriptor, opened either for writing only or for + * reading+writing, for the WIM file (if any) currently being written. + * */ + int out_fd; + + /* The name of the WIM file (if any) that has been opened. */ + tchar *filename; + + /* The lookup table for the WIM file. */ + struct wim_lookup_table *lookup_table; + + /* Information retrieved from the XML data, arranged in an orderly + * manner. */ + struct wim_info *wim_info; + + /* Array of the image metadata, one for each image in the WIM. */ + struct wim_image_metadata **image_metadata; + + /* The header of the WIM file. */ + struct wim_header hdr; + + /* Temporary field */ + void *private; + + /* The currently selected image, indexed starting at 1. If not 0, + * subtract 1 from this to get the index of the current image in the + * image_metadata array. */ + int current_image; + + /* Have any images been deleted? */ + u8 deletion_occurred : 1; + + u8 all_images_verified : 1; + u8 wim_locked : 1; +}; + +extern int +wim_run_full_verifications(WIMStruct *w); + +extern int +read_header(const tchar *filename, int in_fd, struct wim_header *hdr, + int split_ok); + +extern int +write_header(const struct wim_header *hdr, int out_fd); + +extern int +init_header(struct wim_header *hdr, int ctype); + + +extern int +rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to); + +extern int +select_wim_image(WIMStruct *w, int image); + +extern int +for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *)); + +extern int +wim_checksum_unhashed_streams(WIMStruct *w); + +extern int +reopen_wim(WIMStruct *w); + +extern int +close_wim(WIMStruct *w); + +#endif /* _WIMLIB_WIM_H */ diff --git a/src/win32.h b/include/wimlib/win32.h similarity index 58% rename from src/win32.h rename to include/wimlib/win32.h index 89b385f2..f1e53fd1 100644 --- a/src/win32.h +++ b/include/wimlib/win32.h @@ -1,21 +1,15 @@ #ifndef _WIMLIB_WIN32_H #define _WIMLIB_WIN32_H -#include "wimlib_internal.h" +#ifdef __WIN32__ + +#include "wimlib/callback.h" +#include "wimlib/types.h" #include #include -extern int -win32_build_dentry_tree(struct wim_dentry **root_ret, - const tchar *root_disk_path, - struct add_image_params *params); - -extern int -win32_get_file_and_vol_ids(const wchar_t *path, u64 *ino_ret, u64 *dev_ret); - -extern int -win32_read_file(const tchar *filename, HANDLE handle, - u64 offset, size_t size, void *buf); +struct wim_lookup_table_entry; +struct iovec; extern int read_win32_file_prefix(const struct wim_lookup_table_entry *lte, @@ -31,29 +25,24 @@ read_win32_encrypted_file_prefix(const struct wim_lookup_table_entry *lte, void *ctx_or_buf, int _ignored_flags); + +extern void +win32_global_init(void); + +extern void +win32_global_cleanup(void); + #define FNM_PATHNAME 0x1 #define FNM_NOESCAPE 0x2 #define FNM_NOMATCH 1 extern int fnmatch(const tchar *pattern, const tchar *string, int flags); -extern int -win32_do_apply_dentry(const tchar *output_path, - size_t output_path_nbytes, - struct wim_dentry *dentry, - struct apply_args *args); - -extern int -win32_do_apply_dentry_timestamps(const tchar *output_path, - size_t output_path_nbytes, - struct wim_dentry *dentry, - struct apply_args *args); - extern int fsync(int fd); extern unsigned -win32_get_number_of_processors(); +win32_get_number_of_processors(void); extern tchar * realpath(const tchar *path, tchar *resolved_path); @@ -68,22 +57,22 @@ win32_rename_replacement(const tchar *oldpath, const tchar *newpath); extern int win32_truncate_replacement(const tchar *path, off_t size); -extern void -win32_global_init(); - -extern void -win32_global_cleanup(); - extern int win32_strerror_r_replacement(int errnum, tchar *buf, size_t buflen); +extern int +win32_get_file_and_vol_ids(const wchar_t *path, u64 *ino_ret, u64 *dev_ret); + + extern ssize_t -win32_pread(int fd, void *buf, size_t count, off_t offset); +pread(int fd, void *buf, size_t count, off_t offset); extern ssize_t -win32_pwrite(int fd, const void *buf, size_t count, off_t offset); +pwrite(int fd, const void *buf, size_t count, off_t offset); extern ssize_t -win32_writev(int fd, const struct iovec *iov, int iovcnt); +writev(int fd, const struct iovec *iov, int iovcnt); + +#endif /* __WIN32__ */ #endif /* _WIMLIB_WIN32_H */ diff --git a/src/win32_common.h b/include/wimlib/win32_common.h similarity index 93% rename from src/win32_common.h rename to include/wimlib/win32_common.h index 9a61dab1..ebd0564d 100644 --- a/src/win32_common.h +++ b/include/wimlib/win32_common.h @@ -6,8 +6,8 @@ # undef ERROR #endif -#include "util.h" -#include "win32.h" +#include "wimlib/types.h" +#include "wimlib/win32.h" #ifdef ENABLE_ERROR_MESSAGES @@ -21,7 +21,7 @@ win32_error(DWORD err_code) #endif extern void -set_errno_from_GetLastError(); +set_errno_from_GetLastError(void); extern int win32_error_to_errno(DWORD err_code); diff --git a/include/wimlib/write.h b/include/wimlib/write.h new file mode 100644 index 00000000..2cb9a334 --- /dev/null +++ b/include/wimlib/write.h @@ -0,0 +1,34 @@ +#ifndef _WIMLIB_WRITE_H +#define _WIMLIB_WRITE_H + +#include "wimlib.h" +#include "wimlib/types.h" + +/* Internal use only */ +#define WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE 0x80000000 +#define WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE 0x40000000 +#define WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML 0x20000000 +#define WIMLIB_WRITE_MASK_PUBLIC 0x1fffffff + +extern int +begin_write(WIMStruct *w, const tchar *path, int write_flags); + +extern void +close_wim_writable(WIMStruct *w); + +extern int +finish_write(WIMStruct *w, int image, int write_flags, + wimlib_progress_func_t progress_func); + +#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) +extern int +lock_wim(WIMStruct *w, int fd); +#else +static inline int +lock_wim(WIMStruct *w, int fd) +{ + return 0; +} +#endif + +#endif /* _WIMLIB_WRITE_H */ diff --git a/src/xml.h b/include/wimlib/xml.h similarity index 81% rename from src/xml.h rename to include/wimlib/xml.h index d784db14..439bd012 100644 --- a/src/xml.h +++ b/include/wimlib/xml.h @@ -1,7 +1,10 @@ #ifndef _WIMLIB_XML_H #define _WIMLIB_XML_H -#include "util.h" +#include "wimlib/types.h" + +struct image_info; +struct resource_entry; /* A struct wim_info structure corresponds to the entire XML data for a WIM file. */ struct wim_info { @@ -46,10 +49,10 @@ write_xml_data(const struct wim_info *wim_info, int image, int out_fd, u64 total_bytes, struct resource_entry *out_res_entry); extern void -libxml_global_init(); +libxml_global_init(void); extern void -libxml_global_cleanup(); +libxml_global_cleanup(void); static inline u64 wim_info_get_total_bytes(const struct wim_info *info) @@ -63,4 +66,11 @@ wim_info_get_num_images(const struct wim_info *info) return info->num_images; } +#ifdef ENABLE_CUSTOM_MEMORY_ALLOCATOR +extern void +xml_set_memory_allocator(void *(*malloc_func)(size_t), + void (*free_func)(void *), + void *(*realloc_func)(void *, size_t)); +#endif + #endif diff --git a/src/xpress.h b/include/wimlib/xpress.h similarity index 96% rename from src/xpress.h rename to include/wimlib/xpress.h index 2949780c..c07dbae8 100644 --- a/src/xpress.h +++ b/include/wimlib/xpress.h @@ -1,8 +1,6 @@ #ifndef _WIMLIB_XPRESS_H #define _WIMLIB_XPRESS_H -#include "util.h" - /* See the comments in xpress-decompress.c about the XPRESS format. */ //#define ENABLE_XPRESS_DEBUG diff --git a/wimlib_tchar.h b/include/wimlib_tchar.h similarity index 100% rename from wimlib_tchar.h rename to include/wimlib_tchar.h diff --git a/programs/imagex-win32.c b/programs/imagex-win32.c index ca347816..9e93c4cc 100644 --- a/programs/imagex-win32.c +++ b/programs/imagex-win32.c @@ -169,25 +169,25 @@ win32_modify_restore_privileges(bool enable) } void -win32_acquire_capture_privileges() +win32_acquire_capture_privileges(void) { win32_modify_capture_privileges(true); } void -win32_release_capture_privileges() +win32_release_capture_privileges(void) { win32_modify_capture_privileges(false); } void -win32_acquire_restore_privileges() +win32_acquire_restore_privileges(void) { win32_modify_restore_privileges(true); } void -win32_release_restore_privileges() +win32_release_restore_privileges(void) { win32_modify_restore_privileges(false); } diff --git a/programs/imagex-win32.h b/programs/imagex-win32.h index 9e18eab5..5f21fd94 100644 --- a/programs/imagex-win32.h +++ b/programs/imagex-win32.h @@ -28,16 +28,16 @@ extern void globfree(glob_t *pglob); #define GLOB_NOMATCH 3 /* No matches found. */ extern void -win32_acquire_capture_privileges(); +win32_acquire_capture_privileges(void); extern void -win32_release_capture_privileges(); +win32_release_capture_privileges(void); extern void -win32_acquire_restore_privileges(); +win32_acquire_restore_privileges(void); extern void -win32_release_restore_privileges(); +win32_release_restore_privileges(void); extern wchar_t * win32_mbs_to_wcs(const char *mbs, size_t mbs_nbytes, size_t *num_wchars_ret); diff --git a/programs/imagex.c b/programs/imagex.c index c5a653a6..b45d2d4b 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -22,7 +22,10 @@ * along with this program. If not, see . */ -#include "config.h" +#ifdef HAVE_CONFIG_H +# include "config.h" /* Need for PACKAGE_VERSION, etc. */ +#endif + #include "wimlib.h" #include "wimlib_tchar.h" @@ -40,7 +43,7 @@ #include #ifdef HAVE_ALLOCA_H -#include +# include #endif #ifdef __WIN32__ @@ -80,7 +83,7 @@ enum imagex_op_type { }; static void usage(int cmd_type); -static void usage_all(); +static void usage_all(void); static bool imagex_be_quiet = false; @@ -3110,7 +3113,7 @@ static const struct imagex_command imagex_commands[] = { }; static void -version() +version(void) { static const tchar *s = T( @@ -3173,7 +3176,7 @@ usage(int cmd_type) } static void -usage_all() +usage_all(void) { tfputs(T("Usage:\n"), stdout); for (int i = 0; i < ARRAY_LEN(usage_strings); i++) diff --git a/programs/wgetopt.c b/programs/wgetopt.c index 5c9b74e4..ee814d29 100644 --- a/programs/wgetopt.c +++ b/programs/wgetopt.c @@ -278,7 +278,7 @@ _getopt_initialize (int argc, wchar_t *const *argv, const wchar_t *optstring) If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ -int +static int _wgetopt_internal (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct woption *longopts, int *longind, int long_only) { diff --git a/src/add_image.c b/src/add_image.c index fcb4c472..7f337c5d 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -21,9 +21,16 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "lookup_table.h" -#include "xml.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/capture.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/xml.h" /* * Adds the dentry tree and security data for a new image to the image metadata diff --git a/src/capture_common.c b/src/capture_common.c index a18b49ca..e6b5baa4 100644 --- a/src/capture_common.c +++ b/src/capture_common.c @@ -21,15 +21,22 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include +#include "wimlib/assert.h" +#include "wimlib/capture.h" +#include "wimlib/error.h" +#include "wimlib/paths.h" #ifdef __WIN32__ -# include "win32.h" +# include "wimlib/win32.h" /* for fnmatch() equivalent */ #else # include #endif +#include + static int canonicalize_pattern(const tchar *pat, tchar **canonical_pat_ret) diff --git a/src/compress.c b/src/compress.c index c40256a0..89d1245f 100644 --- a/src/compress.c +++ b/src/compress.c @@ -23,7 +23,15 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "compress.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include "wimlib/assert.h" +#include "wimlib/compress.h" +#include "wimlib/util.h" + #include #include diff --git a/src/decompress.c b/src/decompress.c index 6ca0f161..c8be3197 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -23,7 +23,13 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "decompress.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/decompress.h" +#include "wimlib/util.h" + #include /* diff --git a/src/delete_image.c b/src/delete_image.c index 14f8e7e7..862fb66e 100644 --- a/src/delete_image.c +++ b/src/delete_image.c @@ -21,9 +21,16 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "xml.h" -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/error.h" +#include "wimlib/metadata.h" +#include "wimlib/util.h" +#include "wimlib/wim.h" +#include "wimlib/xml.h" /* * Deletes an image from the WIM. diff --git a/src/dentry.c b/src/dentry.c index 6e13d3d6..d77603fe 100644 --- a/src/dentry.c +++ b/src/dentry.c @@ -26,11 +26,20 @@ * wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "buffer_io.h" -#include "dentry.h" -#include "lookup_table.h" -#include "timestamp.h" -#include "wimlib_internal.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/buffer_io.h" +#include "wimlib/dentry.h" +#include "wimlib/encoding.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/resource.h" +#include "wimlib/timestamp.h" + #include /* Calculates the unaligned length, in bytes, of an on-disk WIM dentry that has @@ -713,7 +722,7 @@ dentry_common_init(struct wim_dentry *dentry) } struct wim_inode * -new_timeless_inode() +new_timeless_inode(void) { struct wim_inode *inode = CALLOC(1, sizeof(struct wim_inode)); if (inode) { @@ -735,7 +744,7 @@ new_timeless_inode() } static struct wim_inode * -new_inode() +new_inode(void) { struct wim_inode *inode = new_timeless_inode(); if (inode) { diff --git a/src/encoding.c b/src/encoding.c index 31e6913a..d4f4f399 100644 --- a/src/encoding.c +++ b/src/encoding.c @@ -21,7 +21,15 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/encoding.h" +#include "wimlib/error.h" +#include "wimlib/list.h" +#include "wimlib/util.h" #include #include @@ -362,7 +370,7 @@ iconv_cleanup(struct iconv_list_head *head) } void -iconv_global_cleanup() +iconv_global_cleanup(void) { iconv_cleanup(&iconv_utf8_to_tstr); iconv_cleanup(&iconv_tstr_to_utf8); diff --git a/src/export_image.c b/src/export_image.c index a948ab79..455baa91 100644 --- a/src/export_image.c +++ b/src/export_image.c @@ -21,10 +21,17 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" -#include "xml.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/swm.h" +#include "wimlib/xml.h" static int inode_allocate_needed_ltes(struct wim_inode *inode, diff --git a/src/extract_image.c b/src/extract.c similarity index 98% rename from src/extract_image.c rename to src/extract.c index fad438f5..f1415632 100644 --- a/src/extract_image.c +++ b/src/extract.c @@ -1,7 +1,8 @@ /* - * extract_image.c + * extract.c * - * Support for extracting WIM files. + * Support for extracting WIM images, or files or directories contained in a WIM + * image. */ /* @@ -23,25 +24,30 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "config.h" - -#include -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "wimlib/apply.h" +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/paths.h" +#include "wimlib/resource.h" +#include "wimlib/swm.h" #ifdef __WIN32__ -# include "win32.h" +# include "wimlib/win32.h" /* for realpath() equivalent */ #endif +#include "wimlib/xml.h" -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" -#include "xml.h" - +#include +#include #ifdef WITH_NTFS_3G -# include +# include /* for ntfs_mount(), ntfs_umount() */ #endif +#include +#include +#include static int do_apply_op(struct wim_dentry *dentry, struct apply_args *args, diff --git a/src/file_io.c b/src/file_io.c new file mode 100644 index 00000000..7a367323 --- /dev/null +++ b/src/file_io.c @@ -0,0 +1,168 @@ +/* + * file_io.c - Helper functions for reading and writing to file descriptors. + */ + +/* + * Copyright (C) 2013 Eric Biggers + * + * This file is part of wimlib, a library for working with WIM files. + * + * wimlib is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with wimlib; if not, see http://www.gnu.org/licenses/. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/file_io.h" +#ifdef __WIN32__ +# include "wimlib/win32.h" /* For pread(), pwrite() replacements */ +#else +# include /* for writev() and `struct iovec' */ +#endif + +#include +#include + + +/* Like read(), but keep trying until everything has been written or we know for + * sure that there was an error (or end-of-file). */ +size_t +full_read(int fd, void *buf, size_t count) +{ + ssize_t bytes_read; + size_t bytes_remaining; + + for (bytes_remaining = count; + bytes_remaining != 0; + bytes_remaining -= bytes_read, buf += bytes_read) + { + bytes_read = read(fd, buf, bytes_remaining); + if (bytes_read <= 0) { + if (bytes_read == 0) + errno = EIO; + else if (errno == EINTR) + continue; + break; + } + } + return count - bytes_remaining; +} + +/* Like write(), but keep trying until everything has been written or we know + * for sure that there was an error. */ +size_t +full_write(int fd, const void *buf, size_t count) +{ + ssize_t bytes_written; + size_t bytes_remaining; + + for (bytes_remaining = count; + bytes_remaining != 0; + bytes_remaining -= bytes_written, buf += bytes_written) + { + bytes_written = write(fd, buf, bytes_remaining); + if (bytes_written < 0) { + if (errno == EINTR) + continue; + break; + } + } + return count - bytes_remaining; +} + +/* Like pread(), but keep trying until everything has been read or we know for + * sure that there was an error (or end-of-file) */ +size_t +full_pread(int fd, void *buf, size_t count, off_t offset) +{ + ssize_t bytes_read; + size_t bytes_remaining; + + for (bytes_remaining = count; + bytes_remaining != 0; + bytes_remaining -= bytes_read, buf += bytes_read, + offset += bytes_read) + { + bytes_read = pread(fd, buf, bytes_remaining, offset); + if (bytes_read <= 0) { + if (bytes_read == 0) + errno = EIO; + else if (errno == EINTR) + continue; + break; + } + } + return count - bytes_remaining; +} + +/* Like pwrite(), but keep trying until everything has been written or we know + * for sure that there was an error. */ +size_t +full_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + ssize_t bytes_written; + size_t bytes_remaining; + + for (bytes_remaining = count; + bytes_remaining != 0; + bytes_remaining -= bytes_written, buf += bytes_written, + offset += bytes_written) + { + bytes_written = pwrite(fd, buf, bytes_remaining, offset); + if (bytes_written < 0) { + if (errno == EINTR) + continue; + break; + } + } + return count - bytes_remaining; +} + +/* Like writev(), but keep trying until everything has been written or we know + * for sure that there was an error. */ +size_t +full_writev(int fd, struct iovec *iov, int iovcnt) +{ + size_t total_bytes_written = 0; + while (iovcnt > 0) { + ssize_t bytes_written; + + bytes_written = writev(fd, iov, iovcnt); + if (bytes_written < 0) { + if (errno == EINTR) + continue; + break; + } + total_bytes_written += bytes_written; + while (bytes_written) { + if (bytes_written >= iov[0].iov_len) { + bytes_written -= iov[0].iov_len; + iov++; + iovcnt--; + } else { + iov[0].iov_base += bytes_written; + iov[0].iov_len -= bytes_written; + bytes_written = 0; + } + } + } + return total_bytes_written; +} + +off_t +filedes_offset(int fd) +{ + return lseek(fd, 0, SEEK_CUR); +} diff --git a/src/hardlink.c b/src/hardlink.c index 90446f98..7c82f4ba 100644 --- a/src/hardlink.c +++ b/src/hardlink.c @@ -23,10 +23,14 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "dentry.h" -#include "list.h" -#include "lookup_table.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/capture.h" +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" /* NULL NULL * ^ ^ diff --git a/src/header.c b/src/header.c index 6017cbd9..c0518ecb 100644 --- a/src/header.c +++ b/src/header.c @@ -23,8 +23,19 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "buffer_io.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/assert.h" +#include "wimlib/buffer_io.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/header.h" +#include "wimlib/util.h" +#include "wimlib/wim.h" + #include /* First 8 bytes in every WIM file. */ diff --git a/src/integrity.c b/src/integrity.c index 9afec969..0af6fddd 100644 --- a/src/integrity.c +++ b/src/integrity.c @@ -25,9 +25,18 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "buffer_io.h" -#include "sha1.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/assert.h" +#include "wimlib/buffer_io.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/integrity.h" +#include "wimlib/resource.h" +#include "wimlib/sha1.h" +#include "wimlib/wim.h" /* Size, in bytes, of each SHA1-summed chunk, when wimlib writes integrity * information. */ diff --git a/src/join.c b/src/join.c index 9977942c..6c2b0cdc 100644 --- a/src/join.c +++ b/src/join.c @@ -23,10 +23,20 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "lookup_table.h" -#include "xml.h" -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/resource.h" +#include "wimlib/swm.h" +#include "wimlib/wim.h" +#include "wimlib/write.h" +#include "wimlib/xml.h" + +#include /* for qsort() */ static int move_lte_to_table(struct wim_lookup_table_entry *lte, void *combined_table) diff --git a/src/lookup_table.c b/src/lookup_table.c index 998eb185..2a313060 100644 --- a/src/lookup_table.c +++ b/src/lookup_table.c @@ -24,16 +24,28 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "lookup_table.h" -#include "buffer_io.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/buffer_io.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/paths.h" +#include "wimlib/resource.h" +#include "wimlib/util.h" + #include #include - #ifdef WITH_FUSE -#include +# include /* for unlink() */ #endif +/* Size of each lookup table entry in the WIM file. */ +#define WIM_LOOKUP_TABLE_ENTRY_DISK_SIZE 50 + struct wim_lookup_table * new_lookup_table(size_t capacity) { @@ -58,7 +70,7 @@ new_lookup_table(size_t capacity) } struct wim_lookup_table_entry * -new_lookup_table_entry() +new_lookup_table_entry(void) { struct wim_lookup_table_entry *lte; @@ -824,6 +836,19 @@ out: } #endif +/* + * XXX Probably should store the compression type directly in the lookup table + * entry + */ +int +wim_resource_compression_type(const struct wim_lookup_table_entry *lte) +{ + if (!(lte->resource_entry.flags & WIM_RESHDR_FLAG_COMPRESSED) + || lte->resource_location != RESOURCE_IN_WIM) + return WIMLIB_COMPRESSION_TYPE_NONE; + return wimlib_get_compression_type(lte->wim); +} + /* Resolve an inode's lookup table entries * * This replaces the SHA1 hash fields (which are used to lookup an entry in the diff --git a/src/lz77.c b/src/lz77.c index 36166efe..5afe683b 100644 --- a/src/lz77.c +++ b/src/lz77.c @@ -26,7 +26,13 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "compress.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/compress.h" +#include "wimlib/util.h" + #include #define LZ_MIN_MATCH 3 diff --git a/src/lzx-common.c b/src/lzx-common.c index 5b3d118e..a7bca000 100644 --- a/src/lzx-common.c +++ b/src/lzx-common.c @@ -1,4 +1,31 @@ -#include "lzx.h" +/* + * lzx-common.c - Common data for LZX compression and decompression. + */ + +/* + * Copyright (C) 2012, 2013 Eric Biggers + * + * This file is part of wimlib, a library for working with WIM files. + * + * wimlib is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with wimlib; if not, see http://www.gnu.org/licenses/. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/lzx.h" #ifdef USE_LZX_EXTRA_BITS_ARRAY /* LZX uses what it calls 'position slots' to represent match offsets. diff --git a/src/lzx-compress.c b/src/lzx-compress.c index b23c2df0..a0f09a92 100644 --- a/src/lzx-compress.c +++ b/src/lzx-compress.c @@ -57,9 +57,15 @@ * blocks from one input chunk is not yet implemented. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "wimlib.h" -#include "lzx.h" -#include "compress.h" +#include "wimlib/compress.h" +#include "wimlib/lzx.h" +#include "wimlib/util.h" + #include #include @@ -591,10 +597,10 @@ lzx_make_huffman_codes(const struct lzx_freq_tables *freq_tabs, static void do_call_insn_translation(u32 *call_insn_target, int input_pos, - int32_t file_size) + s32 file_size) { - int32_t abs_offset; - int32_t rel_offset; + s32 abs_offset; + s32 rel_offset; rel_offset = le32_to_cpu(*call_insn_target); if (rel_offset >= -input_pos && rel_offset < file_size) { diff --git a/src/lzx-decompress.c b/src/lzx-decompress.c index 45660267..935600d4 100644 --- a/src/lzx-decompress.c +++ b/src/lzx-decompress.c @@ -106,10 +106,15 @@ * succeed. */ -#include "util.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "wimlib.h" -#include "lzx.h" -#include "decompress.h" +#include "wimlib/decompress.h" +#include "wimlib/lzx.h" +#include "wimlib/util.h" + #include /* Huffman decoding tables and maps from symbols to code lengths. */ @@ -684,10 +689,10 @@ lzx_decode_match(unsigned main_element, int block_type, static void undo_call_insn_translation(u32 *call_insn_target, int input_pos, - int32_t file_size) + s32 file_size) { - int32_t abs_offset; - int32_t rel_offset; + s32 abs_offset; + s32 rel_offset; abs_offset = le32_to_cpu(*call_insn_target); if (abs_offset >= -input_pos && abs_offset < file_size) { diff --git a/src/metadata_resource.c b/src/metadata_resource.c index 2f7dfeb6..8bd9734e 100644 --- a/src/metadata_resource.c +++ b/src/metadata_resource.c @@ -20,9 +20,17 @@ * wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/resource.h" +#include "wimlib/security.h" /* * Reads a metadata resource for an image in the WIM file. The metadata diff --git a/src/mount_image.c b/src/mount_image.c index f816db1e..5d967773 100644 --- a/src/mount_image.c +++ b/src/mount_image.c @@ -26,7 +26,12 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/error.h" #ifdef WITH_FUSE @@ -34,11 +39,18 @@ # error "FUSE mount not supported on Win32! Please configure --without-fuse" #endif -#include "buffer_io.h" -#include "lookup_table.h" -#include "sha1.h" -#include "timestamp.h" -#include "xml.h" +#include "wimlib/encoding.h" +#include "wimlib/file_io.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/paths.h" +#include "wimlib/reparse.h" +#include "wimlib/resource.h" +#include "wimlib/swm.h" +#include "wimlib/timestamp.h" +#include "wimlib/version.h" +#include "wimlib/write.h" +#include "wimlib/xml.h" #include #include @@ -130,13 +142,13 @@ init_wimfs_context(struct wimfs_context *ctx) #define WIMFS_CTX(fuse_ctx) ((struct wimfs_context*)(fuse_ctx)->private_data) static inline struct wimfs_context * -wimfs_get_context() +wimfs_get_context(void) { return WIMFS_CTX(fuse_get_context()); } static inline WIMStruct * -wimfs_get_WIMStruct() +wimfs_get_WIMStruct(void) { return wimfs_get_context()->wim; } @@ -1050,7 +1062,7 @@ struct msg_daemon_info { struct msg_unmount_finished { struct unmount_msg_hdr hdr; - int32_t status; + s32 status; } PACKED; struct msg_write_streams_progress { @@ -2614,7 +2626,7 @@ out: static int -mount_unsupported_error() +mount_unsupported_error(void) { #if defined(__WIN32__) ERROR("Sorry-- Mounting WIM images is not supported on Windows!"); diff --git a/src/ntfs-apply.c b/src/ntfs-3g_apply.c similarity index 96% rename from src/ntfs-apply.c rename to src/ntfs-3g_apply.c index 0297e724..0ec4702f 100644 --- a/src/ntfs-apply.c +++ b/src/ntfs-3g_apply.c @@ -1,9 +1,9 @@ /* - * ntfs-apply.c + * ntfs-3g_apply.c * - * Apply a WIM image to a NTFS volume. Restore as much information as possible, - * including security data, file attributes, DOS names, and alternate data - * streams. + * Apply a WIM image directly to a NTFS volume using libntfs-3g. Restore as + * much information as possible, including security data, file attributes, DOS + * names, and alternate data streams. */ /* @@ -25,23 +25,33 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include "config.h" +#ifdef WITH_NTFS_3G -#include -#include - -#include "wimlib_internal.h" -#include "buffer_io.h" -#include "dentry.h" -#include "lookup_table.h" +#include +#include +#include /* NTFS-3g headers are missing include */ #include -#include /* security.h before xattrs.h */ +#include #include +#include +#include #include -#include -#include + +#include "wimlib/apply.h" +#include "wimlib/buffer_io.h" +#include "wimlib/dentry.h" +#include "wimlib/encoding.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/ntfs_3g.h" +#include "wimlib/reparse.h" +#include "wimlib/security.h" struct ntfs_attr_extract_ctx { u64 offset; @@ -672,7 +682,9 @@ apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg) } void -libntfs3g_global_init() +libntfs3g_global_init(void) { ntfs_set_char_encoding(setlocale(LC_ALL, "")); } + +#endif /* WITH_NTFS_3G */ diff --git a/src/ntfs-capture.c b/src/ntfs-3g_capture.c similarity index 96% rename from src/ntfs-capture.c rename to src/ntfs-3g_capture.c index 5c465046..256e2494 100644 --- a/src/ntfs-capture.c +++ b/src/ntfs-3g_capture.c @@ -1,8 +1,8 @@ /* - * ntfs-capture.c + * ntfs-3g_capture.c * - * Capture a WIM image from a NTFS volume. We capture everything we can, - * including security data and alternate data streams. + * Capture a WIM image directly from a NTFS volume using libntfs-3g. We capture + * everything we can, including security data and alternate data streams. */ /* @@ -25,32 +25,43 @@ */ -#include "config.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include -#include +#ifdef WITH_NTFS_3G -#include "buffer_io.h" -#include "dentry.h" -#include "lookup_table.h" -#include "security.h" -#include "wimlib_internal.h" +#ifdef HAVE_ALLOCA_H +# include + +#endif +#include +#include +#include /* NTFS-3g headers are missing include */ +#include -#include -#include #include +#include +#include #include #include #include /* ntfs-3g/security.h before ntfs-3g/xattrs.h */ -#include +#include #include -#include -#include -#include +#include -#ifdef HAVE_ALLOCA_H -#include -#endif +#include /* This should be included last as it requires + definitions from above not included by itself */ + +#include "wimlib/buffer_io.h" +#include "wimlib/capture.h" +#include "wimlib/dentry.h" +#include "wimlib/encoding.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/ntfs_3g.h" +#include "wimlib/paths.h" +#include "wimlib/security.h" static inline ntfschar * attr_record_name(ATTR_RECORD *ar) @@ -777,3 +788,4 @@ out: } return ret; } +#endif /* WITH_NTFS_3G */ diff --git a/src/paths.c b/src/paths.c new file mode 100644 index 00000000..b4576cc1 --- /dev/null +++ b/src/paths.c @@ -0,0 +1,131 @@ +/* + * paths.c - Path manipulation routines + */ + +/* + * Copyright (C) 2012, 2013 Eric Biggers + * + * This file is part of wimlib, a library for working with WIM files. + * + * wimlib is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with wimlib; if not, see http://www.gnu.org/licenses/. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/paths.h" +#include "wimlib/util.h" + +#include + +/* Like the basename() function, but does not modify @path; it just returns a + * pointer to it. */ +const tchar * +path_basename(const tchar *path) +{ + return path_basename_with_len(path, tstrlen(path)); +} + +/* Like path_basename(), but take an explicit string length. */ +const tchar * +path_basename_with_len(const tchar *path, size_t len) +{ + const tchar *p = &path[len] - 1; + + /* Trailing slashes. */ + while (1) { + if (p == path - 1) + return T(""); + if (*p != T('/')) + break; + p--; + } + + while ((p != path - 1) && *p != T('/')) + p--; + + return p + 1; +} + + +/* + * Returns a pointer to the part of @path following the first colon in the last + * path component, or NULL if the last path component does not contain a colon. + */ +const tchar * +path_stream_name(const tchar *path) +{ + const tchar *base = path_basename(path); + const tchar *stream_name = tstrchr(base, T(':')); + if (!stream_name) + return NULL; + else + return stream_name + 1; +} + + +/* Translate backslashes to forward slashes in-place. */ +void +zap_backslashes(tchar *s) +{ + if (s) { + while (*s != T('\0')) { + if (*s == T('\\')) + *s = T('/'); + s++; + } + } +} + +/* Duplicate a path, with backslashes translated into forward slashes; return + * empty string for NULL input. */ +tchar * +canonicalize_fs_path(const tchar *fs_path) +{ + tchar *canonical_path; + + if (!fs_path) + fs_path = T(""); + canonical_path = TSTRDUP(fs_path); + zap_backslashes(canonical_path); + return canonical_path; +} + +/* Duplicate a path, with backslashes translated into forward slashes; return + * empty string for NULL input; also strip leading and trailing slashes. */ +tchar * +canonicalize_wim_path(const tchar *wim_path) +{ + tchar *p; + tchar *canonical_path; + + if (wim_path == NULL) { + wim_path = T(""); + } else { + while (*wim_path == T('/') || *wim_path == T('\\')) + wim_path++; + } + canonical_path = TSTRDUP(wim_path); + if (canonical_path) { + zap_backslashes(canonical_path); + for (p = tstrchr(canonical_path, T('\0')) - 1; + p >= canonical_path && *p == T('/'); + p--) + { + *p = T('\0'); + } + } + return canonical_path; +} diff --git a/src/rbtree.c b/src/rbtree.c index 6e122da4..10d1dc7c 100644 --- a/src/rbtree.c +++ b/src/rbtree.c @@ -21,7 +21,12 @@ linux/lib/rbtree.c */ -#include "rbtree.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/rbtree.h" +#include /* * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree diff --git a/src/reparse.c b/src/reparse.c index c00c7c1c..766736d4 100644 --- a/src/reparse.c +++ b/src/reparse.c @@ -1,7 +1,5 @@ /* - * reparse.c - * - * Handle reparse data. + * reparse.c - Handle reparse data. */ /* @@ -23,15 +21,28 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "dentry.h" -#include "buffer_io.h" -#include "lookup_table.h" -#include "sha1.h" -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/assert.h" +#include "wimlib/buffer_io.h" +#include "wimlib/dentry.h" +#include "wimlib/encoding.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/reparse.h" +#include "wimlib/resource.h" + +#ifdef __WIN32__ +# include "wimlib/win32.h" /* for win32_get_file_and_vol_ids() */ +#endif + #ifdef HAVE_ALLOCA_H # include #endif +#include +#include static const utf16lechar volume_junction_prefix[11] = { cpu_to_le16('\\'), @@ -447,7 +458,6 @@ unix_get_ino_and_dev(const char *path, u64 *ino_ret, u64 *dev_ret) #endif /* !defined(__WIN32__) */ #ifdef __WIN32__ -# include "win32.h" # define RP_PATH_SEPARATOR L'\\' # define is_rp_path_separator(c) ((c) == L'\\' || (c) == L'/') # define os_get_ino_and_dev win32_get_file_and_vol_ids diff --git a/src/resource.c b/src/resource.c index 4b91be6b..9192062f 100644 --- a/src/resource.c +++ b/src/resource.c @@ -22,25 +22,37 @@ * wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" -#include "buffer_io.h" -#include "sha1.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/buffer_io.h" +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/lookup_table.h" +#include "wimlib/resource.h" +#include "wimlib/sha1.h" #ifdef __WIN32__ -# include "win32.h" +/* for read_win32_file_prefix(), read_win32_encrypted_file_prefix() */ +# include "wimlib/win32.h" #endif -#include -#include -#include -#include -#include +#ifdef WITH_NTFS_3G +/* for read_ntfs_file_prefix() */ +# include "wimlib/ntfs_3g.h" +#endif #ifdef HAVE_ALLOCA_H # include #endif +#include +#include +#include +#include +#include /* * Reads all or part of a compressed WIM resource. diff --git a/src/security.c b/src/security.c index 16e7b912..0d0aa91a 100644 --- a/src/security.c +++ b/src/security.c @@ -23,9 +23,16 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "buffer_io.h" -#include "security.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/assert.h" +#include "wimlib/buffer_io.h" +#include "wimlib/error.h" +#include "wimlib/security.h" +#include "wimlib/sha1.h" +#include "wimlib/util.h" /* At the start of each type of access control entry. */ typedef struct { @@ -150,7 +157,7 @@ empty_sacl_fixup(u8 *descr, u64 *size_p) } struct wim_security_data * -new_wim_security_data() +new_wim_security_data(void) { return CALLOC(1, sizeof(struct wim_security_data)); } @@ -471,12 +478,11 @@ free_sd_tree(struct rb_node *node) /* Frees a security descriptor index set. */ void -destroy_sd_set(struct sd_set *sd_set, bool rollback) +destroy_sd_set(struct wim_sd_set *sd_set, bool rollback) { if (rollback) { struct wim_security_data *sd = sd_set->sd; - int32_t i; - for (i = sd_set->orig_num_entries; i < sd->num_entries; i++) + for (s32 i = sd_set->orig_num_entries; i < sd->num_entries; i++) FREE(sd->descriptors[i]); sd->num_entries = sd_set->orig_num_entries; } @@ -485,7 +491,7 @@ destroy_sd_set(struct sd_set *sd_set, bool rollback) /* Inserts a a new node into the security descriptor index tree. */ static bool -insert_sd_node(struct sd_set *set, struct sd_node *new) +insert_sd_node(struct wim_sd_set *set, struct sd_node *new) { struct rb_root *root = &set->rb_root; struct rb_node **p = &(root->rb_node); @@ -511,7 +517,7 @@ insert_sd_node(struct sd_set *set, struct sd_node *new) /* Returns the index of the security descriptor having a SHA1 message digest of * @hash. If not found, return -1. */ int -lookup_sd(struct sd_set *set, const u8 hash[SHA1_HASH_SIZE]) +lookup_sd(struct wim_sd_set *set, const u8 hash[SHA1_HASH_SIZE]) { struct rb_node *node = set->rb_root.rb_node; @@ -536,7 +542,7 @@ lookup_sd(struct sd_set *set, const u8 hash[SHA1_HASH_SIZE]) * return -1. */ int -sd_set_add_sd(struct sd_set *sd_set, const char descriptor[], size_t size) +sd_set_add_sd(struct wim_sd_set *sd_set, const char descriptor[], size_t size) { u8 hash[SHA1_HASH_SIZE]; int security_id; @@ -600,7 +606,7 @@ out: * descriptors to indices into the security descriptors table of the WIM image * (security IDs). */ int -init_sd_set(struct sd_set *sd_set, struct wim_security_data *sd) +init_sd_set(struct wim_sd_set *sd_set, struct wim_security_data *sd) { int ret; @@ -610,7 +616,7 @@ init_sd_set(struct sd_set *sd_set, struct wim_security_data *sd) /* Remember the original number of security descriptors so that newly * added ones can be rolled back if needed. */ sd_set->orig_num_entries = sd->num_entries; - for (int32_t i = 0; i < sd->num_entries; i++) { + for (s32 i = 0; i < sd->num_entries; i++) { struct sd_node *new; new = MALLOC(sizeof(struct sd_node)); diff --git a/src/security.h b/src/security.h deleted file mode 100644 index e20ad168..00000000 --- a/src/security.h +++ /dev/null @@ -1,29 +0,0 @@ -#include "util.h" -#include "rbtree.h" -#include "sha1.h" - -#ifndef _WIMLIB_SECURITY_H -#define _WIMLIB_SECURITY_H - -/* Red-black tree that maps SHA1 message digests of security descriptors to - * security IDs, which are themselves indices into the table of security - * descriptors in the 'struct wim_security_data'. */ -struct sd_set { - struct wim_security_data *sd; - struct rb_root rb_root; - int32_t orig_num_entries; -}; -extern void -destroy_sd_set(struct sd_set *sd_set, bool rollback); - -extern int -lookup_sd(struct sd_set *set, const u8 hash[SHA1_HASH_SIZE]); - -extern int -sd_set_add_sd(struct sd_set *sd_set, const char descriptor[], - size_t size); - -extern int -init_sd_set(struct sd_set *sd_set, struct wim_security_data *sd); - -#endif /* _WIMLIB_SECURITY_H */ diff --git a/src/sha1.c b/src/sha1.c index f09008d1..f989005a 100644 --- a/src/sha1.c +++ b/src/sha1.c @@ -23,10 +23,12 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "util.h" -#include "wimlib.h" -#include "sha1.h" -#include "endianness.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/sha1.h" + #include /* The SHA1 support in wimlib can use an external libcrypto (part of openssl) or diff --git a/src/split.c b/src/split.c index 5b14b924..b1231b59 100644 --- a/src/split.c +++ b/src/split.c @@ -23,12 +23,22 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "lookup_table.h" -#include "xml.h" -#include "buffer_io.h" -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib.h" +#include "wimlib/buffer_io.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/types.h" +#include "wimlib/write.h" +#include "wimlib/list.h" + +#include /* for open() */ +#include /* for close() */ struct split_args { WIMStruct *w; diff --git a/src/timestamp.c b/src/timestamp.c new file mode 100644 index 00000000..33c61746 --- /dev/null +++ b/src/timestamp.c @@ -0,0 +1,50 @@ +/* + * timestamp.c + */ + +/* + * Copyright (C) 2012, 2013 Eric Biggers + * + * This file is part of wimlib, a library for working with WIM files. + * + * wimlib is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with wimlib; if not, see http://www.gnu.org/licenses/. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/types.h" +#include "wimlib/timestamp.h" + +#include +#include + +u64 +get_wim_timestamp(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return timeval_to_wim_timestamp(tv); +} + +void +wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len) +{ + struct tm tm; + time_t t = wim_timestamp_to_unix(timestamp); + gmtime_r(&t, &tm); + tstrftime(buf, len, T("%a %b %d %H:%M:%S %Y UTC"), &tm); +} + diff --git a/src/unix_apply.c b/src/unix_apply.c index 969b8d2b..6b3ede19 100644 --- a/src/unix_apply.c +++ b/src/unix_apply.c @@ -21,11 +21,12 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "config.h" +#ifndef __WIN32__ -#ifdef HAVE_UTIME_H -# include +#ifdef HAVE_CONFIG_H +# include "config.h" #endif + #include #include #include @@ -33,10 +34,15 @@ #include #include #include +#ifdef HAVE_UTIME_H +# include +#endif -#include "timestamp.h" -#include "wimlib_internal.h" -#include "lookup_table.h" +#include "wimlib/apply.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/reparse.h" +#include "wimlib/timestamp.h" /* Returns the number of components of @path. */ static unsigned @@ -491,3 +497,5 @@ unix_do_apply_dentry_timestamps(const char *output_path, } return 0; } + +#endif /* !__WIN32__ */ diff --git a/src/unix_capture.c b/src/unix_capture.c index 4164a624..eb3005d4 100644 --- a/src/unix_capture.c +++ b/src/unix_capture.c @@ -23,10 +23,9 @@ #ifndef __WIN32__ -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" -#include "timestamp.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #include #include @@ -34,6 +33,14 @@ #include #include +#include "wimlib/capture.h" +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/paths.h" +#include "wimlib/reparse.h" +#include "wimlib/timestamp.h" + static int unix_capture_regular_file(const char *path, u64 size, diff --git a/src/update_image.c b/src/update_image.c index e85cd606..d7a289a3 100644 --- a/src/update_image.c +++ b/src/update_image.c @@ -21,16 +21,22 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" -#include "security.h" -#include "xml.h" -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#ifdef __WIN32__ -# include "win32.h" +#include "wimlib/capture.h" +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#ifdef WITH_NTFS_3G +# include "wimlib/ntfs_3g.h" /* for do_ntfs_umount() */ #endif +#include "wimlib/paths.h" +#include "wimlib/xml.h" + +#include /* Overlays @branch onto @target, both of which must be directories. */ static int @@ -454,6 +460,7 @@ update_op_to_str(int op) return T("rename"); default: wimlib_assert(0); + return NULL; } } @@ -589,7 +596,7 @@ check_update_commands(struct wimlib_update_command *cmds, size_t num_cmds, } -extern void +static void free_update_commands(struct wimlib_update_command *cmds, size_t num_cmds) { if (cmds) { diff --git a/src/util.c b/src/util.c index a5899bcd..df3b5c8a 100644 --- a/src/util.c +++ b/src/util.c @@ -21,36 +21,39 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "config.h" - +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#undef _GNU_SOURCE +#ifdef _GNU_SOURCE +# define _GNU_SOURCE_DEFINED 1 +# undef _GNU_SOURCE +#endif /* Make sure the POSIX-compatible strerror_r() is declared, rather than the GNU * version, which has a different return type. */ #include +#ifdef _GNU_SOURCE_DEFINED +# define _GNU_SOURCE +#endif -#define _GNU_SOURCE +#include "wimlib.h" +#include "wimlib/compiler.h" +#include "wimlib/encoding.h" +#include "wimlib/error.h" +#include "wimlib/types.h" +#include "wimlib/util.h" +#include "wimlib/xml.h" -#include "endianness.h" -#include "timestamp.h" -#include "wimlib_internal.h" +#ifdef __WIN32__ +# include "wimlib/win32.h" /* win32_strerror_r_replacement */ +#endif -#include #include #include #include +#include #include - -#ifdef __WIN32__ -# include "win32.h" -# define pread win32_pread -# define pwrite win32_pwrite -# define writev win32_writev -#else -# include /* for writev() and `struct iovec' */ -#endif - static size_t utf16le_strlen(const utf16lechar *s) { @@ -138,6 +141,11 @@ wimlib_fprintf(FILE *fp, const tchar *format, ...) va_end(va); return ret; } + +#endif /* __WIN32__ */ + +#ifdef ENABLE_ERROR_MESSAGES +static bool wimlib_print_errors = false; #endif #if defined(ENABLE_ERROR_MESSAGES) || defined(ENABLE_DEBUG) @@ -175,9 +183,6 @@ wimlib_vmsg(const tchar *tag, const tchar *format, /* True if wimlib is to print an informational message when an error occurs. * This can be turned off by calling wimlib_set_print_errors(false). */ #ifdef ENABLE_ERROR_MESSAGES -static bool wimlib_print_errors = false; - - void wimlib_error(const tchar *format, ...) { @@ -444,11 +449,7 @@ wimlib_wcsdup(const wchar_t *str) } #endif -extern void -xml_set_memory_allocator(void *(*malloc_func)(size_t), - void (*free_func)(void *), - void *(*realloc_func)(void *, size_t)); -#endif +#endif /* ENABLE_CUSTOM_MEMORY_ALLOCATOR */ WIMLIBAPI int wimlib_set_memory_allocator(void *(*malloc_func)(size_t), @@ -474,7 +475,7 @@ wimlib_set_memory_allocator(void *(*malloc_func)(size_t), static bool seeded = false; static void -seed_random() +seed_random(void) { srand(time(NULL) * getpid()); seeded = true; @@ -507,244 +508,9 @@ randomize_byte_array(u8 *p, size_t n) *p++ = rand(); } -const tchar * -path_basename_with_len(const tchar *path, size_t len) -{ - const tchar *p = &path[len] - 1; - - /* Trailing slashes. */ - while (1) { - if (p == path - 1) - return T(""); - if (*p != T('/')) - break; - p--; - } - - while ((p != path - 1) && *p != T('/')) - p--; - - return p + 1; -} - -/* Like the basename() function, but does not modify @path; it just returns a - * pointer to it. */ -const tchar * -path_basename(const tchar *path) -{ - return path_basename_with_len(path, tstrlen(path)); -} - -/* - * Returns a pointer to the part of @path following the first colon in the last - * path component, or NULL if the last path component does not contain a colon. - */ -const tchar * -path_stream_name(const tchar *path) -{ - const tchar *base = path_basename(path); - const tchar *stream_name = tstrchr(base, T(':')); - if (!stream_name) - return NULL; - else - return stream_name + 1; -} - -u64 -get_wim_timestamp() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return timeval_to_wim_timestamp(tv); -} - -void -wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len) -{ - struct tm tm; - time_t t = wim_timestamp_to_unix(timestamp); - gmtime_r(&t, &tm); - tstrftime(buf, len, T("%a %b %d %H:%M:%S %Y UTC"), &tm); -} - -void -zap_backslashes(tchar *s) -{ - if (s) { - while (*s != T('\0')) { - if (*s == T('\\')) - *s = T('/'); - s++; - } - } -} - -tchar * -canonicalize_fs_path(const tchar *fs_path) -{ - tchar *canonical_path; - - if (!fs_path) - fs_path = T(""); - canonical_path = TSTRDUP(fs_path); - zap_backslashes(canonical_path); - return canonical_path; -} - -/* Strip leading and trailing slashes from a string. Also translates - * backslashes into forward slashes. */ -tchar * -canonicalize_wim_path(const tchar *wim_path) -{ - tchar *p; - tchar *canonical_path; - - if (wim_path == NULL) { - wim_path = T(""); - } else { - while (*wim_path == T('/') || *wim_path == T('\\')) - wim_path++; - } - canonical_path = TSTRDUP(wim_path); - if (canonical_path) { - zap_backslashes(canonical_path); - for (p = tstrchr(canonical_path, T('\0')) - 1; - p >= canonical_path && *p == T('/'); - p--) - { - *p = T('\0'); - } - } - return canonical_path; -} - -/* Like read(), but keep trying until everything has been written or we know for - * sure that there was an error (or end-of-file). */ -size_t -full_read(int fd, void *buf, size_t count) -{ - ssize_t bytes_read; - size_t bytes_remaining; - - for (bytes_remaining = count; - bytes_remaining != 0; - bytes_remaining -= bytes_read, buf += bytes_read) - { - bytes_read = read(fd, buf, bytes_remaining); - if (bytes_read <= 0) { - if (bytes_read == 0) - errno = EIO; - else if (errno == EINTR) - continue; - break; - } - } - return count - bytes_remaining; -} - -/* Like write(), but keep trying until everything has been written or we know - * for sure that there was an error. */ -size_t -full_write(int fd, const void *buf, size_t count) -{ - ssize_t bytes_written; - size_t bytes_remaining; - - for (bytes_remaining = count; - bytes_remaining != 0; - bytes_remaining -= bytes_written, buf += bytes_written) - { - bytes_written = write(fd, buf, bytes_remaining); - if (bytes_written < 0) { - if (errno == EINTR) - continue; - break; - } - } - return count - bytes_remaining; -} - -/* Like pread(), but keep trying until everything has been read or we know for - * sure that there was an error (or end-of-file) */ -size_t -full_pread(int fd, void *buf, size_t count, off_t offset) -{ - ssize_t bytes_read; - size_t bytes_remaining; - - for (bytes_remaining = count; - bytes_remaining != 0; - bytes_remaining -= bytes_read, buf += bytes_read, - offset += bytes_read) - { - bytes_read = pread(fd, buf, bytes_remaining, offset); - if (bytes_read <= 0) { - if (bytes_read == 0) - errno = EIO; - else if (errno == EINTR) - continue; - break; - } - } - return count - bytes_remaining; -} - -/* Like pwrite(), but keep trying until everything has been written or we know - * for sure that there was an error. */ -size_t -full_pwrite(int fd, const void *buf, size_t count, off_t offset) -{ - ssize_t bytes_written; - size_t bytes_remaining; - - for (bytes_remaining = count; - bytes_remaining != 0; - bytes_remaining -= bytes_written, buf += bytes_written, - offset += bytes_written) - { - bytes_written = pwrite(fd, buf, bytes_remaining, offset); - if (bytes_written < 0) { - if (errno == EINTR) - continue; - break; - } - } - return count - bytes_remaining; -} - -/* Like writev(), but keep trying until everything has been written or we know - * for sure that there was an error. */ -size_t -full_writev(int fd, struct iovec *iov, int iovcnt) -{ - size_t total_bytes_written = 0; - while (iovcnt > 0) { - ssize_t bytes_written; - - bytes_written = writev(fd, iov, iovcnt); - if (bytes_written < 0) { - if (errno == EINTR) - continue; - break; - } - total_bytes_written += bytes_written; - while (bytes_written) { - if (bytes_written >= iov[0].iov_len) { - bytes_written -= iov[0].iov_len; - iov++; - iovcnt--; - } else { - iov[0].iov_base += bytes_written; - iov[0].iov_len -= bytes_written; - bytes_written = 0; - } - } - } - return total_bytes_written; -} -off_t -filedes_offset(int fd) +void print_byte_field(const u8 field[], size_t len, FILE *out) { - return lseek(fd, 0, SEEK_CUR); + while (len--) + tfprintf(out, T("%02hhx"), *field++); } diff --git a/src/util.h b/src/util.h deleted file mode 100644 index 3d22cf40..00000000 --- a/src/util.h +++ /dev/null @@ -1,325 +0,0 @@ -#ifndef _WIMLIB_UTIL_H -#define _WIMLIB_UTIL_H - -#include "config.h" -#include "wimlib_tchar.h" - -#include -#include -#include -#include -#include - -#ifdef __GNUC__ -# if defined(__CYGWIN__) || defined(__WIN32__) -# define WIMLIBAPI __declspec(dllexport) -# else -# define WIMLIBAPI __attribute__((visibility("default"))) -# endif -# define ALWAYS_INLINE inline __attribute__((always_inline)) -# define PACKED __attribute__((packed)) -# define FORMAT(type, format_str, args_start) \ - /*__attribute__((format(type, format_str, args_start))) */ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) -# define COLD __attribute__((cold)) -# else -# define COLD -# endif -#else -# define WIMLIBAPI -# define ALWAYS_INLINE inline -# define FORMAT(type, format_str, args_start) -# define COLD -# define PACKED -#endif /* __GNUC__ */ - - -#if 0 -#ifdef WITH_FUSE -#define atomic_inc(ptr) \ - __sync_fetch_and_add(ptr, 1) - -#define atomic_dec(ptr) \ - __sync_sub_and_fetch(ptr, 1) -#endif -#endif - -#ifndef _NTFS_TYPES_H -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -#endif - - -/* A pointer to 'utf16lechar' indicates a UTF-16LE encoded string */ -typedef u16 utf16lechar; - -#define TMALLOC(n) MALLOC((n) * sizeof(tchar)) - -/* encoding.c */ -extern void -iconv_global_cleanup(); - -extern bool wimlib_mbs_is_utf8; - -#define DECLARE_CHAR_CONVERSION_FUNCTIONS(varname1, varname2, \ - chartype1, chartype2) \ - \ -extern int \ -varname1##_to_##varname2(const chartype1 *in, size_t in_nbytes, \ - chartype2 **out_ret, \ - size_t *out_nbytes_ret); \ - \ -extern int \ -varname1##_to_##varname2##_nbytes(const chartype1 *in, size_t in_nbytes,\ - size_t *out_nbytes_ret); \ - \ -extern int \ -varname1##_to_##varname2##_buf(const chartype1 *in, size_t in_nbytes, \ - chartype2 *out); - - -#if !TCHAR_IS_UTF16LE -DECLARE_CHAR_CONVERSION_FUNCTIONS(utf16le, tstr, utf16lechar, tchar); -DECLARE_CHAR_CONVERSION_FUNCTIONS(tstr, utf16le, tchar, utf16lechar); -#endif - -extern int -utf8_to_tstr_simple(const char *utf8str, tchar **out); - -extern int -tstr_to_utf8_simple(const tchar *tstr, char **out); - -#ifndef min -#define min(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \ - (__a < __b) ? __a : __b; }) -#endif - -#ifndef max -#define max(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); \ - (__a > __b) ? __a : __b; }) -#endif - -#ifndef swap -#define swap(a, b) ({typeof(a) _a = a; (a) = (b); (b) = _a;}) -#endif - -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#ifndef container_of -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) -#endif - -#define DIV_ROUND_UP(numerator, denominator) \ - (((numerator) + (denominator) - 1) / (denominator)) - -#define MODULO_NONZERO(numerator, denominator) \ - (((numerator) % (denominator)) ? ((numerator) % (denominator)) : (denominator)) - -#define ARRAY_LEN(array) (sizeof(array) / sizeof((array)[0])) - -#define ZERO_ARRAY(array) memset(array, 0, sizeof(array)) - -/* Used for buffering FILE IO in a few places */ -#define BUFFER_SIZE 32768 - -static inline void FORMAT(printf, 1, 2) -dummy_tprintf(const tchar *format, ...) -{ -} - -#ifdef ENABLE_ERROR_MESSAGES -extern void -wimlib_error(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; - -extern void -wimlib_error_with_errno(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; - -extern void -wimlib_warning(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; - -extern void -wimlib_warning_with_errno(const tchar *format, ...) FORMAT(printf, 1, 2) COLD; -# define ERROR(format, ...) wimlib_error(T(format), ## __VA_ARGS__) -# define ERROR_WITH_ERRNO(format, ...) wimlib_error_with_errno(T(format), ## __VA_ARGS__) -# define WARNING(format, ...) wimlib_warning(T(format), ## __VA_ARGS__) -# define WARNING_WITH_ERRNO(format, ...) wimlib_warning_with_errno(T(format), ## __VA_ARGS__) -#else /* ENABLE_ERROR_MESSAGES */ -# define ERROR(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) -# define ERROR_WITH_ERRNO(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) -# define WARNING(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) -# define WARNING_WITH_ERRNO(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) -#endif /* !ENABLE_ERROR_MESSAGES */ - -#if defined(ENABLE_MORE_DEBUG) && !defined(ENABLE_DEBUG) -# define ENABLE_DEBUG 1 -#endif - -#if defined(ENABLE_MORE_ASSERTIONS) && !defined(ENABLE_ASSERTIONS) -# define ENABLE_ASSERTIONS 1 -#endif - -#ifdef ENABLE_DEBUG -extern void -wimlib_debug(const tchar *file, int line, const char *func, - const tchar *format, ...); -# define DEBUG(format, ...) \ - wimlib_debug(T(__FILE__), __LINE__, __func__, T(format), ## __VA_ARGS__) - -#else -# define DEBUG(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) -#endif /* !ENABLE_DEBUG */ - -#ifdef ENABLE_MORE_DEBUG -# define DEBUG2(format, ...) DEBUG(format, ## __VA_ARGS__) -#else -# define DEBUG2(format, ...) dummy_tprintf(T(format), ## __VA_ARGS__) -#endif /* !ENABLE_MORE_DEBUG */ - -#ifdef ENABLE_ASSERTIONS -#include -# define wimlib_assert(expr) assert(expr) -#else -# define wimlib_assert(expr) -#endif /* !ENABLE_ASSERTIONS */ - -#ifdef ENABLE_MORE_ASSERTIONS -# define wimlib_assert2(expr) wimlib_assert(expr) -#else -# define wimlib_assert2(expr) -#endif /* !ENABLE_MORE_ASSERTIONS */ - -#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) - -#ifdef ENABLE_CUSTOM_MEMORY_ALLOCATOR -extern void *(*wimlib_malloc_func)(size_t); -extern void (*wimlib_free_func)(void *); -extern void *(*wimlib_realloc_func)(void *, size_t); -extern void *wimlib_calloc(size_t nmemb, size_t size); -#ifdef __WIN32__ -extern wchar_t *wimlib_wcsdup(const wchar_t *str); -#endif -extern char *wimlib_strdup(const char *str); -# define MALLOC wimlib_malloc_func -# define FREE wimlib_free_func -# define REALLOC wimlib_realloc_func -# define CALLOC wimlib_calloc -# define STRDUP wimlib_strdup -# define WSTRDUP wimlib_wcsdup -#else /* ENABLE_CUSTOM_MEMORY_ALLOCATOR */ -# include -# include -# define MALLOC malloc -# define FREE free -# define REALLOC realloc -# define CALLOC calloc -# define STRDUP strdup -# define WSTRDUP wcsdup -#endif /* !ENABLE_CUSTOM_MEMORY_ALLOCATOR */ - - -/* util.c */ -extern void -randomize_byte_array(u8 *p, size_t n); - -extern void -randomize_char_array_with_alnum(tchar p[], size_t n); - -const tchar * -path_basename_with_len(const tchar *path, size_t len); - -const tchar * -path_basename(const tchar *path); - -extern const tchar * -path_stream_name(const tchar *path); - -static inline void -print_byte_field(const u8 field[], size_t len, FILE *out) -{ - while (len--) - tfprintf(out, T("%02hhx"), *field++); -} - -static inline u32 -bsr32(u32 n) -{ -#if defined(__x86__) || defined(__x86_64__) - asm("bsrl %0, %0;" - : "=r"(n) - : "0" (n)); - return n; -#else - u32 pow = 0; - while ((n >>= 1) != 0) - pow++; - return pow; -#endif -} - -#ifdef __WIN32__ -# define wimlib_fprintf fwprintf -# define wimlib_printf wprintf -#else /* __WIN32__ */ -extern int -wimlib_fprintf(FILE *fp, const tchar *format, ...) FORMAT(printf, 2, 3); - -extern int -wimlib_printf(const tchar *format, ...) FORMAT(printf, 1, 2); -#endif /* !__WIN32__ */ - -extern void -zap_backslashes(tchar *s); - -extern tchar * -canonicalize_wim_path(const tchar *wim_path); - -extern tchar * -canonicalize_fs_path(const tchar *fs_path); - -static inline u64 -hash_u64(u64 n) -{ - return n * 0x9e37fffffffc0001ULL; -} - -extern size_t -full_read(int fd, void *buf, size_t n); - -extern size_t -full_write(int fd, const void *buf, size_t n); - -extern size_t -full_pread(int fd, void *buf, size_t nbyte, off_t offset); - -extern size_t -full_pwrite(int fd, const void *buf, size_t count, off_t offset); - -#ifdef __WIN32__ -struct iovec { - void *iov_base; - size_t iov_len; -}; -#else -struct iovec; -#endif - -extern size_t -full_writev(int fd, struct iovec *iov, int iovcnt); - -extern off_t -filedes_offset(int fd); - -#ifndef __WIN32__ -# define O_BINARY 0 -#endif - -#endif /* _WIMLIB_UTIL_H */ diff --git a/src/verify.c b/src/verify.c index 6da6b6a9..9e7182fc 100644 --- a/src/verify.c +++ b/src/verify.c @@ -26,9 +26,16 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/dentry.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/security.h" +#include "wimlib/swm.h" static int verify_inode(struct wim_inode *inode, const WIMStruct *w) diff --git a/src/wim.c b/src/wim.c index 8022423c..fd197140 100644 --- a/src/wim.c +++ b/src/wim.c @@ -23,27 +23,38 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "config.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/error.h" +#include "wimlib/dentry.h" +#include "wimlib/encoding.h" +#include "wimlib/file_io.h" +#include "wimlib/integrity.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#ifdef WITH_NTFS_3G +# include "wimlib/ntfs_3g.h" /* for do_ntfs_umount() */ +#endif +#include "wimlib/security.h" +#include "wimlib/wim.h" +#include "wimlib/xml.h" + +#ifdef __WIN32__ +# include "wimlib/win32.h" /* for realpath() replacement */ +#endif #include #include +#ifndef __WIN32__ +# include +#endif #include #include #include #include -#ifdef __WIN32__ -# include "win32.h" -#else -# include -#endif - -#include "buffer_io.h" -#include "dentry.h" -#include "lookup_table.h" -#include "wimlib_internal.h" -#include "xml.h" - static int image_print_metadata(WIMStruct *w) { @@ -62,7 +73,7 @@ image_print_files(WIMStruct *w) } static WIMStruct * -new_wim_struct() +new_wim_struct(void) { WIMStruct *w = CALLOC(1, sizeof(WIMStruct)); if (w) { @@ -599,7 +610,7 @@ append_image_metadata(WIMStruct *w, struct wim_image_metadata *imd) struct wim_image_metadata * -new_image_metadata() +new_image_metadata(void) { struct wim_image_metadata *imd; @@ -690,7 +701,7 @@ wimlib_free(WIMStruct *w) } static bool -test_locale_ctype_utf8() +test_locale_ctype_utf8(void) { #ifdef __WIN32__ return false; @@ -724,7 +735,7 @@ wimlib_global_init(int init_flags) /* Free global memory allocations. Not strictly necessary if the process using * wimlib is just about to exit (as is the case for 'imagex'). */ WIMLIBAPI void -wimlib_global_cleanup() +wimlib_global_cleanup(void) { libxml_global_cleanup(); iconv_global_cleanup(); diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h deleted file mode 100644 index 84a7998f..00000000 --- a/src/wimlib_internal.h +++ /dev/null @@ -1,850 +0,0 @@ -/* - * wimlib_internal.h - * - * Internal header for wimlib. - */ - -/* - * Copyright (C) 2012, 2013 Eric Biggers - * - * This file is part of wimlib, a library for working with WIM files. - * - * wimlib is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at your option) - * any later version. - * - * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with wimlib; if not, see http://www.gnu.org/licenses/. - */ - -#ifndef _WIMLIB_INTERNAL_H -#define _WIMLIB_INTERNAL_H - -#include "config.h" -#include "util.h" -#include "list.h" -#include "wimlib.h" -#include "security.h" - -#define WIMLIB_MAKEVERSION(major, minor, patch) \ - ((major << 20) | (minor << 10) | patch) - - -#define WIMLIB_VERSION_CODE \ - WIMLIB_MAKEVERSION(WIMLIB_MAJOR_VERSION,\ - WIMLIB_MINOR_VERSION,\ - WIMLIB_PATCH_VERSION) - -#define WIMLIB_GET_PATCH_VERSION(version) \ - ((version >> 0) & ((1 << 10) - 1)) -#define WIMLIB_GET_MINOR_VERSION(version) \ - ((version >> 10) & ((1 << 10) - 1)) -#define WIMLIB_GET_MAJOR_VERSION(version) \ - ((version >> 20) & ((1 << 10) - 1)) - - -struct stat; -struct wim_dentry; -struct wim_inode; -struct sd_set; - -#define WIM_MAGIC_LEN 8 -#define WIM_GID_LEN 16 -#define WIM_UNUSED_LEN 60 - -/* Length of the WIM header on disk. */ -#define WIM_HEADER_DISK_SIZE (148 + WIM_UNUSED_LEN) - -/* Compressed resources in the WIM are divided into separated compressed chunks - * of this size. */ -#define WIM_CHUNK_SIZE 32768 - -/* Version of the WIM file. There is an older version, but we don't support it - * yet. The differences between the versions are undocumented. */ -#define WIM_VERSION 0x10d00 - -#define REPARSE_POINT_MAX_SIZE (16 * 1024) - -/* Metadata for a resource in a WIM file. */ -struct resource_entry { - /* Size, in bytes, of the resource in the WIM file. */ - u64 size : 56; - - /* Bitwise or of one or more of the WIM_RESHDR_FLAG_* flags. */ - u64 flags : 8; - - /* Offset, in bytes, of the resource in the WIM file. */ - u64 offset; - - /* Uncompressed size of the resource in the WIM file. Is the same as - * @size if the resource is uncompressed. */ - u64 original_size; -}; - -/* Flags for the `flags' field of the struct resource_entry structure. */ - -/* I haven't seen this flag used in any of the WIMs I have examined. I assume - * it means that there are no references to the stream, so the space is free. - * However, even after deleting files from a WIM mounted with `imagex.exe - * /mountrw', I could not see this flag being used. Either way, we don't - * actually use this flag for anything. */ -#define WIM_RESHDR_FLAG_FREE 0x01 - -/* Indicates that the stream is a metadata resource for a WIM image. */ -#define WIM_RESHDR_FLAG_METADATA 0x02 - -/* Indicates that the stream is compressed. */ -#define WIM_RESHDR_FLAG_COMPRESSED 0x04 - -/* I haven't seen this flag used in any of the WIMs I have examined. Perhaps it - * means that a stream could possibly be split among multiple split WIM parts. - * However, `imagex.exe /split' does not seem to create any WIMs like this. - * Either way, we don't actually use this flag for anything. */ -#define WIM_RESHDR_FLAG_SPANNED 0x08 - -/* Header at the very beginning of the WIM file. */ -struct wim_header { - /* Identifies the file as WIM file. Must be exactly - * {'M', 'S', 'W', 'I', 'M', 0, 0, 0} */ - //u8 magic[WIM_MAGIC_LEN]; - - /* size of WIM header in bytes. */ - //u32 hdr_size; - - /* Version of the WIM file. Microsoft provides no documentation about - * exactly what this field affects about the file format, other than the - * fact that more recent versions have a higher value. */ - //u32 version; - - /* Bitwise OR of one or more of the WIM_HDR_FLAG_* defined below. */ - u32 flags; - - /* The size of the pieces that the uncompressed files were split up into - * when they were compressed. This should be the same as - * WIM_CHUNK_SIZE. Microsoft incorrectly documents this as "the size of - * the compressed .wim file in bytes".*/ - //u32 chunk_size; - - /* A unique identifier for the WIM file. */ - u8 guid[WIM_GID_LEN]; - - /* Part number of the WIM file in a spanned set. */ - u16 part_number; - - /* Total number of parts in a spanned set. */ - u16 total_parts; - - /* Number of images in the WIM file. */ - u32 image_count; - - /* Location, size, and flags of the lookup table of the WIM. */ - struct resource_entry lookup_table_res_entry; - - /* Location, size, and flags for the XML data of the WIM. */ - struct resource_entry xml_res_entry; - - /* Location, size, and flags for the boot metadata. This means the - * metadata resource for the image specified by boot_idx below. Should - * be zeroed out if boot_idx is 0. */ - struct resource_entry boot_metadata_res_entry; - - /* The index of the bootable image in the WIM file. If 0, there are no - * bootable images available. */ - u32 boot_idx; - - /* The location of the optional integrity table used to verify the - * integrity WIM. Zeroed out if there is no integrity table.*/ - struct resource_entry integrity; - - /* Reserved for future disuse */ - //u8 unused[WIM_UNUSED_LEN]; -}; - -/* Flags for the `flags' field of the struct wim_header: */ - -/* Reserved for future use */ -#define WIM_HDR_FLAG_RESERVED 0x00000001 - -/* Files and metadata in the WIM are compressed. */ -#define WIM_HDR_FLAG_COMPRESSION 0x00000002 - -/* WIM is read-only (wimlib ignores this because it's pretty much pointless) */ -#define WIM_HDR_FLAG_READONLY 0x00000004 - -/* Resource data specified by images in this WIM may be contained in a different - * WIM. Or in other words, this WIM is part of a split WIM. */ -#define WIM_HDR_FLAG_SPANNED 0x00000008 - -/* The WIM contains resources only; no filesystem metadata. wimlib ignores this - * flag, as it looks for resources in all the WIMs anyway. */ -#define WIM_HDR_FLAG_RESOURCE_ONLY 0x00000010 - -/* The WIM contains metadata only. wimlib ignores this flag. Note that all the - * metadata resources for a split WIM should be in the first part. */ -#define WIM_HDR_FLAG_METADATA_ONLY 0x00000020 - -/* Lock field to prevent multiple writers from writing the WIM concurrently. - * wimlib ignores this flag as it uses flock() to acquire a real lock on the - * file (if supported by the underlying filesystem). */ -#define WIM_HDR_FLAG_WRITE_IN_PROGRESS 0x00000040 - -/* Reparse point fixup flag. See docs for --rpfix and --norpfix in imagex, or - * WIMLIB_ADD_FLAG_{RPFIX,NORPFIX} in wimlib.h. Note that - * WIM_HDR_FLAG_RP_FIX is a header flag and just sets the default behavior for - * the WIM; it can still be overridder on a per-image basis. But there is no - * flag to set the default behavior for a specific image. */ -#define WIM_HDR_FLAG_RP_FIX 0x00000080 - -/* Unused, reserved flag for another compression type */ -#define WIM_HDR_FLAG_COMPRESS_RESERVED 0x00010000 - -/* Resources within the WIM are compressed using "XPRESS" compression, which is - * a LZ77-based compression algorithm. */ -#define WIM_HDR_FLAG_COMPRESS_XPRESS 0x00020000 - -/* Resources within the WIM are compressed using "LZX" compression. This is also - * a LZ77-based algorithm. */ -#define WIM_HDR_FLAG_COMPRESS_LZX 0x00040000 - -#ifdef WITH_NTFS_3G -struct _ntfs_volume; -#endif - -/* Table of security descriptors for a WIM image. */ -struct wim_security_data { - /* The total length of the security data, in bytes. If there are no - * security descriptors, this field, when read from the on-disk metadata - * resource, may be either 8 (which is correct) or 0 (which is - * interpreted as 0). */ - u32 total_length; - - /* The number of security descriptors in the array @descriptors, below. - * It is really an unsigned int on-disk, but it must fit into an int - * because the security ID's are signed. (Not like you would ever have - * more than a few hundred security descriptors anyway.) */ - int32_t num_entries; - - /* Array of sizes of the descriptors in the array @descriptors. */ - u64 *sizes; - - /* Array of descriptors. */ - u8 **descriptors; -}; - -/* Metadata for a WIM image */ -struct wim_image_metadata { - - /* Number of WIMStruct's that are sharing this image metadata (from - * calls to wimlib_export_image().) */ - unsigned long refcnt; - - /* Pointer to the root dentry of the image. */ - struct wim_dentry *root_dentry; - - /* Pointer to the security data of the image. */ - struct wim_security_data *security_data; - - /* Pointer to the lookup table entry for this image's metadata resource - */ - struct wim_lookup_table_entry *metadata_lte; - - /* Linked list of 'struct wim_inode's for this image. */ - struct list_head inode_list; - - /* Linked list of 'struct wim_lookup_table_entry's for this image that - * are referred to in the dentry tree, but have not had a SHA1 message - * digest calculated yet and therefore have not been inserted into the - * WIM's lookup table. This list is added to during wimlib_add_image() - * and wimlib_mount_image() (read-write only). */ - struct list_head unhashed_streams; - - /* 1 iff the dentry tree has been modified. If this is the case, the - * memory for the dentry tree should not be freed when switching to a - * different WIM image. */ - u8 modified : 1; - -#ifdef WITH_NTFS_3G - struct _ntfs_volume *ntfs_vol; -#endif -}; - -/* The opaque structure exposed to the wimlib API. */ -struct WIMStruct { - - /* File descriptor for the WIM file, opened for reading, or -1 if it has - * not been opened or there is no associated file backing it yet. */ - int in_fd; - - /* File descriptor, opened either for writing only or for - * reading+writing, for the WIM file (if any) currently being written. - * */ - int out_fd; - - /* The name of the WIM file (if any) that has been opened. */ - tchar *filename; - - /* The lookup table for the WIM file. */ - struct wim_lookup_table *lookup_table; - - /* Information retrieved from the XML data, arranged in an orderly - * manner. */ - struct wim_info *wim_info; - - /* Array of the image metadata, one for each image in the WIM. */ - struct wim_image_metadata **image_metadata; - - /* The header of the WIM file. */ - struct wim_header hdr; - - /* Temporary field */ - void *private; - - /* The currently selected image, indexed starting at 1. If not 0, - * subtract 1 from this to get the index of the current image in the - * image_metadata array. */ - int current_image; - - /* Have any images been deleted? */ - u8 deletion_occurred : 1; - - u8 all_images_verified : 1; - u8 wim_locked : 1; -}; - -/* Inline utility functions for WIMStructs. */ - -static inline struct wim_image_metadata * -wim_get_current_image_metadata(WIMStruct *w) -{ - return w->image_metadata[w->current_image - 1]; -} - -static inline const struct wim_image_metadata * -wim_get_const_current_image_metadata(const WIMStruct *w) -{ - return w->image_metadata[w->current_image - 1]; -} - -static inline struct wim_dentry * -wim_root_dentry(WIMStruct *w) -{ - return wim_get_current_image_metadata(w)->root_dentry; -} - -static inline struct wim_security_data * -wim_security_data(WIMStruct *w) -{ - return wim_get_current_image_metadata(w)->security_data; -} - -static inline const struct wim_security_data * -wim_const_security_data(const WIMStruct *w) -{ - return wim_get_const_current_image_metadata(w)->security_data; -} - -/* Nonzero if a struct resource_entry indicates a compressed resource. */ -static inline int -resource_is_compressed(const struct resource_entry *entry) -{ - return (entry->flags & WIM_RESHDR_FLAG_COMPRESSED); -} - -/* Iterate over each inode in a WIM image that has not yet been hashed */ -#define image_for_each_inode(inode, imd) \ - list_for_each_entry(inode, &imd->inode_list, i_list) - -/* Iterate over each stream in a WIM image that has not yet been hashed */ -#define image_for_each_unhashed_stream(lte, imd) \ - list_for_each_entry(lte, &imd->unhashed_streams, unhashed_list) - -/* Iterate over each stream in a WIM image that has not yet been hashed (safe - * against stream removal) */ -#define image_for_each_unhashed_stream_safe(lte, tmp, imd) \ - list_for_each_entry_safe(lte, tmp, &imd->unhashed_streams, unhashed_list) - -#if 1 -# define copy_resource_entry(dst, src) memcpy(dst, src, sizeof(struct resource_entry)) -# define zero_resource_entry(entry) memset(entry, 0, sizeof(struct resource_entry)) -#else -static inline void -copy_resource_entry(struct resource_entry *dst, - const struct resource_entry *src) -{ - BUILD_BUG_ON(sizeof(struct resource_entry) != 24); - ((u64*)dst)[0] = ((u64*)src)[0]; - ((u64*)dst)[1] = ((u64*)src)[1]; - ((u64*)dst)[2] = ((u64*)src)[2]; -} - -static inline void -zero_resource_entry(struct resource_entry *entry) -{ - BUILD_BUG_ON(sizeof(struct resource_entry) != 24); - ((u64*)entry)[0] = 0; - ((u64*)entry)[1] = 0; - ((u64*)entry)[2] = 0; -} -#endif - -/* add_image.c */ - -/* Hash table to find inodes, given an inode number (in the case of reading - * a WIM images), or both an inode number and a device number (in the case of - * capturing a WIM image). */ -struct wim_inode_table { - /* Fields for the hash table */ - struct hlist_head *array; - u64 num_entries; - u64 capacity; - - /* - * Linked list of "extra" inodes. These may be: - * - * - inodes with link count 1, which are all allowed to have 0 for their - * inode number, meaning we cannot insert them into the hash table. - * - * - Groups we create ourselves by splitting a nominal inode due to - * inconsistencies in the dentries. These inodes will share an inode - * number with some other inode until assign_inode_numbers() is - * called. - */ - struct list_head extra_inodes; -}; - -/* Common parameters to implementations of building an in-memory dentry tree - * from an on-disk directory structure. */ -struct add_image_params { - /* Pointer to the lookup table of the WIM. */ - struct wim_lookup_table *lookup_table; - - /* Hash table of inodes that have been captured for this tree so far. */ - struct wim_inode_table inode_table; - - /* The set of security descriptors that have been captured for this - * image so far. */ - struct sd_set sd_set; - - /* Pointer to the capture configuration, which indicates whether any - * files should be excluded from capture or not. */ - const struct wimlib_capture_config *config; - - /* Flags that affect the capture operation (WIMLIB_ADD_FLAG_*) */ - int add_flags; - - /* If non-NULL, the user-supplied progress function. */ - wimlib_progress_func_t progress_func; - - /* Extra argument; set to point to a pointer to the ntfs_volume for - * libntfs-3g capture. */ - void *extra_arg; - - u64 capture_root_ino; - u64 capture_root_dev; -}; - - -/* capture_common.c */ - -extern bool -exclude_path(const tchar *path, size_t path_len, - const struct wimlib_capture_config *config, - bool exclude_prefix); - -extern struct wimlib_capture_config * -copy_capture_config(const struct wimlib_capture_config *config); - -extern int -copy_and_canonicalize_capture_config(const struct wimlib_capture_config *config, - struct wimlib_capture_config **config_copy_ret); - -extern void -free_capture_config(struct wimlib_capture_config *config); - -/* extract_image.c */ - -/* Internal use only */ -#define WIMLIB_EXTRACT_FLAG_MULTI_IMAGE 0x80000000 -#define WIMLIB_EXTRACT_FLAG_NO_STREAMS 0x40000000 -#define WIMLIB_EXTRACT_MASK_PUBLIC 0x3fffffff - -/* hardlink.c */ - -extern int -init_inode_table(struct wim_inode_table *table, size_t capacity); - -extern int -inode_table_new_dentry(struct wim_inode_table *table, const tchar *name, - u64 ino, u64 devno, bool noshare, - struct wim_dentry **dentry_ret); - -extern void -inode_ref_streams(struct wim_inode *inode); - -extern void -inode_table_prepare_inode_list(struct wim_inode_table *table, - struct list_head *head); - -static inline void -destroy_inode_table(struct wim_inode_table *table) -{ - FREE(table->array); -} - - -extern int -dentry_tree_fix_inodes(struct wim_dentry *root, struct list_head *inode_list); - -/* header.c */ - -extern int -read_header(const tchar *filename, int in_fd, struct wim_header *hdr, - int split_ok); - -extern int -write_header(const struct wim_header *hdr, int out_fd); - -extern int -init_header(struct wim_header *hdr, int ctype); - -/* integrity.c */ - -#define WIM_INTEGRITY_OK 0 -#define WIM_INTEGRITY_NOT_OK -1 -#define WIM_INTEGRITY_NONEXISTENT -2 - -extern int -write_integrity_table(int fd, - struct resource_entry *integrity_res_entry, - off_t new_lookup_table_end, - off_t old_lookup_table_end, - wimlib_progress_func_t progress_func); - -extern int -check_wim_integrity(WIMStruct *w, wimlib_progress_func_t progress_func); - -/* join.c */ - -extern void -merge_lookup_tables(WIMStruct *w, - WIMStruct **additional_swms, unsigned num_additional_swms); - -extern void -unmerge_lookup_table(WIMStruct *wim); - -/* metadata_resource.c */ - -extern int -read_metadata_resource(WIMStruct *w, - struct wim_image_metadata *image_metadata); - -extern int -write_metadata_resource(WIMStruct *w); - -/* ntfs-apply.c */ - -struct apply_args { - WIMStruct *w; - const tchar *target; - unsigned target_nchars; - unsigned wim_source_path_nchars; - struct wim_dentry *extract_root; - tchar *target_realpath; - unsigned target_realpath_len; - int extract_flags; - union wimlib_progress_info progress; - wimlib_progress_func_t progress_func; - int (*apply_dentry)(struct wim_dentry *, void *); - union { - #ifdef WITH_NTFS_3G - struct { - /* NTFS apply only */ - struct _ntfs_volume *vol; - }; - #endif - #ifdef __WIN32__ - struct { - /* Normal apply only (Win32) */ - unsigned long num_set_sacl_priv_notheld; - unsigned long num_set_sd_access_denied; - unsigned vol_flags; - unsigned long num_hard_links_failed; - unsigned long num_soft_links_failed; - bool have_vol_flags; - }; - #else - struct { - /* Normal apply only (UNIX) */ - unsigned long num_utime_warnings; - }; - #endif - }; -}; - -extern int -apply_dentry_ntfs(struct wim_dentry *dentry, void *arg); - -extern int -apply_dentry_timestamps_ntfs(struct wim_dentry *dentry, void *arg); - -extern void -libntfs3g_global_init(); - -/* ntfs-capture.c */ - -typedef int (*consume_data_callback_t)(const void *buf, size_t len, void *ctx); - -extern int -read_ntfs_file_prefix(const struct wim_lookup_table_entry *lte, - u64 size, - consume_data_callback_t cb, - void *ctx_or_buf, - int _ignored_flags); -extern int -build_dentry_tree_ntfs(struct wim_dentry **root_p, - const tchar *device, - struct add_image_params *ctx); - -#ifdef WITH_NTFS_3G -extern int -do_ntfs_umount(struct _ntfs_volume *vol); -#endif - -/* reparse.c */ - -/* Structured format for symbolic link, junction point, or mount point reparse - * data. */ -struct reparse_data { - /* Reparse point tag (see WIM_IO_REPARSE_TAG_* values) */ - u32 rptag; - - /* Length of reparse data, not including the 8-byte header (ReparseTag, - * ReparseDataLength, ReparseReserved) */ - u16 rpdatalen; - - /* ReparseReserved */ - u16 rpreserved; - - /* Flags (only for WIM_IO_REPARSE_TAG_SYMLINK reparse points). - * SYMBOLIC_LINK_RELATIVE means this is a relative symbolic link; - * otherwise should be set to 0. */ -#define SYMBOLIC_LINK_RELATIVE 0x00000001 - u32 rpflags; - - /* Pointer to the substitute name of the link (UTF-16LE). */ - utf16lechar *substitute_name; - - /* Pointer to the print name of the link (UTF-16LE). */ - utf16lechar *print_name; - - /* Number of bytes of the substitute name, not including null terminator - * if present */ - u16 substitute_name_nbytes; - - /* Number of bytes of the print name, not including null terminator if - * present */ - u16 print_name_nbytes; -}; - -enum { - SUBST_NAME_IS_RELATIVE_LINK = -1, - SUBST_NAME_IS_VOLUME_JUNCTION = -2, - SUBST_NAME_IS_UNKNOWN = -3, -}; -extern int -parse_substitute_name(const utf16lechar *substitute_name, - u16 substitute_name_nbytes, - u32 rptag); - -extern int -parse_reparse_data(const u8 *rpbuf, u16 rpbuflen, struct reparse_data *rpdata); - -extern int -make_reparse_buffer(const struct reparse_data *rpdata, u8 *buf); - -extern int -wim_inode_get_reparse_data(const struct wim_inode *inode, u8 *rpbuf); - -#ifndef __WIN32__ -ssize_t -wim_inode_readlink(const struct wim_inode *inode, char *buf, size_t buf_len); - -extern int -wim_inode_set_symlink(struct wim_inode *inode, const char *target, - struct wim_lookup_table *lookup_table); -#endif -extern tchar * -capture_fixup_absolute_symlink(tchar *dest, - u64 capture_root_ino, u64 capture_root_dev); - - -/* resource.c */ - -#define WIMLIB_RESOURCE_FLAG_RAW 0x1 -#define WIMLIB_RESOURCE_FLAG_RECOMPRESS 0x4 - -extern int -read_resource_prefix(const struct wim_lookup_table_entry *lte, - u64 size, consume_data_callback_t cb, void *ctx_or_buf, - int flags); - -extern const void * -get_resource_entry(const void *p, struct resource_entry *entry); - -extern void * -put_resource_entry(void *p, const struct resource_entry *entry); - -extern int -read_partial_wim_resource_into_buf(const struct wim_lookup_table_entry *lte, - size_t size, u64 offset, void *buf); -extern int -read_full_resource_into_buf(const struct wim_lookup_table_entry *lte, void *buf); - -extern int -write_wim_resource(struct wim_lookup_table_entry *lte, int out_fd, - int out_ctype, struct resource_entry *out_res_entry, - int flags); - -extern int -extract_wim_resource(const struct wim_lookup_table_entry *lte, - u64 size, - consume_data_callback_t extract_chunk, - void *extract_chunk_arg); - -extern int -extract_wim_resource_to_fd(const struct wim_lookup_table_entry *lte, - int fd, u64 size); - -extern int -sha1_resource(struct wim_lookup_table_entry *lte); - -extern int -copy_resource(struct wim_lookup_table_entry *lte, void *w); - -/* security.c */ -extern struct wim_security_data * -new_wim_security_data(); - -extern int -read_security_data(const u8 metadata_resource[], - u64 metadata_resource_len, struct wim_security_data **sd_p); -extern void -print_security_data(const struct wim_security_data *sd); - -extern u8 * -write_security_data(const struct wim_security_data *sd, u8 *p); - -extern void -free_security_data(struct wim_security_data *sd); - -/* unix_apply.c */ -#ifndef __WIN32__ -extern int -unix_do_apply_dentry(const char *output_path, size_t output_path_len, - struct wim_dentry *dentry, struct apply_args *args); -extern int -unix_do_apply_dentry_timestamps(const char *output_path, - size_t output_path_len, - struct wim_dentry *dentry, - struct apply_args *args); -#endif - -/* unix_capture.c */ -#ifndef __WIN32__ -extern int -unix_build_dentry_tree(struct wim_dentry **root_ret, - const char *root_disk_path, - struct add_image_params *params); -#endif - -/* update_image.c */ -extern int -rename_wim_path(WIMStruct *wim, const tchar *from, const tchar *to); - -/* verify.c */ - -extern int -verify_dentry(struct wim_dentry *dentry, void *wim); - -extern int -wim_run_full_verifications(WIMStruct *w); - -extern int -verify_swm_set(WIMStruct *w, - WIMStruct **additional_swms, unsigned num_additional_swms); - -/* wim.c */ - -extern int -select_wim_image(WIMStruct *w, int image); - -extern int -for_image(WIMStruct *w, int image, int (*visitor)(WIMStruct *)); - -extern void -destroy_image_metadata(struct wim_image_metadata *imd, - struct wim_lookup_table *table, - bool free_metadata_lte); - -extern void -put_image_metadata(struct wim_image_metadata *imd, - struct wim_lookup_table *table); - -extern int -append_image_metadata(WIMStruct *w, struct wim_image_metadata *imd); - -extern struct wim_image_metadata * -new_image_metadata(); - -extern struct wim_image_metadata ** -new_image_metadata_array(unsigned num_images); - -extern int -wim_checksum_unhashed_streams(WIMStruct *w); - -extern int -reopen_wim(WIMStruct *w); - -extern int -close_wim(WIMStruct *w); - -/* write.c */ - -/* Internal use only */ -#define WIMLIB_WRITE_FLAG_NO_LOOKUP_TABLE 0x80000000 -#define WIMLIB_WRITE_FLAG_REUSE_INTEGRITY_TABLE 0x40000000 -#define WIMLIB_WRITE_FLAG_CHECKPOINT_AFTER_XML 0x20000000 -#define WIMLIB_WRITE_MASK_PUBLIC 0x1fffffff - -/* We are capturing a tree to be placed in the root of the WIM image */ -#define WIMLIB_ADD_FLAG_ROOT 0x80000000 - -extern int -begin_write(WIMStruct *w, const tchar *path, int write_flags); - -extern void -close_wim_writable(WIMStruct *w); - -extern int -finish_write(WIMStruct *w, int image, int write_flags, - wimlib_progress_func_t progress_func); - -#if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) -extern int -lock_wim(WIMStruct *w, int fd); -#else -static inline int -lock_wim(WIMStruct *w, int fd) -{ - return 0; -} -#endif - -#endif /* _WIMLIB_INTERNAL_H */ - diff --git a/src/win32_apply.c b/src/win32_apply.c index 31c37452..272a1dda 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -23,13 +23,22 @@ #ifdef __WIN32__ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include /* for SetSecurityInfo() */ -#include "win32_common.h" -#include "wimlib_internal.h" -#include "dentry.h" -#include "lookup_table.h" -#include "endianness.h" +#include "wimlib/win32_common.h" + +#include "wimlib/apply.h" +#include "wimlib/dentry.h" +#include "wimlib/endianness.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/reparse.h" +#include "wimlib/security.h" #define MAX_CREATE_HARD_LINK_WARNINGS 5 #define MAX_CREATE_SOFT_LINK_WARNINGS 5 diff --git a/src/win32_capture.c b/src/win32_capture.c index aeabfa91..7f6df42e 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -23,11 +23,18 @@ #ifdef __WIN32__ -#include "win32_common.h" -#include "wimlib_internal.h" -#include "lookup_table.h" -#include "security.h" -#include "endianness.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "wimlib/win32_common.h" + +#include "wimlib/capture.h" +#include "wimlib/endianness.h" +#include "wimlib/error.h" +#include "wimlib/lookup_table.h" +#include "wimlib/paths.h" +#include "wimlib/reparse.h" #define MAX_GET_SD_ACCESS_DENIED_WARNINGS 1 #define MAX_GET_SACL_PRIV_NOTHELD_WARNINGS 1 @@ -254,7 +261,7 @@ win32_get_short_name(struct wim_dentry *dentry, const wchar_t *path) static int win32_get_security_descriptor(struct wim_dentry *dentry, - struct sd_set *sd_set, + struct wim_sd_set *sd_set, const wchar_t *path, struct win32_capture_state *state, int add_flags) @@ -417,40 +424,6 @@ out_find_close: return ret; } -int -win32_get_file_and_vol_ids(const wchar_t *path, u64 *ino_ret, u64 *dev_ret) -{ - HANDLE hFile; - DWORD err; - BY_HANDLE_FILE_INFORMATION file_info; - int ret; - - hFile = win32_open_existing_file(path, FILE_READ_ATTRIBUTES); - if (hFile == INVALID_HANDLE_VALUE) { - err = GetLastError(); - if (err != ERROR_FILE_NOT_FOUND) { - WARNING("Failed to open \"%ls\" to get file " - "and volume IDs", path); - win32_error(err); - } - return WIMLIB_ERR_OPEN; - } - - if (!GetFileInformationByHandle(hFile, &file_info)) { - err = GetLastError(); - ERROR("Failed to get file information for \"%ls\"", path); - win32_error(err); - ret = WIMLIB_ERR_STAT; - } else { - *ino_ret = ((u64)file_info.nFileIndexHigh << 32) | - (u64)file_info.nFileIndexLow; - *dev_ret = file_info.dwVolumeSerialNumber; - ret = 0; - } - CloseHandle(hFile); - return ret; -} - /* Reparse point fixup status code */ enum rp_status { /* Reparse point corresponded to an absolute symbolic link or junction diff --git a/src/win32_common.c b/src/win32_common.c index 668f96d8..e0d39ac3 100644 --- a/src/win32_common.c +++ b/src/win32_common.c @@ -1,7 +1,5 @@ /* - * win32_common.c - Windows code common to applying and capturing images, as - * well as replacements for various functions not available on Windows, such as - * fsync(). + * win32_common.c - Windows code common to applying and capturing images. */ /* @@ -25,11 +23,16 @@ #ifdef __WIN32__ -#include /* for PathMatchSpecW() */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include -#include -#include "win32_common.h" +#include "wimlib/win32_common.h" + +#include "wimlib/assert.h" +#include "wimlib/error.h" #ifdef ENABLE_ERROR_MESSAGES void @@ -321,229 +324,11 @@ win32_error_to_errno(DWORD err_code) } void -set_errno_from_GetLastError() +set_errno_from_GetLastError(void) { errno = win32_error_to_errno(GetLastError()); } -/* Replacement for POSIX fsync() */ -int -fsync(int fd) -{ - HANDLE h; - - h = (HANDLE)_get_osfhandle(fd); - if (h == INVALID_HANDLE_VALUE) - goto err; - if (!FlushFileBuffers(h)) - goto err_set_errno; - return 0; -err_set_errno: - set_errno_from_GetLastError(); -err: - return -1; -} - -/* Use the Win32 API to get the number of processors */ -unsigned -win32_get_number_of_processors() -{ - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; -} - -/* Replacement for POSIX-2008 realpath(). Warning: partial functionality only - * (resolved_path must be NULL). Also I highly doubt that GetFullPathName - * really does the right thing under all circumstances. */ -wchar_t * -realpath(const wchar_t *path, wchar_t *resolved_path) -{ - DWORD ret; - DWORD err; - wimlib_assert(resolved_path == NULL); - - ret = GetFullPathNameW(path, 0, NULL, NULL); - if (!ret) { - err = GetLastError(); - goto fail_win32; - } - - resolved_path = TMALLOC(ret); - if (!resolved_path) - goto out; - ret = GetFullPathNameW(path, ret, resolved_path, NULL); - if (!ret) { - err = GetLastError(); - free(resolved_path); - resolved_path = NULL; - goto fail_win32; - } - goto out; -fail_win32: - errno = win32_error_to_errno(err); -out: - return resolved_path; -} - -/* rename() on Windows fails if the destination file exists. And we need to - * make it work on wide characters. Fix it. */ -int -win32_rename_replacement(const wchar_t *oldpath, const wchar_t *newpath) -{ - if (MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) { - return 0; - } else { - set_errno_from_GetLastError(); - return -1; - } -} - -/* Replacement for POSIX fnmatch() (partial functionality only) */ -int -fnmatch(const wchar_t *pattern, const wchar_t *string, int flags) -{ - if (PathMatchSpecW(string, pattern)) - return 0; - else - return FNM_NOMATCH; -} - -/* truncate() replacement */ -int -win32_truncate_replacement(const wchar_t *path, off_t size) -{ - DWORD err = NO_ERROR; - LARGE_INTEGER liOffset; - - HANDLE h = win32_open_existing_file(path, GENERIC_WRITE); - if (h == INVALID_HANDLE_VALUE) - goto fail; - - liOffset.QuadPart = size; - if (!SetFilePointerEx(h, liOffset, NULL, FILE_BEGIN)) - goto fail_close_handle; - - if (!SetEndOfFile(h)) - goto fail_close_handle; - CloseHandle(h); - return 0; - -fail_close_handle: - err = GetLastError(); - CloseHandle(h); -fail: - if (err == NO_ERROR) - err = GetLastError(); - errno = win32_error_to_errno(err); - return -1; -} - - -/* This really could be replaced with _wcserror_s, but this doesn't seem to - * actually be available in MSVCRT.DLL on Windows XP (perhaps it's statically - * linked in by Visual Studio...?). */ -extern int -win32_strerror_r_replacement(int errnum, wchar_t *buf, size_t buflen) -{ - static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER; - - pthread_mutex_lock(&strerror_lock); - mbstowcs(buf, strerror(errnum), buflen); - buf[buflen - 1] = '\0'; - pthread_mutex_unlock(&strerror_lock); - return 0; -} - -static int -do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset, - bool is_pwrite) -{ - HANDLE h; - LARGE_INTEGER orig_offset; - DWORD bytes_read_or_written; - LARGE_INTEGER relative_offset; - OVERLAPPED overlapped; - BOOL bret; - - wimlib_assert(count <= 0xffffffff); - - h = (HANDLE)_get_osfhandle(fd); - if (h == INVALID_HANDLE_VALUE) - goto err; - - /* Get original position */ - relative_offset.QuadPart = 0; - if (!SetFilePointerEx(h, relative_offset, &orig_offset, FILE_CURRENT)) - goto err_set_errno; - - memset(&overlapped, 0, sizeof(overlapped)); - overlapped.Offset = offset; - overlapped.OffsetHigh = offset >> 32; - - /* Do the read or write at the specified offset */ - if (is_pwrite) - bret = WriteFile(h, buf, count, &bytes_read_or_written, &overlapped); - else - bret = ReadFile(h, buf, count, &bytes_read_or_written, &overlapped); - if (!bret) - goto err_set_errno; - - /* Restore the original position */ - if (!SetFilePointerEx(h, orig_offset, NULL, FILE_BEGIN)) - goto err_set_errno; - - return bytes_read_or_written; -err_set_errno: - set_errno_from_GetLastError(); -err: - return -1; -} - -/* Dumb Windows implementation of pread(). It temporarily changes the file - * offset, so it is not safe to use with readers/writers on the same file - * descriptor. */ -extern ssize_t -win32_pread(int fd, void *buf, size_t count, off_t offset) -{ - return do_pread_or_pwrite(fd, buf, count, offset, false); -} - -/* Dumb Windows implementation of pwrite(). It temporarily changes the file - * offset, so it is not safe to use with readers/writers on the same file - * descriptor. */ -extern ssize_t -win32_pwrite(int fd, const void *buf, size_t count, off_t offset) -{ - return do_pread_or_pwrite(fd, (void*)buf, count, offset, true); -} - -/* Dumb Windows implementation of writev(). It writes the vectors one at a - * time. */ -extern ssize_t -win32_writev(int fd, const struct iovec *iov, int iovcnt) -{ - ssize_t total_bytes_written = 0; - - if (iovcnt <= 0) { - errno = EINVAL; - return -1; - } - for (int i = 0; i < iovcnt; i++) { - ssize_t bytes_written; - - bytes_written = write(fd, iov[i].iov_base, iov[i].iov_len); - if (bytes_written >= 0) - total_bytes_written += bytes_written; - if (bytes_written != iov[i].iov_len) { - if (total_bytes_written == 0) - total_bytes_written = -1; - break; - } - } - return total_bytes_written; -} - /* Given a path, which may not yet exist, get a set of flags that describe the * features of the volume the path is on. */ int @@ -636,7 +421,7 @@ windows_version_is_at_least(unsigned major, unsigned minor) /* Try to dynamically load some functions */ void -win32_global_init() +win32_global_init(void) { DWORD err; @@ -665,7 +450,7 @@ win32_global_init() } void -win32_global_cleanup() +win32_global_cleanup(void) { if (hKernel32 != NULL) { DEBUG("Closing Kernel32.dll"); diff --git a/src/win32_replacements.c b/src/win32_replacements.c new file mode 100644 index 00000000..36cc8a35 --- /dev/null +++ b/src/win32_replacements.c @@ -0,0 +1,292 @@ +/* + * win32_replacements.c - Replacements for various functions not available on + * Windows, such as fsync(). + */ + +/* + * Copyright (C) 2013 Eric Biggers + * + * This file is part of wimlib, a library for working with WIM files. + * + * wimlib is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with wimlib; if not, see http://www.gnu.org/licenses/. + */ + +#ifdef __WIN32__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include /* for PathMatchSpecW() */ +#include "wimlib/win32_common.h" + +#include "wimlib/assert.h" +#include "wimlib/file_io.h" +#include "wimlib/error.h" +#include "wimlib/util.h" + +/* Replacement for POSIX fsync() */ +int +fsync(int fd) +{ + HANDLE h; + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) + goto err; + if (!FlushFileBuffers(h)) + goto err_set_errno; + return 0; +err_set_errno: + set_errno_from_GetLastError(); +err: + return -1; +} + +/* Use the Win32 API to get the number of processors */ +unsigned +win32_get_number_of_processors(void) +{ + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; +} + +/* Replacement for POSIX-2008 realpath(). Warning: partial functionality only + * (resolved_path must be NULL). Also I highly doubt that GetFullPathName + * really does the right thing under all circumstances. */ +wchar_t * +realpath(const wchar_t *path, wchar_t *resolved_path) +{ + DWORD ret; + DWORD err; + wimlib_assert(resolved_path == NULL); + + ret = GetFullPathNameW(path, 0, NULL, NULL); + if (!ret) { + err = GetLastError(); + goto fail_win32; + } + + resolved_path = MALLOC(ret * sizeof(wchar_t)); + if (!resolved_path) + goto out; + ret = GetFullPathNameW(path, ret, resolved_path, NULL); + if (!ret) { + err = GetLastError(); + free(resolved_path); + resolved_path = NULL; + goto fail_win32; + } + goto out; +fail_win32: + errno = win32_error_to_errno(err); +out: + return resolved_path; +} + +/* rename() on Windows fails if the destination file exists. And we need to + * make it work on wide characters. Fix it. */ +int +win32_rename_replacement(const wchar_t *oldpath, const wchar_t *newpath) +{ + if (MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) { + return 0; + } else { + set_errno_from_GetLastError(); + return -1; + } +} + +/* Replacement for POSIX fnmatch() (partial functionality only) */ +int +fnmatch(const wchar_t *pattern, const wchar_t *string, int flags) +{ + if (PathMatchSpecW(string, pattern)) + return 0; + else + return FNM_NOMATCH; +} + +/* truncate() replacement */ +int +win32_truncate_replacement(const wchar_t *path, off_t size) +{ + DWORD err = NO_ERROR; + LARGE_INTEGER liOffset; + + HANDLE h = win32_open_existing_file(path, GENERIC_WRITE); + if (h == INVALID_HANDLE_VALUE) + goto fail; + + liOffset.QuadPart = size; + if (!SetFilePointerEx(h, liOffset, NULL, FILE_BEGIN)) + goto fail_close_handle; + + if (!SetEndOfFile(h)) + goto fail_close_handle; + CloseHandle(h); + return 0; + +fail_close_handle: + err = GetLastError(); + CloseHandle(h); +fail: + if (err == NO_ERROR) + err = GetLastError(); + errno = win32_error_to_errno(err); + return -1; +} + + +/* This really could be replaced with _wcserror_s, but this doesn't seem to + * actually be available in MSVCRT.DLL on Windows XP (perhaps it's statically + * linked in by Visual Studio...?). */ +extern int +win32_strerror_r_replacement(int errnum, wchar_t *buf, size_t buflen) +{ + static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&strerror_lock); + mbstowcs(buf, strerror(errnum), buflen); + buf[buflen - 1] = '\0'; + pthread_mutex_unlock(&strerror_lock); + return 0; +} + +static int +do_pread_or_pwrite(int fd, void *buf, size_t count, off_t offset, + bool is_pwrite) +{ + HANDLE h; + LARGE_INTEGER orig_offset; + DWORD bytes_read_or_written; + LARGE_INTEGER relative_offset; + OVERLAPPED overlapped; + BOOL bret; + + wimlib_assert(count <= 0xffffffff); + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) + goto err; + + /* Get original position */ + relative_offset.QuadPart = 0; + if (!SetFilePointerEx(h, relative_offset, &orig_offset, FILE_CURRENT)) + goto err_set_errno; + + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.Offset = offset; + overlapped.OffsetHigh = offset >> 32; + + /* Do the read or write at the specified offset */ + if (is_pwrite) + bret = WriteFile(h, buf, count, &bytes_read_or_written, &overlapped); + else + bret = ReadFile(h, buf, count, &bytes_read_or_written, &overlapped); + if (!bret) + goto err_set_errno; + + /* Restore the original position */ + if (!SetFilePointerEx(h, orig_offset, NULL, FILE_BEGIN)) + goto err_set_errno; + + return bytes_read_or_written; +err_set_errno: + set_errno_from_GetLastError(); +err: + return -1; +} + +/* Dumb Windows implementation of pread(). It temporarily changes the file + * offset, so it is not safe to use with readers/writers on the same file + * descriptor. */ +ssize_t +pread(int fd, void *buf, size_t count, off_t offset) +{ + return do_pread_or_pwrite(fd, buf, count, offset, false); +} + +/* Dumb Windows implementation of pwrite(). It temporarily changes the file + * offset, so it is not safe to use with readers/writers on the same file + * descriptor. */ +ssize_t +pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return do_pread_or_pwrite(fd, (void*)buf, count, offset, true); +} + +/* Dumb Windows implementation of writev(). It writes the vectors one at a + * time. */ +ssize_t writev(int fd, const struct iovec *iov, int iovcnt) +{ + ssize_t total_bytes_written = 0; + + if (iovcnt <= 0) { + errno = EINVAL; + return -1; + } + for (int i = 0; i < iovcnt; i++) { + ssize_t bytes_written; + + bytes_written = write(fd, iov[i].iov_base, iov[i].iov_len); + if (bytes_written >= 0) + total_bytes_written += bytes_written; + if (bytes_written != iov[i].iov_len) { + if (total_bytes_written == 0) + total_bytes_written = -1; + break; + } + } + return total_bytes_written; +} + +int +win32_get_file_and_vol_ids(const wchar_t *path, u64 *ino_ret, u64 *dev_ret) +{ + HANDLE hFile; + DWORD err; + BY_HANDLE_FILE_INFORMATION file_info; + int ret; + + hFile = win32_open_existing_file(path, FILE_READ_ATTRIBUTES); + if (hFile == INVALID_HANDLE_VALUE) { + err = GetLastError(); + if (err != ERROR_FILE_NOT_FOUND) { + WARNING("Failed to open \"%ls\" to get file " + "and volume IDs", path); + win32_error(err); + } + return WIMLIB_ERR_OPEN; + } + + if (!GetFileInformationByHandle(hFile, &file_info)) { + err = GetLastError(); + ERROR("Failed to get file information for \"%ls\"", path); + win32_error(err); + ret = WIMLIB_ERR_STAT; + } else { + *ino_ret = ((u64)file_info.nFileIndexHigh << 32) | + (u64)file_info.nFileIndexLow; + *dev_ret = file_info.dwVolumeSerialNumber; + ret = 0; + } + CloseHandle(hFile); + return ret; +} + + +#endif /* __WIN32__ */ diff --git a/src/write.c b/src/write.c index 0905e7d7..abbe4c01 100644 --- a/src/write.c +++ b/src/write.c @@ -24,25 +24,31 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "config.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #if defined(HAVE_SYS_FILE_H) && defined(HAVE_FLOCK) -/* On BSD, this should be included before "list.h" so that "list.h" can +/* On BSD, this should be included before "wimlib/list.h" so that "wimlib/list.h" can * overwrite the LIST_HEAD macro. */ # include #endif +#include "wimlib/endianness.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/header.h" +#include "wimlib/integrity.h" +#include "wimlib/lookup_table.h" +#include "wimlib/metadata.h" +#include "wimlib/resource.h" +#include "wimlib/write.h" +#include "wimlib/xml.h" + #ifdef __WIN32__ -# include "win32.h" +# include "wimlib/win32.h" /* win32_get_number_of_processors() */ #endif -#include "list.h" -#include "wimlib_internal.h" -#include "buffer_io.h" -#include "dentry.h" -#include "lookup_table.h" -#include "xml.h" - #ifdef ENABLE_MULTITHREADED_COMPRESSION # include #endif @@ -1200,7 +1206,7 @@ main_thread_process_next_stream(struct wim_lookup_table_entry *lte, void *_ctx) } static long -get_default_num_threads() +get_default_num_threads(void) { #ifdef __WIN32__ return win32_get_number_of_processors(); diff --git a/src/xml.c b/src/xml.c index 19cf5f32..d10c38e3 100644 --- a/src/xml.c +++ b/src/xml.c @@ -23,18 +23,26 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "dentry.h" -#include "lookup_table.h" -#include "timestamp.h" -#include "wimlib_internal.h" -#include "xml.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include +#include "wimlib/dentry.h" +#include "wimlib/encoding.h" +#include "wimlib/metadata.h" +#include "wimlib/error.h" +#include "wimlib/file_io.h" +#include "wimlib/lookup_table.h" +#include "wimlib/resource.h" +#include "wimlib/timestamp.h" +#include "wimlib/xml.h" + +#include #include #include #include -#include #include +#include /* Structures used to form an in-memory representation of the XML data (other * than the raw parse tree from libxml). */ @@ -440,7 +448,7 @@ xml_read_image_info(xmlNode *image_node, struct image_info *image_info) if (!image_info->name) { tchar *empty_name; WARNING("Image with index %d has no name", image_info->index); - empty_name = TMALLOC(1); + empty_name = MALLOC(sizeof(tchar)); if (!empty_name) return WIMLIB_ERR_NOMEM; *empty_name = T('\0'); @@ -1221,14 +1229,14 @@ print_image_info(const struct wim_info *wim_info, int image) } void -libxml_global_init() +libxml_global_init(void) { xmlInitParser(); xmlInitCharEncodingHandlers(); } void -libxml_global_cleanup() +libxml_global_cleanup(void) { xmlCleanupParser(); xmlCleanupCharEncodingHandlers(); diff --git a/src/xpress-compress.c b/src/xpress-compress.c index ec63eb18..6b28cca1 100644 --- a/src/xpress-compress.c +++ b/src/xpress-compress.c @@ -25,9 +25,15 @@ * along with wimlib; if not, see http://www.gnu.org/licenses/. */ -#include "xpress.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include "wimlib.h" -#include "compress.h" +#include "wimlib/assert.h" +#include "wimlib/compress.h" +#include "wimlib/util.h" +#include "wimlib/xpress.h" #include #include diff --git a/src/xpress-decompress.c b/src/xpress-decompress.c index 6756b159..584fa4aa 100644 --- a/src/xpress-decompress.c +++ b/src/xpress-decompress.c @@ -71,12 +71,16 @@ * extra symbol is there or not. */ -#include "util.h" -#include "xpress.h" -#include "wimlib.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "wimlib.h" +#include "wimlib/assert.h" #define XPRESS_DECOMP -#include "decompress.h" +#include "wimlib/decompress.h" +#include "wimlib/util.h" +#include "wimlib/xpress.h" /* * Decodes a symbol @huffsym that begins an XPRESS match. diff --git a/tests/common_tests.sh b/tests/common_tests.sh index 6e585a8a..4aaeadbf 100644 --- a/tests/common_tests.sh +++ b/tests/common_tests.sh @@ -49,7 +49,7 @@ do_test 'echo 888 > file; echo 888 > file3' msg "C source code of wimlib" -do_test 'cp $srcdir/src/*.{c,h} .' +do_test 'cp $srcdir/src/*.c .' msg "tons of random stuff" do_test 'echo -n 8 > file; diff --git a/tests/test-imagex b/tests/test-imagex index 234683e6..1931c05f 100755 --- a/tests/test-imagex +++ b/tests/test-imagex @@ -18,7 +18,7 @@ cd $TEST_SUBDIR # Make test directory mkdir dir -cp $srcdir/src/*.c $srcdir/src/*.h dir +cp $srcdir/src/*.c dir mkdir dir/subdir echo 'hello' > dir/subdir/hello echo 'hello' > dir/subdir/hello2 diff --git a/tests/test-imagex-mount b/tests/test-imagex-mount index d7c75e16..13b4e0cd 100755 --- a/tests/test-imagex-mount +++ b/tests/test-imagex-mount @@ -24,7 +24,7 @@ cleanup() { init() { mkdir dir - cp $srcdir/src/*.c $srcdir/src/*.h dir + cp $srcdir/src/*.c dir mkdir dir/subdir echo 'hello' > dir/subdir/hello echo 'hello' > dir/subdir/hello2 diff --git a/tests/test-imagex-ntfs b/tests/test-imagex-ntfs index 9705d9ec..ff67985a 100755 --- a/tests/test-imagex-ntfs +++ b/tests/test-imagex-ntfs @@ -220,7 +220,7 @@ do_test 'echo 999 > file; #setfattr -v DOSNAME -n system.ntfs_dos_name file;' msg "C source code of wimlib" -do_test 'cp $srcdir/src/*.{c,h} .' +do_test 'cp $srcdir/src/*.c .' msg "file with security descriptor" do_test 'touch file; -- 2.43.0