*/
/*
- * 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
* wimlib_extract_pathlist(). Internally, all end up calling
* do_wimlib_extract_paths() and extract_trees().
*
- * Although wimlib supports multiple extraction modes/backends (NTFS-3g, UNIX,
+ * Although wimlib supports multiple extraction modes/backends (NTFS-3G, UNIX,
* Win32), this file does not itself have code to extract files or directories
* to any specific target; instead, it handles generic functionality and relies
* on lower-level callback functions declared in `struct apply_operations' to do
#include <errno.h>
#include <fcntl.h>
+#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include "wimlib/endianness.h"
#include "wimlib/error.h"
#include "wimlib/metadata.h"
+#include "wimlib/object_id.h"
#include "wimlib/pathlist.h"
#include "wimlib/paths.h"
#include "wimlib/pattern.h"
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). */
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);
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) {
features->security_descriptors++;
if (inode_has_unix_data(inode))
features->unix_data++;
+ if (inode_has_object_id(inode))
+ features->object_ids++;
}
/* Tally features necessary to extract a dentry and the corresponding inode. */
/* 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)
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",
required_features->unix_data);
}
+ /* Object IDs. */
+ if (required_features->object_ids && !supported_features->object_ids) {
+ WARNING("Ignoring object IDs of %lu files",
+ required_features->object_ids);
+ }
+
/* DOS Names. */
if (required_features->short_names &&
!supported_features->short_names)
#ifndef WITH_NTFS_3G
if (extract_flags & WIMLIB_EXTRACT_FLAG_NTFS) {
- ERROR("wimlib was compiled without support for NTFS-3g, so\n"
+ ERROR("wimlib was compiled without support for NTFS-3G, so\n"
" it cannot apply a WIM image directly to an NTFS volume.");
return WIMLIB_ERR_UNSUPPORTED;
}
/* 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;
- } 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;