Report progress for capture symlink fixups
authorEric Biggers <ebiggers3@gmail.com>
Fri, 23 May 2014 15:32:37 +0000 (10:32 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Fri, 23 May 2014 17:33:10 +0000 (12:33 -0500)
wimcapture: On non-Windows, warn when the target of an absolute symbolic
link is adjusted.

include/wimlib.h
programs/imagex.c
src/capture_common.c
src/unix_capture.c
src/win32_capture.c

index 702c3a6..ea15d8e 100644 (file)
@@ -719,6 +719,14 @@ union wimlib_progress_info {
                         * 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,
                } status;
 
                union {
@@ -728,9 +736,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, this is
-                        * the target of the absolute symbolic link or junction
-                        * point.  */
+                        * 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.  */
                        const wimlib_tchar *symlink_target;
                };
 
index 059e6d9..6351475 100644 (file)
@@ -1086,6 +1086,24 @@ imagex_progress_func(enum wimlib_progress_msg msg,
                                        "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.)  */
+               #ifndef __WIN32__
+                       imagex_printf(T("\nWARNING: Adjusted target of "
+                                       "absolute symbolic link \"%"TS"\"\n"
+                                       "           (Use --norpfix to capture "
+                                       "absolute symbolic links as-is)\n"),
+                                       info->scan.cur_path);
+               #endif
+                       break;
                }
                break;
        case WIMLIB_PROGRESS_MSG_SCAN_END:
index 943d919..be7c898 100644 (file)
@@ -63,6 +63,7 @@ do_capture_progress(struct add_image_params *params, int status,
        case WIMLIB_SCAN_DENTRY_UNSUPPORTED:
        case WIMLIB_SCAN_DENTRY_EXCLUDED:
        case WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK:
+       case WIMLIB_SCAN_DENTRY_FIXED_SYMLINK:
                if (!(params->add_flags & WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE))
                        return 0;
        }
index ba540c9..8fb4cba 100644 (file)
@@ -281,22 +281,31 @@ unix_scan_symlink(struct wim_dentry **root_p, const char *full_path,
        if ((params->add_flags & WIMLIB_ADD_FLAG_RPFIX) &&
             dest[0] == '/')
        {
+               /* 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);
-               if (!dest) {
-                       /* RPFIX (reparse point fixup) mode:  Ignore
-                        * absolute symbolic link that points out of the
-                        * tree to be captured.  */
+               params->progress.scan.cur_path = full_path;
+               params->progress.scan.symlink_target = deref_name_buf;
+               if (dest) {
+                       /* Successfully fixed the link target.  */
+                       inode->i_not_rpfixed = 0;
+                       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;
-                       params->progress.scan.cur_path = full_path;
-                       params->progress.scan.symlink_target = deref_name_buf;
                        return do_capture_progress(params,
                                                   WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK,
                                                   NULL);
                }
-               inode->i_not_rpfixed = 0;
        }
        ret = wim_inode_set_symlink(inode, dest, params->lookup_table);
        if (ret)
index 064241e..27b3794 100644 (file)
@@ -589,12 +589,29 @@ out_close_root_dir:
 }
 
 static int
+winnt_rpfix_progress(struct add_image_params *params, const wchar_t *path,
+                    const struct reparse_data *rpdata,
+                    enum wimlib_progress_msg msg)
+{
+       size_t print_name_nchars = rpdata->print_name_nbytes / sizeof(wchar_t);
+       wchar_t print_name0[print_name_nchars + 1];
+
+       wmemcpy(print_name0, rpdata->print_name, print_name_nchars);
+       print_name0[print_name_nchars] = L'\0';
+
+       params->progress.scan.cur_path = printable_path(path);
+       params->progress.scan.symlink_target = print_name0;
+       return do_capture_progress(params, msg, NULL);
+}
+
+static int
 winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                u64 capture_root_ino, u64 capture_root_dev,
                const wchar_t *path, struct add_image_params *params)
 {
        struct reparse_data rpdata;
        const wchar_t *rel_target;
+       int ret;
 
        if (parse_reparse_data(rpbuf, *rpbuflen_p, &rpdata)) {
                /* Couldn't even understand the reparse data.  Don't try the
@@ -636,16 +653,8 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                /* Target points outside of the tree being captured.  Exclude
                 * this reparse point from the capture (but inform the library
                 * user).  */
-               size_t print_name_nchars = rpdata.print_name_nbytes / sizeof(wchar_t);
-               wchar_t print_name0[print_name_nchars + 1];
-               print_name0[print_name_nchars] = L'\0';
-               wmemcpy(print_name0, rpdata.print_name, print_name_nchars);
-
-               params->progress.scan.cur_path = printable_path(path);
-               params->progress.scan.symlink_target = print_name0;
-               int ret = do_capture_progress(params,
-                                             WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK,
-                                             NULL);
+               ret = winnt_rpfix_progress(params, path, &rpdata,
+                                          WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK);
                if (ret)
                        return ret;
                return RP_EXCLUDED;
@@ -687,6 +696,10 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                if (make_reparse_buffer(&rpdata, rpbuf, rpbuflen_p))
                        return RP_NOT_FIXED;
        }
+       ret = winnt_rpfix_progress(params, path, &rpdata,
+                                  WIMLIB_SCAN_DENTRY_FIXED_SYMLINK);
+       if (ret)
+               return ret;
        return RP_FIXED;
 }