]> wimlib.net Git - wimlib/blobdiff - src/win32_capture.c
Refactor some of the dentry, inode, and lookup table code
[wimlib] / src / win32_capture.c
index fa3f04fbff8ef28235c9df2e690e3684669089dd..cf5c65c9498225b5c5c23211a213a0698cf75636 100644 (file)
@@ -30,6 +30,7 @@
 #include "wimlib/win32_common.h"
 
 #include "wimlib/capture.h"
+#include "wimlib/dentry.h"
 #include "wimlib/endianness.h"
 #include "wimlib/error.h"
 #include "wimlib/lookup_table.h"
@@ -110,6 +111,9 @@ win32_encrypted_export_cb(unsigned char *data, void *_ctx, unsigned long len)
        int ret;
        size_t bytes_to_consume = min(len, ctx->bytes_remaining);
 
+       if (bytes_to_consume == 0)
+               return ERROR_SUCCESS;
+
        ret = (*ctx->read_prefix_cb)(data, bytes_to_consume, ctx->read_prefix_ctx);
        if (ret) {
                ctx->wimlib_err_code = ret;
@@ -618,7 +622,7 @@ win32_capture_maybe_rpfix_target(wchar_t *target, u16 *target_nbytes_p,
 static int
 win32_capture_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                        u64 capture_root_ino, u64 capture_root_dev,
-                       const wchar_t *path)
+                       const wchar_t *path, struct add_image_params *params)
 {
        struct reparse_data rpdata;
        int ret;
@@ -655,17 +659,18 @@ win32_capture_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                        ret = -ret;
        } else {
                if (rp_status == RP_EXCLUDED) {
+                       /* Ignoring absolute symbolic link or junction point
+                        * that points out of the tree to be captured.  */
                        size_t print_name_nchars = rpdata.print_name_nbytes / 2;
                        wchar_t print_name0[print_name_nchars + 1];
                        print_name0[print_name_nchars] = L'\0';
                        wmemcpy(print_name0, rpdata.print_name, print_name_nchars);
-                       WARNING("Ignoring %ls pointing out of capture directory:\n"
-                               "          \"%ls\" -> \"%ls\"\n"
-                               "          (Use --norpfix to capture all symbolic links "
-                               "and junction points as-is)",
-                               (rpdata.rptag == WIM_IO_REPARSE_TAG_SYMLINK) ?
-                                       L"absolute symbolic link" : L"junction point",
-                               path, print_name0);
+
+                       params->progress.scan.cur_path = path;
+                       params->progress.scan.symlink_target = print_name0;
+                       do_capture_progress(params,
+                                           WIMLIB_SCAN_DENTRY_EXCLUDED_SYMLINK,
+                                           NULL);
                }
                ret = rp_status;
        }
@@ -734,7 +739,8 @@ win32_get_reparse_data(HANDLE hFile, const wchar_t *path,
                                              &rpbuflen,
                                              params->capture_root_ino,
                                              params->capture_root_dev,
-                                             path);
+                                             path,
+                                             params);
        } else {
                ret = RP_NOT_FIXED;
        }
@@ -790,7 +796,8 @@ win32_get_encrypted_file_size(const wchar_t *path, u64 *size_ret)
  *
  * @inode:              WIM inode to save the stream into.
  *
- * @lookup_table:       Stream lookup table for the WIM.
+ * @unhashed_streams:   List of unhashed streams that have been added to the WIM
+ *                      image.
  *
  * @dat:                A `WIN32_FIND_STREAM_DATA' structure that specifies the
  *                      stream name.
@@ -801,7 +808,7 @@ static int
 win32_capture_stream(const wchar_t *path,
                     size_t path_num_chars,
                     struct wim_inode *inode,
-                    struct wim_lookup_table *lookup_table,
+                    struct list_head *unhashed_streams,
                     WIN32_FIND_STREAM_DATA *dat)
 {
        struct wim_ads_entry *ads_entry;
@@ -911,7 +918,7 @@ win32_capture_stream(const wchar_t *path,
                stream_id = 0;
                inode->i_lte = lte;
        }
-       lookup_table_insert_unhashed(lookup_table, lte, inode, stream_id);
+       add_unhashed_stream(lte, inode, stream_id, unhashed_streams);
        ret = 0;
 out_free_spath:
        FREE(spath);
@@ -941,7 +948,7 @@ win32_capture_streams(HANDLE *hFile_p,
                      const wchar_t *path,
                      size_t path_num_chars,
                      struct wim_inode *inode,
-                     struct wim_lookup_table *lookup_table,
+                     struct list_head *unhashed_streams,
                      u64 file_size,
                      unsigned vol_flags)
 {
@@ -1027,7 +1034,7 @@ win32_capture_streams(HANDLE *hFile_p,
 
                        /* Capture the stream.  */
                        ret = win32_capture_stream(path, path_num_chars, inode,
-                                                  lookup_table, &dat);
+                                                  unhashed_streams, &dat);
                        if (ret)
                                goto out_free_buf;
                }
@@ -1084,7 +1091,7 @@ use_FindFirstStream:
        do {
                ret = win32_capture_stream(path,
                                           path_num_chars,
-                                          inode, lookup_table,
+                                          inode, unhashed_streams,
                                           &dat);
                if (ret)
                        goto out_find_close;
@@ -1111,7 +1118,7 @@ unnamed_only:
        wcscpy(dat.cStreamName, L"::$DATA");
        dat.StreamSize.QuadPart = file_size;
        return win32_capture_stream(path, path_num_chars,
-                                   inode, lookup_table, &dat);
+                                   inode, unhashed_streams, &dat);
 }
 
 static int
@@ -1123,7 +1130,7 @@ win32_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                  unsigned vol_flags)
 {
        struct wim_dentry *root = NULL;
-       struct wim_inode *inode;
+       struct wim_inode *inode = NULL;
        DWORD err;
        u64 file_size;
        int ret;
@@ -1199,7 +1206,7 @@ again:
                        not_rpfixed = 0;
                } else if (ret == RP_EXCLUDED) {
                        ret = 0;
-                       goto out_progress;
+                       goto out;
                } else {
                        not_rpfixed = 1;
                }
@@ -1261,7 +1268,7 @@ again:
                                    path,
                                    path_num_chars,
                                    inode,
-                                   params->lookup_table,
+                                   params->unhashed_streams,
                                    file_size,
                                    vol_flags);
        if (ret)
@@ -1355,7 +1362,6 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
        struct win32_capture_state state;
        unsigned vol_flags;
        DWORD dret;
-       bool need_prefix_free = false;
 
        if (!win32func_FindFirstStreamW
 #ifdef WITH_NTDLL
@@ -1384,8 +1390,8 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
        /* WARNING: There is no check for overflow later when this buffer is
         * being used!  But it's as long as the maximum path length understood
         * by Windows NT (which is NOT the same as MAX_PATH). */
-       path = MALLOC(WINDOWS_NT_MAX_PATH * sizeof(wchar_t));
-       if (!path)
+       path = MALLOC((WINDOWS_NT_MAX_PATH + 1) * sizeof(wchar_t));
+       if (path == NULL)
                return WIMLIB_ERR_NOMEM;
 
        /* Work around defective behavior in Windows where paths longer than 260
@@ -1393,37 +1399,45 @@ win32_build_dentry_tree(struct wim_dentry **root_ret,
         * turned into absolute paths and prefixed with "\\?\".  */
 
        if (wcsncmp(root_disk_path, L"\\\\?\\", 4)) {
-               dret = GetFullPathName(root_disk_path, WINDOWS_NT_MAX_PATH - 4,
+               dret = GetFullPathName(root_disk_path, WINDOWS_NT_MAX_PATH - 3,
                                       &path[4], NULL);
 
-               if (dret == 0 || dret >= WINDOWS_NT_MAX_PATH - 4) {
+               if (dret == 0 || dret >= WINDOWS_NT_MAX_PATH - 3) {
                        WARNING("Can't get full path name for \"%ls\"", root_disk_path);
                        wmemcpy(path, root_disk_path, path_nchars + 1);
                } else {
                        wmemcpy(path, L"\\\\?\\", 4);
                        path_nchars = 4 + dret;
-                       /* Update pattern prefix */
-                       if (params->config != NULL)
-                       {
-                               params->config->_prefix = TSTRDUP(path);
-                               params->config->_prefix_num_tchars = path_nchars;
-                               if (params->config->_prefix == NULL)
-                               {
-                                       ret = WIMLIB_ERR_NOMEM;
-                                       goto out_free_path;
-                               }
-                               need_prefix_free = true;
-                       }
                }
        } else {
                wmemcpy(path, root_disk_path, path_nchars + 1);
        }
 
+       /* Strip trailing slashes.  */
+       while (path_nchars >= 2 &&
+              is_any_path_separator(path[path_nchars - 1]) &&
+              path[path_nchars - 2] != L':')
+       {
+               path[--path_nchars] = L'\0';
+       }
+
+       /* Update pattern prefix.  */
+       if (params->config != NULL)
+       {
+               params->config->_prefix = TSTRDUP(path);
+               params->config->_prefix_num_tchars = path_nchars;
+               if (params->config->_prefix == NULL)
+               {
+                       ret = WIMLIB_ERR_NOMEM;
+                       goto out_free_path;
+               }
+       }
+
        memset(&state, 0, sizeof(state));
        ret = win32_build_dentry_tree_recursive(root_ret, path,
                                                path_nchars, params,
                                                &state, vol_flags);
-       if (need_prefix_free)
+       if (params->config != NULL)
                FREE(params->config->_prefix);
 out_free_path:
        FREE(path);