]> wimlib.net Git - wimlib/blobdiff - src/unix_apply.c
Windows: improved error messages
[wimlib] / src / unix_apply.c
index a683b4da1d2ce194a3f7ccafba96e6377897b7b9..afa4b723084f7c9bfce39f738b5887336eefc4d3 100644 (file)
@@ -5,44 +5,42 @@
 /*
  * Copyright (C) 2012, 2013, 2014 Eric Biggers
  *
- * This file is part of wimlib, a library for working with WIM files.
+ * This file is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option) any
+ * later version.
  *
- * wimlib is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option)
- * any later version.
- *
- * wimlib is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * This file is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  * details.
  *
- * You should have received a copy of the GNU General Public License
- * along with wimlib; if not, see http://www.gnu.org/licenses/.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file; if not, see http://www.gnu.org/licenses/.
  */
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
 #endif
 
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 #include "wimlib/apply.h"
 #include "wimlib/assert.h"
 #include "wimlib/dentry.h"
 #include "wimlib/error.h"
 #include "wimlib/file_io.h"
+#include "wimlib/lookup_table.h"
 #include "wimlib/reparse.h"
 #include "wimlib/timestamp.h"
 #include "wimlib/unix_data.h"
 
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
 /* We don't require O_NOFOLLOW, but the advantage of having it is that if we
  * need to extract a file to a location at which there exists a symbolic link,
  * open(..., O_NOFOLLOW | ...) recognizes the symbolic link rather than
@@ -372,7 +370,8 @@ unix_create_if_directory(const struct wim_dentry *dentry,
                ERROR_WITH_ERRNO("Can't create directory \"%s\"", path);
                return WIMLIB_ERR_MKDIR;
        }
-       return 0;
+
+       return report_file_created(&ctx->common);
 }
 
 /* If @dentry represents an empty regular file or a special file, create it, set
@@ -444,7 +443,11 @@ unix_extract_if_empty_file(const struct wim_dentry *dentry,
        if (ret)
                return ret;
 
-       return unix_create_hardlinks(inode, dentry, path, ctx);
+       ret = unix_create_hardlinks(inode, dentry, path, ctx);
+       if (ret)
+               return ret;
+
+       return report_file_created(&ctx->common);
 }
 
 static int
@@ -467,6 +470,29 @@ unix_create_dirs_and_empty_files(const struct list_head *dentry_list,
        return 0;
 }
 
+static void
+unix_count_dentries(const struct list_head *dentry_list,
+                   uint64_t *dir_count_ret, uint64_t *empty_file_count_ret)
+{
+       const struct wim_dentry *dentry;
+       uint64_t dir_count = 0;
+       uint64_t empty_file_count = 0;
+
+       list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
+
+               const struct wim_inode *inode = dentry->d_inode;
+
+               if (inode_is_directory(inode))
+                       dir_count++;
+               else if ((dentry == inode_first_extraction_dentry(inode)) &&
+                        !inode_unnamed_lte_resolved(inode))
+                       empty_file_count++;
+       }
+
+       *dir_count_ret = dir_count;
+       *empty_file_count_ret = empty_file_count;
+}
+
 static int
 unix_create_symlink(const struct wim_inode *inode, const char *path,
                    const u8 *rpdata, u16 rpdatalen, bool rpfix,
@@ -680,6 +706,9 @@ unix_set_dir_metadata(struct list_head *dentry_list, struct unix_apply_ctx *ctx)
                        ret = unix_set_metadata(-1, dentry->d_inode, NULL, ctx);
                        if (ret)
                                return ret;
+                       ret = report_file_metadata_applied(&ctx->common);
+                       if (ret)
+                               return ret;
                }
        }
        return 0;
@@ -691,6 +720,8 @@ unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
        int ret;
        struct unix_apply_ctx *ctx = (struct unix_apply_ctx *)_ctx;
        size_t path_max;
+       uint64_t dir_count;
+       uint64_t empty_file_count;
 
        /* Compute the maximum path length that will be needed, then allocate
         * some path buffers.  */
@@ -712,10 +743,21 @@ unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
         * because we can't extract any other files until their directories
         * exist.  Empty files are needed because they don't have
         * representatives in the stream list.  */
+
+       unix_count_dentries(dentry_list, &dir_count, &empty_file_count);
+
+       ret = start_file_structure_phase(&ctx->common, dir_count + empty_file_count);
+       if (ret)
+               goto out;
+
        ret = unix_create_dirs_and_empty_files(dentry_list, ctx);
        if (ret)
                goto out;
 
+       ret = end_file_structure_phase(&ctx->common);
+       if (ret)
+               goto out;
+
        /* Get full path to target if needed for absolute symlink fixups.  */
        if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_RPFIX) &&
            ctx->common.required_features.symlink_reparse_points)
@@ -742,11 +784,21 @@ unix_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
        if (ret)
                goto out;
 
+
        /* Set directory metadata.  We do this last so that we get the right
         * directory timestamps.  */
+       ret = start_file_metadata_phase(&ctx->common, dir_count);
+       if (ret)
+               goto out;
+
        ret = unix_set_dir_metadata(dentry_list, ctx);
        if (ret)
                goto out;
+
+       ret = end_file_metadata_phase(&ctx->common);
+       if (ret)
+               goto out;
+
        if (ctx->num_special_files_ignored) {
                WARNING("%lu special files were not extracted due to EPERM!",
                        ctx->num_special_files_ignored);