+/*
+ * Makes a NTFS hard link
+ *
+ * It is named @from_dentry->file_name and is located under the directory
+ * specified by @dir_ni, and it is made to point to the previously extracted
+ * file located at @inode->extracted_file.
+ *
+ * Return 0 on success, nonzero on failure.
+ */
+static int apply_hardlink_ntfs(const struct dentry *from_dentry,
+ const struct inode *inode,
+ ntfs_inode *dir_ni,
+ ntfs_inode **to_ni_ret)
+{
+ int ret;
+ char *p;
+ char orig;
+ const char *dir_name;
+
+ ntfs_inode *to_ni;
+ ntfs_volume *vol;
+
+ wimlib_assert(dentry_is_regular_file(from_dentry)
+ && inode_is_regular_file(inode));
+
+ if (ntfs_inode_close(dir_ni) != 0) {
+ ERROR_WITH_ERRNO("Error closing directory");
+ return WIMLIB_ERR_NTFS_3G;
+ }
+
+ vol = dir_ni->vol;
+
+ DEBUG("Extracting NTFS hard link `%s' => `%s'",
+ from_dentry->full_path_utf8, inode->extracted_file);
+
+ to_ni = ntfs_pathname_to_inode(vol, NULL, inode->extracted_file);
+ if (!to_ni) {
+ ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
+ inode->extracted_file);
+ return WIMLIB_ERR_NTFS_3G;
+ }
+ p = from_dentry->full_path_utf8 + from_dentry->full_path_utf8_len;
+ do {
+ p--;
+ } while (*p != '/');
+
+ orig = *p;
+ *p = '\0';
+ dir_name = from_dentry->full_path_utf8;
+
+ dir_ni = ntfs_pathname_to_inode(vol, NULL, dir_name);
+ if (!dir_ni) {
+ ERROR_WITH_ERRNO("Could not find NTFS inode for `%s'",
+ from_dentry->full_path_utf8);
+ *p = orig;
+ return WIMLIB_ERR_NTFS_3G;
+ }
+ *p = orig;
+
+ ret = ntfs_link(to_ni, dir_ni,
+ (ntfschar*)from_dentry->file_name,
+ from_dentry->file_name_len / 2);
+ if (ret != 0) {
+ ERROR_WITH_ERRNO("Could not create hard link `%s' => `%s'",
+ from_dentry->full_path_utf8,
+ inode->extracted_file);
+ ret = WIMLIB_ERR_NTFS_3G;
+ }
+ *to_ni_ret = to_ni;
+ return ret;
+}
+
+static int
+apply_file_attributes_and_security_data(ntfs_inode *ni,
+ ntfs_inode *dir_ni,
+ const struct dentry *dentry,
+ const WIMStruct *w)
+{
+ DEBUG("Setting NTFS file attributes on `%s' to %#"PRIx32,
+ dentry->full_path_utf8, dentry->d_inode->attributes);
+ int ret;
+ struct SECURITY_CONTEXT ctx;
+ u32 attributes_le32;
+ attributes_le32 = cpu_to_le32(dentry->d_inode->attributes);
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.vol = ni->vol;
+ ret = ntfs_xattr_system_setxattr(&ctx, XATTR_NTFS_ATTRIB,
+ ni, dir_ni,
+ (const char*)&attributes_le32,
+ sizeof(u32), 0);
+ if (ret != 0) {
+ ERROR("Failed to set NTFS file attributes on `%s'",
+ dentry->full_path_utf8);
+ return WIMLIB_ERR_NTFS_3G;
+ }
+ if (dentry->d_inode->security_id != -1) {
+ const struct wim_security_data *sd;
+ const char *descriptor;
+
+ sd = wim_const_security_data(w);
+ wimlib_assert(dentry->d_inode->security_id < sd->num_entries);
+ descriptor = (const char *)sd->descriptors[dentry->d_inode->security_id];
+ DEBUG("Applying security descriptor %d to `%s'",
+ dentry->d_inode->security_id, dentry->full_path_utf8);