From daf72364fc96380cdc0d8ceeeda640d82930f1b9 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 23 May 2014 10:32:37 -0500 Subject: [PATCH] Report progress for capture symlink fixups wimcapture: On non-Windows, warn when the target of an absolute symbolic link is adjusted. --- include/wimlib.h | 14 +++++++++++--- programs/imagex.c | 18 ++++++++++++++++++ src/capture_common.c | 1 + src/unix_capture.c | 23 ++++++++++++++++------- src/win32_capture.c | 33 +++++++++++++++++++++++---------- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/include/wimlib.h b/include/wimlib.h index 702c3a63..ea15d8e7 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -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; }; diff --git a/programs/imagex.c b/programs/imagex.c index 059e6d9b..6351475f 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -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: diff --git a/src/capture_common.c b/src/capture_common.c index 943d919b..be7c8983 100644 --- a/src/capture_common.c +++ b/src/capture_common.c @@ -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; } diff --git a/src/unix_capture.c b/src/unix_capture.c index ba540c98..8fb4cba8 100644 --- a/src/unix_capture.c +++ b/src/unix_capture.c @@ -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) diff --git a/src/win32_capture.c b/src/win32_capture.c index 064241e1..27b3794f 100644 --- a/src/win32_capture.c +++ b/src/win32_capture.c @@ -588,6 +588,22 @@ out_close_root_dir: return p; } +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, @@ -595,6 +611,7 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p, { 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; } -- 2.43.0