]> wimlib.net Git - wimlib/blobdiff - src/win32_apply.c
win32_apply.c: Fix reparse point fixup of device-direct links (no trailing slash)
[wimlib] / src / win32_apply.c
index fcb2c001abd128e77861b021b5e8fbf8a87eccd5..280f7f541f46f8e3ceae71693a2711b07afec938 100644 (file)
@@ -21,6 +21,8 @@
  * along with wimlib; if not, see http://www.gnu.org/licenses/.
  */
 
+#ifdef __WIN32__
+
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
@@ -357,7 +359,7 @@ dentry_extraction_path_length(const struct wim_dentry *dentry)
        d = dentry;
        do {
                len += d->d_extraction_name_nchars + 1;
-               d = d->parent;
+               d = d->d_parent;
        } while (!dentry_is_root(d) && will_extract_dentry(d));
 
        return --len;  /* No leading slash  */
@@ -426,8 +428,8 @@ build_extraction_path(const struct wim_dentry *dentry,
        ctx->pathbuf.Length = len * sizeof(wchar_t);
        p = ctx->pathbuf.Buffer + len;
        for (d = dentry;
-            !dentry_is_root(d->parent) && will_extract_dentry(d->parent);
-            d = d->parent)
+            !dentry_is_root(d->d_parent) && will_extract_dentry(d->d_parent);
+            d = d->d_parent)
        {
                p -= d->d_extraction_name_nchars;
                wmemcpy(p, d->d_extraction_name, d->d_extraction_name_nchars);
@@ -985,22 +987,6 @@ create_directories(struct list_head *dentry_list,
        return 0;
 }
 
-/* Gets the number of bytes to allocate for the specified inode.  */
-static void
-inode_get_allocation_size(const struct wim_inode *inode,
-                         LARGE_INTEGER *allocation_size_ret)
-{
-       const struct wim_lookup_table_entry *unnamed_stream;
-
-       /* We just count the unnamed data stream.  */
-
-       unnamed_stream = inode_unnamed_lte_resolved(inode);
-       if (unnamed_stream)
-               allocation_size_ret->QuadPart = unnamed_stream->size;
-       else
-               allocation_size_ret->QuadPart = 0;
-}
-
 /*
  * Creates the nondirectory file named by @dentry.
  *
@@ -1013,17 +999,12 @@ create_nondirectory_inode(HANDLE *h_ret, const struct wim_dentry *dentry,
                          struct win32_apply_ctx *ctx)
 {
        const struct wim_inode *inode;
-       LARGE_INTEGER allocation_size;
        ULONG attrib;
        NTSTATUS status;
        bool retried = false;
 
        inode = dentry->d_inode;
 
-       /* To increase performance, we will pre-allocate space for the file
-        * data.  */
-       inode_get_allocation_size(inode, &allocation_size);
-
        /* If the file already exists and has FILE_ATTRIBUTE_SYSTEM and/or
         * FILE_ATTRIBUTE_HIDDEN, these must be specified in order to supersede
         * the file.
@@ -1049,7 +1030,7 @@ create_nondirectory_inode(HANDLE *h_ret, const struct wim_dentry *dentry,
        build_extraction_path(dentry, ctx);
 retry:
        status = do_create_file(h_ret, GENERIC_READ | GENERIC_WRITE | DELETE,
-                               &allocation_size, attrib, FILE_SUPERSEDE,
+                               NULL, attrib, FILE_SUPERSEDE,
                                FILE_NON_DIRECTORY_FILE, ctx);
        if (NT_SUCCESS(status)) {
                int ret;
@@ -1291,7 +1272,7 @@ begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
 {
        const struct wim_inode *inode = dentry->d_inode;
        size_t stream_name_nchars = 0;
-       LARGE_INTEGER allocation_size;
+       FILE_ALLOCATION_INFORMATION alloc_info;
        HANDLE h;
        NTSTATUS status;
 
@@ -1363,7 +1344,9 @@ begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
                                            &info, ctx->common.progctx);
                        FREE(dentry->_full_path);
                        dentry->_full_path = NULL;
-                       return ret;
+                       if (ret)
+                               return ret;
+                       /* Go on and open the file for normal extraction.  */
                } else {
                        FREE(dentry->_full_path);
                        dentry->_full_path = NULL;
@@ -1378,15 +1361,14 @@ begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
 
        /* Too many open handles?  */
        if (ctx->num_open_handles == MAX_OPEN_HANDLES) {
-               ERROR("Too many open handles!");
+               ERROR("Can't extract data: too many open files!");
                return WIMLIB_ERR_UNSUPPORTED;
        }
 
        /* Open a new handle  */
-       allocation_size.QuadPart = stream->size;
        status = do_create_file(&h,
                                FILE_WRITE_DATA | SYNCHRONIZE,
-                               &allocation_size, 0, FILE_OPEN_IF,
+                               NULL, 0, FILE_OPEN_IF,
                                FILE_SEQUENTIAL_ONLY |
                                        FILE_SYNCHRONOUS_IO_NONALERT,
                                ctx);
@@ -1399,6 +1381,12 @@ begin_extract_stream_instance(const struct wim_lookup_table_entry *stream,
        }
 
        ctx->open_handles[ctx->num_open_handles++] = h;
+
+       /* Allocate space for the data.  */
+       alloc_info.AllocationSize.QuadPart = stream->size;
+       (*func_NtSetInformationFile)(h, &ctx->iosb,
+                                    &alloc_info, sizeof(alloc_info),
+                                    FileAllocationInformation);
        return 0;
 }
 
@@ -1483,7 +1471,13 @@ skip_nt_toplevel_component(const wchar_t *path, size_t path_nchars)
 
 /* Given a Windows NT namespace path, such as \??\e:\Windows\System32, return a
  * pointer to the suffix of the path that is device-relative, such as
- * Windows\System32.  */
+ * Windows\System32.
+ *
+ * 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
+ * characters.  */
 static const wchar_t *
 get_device_relative_path(const wchar_t *path, size_t path_nchars)
 {
@@ -1496,7 +1490,7 @@ get_device_relative_path(const wchar_t *path, size_t path_nchars)
 
        path = wmemchr(path, L'\\', (end - path));
        if (!path)
-               return orig_path;
+               return end;
        do {
                path++;
        } while (path != end && *path == L'\\');
@@ -1545,14 +1539,18 @@ try_rpfix(u8 *rpbuf, u16 *rpbuflen_p, struct win32_apply_ctx *ctx)
 
        target_ntpath_nchars = ctx->target_ntpath.Length / sizeof(wchar_t);
 
-       fixed_subst_name_nchars = target_ntpath_nchars + 1 + relpath_nchars;
+       fixed_subst_name_nchars = target_ntpath_nchars;
+       if (relpath_nchars)
+               fixed_subst_name_nchars += 1 + relpath_nchars;
        wchar_t fixed_subst_name[fixed_subst_name_nchars];
 
        wmemcpy(fixed_subst_name, ctx->target_ntpath.Buffer,
                target_ntpath_nchars);
-       fixed_subst_name[target_ntpath_nchars] = L'\\';
-       wmemcpy(&fixed_subst_name[target_ntpath_nchars + 1],
-               relpath, relpath_nchars);
+       if (relpath_nchars) {
+               fixed_subst_name[target_ntpath_nchars] = L'\\';
+               wmemcpy(&fixed_subst_name[target_ntpath_nchars + 1],
+                       relpath, relpath_nchars);
+       }
        /* Doesn't need to be null-terminated.  */
 
        /* Print name should be Win32, but not all NT names can even be
@@ -2093,3 +2091,5 @@ const struct apply_operations win32_apply_ops = {
        .extract                = win32_extract,
        .context_size           = sizeof(struct win32_apply_ctx),
 };
+
+#endif /* __WIN32__ */