+ supported_features->hard_links = 1;
+ supported_features->symlink_reparse_points = 1;
+ supported_features->unix_data = 1;
+ supported_features->timestamps = 1;
+ supported_features->case_sensitive_filenames = 1;
+ return 0;
+}
+
+#define NUM_PATHBUFS 2 /* We need 2 when creating hard links */
+
+struct unix_apply_ctx {
+ /* Extract flags, the pointer to the WIMStruct, etc. */
+ struct apply_ctx common;
+
+ /* Buffers for building extraction paths (allocated). */
+ char *pathbufs[NUM_PATHBUFS];
+
+ /* Index of next pathbuf to use */
+ unsigned which_pathbuf;
+
+ /* Currently open file descriptors for extraction */
+ struct filedes open_fds[MAX_OPEN_FILES];
+
+ /* Number of currently open file descriptors in open_fds, starting from
+ * the beginning of the array. */
+ unsigned num_open_fds;
+
+ /* Buffer for reading reparse point data into memory */
+ u8 reparse_data[REPARSE_DATA_MAX_SIZE];
+
+ /* Pointer to the next byte in @reparse_data to fill */
+ u8 *reparse_ptr;
+
+ /* Absolute path to the target directory (allocated buffer). Only set
+ * if needed for absolute symbolic link fixups. */
+ char *target_abspath;
+
+ /* Number of characters in target_abspath. */
+ size_t target_abspath_nchars;
+
+ /* Number of special files we couldn't create due to EPERM */
+ unsigned long num_special_files_ignored;
+};
+
+/* Returns the number of characters needed to represent the path to the
+ * specified @dentry when extracted, not including the null terminator or the
+ * path to the target directory itself. */
+static size_t
+unix_dentry_path_length(const struct wim_dentry *dentry)
+{
+ size_t len = 0;
+ const struct wim_dentry *d;
+
+ d = dentry;
+ do {
+ len += d->d_extraction_name_nchars + 1;
+ d = d->d_parent;
+ } while (!dentry_is_root(d) && will_extract_dentry(d));
+
+ return len;
+}
+
+/* Returns the maximum number of characters needed to represent the path to any
+ * dentry in @dentry_list when extracted, including the null terminator and the
+ * path to the target directory itself. */
+static size_t
+unix_compute_path_max(const struct list_head *dentry_list,
+ const struct unix_apply_ctx *ctx)
+{
+ size_t max = 0;
+ size_t len;
+ const struct wim_dentry *dentry;
+
+ list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
+ len = unix_dentry_path_length(dentry);
+ if (len > max)
+ max = len;