- /* This mode overrides the normal hard-link extraction and
- * instead either symlinks or hardlinks *all* identical files in
- * the WIM, even if they are in a different image (in the case
- * of a multi-image extraction) */
-
- if (args->extract_flags & WIMLIB_EXTRACT_FLAG_HARDLINK) {
- if (link(lte->extracted_file, output_path) != 0) {
- ERROR_WITH_ERRNO("Failed to hard link "
- "`%s' to `%s'",
- output_path, lte->extracted_file);
- return WIMLIB_ERR_LINK;
+ {
+ struct timespec times[2];
+
+ times[0] = wim_timestamp_to_timespec(atime);
+ times[1] = wim_timestamp_to_timespec(mtime);
+
+ errno = ENOSYS;
+#ifdef HAVE_FUTIMENS
+ if (fd >= 0 && !futimens(fd, times))
+ return 0;
+#endif
+#ifdef HAVE_UTIMENSAT
+ if (fd < 0 && !utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW))
+ return 0;
+#endif
+ if (errno != ENOSYS)
+ return WIMLIB_ERR_SET_TIMESTAMPS;
+ }
+ {
+ struct timeval times[2];
+
+ times[0] = wim_timestamp_to_timeval(atime);
+ times[1] = wim_timestamp_to_timeval(mtime);
+
+ if (fd >= 0 && !futimes(fd, times))
+ return 0;
+ if (fd < 0 && !lutimes(path, times))
+ return 0;
+ return WIMLIB_ERR_SET_TIMESTAMPS;
+ }
+}
+
+static int
+unix_set_owner_and_group(int fd, const char *path, uid_t uid, gid_t gid)
+{
+ if (fd >= 0 && !fchown(fd, uid, gid))
+ return 0;
+ if (fd < 0 && !lchown(path, uid, gid))
+ return 0;
+ return WIMLIB_ERR_SET_SECURITY;
+}
+
+static int
+unix_set_mode(int fd, const char *path, mode_t mode)
+{
+ if (fd >= 0 && !fchmod(fd, mode))
+ return 0;
+ if (fd < 0 && !chmod(path, mode))
+ return 0;
+ return WIMLIB_ERR_SET_SECURITY;
+}
+
+#ifdef HAVE_LINUX_XATTR_SUPPORT
+/* Apply extended attributes to a file */
+static int
+apply_linux_xattrs(int fd, const struct wim_inode *inode,
+ const char *path, struct unix_apply_ctx *ctx,
+ const void *entries, size_t entries_size, bool is_old_format)
+{
+ const void * const entries_end = entries + entries_size;
+ char name[WIM_XATTR_NAME_MAX + 1];
+
+ for (const void *entry = entries;
+ entry < entries_end;
+ entry = is_old_format ? (const void *)old_xattr_entry_next(entry) :
+ (const void *)xattr_entry_next(entry))
+ {
+ bool valid;
+ u16 name_len;
+ const void *value;
+ u32 value_len;
+ int res;
+
+ if (is_old_format) {
+ valid = old_valid_xattr_entry(entry,
+ entries_end - entry);
+ } else {
+ valid = valid_xattr_entry(entry, entries_end - entry);