#define MAX_GET_SD_ACCESS_DENIED_WARNINGS 1
#define MAX_GET_SACL_PRIV_NOTHELD_WARNINGS 1
+#define MAX_CREATE_HARD_LINK_WARNINGS 5
struct win32_capture_state {
unsigned long num_get_sd_access_denied;
unsigned long num_get_sacl_priv_notheld;
/* Load a reparse point into a WIM inode. It is just stored in memory.
*
- * @hFile: Open handle to a reparse point, with permission to read the reparse
- * data.
+ * @hFile is the open handle to a reparse point, with permission to read the
+ * reparse data.
*
- * @inode: WIM inode for the reparse point.
- *
- * @lookup_table: Stream lookup table for the WIM; an entry will be added to it
- * for the reparse point unless an entry already exists for
- * the exact same data stream.
- *
- * @path: External path to the reparse point. Used for error messages only.
- *
- * Returns 0 on success; nonzero on failure. */
+ * @inode is the WIM inode for the reparse point.
+ */
static int
win32_capture_reparse_point(struct wim_dentry **root_p,
HANDLE hFile,
inode->i_not_rpfixed = 0;
}
}
- return inode_add_ads_with_data(inode, L"", reparse_point_buf + 8,
- bytesReturned - 8, params->lookup_table);
+ return inode_set_unnamed_stream(inode, reparse_point_buf + 8,
+ bytesReturned - 8, params->lookup_table);
}
/* Scans an unnamed or named stream of a Win32 file (not a reparse point
}
}
+ /* If zero length stream, no lookup table entry needed. */
+ if ((u64)dat->StreamSize.QuadPart == 0) {
+ ret = 0;
+ goto out;
+ }
+
/* Create a UTF-16LE string @spath that gives the filename, then a
* colon, then the stream name. Or, if it's an unnamed stream, just the
* filename. It is MALLOC()'ed so that it can be saved in the
vol_flags);
if (ret)
goto out;
- if (unnamed_lte)
+ if (unnamed_lte && inode->i_extracted_file == NULL)
*completed_bytes_p += wim_resource_size(unnamed_lte);
if (!(vol_flags & FILE_NAMED_STREAMS))
vol_flags);
if (ret)
break;
- if (ads_entry->lte)
+ if (ads_entry->lte && inode->i_extracted_file == NULL)
*completed_bytes_p += wim_resource_size(ads_entry->lte);
}
}
win32_error(err);
return WIMLIB_ERR_LINK;
} else {
- WARNING("Can't create hard link \"%ls => %ls\":\n"
- " Volume does not support hard links!\n"
- " Falling back to extracting a copy of the file.");
+ args->num_hard_links_failed++;
+ if (args->num_hard_links_failed < MAX_CREATE_HARD_LINK_WARNINGS) {
+ WARNING("Can't create hard link \"%ls => %ls\":\n"
+ " Volume does not support hard links!\n"
+ " Falling back to extracting a copy of the file.",
+ output_path, inode->i_extracted_file);
+ } else if (args->num_hard_links_failed == MAX_CREATE_HARD_LINK_WARNINGS) {
+ WARNING("Suppressing further hard linking warnings...");
+ }
}
}
+
+ if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT &&
+ !(args->vol_flags & FILE_SUPPORTS_REPARSE_POINTS))
+ {
+ WARNING("Skipping extraction of reparse point \"%ls\":\n"
+ " Not supported by destination filesystem",
+ output_path);
+ struct wim_lookup_table_entry *lte;
+ lte = inode_unnamed_lte_resolved(inode);
+ if (lte)
+ args->progress.extract.completed_bytes += wim_resource_size(lte);
+ return 0;
+ }
+
/* Create the file, directory, or reparse point, and extract the
* data streams. */
ret = win32_extract_streams(inode, output_path,
HANDLE h;
const struct wim_inode *inode = dentry->d_inode;
+ if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT &&
+ !(args->vol_flags & FILE_SUPPORTS_REPARSE_POINTS))
+ {
+ /* Skip reparse points not extracted */
+ return 0;
+ }
+
+ /* Windows doesn't let you change the timestamps of the root directory
+ * (at least on FAT, which is dumb but expected since FAT doesn't store
+ * any metadata about the root directory...) */
+ if (path_is_root_of_drive(path))
+ return 0;
+
DEBUG("Opening \"%ls\" to set timestamps", path);
h = win32_open_existing_file(path, FILE_WRITE_ATTRIBUTES);
if (h == INVALID_HANDLE_VALUE) {