]> wimlib.net Git - wimlib/blobdiff - src/extract.c
dentry.{c,h}: Cleanup and fixes
[wimlib] / src / extract.c
index df144785c92ce76e43d0b8937c92365a8cb89290..d6cc9c45d75ee854382a6c9c4d4fcffc7a02bcd0 100644 (file)
@@ -55,7 +55,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#define MAX_LONG_PATH_WARNINGS 5
+#define MAX_EXTRACT_LONG_PATH_WARNINGS 5
 
 static int
 do_apply_op(struct wim_dentry *dentry, struct apply_args *args,
@@ -105,11 +105,11 @@ do_apply_op(struct wim_dentry *dentry, struct apply_args *args,
        /* + 1 for '\0', -4 for \\?\.  */
        if (extraction_path_nchars + 1 - 4 > MAX_PATH) {
                if (dentry->needs_extraction &&
-                   args->num_long_paths < MAX_LONG_PATH_WARNINGS)
+                   args->num_long_paths < MAX_EXTRACT_LONG_PATH_WARNINGS)
                {
                        WARNING("Path \"%ls\" exceeds MAX_PATH and will not be accessible "
                                "to most Windows software", extraction_path);
-                       if (++args->num_long_paths == MAX_LONG_PATH_WARNINGS)
+                       if (++args->num_long_paths == MAX_EXTRACT_LONG_PATH_WARNINGS)
                                WARNING("Suppressing further warnings about long paths");
                }
        }
@@ -294,8 +294,11 @@ dentry_resolve_and_zero_lte_refcnt(struct wim_dentry *dentry, void *_lookup_tabl
        struct wim_inode *inode = dentry->d_inode;
        struct wim_lookup_table *lookup_table = _lookup_table;
        struct wim_lookup_table_entry *lte;
+       int ret;
 
-       inode_resolve_ltes(inode, lookup_table);
+       ret = inode_resolve_ltes(inode, lookup_table);
+       if (ret)
+               return ret;
        for (unsigned i = 0; i <= inode->i_num_ads; i++) {
                lte = inode_stream_lte_resolved(inode, i);
                if (lte)
@@ -304,19 +307,23 @@ dentry_resolve_and_zero_lte_refcnt(struct wim_dentry *dentry, void *_lookup_tabl
        return 0;
 }
 
-static void
+static int
 find_streams_for_extraction(struct wim_dentry *root,
                            struct list_head *stream_list,
                            struct wim_lookup_table *lookup_table,
                            int extract_flags)
 {
        struct find_streams_ctx ctx;
+       int ret;
 
        INIT_LIST_HEAD(&ctx.stream_list);
        ctx.extract_flags = extract_flags;
-       for_dentry_in_tree(root, dentry_resolve_and_zero_lte_refcnt, lookup_table);
+       ret = for_dentry_in_tree(root, dentry_resolve_and_zero_lte_refcnt, lookup_table);
+       if (ret)
+               return ret;
        for_dentry_in_tree(root, dentry_find_streams_to_extract, &ctx);
        list_transfer(&ctx.stream_list, stream_list);
+       return 0;
 }
 
 struct apply_operations {
@@ -432,9 +439,11 @@ static int
 extract_dentry_to_stdout(struct wim_dentry *dentry)
 {
        int ret = 0;
-       if (!dentry_is_regular_file(dentry)) {
+       if (dentry->d_inode->i_attributes & (FILE_ATTRIBUTE_REPARSE_POINT |
+                                            FILE_ATTRIBUTE_DIRECTORY))
+       {
                ERROR("\"%"TS"\" is not a regular file and therefore cannot be "
-                     "extracted to standard output", dentry->_full_path);
+                     "extracted to standard output", dentry_full_path(dentry));
                ret = WIMLIB_ERR_NOT_A_REGULAR_FILE;
        } else {
                struct wim_lookup_table_entry *lte;
@@ -627,19 +636,22 @@ skip_dentry:
 static int
 dentry_reset_needs_extraction(struct wim_dentry *dentry, void *_ignore)
 {
+       struct wim_inode *inode = dentry->d_inode;
+
        dentry->needs_extraction = 0;
        dentry->not_extracted = 0;
-       dentry->is_win32_name = 0;
-       dentry->d_inode->i_visited = 0;
-       dentry->d_inode->i_dos_name_extracted = 0;
-       FREE(dentry->d_inode->i_extracted_file);
-       dentry->d_inode->i_extracted_file = NULL;
+       inode->i_visited = 0;
+       inode->i_dos_name_extracted = 0;
+       FREE(inode->i_extracted_file);
+       inode->i_extracted_file = NULL;
        if ((void*)dentry->extraction_name != (void*)dentry->file_name)
                FREE(dentry->extraction_name);
        dentry->extraction_name = NULL;
        return 0;
 }
 
+#define WINDOWS_NT_MAX_PATH 32768
+
 /*
  * extract_tree - Extract a file or directory tree from the currently selected
  *               WIM image.
@@ -698,27 +710,24 @@ extract_tree(WIMStruct *wim, const tchar *wim_source_path, const tchar *target,
        /* Work around defective behavior in Windows where paths longer than 260
         * characters are not supported by default; instead they need to be
         * turned into absolute paths and prefixed with "\\?\".  */
-       args.target_lowlevel_path = MALLOC(32768 * sizeof(wchar_t));
+       args.target_lowlevel_path = MALLOC(WINDOWS_NT_MAX_PATH * sizeof(wchar_t));
        if (!args.target_lowlevel_path)
        {
                ret = WIMLIB_ERR_NOMEM;
                goto out;
        }
-       args.target_lowlevel_path[0] = L'\\';
-       args.target_lowlevel_path[1] = L'\\';
-       args.target_lowlevel_path[2] = L'?';
-       args.target_lowlevel_path[3] = L'\\';
        args.target_lowlevel_path_nchars =
-               GetFullPathName(args.target, 32768 - 4,
+               GetFullPathName(args.target, WINDOWS_NT_MAX_PATH - 4,
                                &args.target_lowlevel_path[4], NULL);
 
        if (args.target_lowlevel_path_nchars == 0 ||
-           args.target_lowlevel_path_nchars >= 32768 - 4)
+           args.target_lowlevel_path_nchars >= WINDOWS_NT_MAX_PATH - 4)
        {
                WARNING("Can't get full path name for \"%ls\"", args.target);
                FREE(args.target_lowlevel_path);
                args.target_lowlevel_path = NULL;
        } else {
+               wmemcpy(args.target_lowlevel_path, L"\\\\?\\", 4);
                args.target_lowlevel_path_nchars += 4;
        }
 #endif
@@ -765,9 +774,11 @@ extract_tree(WIMStruct *wim, const tchar *wim_source_path, const tchar *target,
                goto out_dentry_reset_needs_extraction;
 
        /* Build a list of the streams that need to be extracted */
-       find_streams_for_extraction(root,
-                                   &stream_list,
-                                   wim->lookup_table, extract_flags);
+       ret = find_streams_for_extraction(root,
+                                         &stream_list,
+                                         wim->lookup_table, extract_flags);
+       if (ret)
+               goto out_dentry_reset_needs_extraction;
 
        /* Calculate the number of bytes of data that will be extracted */
        calculate_bytes_to_extract(&stream_list, extract_flags,
@@ -1178,7 +1189,7 @@ extract_all_images(WIMStruct *wim,
        }
 
        tmemcpy(buf, target, output_path_len);
-       buf[output_path_len] = T('/');
+       buf[output_path_len] = OS_PREFERRED_PATH_SEPARATOR;
        for (image = 1; image <= wim->hdr.image_count; image++) {
                image_name = wimlib_get_image_name(wim, image);
                if (image_name_ok_as_dir(image_name)) {