Don't exclude out-of-tree absolute symlinks in reparse point fix mode
authorEric Biggers <ebiggers3@gmail.com>
Wed, 11 Jun 2014 01:55:10 +0000 (20:55 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Wed, 11 Jun 2014 01:58:31 +0000 (20:58 -0500)
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.

NEWS
doc/man1/imagex-capture.1.in
include/wimlib.h
programs/imagex.c
src/capture_common.c
src/unix_capture.c
src/win32_apply.c
src/win32_capture.c
tests/test-imagex-capture_and_apply
tests/win32-test-imagex-capture_and_apply.bat

diff --git a/NEWS b/NEWS
index b5dd7da..45a2e97 100644 (file)
--- 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.
index 2d23ce6..465b01b 100644 (file)
@@ -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
index 7d39ba6..5e49f92 100644 (file)
@@ -717,20 +717,18 @@ union wimlib_progress_info {
                        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
                         * being adjusted.  (Reparse point fixups can be
                         * 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
+                        * <b>not</b> point into the capture directory, so its
+                        * target is <b>not</b> 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.
index 67a9723..81f2f9f 100644 (file)
@@ -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:
index be7c898..7d7315a 100644 (file)
@@ -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;
        }
index 8b1e793..15e1d15 100644 (file)
@@ -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)
index 280f7f5..842d588 100644 (file)
@@ -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)
index bc5422e..30dc3ef 100644 (file)
@@ -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;
index 105d0f3..672c8ae 100755 (executable)
@@ -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"
index 01e3f32..2ce8feb 100644 (file)
@@ -330,17 +330,6 @@ del tmp1 tmp2
 md in.dir\r
 cd in.dir\r
 \r
-echo Testing rpfix exclude\r
-mklink otherlink c:\some\other\directory > nul\r
-cd ..\r
-%WIMLIB_IMAGEX% capture in.dir test.wim > nul\r
-%WIMLIB_IMAGEX% apply test.wim out.dir > nul\r
-rd out.dir\r
-if %errorlevel% neq 0 exit /b %errorlevel%\r
-rd /s /q in.dir\r
-md in.dir\r
-cd in.dir\r
-\r
 echo Testing rpfix relative\r
 echo 1 > file\r
 mklink relink file > nul\r