]> wimlib.net Git - wimlib/blobdiff - src/extract.c
extract.c: replace tempnam() with mkstemp() on non-Windows
[wimlib] / src / extract.c
index 04d484f4e4216c4f3e2bc9ca1e4c7522e3f82555..496d9c9870664ba050902139a942363197956605 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 /*
- * Copyright (C) 2012, 2013, 2014, 2015 Eric Biggers
+ * Copyright (C) 2012-2016 Eric Biggers
  *
  * 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
@@ -41,6 +41,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <stdlib.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
@@ -259,6 +260,55 @@ read_blobs_from_pipe(struct apply_ctx *ctx, const struct read_blob_callbacks *cb
        return 0;
 }
 
+static int
+handle_pwm_metadata_resource(WIMStruct *pwm, int image, bool is_needed)
+{
+       struct blob_descriptor *blob;
+       struct wim_reshdr reshdr;
+       struct wim_resource_descriptor *rdesc;
+       int ret;
+
+       ret = WIMLIB_ERR_NOMEM;
+       blob = new_blob_descriptor();
+       if (!blob)
+               goto out;
+
+       ret = read_pwm_blob_header(pwm, blob->hash, &reshdr, NULL);
+       if (ret)
+               goto out;
+
+       ret = WIMLIB_ERR_INVALID_PIPABLE_WIM;
+       if (!(reshdr.flags & WIM_RESHDR_FLAG_METADATA)) {
+               ERROR("Expected metadata resource, but found non-metadata "
+                     "resource");
+               goto out;
+       }
+
+       ret = WIMLIB_ERR_NOMEM;
+       rdesc = MALLOC(sizeof(*rdesc));
+       if (!rdesc)
+               goto out;
+
+       wim_reshdr_to_desc_and_blob(&reshdr, pwm, rdesc, blob);
+       pwm->refcnt++;
+
+       ret = WIMLIB_ERR_NOMEM;
+       pwm->image_metadata[image - 1] = new_unloaded_image_metadata(blob);
+       if (!pwm->image_metadata[image - 1])
+               goto out;
+       blob = NULL;
+
+       /* If the metadata resource is for the image being extracted, then parse
+        * it and save the metadata in memory.  Otherwise, skip over it.  */
+       if (is_needed)
+               ret = select_wim_image(pwm, image);
+       else
+               ret = skip_wim_resource(rdesc);
+out:
+       free_blob_descriptor(blob);
+       return ret;
+}
+
 /* Creates a temporary file opened for writing.  The open file descriptor is
  * returned in @fd_ret and its name is returned in @name_ret (dynamically
  * allocated).  */
@@ -266,27 +316,33 @@ static int
 create_temporary_file(struct filedes *fd_ret, tchar **name_ret)
 {
        tchar *name;
-       int open_flags;
        int raw_fd;
 
+#ifdef __WIN32__
 retry:
-       name = ttempnam(NULL, T("wimlib"));
+       name = _wtempnam(NULL, L"wimlib");
        if (!name) {
                ERROR_WITH_ERRNO("Failed to create temporary filename");
                return WIMLIB_ERR_NOMEM;
        }
-
-       open_flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY;
-#ifdef __WIN32__
-       open_flags |= _O_SHORT_LIVED;
-#endif
-       raw_fd = topen(name, open_flags, 0600);
+       raw_fd = _wopen(name, O_WRONLY | O_CREAT | O_EXCL | O_BINARY |
+                       _O_SHORT_LIVED, 0600);
+       if (raw_fd < 0 && errno == EEXIST) {
+               FREE(name);
+               goto retry;
+       }
+#else /* __WIN32__ */
+       const char *tmpdir = getenv("TMPDIR");
+       if (!tmpdir)
+               tmpdir = P_tmpdir;
+       name = MALLOC(strlen(tmpdir) + 1 + 6 + 6 + 1);
+       if (!name)
+               return WIMLIB_ERR_NOMEM;
+       sprintf(name, "%s/wimlibXXXXXX", tmpdir);
+       raw_fd = mkstemp(name);
+#endif /* !__WIN32__ */
 
        if (raw_fd < 0) {
-               if (errno == EEXIST) {
-                       FREE(name);
-                       goto retry;
-               }
                ERROR_WITH_ERRNO("Failed to create temporary file "
                                 "\"%"TS"\"", name);
                FREE(name);
@@ -1073,12 +1129,14 @@ static void
 inode_tally_features(const struct wim_inode *inode,
                     struct wim_features *features)
 {
-       if (inode->i_attributes & FILE_ATTRIBUTE_ARCHIVE)
-               features->archive_files++;
+       if (inode->i_attributes & FILE_ATTRIBUTE_READONLY)
+               features->readonly_files++;
        if (inode->i_attributes & FILE_ATTRIBUTE_HIDDEN)
                features->hidden_files++;
        if (inode->i_attributes & FILE_ATTRIBUTE_SYSTEM)
                features->system_files++;
+       if (inode->i_attributes & FILE_ATTRIBUTE_ARCHIVE)
+               features->archive_files++;
        if (inode->i_attributes & FILE_ATTRIBUTE_COMPRESSED)
                features->compressed_files++;
        if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
@@ -1156,9 +1214,11 @@ do_feature_check(const struct wim_features *required_features,
 
        /* File attributes.  */
        if (!(extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES)) {
-               /* Note: Don't bother the user about FILE_ATTRIBUTE_ARCHIVE.
-                * We're an archive program, so theoretically we can do what we
-                * want with it.  */
+
+               if (required_features->readonly_files &&
+                   !supported_features->readonly_files)
+                       WARNING("Ignoring FILE_ATTRIBUTE_READONLY of %lu files",
+                               required_features->readonly_files);
 
                if (required_features->hidden_files &&
                    !supported_features->hidden_files)
@@ -1170,6 +1230,10 @@ do_feature_check(const struct wim_features *required_features,
                        WARNING("Ignoring FILE_ATTRIBUTE_SYSTEM of %lu files",
                                required_features->system_files);
 
+               /* Note: Don't bother the user about FILE_ATTRIBUTE_ARCHIVE.
+                * We're an archive program, so theoretically we can do what we
+                * want with it.  */
+
                if (required_features->compressed_files &&
                    !supported_features->compressed_files)
                        WARNING("Ignoring FILE_ATTRIBUTE_COMPRESSED of %lu files",
@@ -1898,52 +1962,9 @@ wimlib_extract_image_from_pipe_with_progress(int pipe_fd,
 
        /* Load the needed metadata resource.  */
        for (i = 1; i <= pwm->hdr.image_count; i++) {
-               struct wim_image_metadata *imd;
-               struct wim_reshdr reshdr;
-               struct wim_resource_descriptor *metadata_rdesc;
-
-               imd = pwm->image_metadata[i - 1];
-
-               ret = WIMLIB_ERR_NOMEM;
-               imd->metadata_blob = new_blob_descriptor();
-               if (!imd->metadata_blob)
-                       goto out_wimlib_free;
-
-               imd->metadata_blob->is_metadata = 1;
-
-               ret = read_pwm_blob_header(pwm, imd->metadata_blob->hash,
-                                          &reshdr, NULL);
+               ret = handle_pwm_metadata_resource(pwm, i, i == image);
                if (ret)
                        goto out_wimlib_free;
-
-               if (!(reshdr.flags & WIM_RESHDR_FLAG_METADATA)) {
-                       ERROR("Expected metadata resource, but found "
-                             "non-metadata resource");
-                       ret = WIMLIB_ERR_INVALID_PIPABLE_WIM;
-                       goto out_wimlib_free;
-               }
-
-               ret = WIMLIB_ERR_NOMEM;
-               metadata_rdesc = MALLOC(sizeof(struct wim_resource_descriptor));
-               if (!metadata_rdesc)
-                       goto out_wimlib_free;
-               wim_reshdr_to_desc_and_blob(&reshdr, pwm, metadata_rdesc,
-                                           imd->metadata_blob);
-
-               if (i == image) {
-                       /* Metadata resource is for the image being extracted.
-                        * Parse it and save the metadata in memory.  */
-                       ret = read_metadata_resource(imd);
-                       if (ret)
-                               goto out_wimlib_free;
-                       imd->modified = 1;
-               } else {
-                       /* Metadata resource is not for the image being
-                        * extracted.  Skip over it.  */
-                       ret = skip_wim_resource(metadata_rdesc);
-                       if (ret)
-                               goto out_wimlib_free;
-               }
        }
        /* Extract the image.  */
        extract_flags |= WIMLIB_EXTRACT_FLAG_FROM_PIPE;