- struct lookup_table *lookup_table;
- int link_type;
- bool is_multi_image_extraction;
- struct lookup_table_entry *lte;
- int ret;
- int out_fd;
- const struct resource_entry *res_entry;
-
- lookup_table = w->lookup_table;
- link_type = w->link_type;
- is_multi_image_extraction = w->is_multi_image_extraction;
- lte = lookup_resource(lookup_table, dentry->hash);
-
- /* If we already extracted the same file or a hard link copy of it, we
- * may be able to simply create a link. The exact action is specified
- * by the current @link_type. */
- if (link_type != WIM_LINK_TYPE_NONE && lte && lte->out_refcnt != 0) {
- wimlib_assert(lte->file_on_disk);
-
- if (link_type == WIM_LINK_TYPE_HARD) {
- if (link(lte->file_on_disk, output_path) != 0) {
- ERROR("Failed to hard link `%s' to `%s': %m\n",
- output_path, lte->file_on_disk);
- return WIMLIB_ERR_LINK;
- }
- } else {
- int num_path_components;
- int num_output_dir_path_components;
- size_t file_on_disk_len;
- char *p;
- const char *p2;
- size_t i;
-
- num_path_components =
- get_num_path_components(dentry->full_path_utf8) - 1;
- num_output_dir_path_components =
- get_num_path_components(w->output_dir);
-
- if (is_multi_image_extraction) {
- num_path_components++;
- num_output_dir_path_components--;
- }
- file_on_disk_len = strlen(lte->file_on_disk);
+ /* 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) */
+ wimlib_assert(lte->extracted_file);
+
+ if (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;
+ }
+ } else {
+ int num_path_components;
+ int num_output_dir_path_components;
+ size_t extracted_file_len;
+ char *p;
+ const char *p2;
+ size_t i;
+
+ wimlib_assert(extract_flags & WIMLIB_EXTRACT_FLAG_SYMLINK);
+
+ num_path_components =
+ get_num_path_components(dentry->full_path_utf8) - 1;
+ num_output_dir_path_components =
+ get_num_path_components(output_dir);
+
+ if (extract_flags & WIMLIB_EXTRACT_FLAG_MULTI_IMAGE) {
+ num_path_components++;
+ num_output_dir_path_components--;
+ }
+ extracted_file_len = strlen(lte->extracted_file);
+
+ char buf[extracted_file_len + 3 * num_path_components + 1];
+ p = &buf[0];
+
+ for (i = 0; i < num_path_components; i++) {
+ *p++ = '.';
+ *p++ = '.';
+ *p++ = '/';
+ }
+ p2 = lte->extracted_file;
+ while (*p2 == '/')
+ p2++;
+ while (num_output_dir_path_components--)
+ p2 = path_next_part(p2, NULL);
+ strcpy(p, p2);
+ if (symlink(buf, output_path) != 0) {
+ ERROR_WITH_ERRNO("Failed to symlink `%s' to "
+ "`%s'",
+ buf, lte->extracted_file);
+ return WIMLIB_ERR_LINK;
+ }