- if (fchown(fd, unix_data->uid, unix_data->gid)) {
- if (errno == EPERM &&
- !(extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS))
- {
- WARNING_WITH_ERRNO("failed to set file UNIX "
- "owner/group on \"%s\"", path);
- } else {
- ERROR_WITH_ERRNO("failed to set file UNIX "
- "owner/group on \"%s\"", path);
- return (errno == EPERM) ? WIMLIB_ERR_INSUFFICIENT_PRIVILEGES_TO_EXTRACT :
- WIMLIB_ERR_WRITE;
+/*
+ * Set metadata on an extracted file.
+ *
+ * @fd is an open file descriptor to the extracted file, or -1. @path is the
+ * path to the extracted file, or NULL. If valid, this function uses @fd.
+ * Otherwise, if valid, it uses @path. Otherwise, it calculates the path to one
+ * alias of the extracted file and uses it.
+ */
+static int
+unix_set_metadata(int fd, const struct wim_inode *inode,
+ const char *path, struct unix_apply_ctx *ctx)
+{
+ int ret;
+ struct wimlib_unix_data unix_data;
+
+ if (fd < 0 && !path)
+ path = unix_build_inode_extraction_path(inode, ctx);
+
+ if ((ctx->common.extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA)
+ && inode_get_unix_data(inode, &unix_data))
+ {
+ u32 uid = unix_data.uid;
+ u32 gid = unix_data.gid;
+ u32 mode = unix_data.mode;
+
+ ret = unix_set_owner_and_group(fd, path, uid, gid);
+ if (ret) {
+ if (!path)
+ path = unix_build_inode_extraction_path(inode, ctx);
+ if (ctx->common.extract_flags &
+ WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
+ {
+ ERROR_WITH_ERRNO("Can't set uid=%"PRIu32" and "
+ "gid=%"PRIu32" on \"%s\"",
+ uid, gid, path);
+ return ret;
+ } else {
+ WARNING_WITH_ERRNO("Can't set uid=%"PRIu32" and "
+ "gid=%"PRIu32" on \"%s\"",
+ uid, gid, path);
+ }
+ }
+
+ ret = 0;
+ if (!inode_is_symlink(inode))
+ ret = unix_set_mode(fd, path, mode);
+ if (ret) {
+ if (!path)
+ path = unix_build_inode_extraction_path(inode, ctx);
+ if (ctx->common.extract_flags &
+ WIMLIB_EXTRACT_FLAG_STRICT_ACLS)
+ {
+ ERROR_WITH_ERRNO("Can't set mode=0%"PRIo32" "
+ "on \"%s\"", mode, path);
+ return ret;
+ } else {
+ WARNING_WITH_ERRNO("Can't set mode=0%"PRIo32" "
+ "on \"%s\"", mode, path);
+ }