From: Eric Biggers Date: Wed, 11 Jun 2014 01:55:10 +0000 (-0500) Subject: Don't exclude out-of-tree absolute symlinks in reparse point fix mode X-Git-Tag: v1.7.0~43 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=157ec1472cea867b62aa59405fe9023aa0549399 Don't exclude out-of-tree absolute symlinks in reparse point fix mode Excluding such links may not be the expected behavior. In addition, Microsoft's documentation for ImageX seems to be incorrect when it states that ImageX excludes such links. Actually, it does not. So, for the sake of consistency and also doing something that may more sense anyway, just retain such links, but leave their targets as-is. --- diff --git a/NEWS b/NEWS index b5dd7dae..45a2e978 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ Version 1.7.0-BETA: nondirectory files by default. Use the --no-replace option to get the old behavior. + In reparse-point fixup mode (the default for capture), symbolic links + and junctions that point outside the tree being captured are no longer + excluded from capture. + Added support for "WIMBoot" capture and extraction. See the documentation for the new '--wimboot' option to wimcapture and wimapply for more information. diff --git a/doc/man1/imagex-capture.1.in b/doc/man1/imagex-capture.1.in index 2d23ce6f..465b01b0 100644 --- a/doc/man1/imagex-capture.1.in +++ b/doc/man1/imagex-capture.1.in @@ -371,10 +371,8 @@ although the Administrator should have permission to read everything anyway. Set whether to fix targets of absolute symbolic links (reparse points in Windows terminology) or not. When enabled (\fB--rpfix\fR), absolute symbolic links that point inside the directory tree being captured will be adjusted to be absolute -relative to the root of the directory tree being captured. In addition, -absolute symbolic links that point outside the directory tree being captured -will be ignored and not be captured at all. When disabled (\fB--norpfix\fR), -absolute symbolic links will be captured exactly as is. +relative to the root of the directory tree being captured. When disabled +(\fB--norpfix\fR), absolute symbolic links will be captured exactly as is. .IP "" The default behavior for \fB@IMAGEX_PROGNAME@ capture\fR is equivalent to \fB--rpfix\fR. The default behavior for \fB@IMAGEX_PROGNAME@ append\fR will be diff --git a/include/wimlib.h b/include/wimlib.h index 7d39ba64..5e49f92e 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -716,14 +716,6 @@ union wimlib_progress_info { * unsupported (e.g. an encrypted or device file). */ WIMLIB_SCAN_DENTRY_UNSUPPORTED, - /** The file is an absolute symbolic link or junction - * point and it is being excluded from capture because - * it points outside of the capture directory and - * reparse-point fixups are enabled. (Reparse point - * fixups can be disabled by using the flag - * ::WIMLIB_ADD_FLAG_NORPFIX.) */ - WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK, - /** The file is an absolute symbolic link or junction * that points into the capture directory, and * reparse-point fixups are enabled, so its target is @@ -731,6 +723,12 @@ union wimlib_progress_info { * disabled with the flag ::WIMLIB_ADD_FLAG_NORPFIX.) */ WIMLIB_SCAN_DENTRY_FIXED_SYMLINK, + + /** Reparse-point fixups are enabled, but the file is an + * absolute symbolic link or junction that does + * not point into the capture directory, so its + * target is not being adjusted. */ + WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK, } status; union { @@ -740,9 +738,9 @@ union wimlib_progress_info { const wimlib_tchar *wim_target_path; /** For ::WIMLIB_PROGRESS_MSG_SCAN_DENTRY and a status - * of @p WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK or @p - * WIMLIB_SCAN_DENTRY_FIXED_SYMLINK, this is the target - * of the absolute symbolic link or junction. */ + * of @p WIMLIB_SCAN_DENTRY_FIXED_SYMLINK or @p + * WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK, this is the + * target of the absolute symbolic link or junction. */ const wimlib_tchar *symlink_target; }; @@ -1378,8 +1376,7 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour /** Reparse-point fixups: Modify absolute symbolic links (or junction points, * in the case of Windows) that point inside the directory being captured to * instead be absolute relative to the directory being captured, rather than the - * current root; also exclude absolute symbolic links that point outside the - * directory tree being captured. + * current root. * * Without this flag, the default is to do this if WIM_HDR_FLAG_RP_FIX is set in * the WIM header or if this is the first image being added. diff --git a/programs/imagex.c b/programs/imagex.c index 67a97239..81f2f9f6 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -1078,24 +1078,13 @@ imagex_progress_func(enum wimlib_progress_msg msg, imagex_printf(T("\nWARNING: Excluding unsupported file or directory\n" " \"%"TS"\" from capture\n"), info->scan.cur_path); break; - case WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK: - imagex_printf(T("\nWARNING: Ignoring absolute symbolic link " - "with out-of-tree target:\n" - " \"%"TS"\" => \"%"TS"\"\n" - " (Use --norpfix to capture " - "absolute symbolic links as-is)\n"), - info->scan.cur_path, info->scan.symlink_target); - break; case WIMLIB_SCAN_DENTRY_FIXED_SYMLINK: /* Symlink fixups are enabled by default. This is * mainly intended for Windows, which for some reason * uses absolute junctions (with drive letters!) in the * default installation. On UNIX-like systems, warn the * user when fixing the target of an absolute symbolic - * link, so they know to disable this if they want. - * (Although, more likely they will get the warning - * about an absolute symbolic link with an out-of-tree - * target first.) */ + * link, so they know to disable this if they want. */ #ifndef __WIN32__ imagex_printf(T("\nWARNING: Adjusted target of " "absolute symbolic link \"%"TS"\"\n" @@ -1104,6 +1093,8 @@ imagex_progress_func(enum wimlib_progress_msg msg, info->scan.cur_path); #endif break; + default: + break; } break; case WIMLIB_PROGRESS_MSG_SCAN_END: diff --git a/src/capture_common.c b/src/capture_common.c index be7c8983..7d7315a8 100644 --- a/src/capture_common.c +++ b/src/capture_common.c @@ -62,8 +62,8 @@ do_capture_progress(struct add_image_params *params, int status, return 0; case WIMLIB_SCAN_DENTRY_UNSUPPORTED: case WIMLIB_SCAN_DENTRY_EXCLUDED: - case WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK: case WIMLIB_SCAN_DENTRY_FIXED_SYMLINK: + case WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK: if (!(params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE)) return 0; } diff --git a/src/unix_capture.c b/src/unix_capture.c index 8b1e7934..15e1d153 100644 --- a/src/unix_capture.c +++ b/src/unix_capture.c @@ -251,8 +251,7 @@ unix_fixup_abslink(char *dest, u64 ino, u64 dev) } static int -unix_scan_symlink(struct wim_dentry **root_p, const char *full_path, - int dirfd, const char *relpath, +unix_scan_symlink(const char *full_path, int dirfd, const char *relpath, struct wim_inode *inode, struct add_image_params *params) { char deref_name_buf[4096]; @@ -281,31 +280,33 @@ unix_scan_symlink(struct wim_dentry **root_p, const char *full_path, if ((params->add_flags & WIMLIB_ADD_FLAG_RPFIX) && dest[0] == '/') { + char *fixed_dest; + /* RPFIX (reparse point fixup) mode: Change target of absolute * symbolic link to be "absolute" relative to the tree being * captured. */ - dest = unix_fixup_abslink(dest, - params->capture_root_ino, - params->capture_root_dev); + fixed_dest = unix_fixup_abslink(dest, + params->capture_root_ino, + params->capture_root_dev); params->progress.scan.cur_path = full_path; params->progress.scan.symlink_target = deref_name_buf; - if (dest) { - /* Successfully fixed the link target. */ + if (fixed_dest) { + /* Link points inside the tree being captured, so it was + * fixed. */ inode->i_not_rpfixed = 0; + dest = fixed_dest; ret = do_capture_progress(params, WIMLIB_SCAN_DENTRY_FIXED_SYMLINK, NULL); - if (ret) - return ret; } else { - /* Link points outside of the tree being captured. - * Exclude it. */ - free_dentry(*root_p); - *root_p = NULL; - return do_capture_progress(params, - WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK, - NULL); + /* Link points outside the tree being captured, so it + * was not fixed. */ + ret = do_capture_progress(params, + WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK, + NULL); } + if (ret) + return ret; } ret = wim_inode_set_symlink(inode, dest, params->lookup_table); if (ret) @@ -422,10 +423,8 @@ unix_build_dentry_tree_recursive(struct wim_dentry **tree_ret, ret = unix_scan_directory(tree, full_path, full_path_len, dirfd, relpath, params); } else if (S_ISLNK(stbuf.st_mode)) { - ret = unix_scan_symlink(&tree, full_path, dirfd, relpath, + ret = unix_scan_symlink(full_path, dirfd, relpath, inode, params); - if (!tree) - goto out; } if (ret) diff --git a/src/win32_apply.c b/src/win32_apply.c index 280f7f54..842d588e 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -1476,7 +1476,7 @@ skip_nt_toplevel_component(const wchar_t *path, size_t path_nchars) * The path has an explicit length and is not necessarily null terminated. * * If the path just something like \??\e: then the returned pointer will point - * just past the colon; in this case the length of the result will be 0 + * just past the colon. In this case the length of the result will be 0 * characters. */ static const wchar_t * get_device_relative_path(const wchar_t *path, size_t path_nchars) diff --git a/src/win32_capture.c b/src/win32_capture.c index bc5422e8..30dc3ef5 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -453,9 +453,6 @@ out_free_buf: /* Reparse point fixup status code */ enum rp_status { - /* Reparse point should be excluded from capture */ - RP_EXCLUDED = -0, - /* Reparse point will be captured literally (no fixup) */ RP_NOT_FIXED = -1, @@ -650,14 +647,13 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p, capture_root_ino, capture_root_dev); if (!rel_target) { - /* Target points outside of the tree being captured. Exclude - * this reparse point from the capture (but inform the library - * user). */ + /* Target points outside of the tree being captured. Don't + * adjust it. */ ret = winnt_rpfix_progress(params, path, &rpdata, - WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK); + WIMLIB_SCAN_DENTRY_NOT_FIXED_SYMLINK); if (ret) return ret; - return RP_EXCLUDED; + return RP_NOT_FIXED; } if (rel_target == rpdata.substitute_name) { @@ -722,7 +718,7 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p, * On success, the length of the reparse point buffer in bytes is written * to this location. * - * On success, returns a nonpositive `enum rp_status' value. + * On success, returns a negative `enum rp_status' value. * On failure, returns a positive error code. */ static int @@ -1201,9 +1197,6 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret, ret = winnt_get_reparse_data(h, full_path, params, rpbuf, &rpbuflen); switch (ret) { - case RP_EXCLUDED: - ret = 0; - goto out; case RP_FIXED: not_rpfixed = 0; break; diff --git a/tests/test-imagex-capture_and_apply b/tests/test-imagex-capture_and_apply index 105d0f39..672c8ae3 100755 --- a/tests/test-imagex-capture_and_apply +++ b/tests/test-imagex-capture_and_apply @@ -170,9 +170,9 @@ if [[ `readlink out.dir/absrootlink` != "/" ]] || error "imagex capture --rpfix failed to fix absolute link to capture root" fi -if [[ -e out.dir/absnonexistent ]] || - [[ -e out.dir/absoutoftree ]]; then - error "imagex capture --rpfix failed to exclude out of tree absolute links" +if [[ ! -L out.dir/absnonexistent ]] || + [[ ! -L out.dir/absoutoftree ]]; then + error "imagex capture --rpfix failed to also capture out of tree absolute links" fi if [[ `readlink out.dir/relalink` != "file" ]]; then error "imagex capture --rpfix failed to capture relative symlink" diff --git a/tests/win32-test-imagex-capture_and_apply.bat b/tests/win32-test-imagex-capture_and_apply.bat index 01e3f320..2ce8febb 100644 --- a/tests/win32-test-imagex-capture_and_apply.bat +++ b/tests/win32-test-imagex-capture_and_apply.bat @@ -330,17 +330,6 @@ del tmp1 tmp2 md in.dir cd in.dir -echo Testing rpfix exclude -mklink otherlink c:\some\other\directory > nul -cd .. -%WIMLIB_IMAGEX% capture in.dir test.wim > nul -%WIMLIB_IMAGEX% apply test.wim out.dir > nul -rd out.dir -if %errorlevel% neq 0 exit /b %errorlevel% -rd /s /q in.dir -md in.dir -cd in.dir - echo Testing rpfix relative echo 1 > file mklink relink file > nul