- /* The root of the dentry tree being extracted may not be extracted to
- * its original name, so its short name should be ignored. */
- if (dentry == ctx->target_dentry)
- return 0;
-
- if (ctx->supported_features.short_names) {
- ret = ctx->ops->set_short_name(path,
- dentry->short_name,
- dentry->short_name_nbytes / 2,
- ctx);
- if (ret && (ctx->extract_flags &
- WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES))
- {
- ERROR_WITH_ERRNO("Failed to set short name of "
- "\"%"TS"\"", path);
- return ret;
- }
- }
- return 0;
-}
-
-/* Set security descriptor, UNIX data, or neither on an extracted file, taking
- * into account the current extraction mode and flags. */
-static int
-extract_security(const tchar *path, struct apply_ctx *ctx,
- struct wim_dentry *dentry)
-{
- int ret;
- struct wim_inode *inode = dentry->d_inode;
-
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_NO_ACLS)
- return 0;
-
- if ((ctx->target_dentry == dentry) && ctx->root_dentry_is_special)
- return 0;
-
-#ifndef __WIN32__
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_UNIX_DATA) {
- struct wimlib_unix_data data;
-
- ret = inode_get_unix_data(inode, &data, NULL);
- if (ret < 0)
- ret = 0;
- else if (ret == 0)
- ret = ctx->ops->set_unix_data(path, &data, ctx);
- if (ret) {
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS) {
- ERROR_WITH_ERRNO("Failed to set UNIX owner, "
- "group, and/or mode on "
- "\"%"TS"\"", path);
- return ret;
- } else {
- WARNING_WITH_ERRNO("Failed to set UNIX owner, "
- "group, and/or/mode on "
- "\"%"TS"\"", path);
- }
- }
- }
- else
-#endif /* __WIN32__ */
- if (ctx->supported_features.security_descriptors &&
- inode->i_security_id != -1)
- {
- const struct wim_security_data *sd;
- const u8 *desc;
- size_t desc_size;
-
- sd = wim_const_security_data(ctx->wim);
- desc = sd->descriptors[inode->i_security_id];
- desc_size = sd->sizes[inode->i_security_id];
-
- ret = ctx->ops->set_security_descriptor(path, desc,
- desc_size, ctx);
- if (ret) {
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS) {
- ERROR_WITH_ERRNO("Failed to set security "
- "descriptor on \"%"TS"\"", path);
- return ret;
- } else {
- #if 0
- if (errno != EACCES) {
- WARNING_WITH_ERRNO("Failed to set "
- "security descriptor "
- "on \"%"TS"\"", path);
- }
- #endif
- ctx->no_security_descriptors++;
- }
- }
- }
- return 0;
-}
-
-/* Set timestamps on an extracted file. Failure is warning-only unless
- * WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS is set. */
-static int
-extract_timestamps(const tchar *path, struct apply_ctx *ctx,
- struct wim_dentry *dentry)
-{
- struct wim_inode *inode = dentry->d_inode;
- int ret;
-
- if ((ctx->target_dentry == dentry) && ctx->root_dentry_is_special)
- return 0;
-
- if (ctx->ops->set_timestamps) {
- ret = ctx->ops->set_timestamps(path,
- inode->i_creation_time,
- inode->i_last_write_time,
- inode->i_last_access_time,
- ctx);
- if (ret) {
- if (ctx->extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_TIMESTAMPS) {
- ERROR_WITH_ERRNO("Failed to set timestamps "
- "on \"%"TS"\"", path);
- return ret;
- } else {
- WARNING_WITH_ERRNO("Failed to set timestamps "
- "on \"%"TS"\"", path);
- }
- }
- }
- return 0;
-}
-
-/* Check whether the extraction of a dentry should be skipped completely. */
-static bool
-dentry_is_supported(struct wim_dentry *dentry,
- const struct wim_features *supported_features)
-{
- struct wim_inode *inode = dentry->d_inode;
-
- if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
- return supported_features->reparse_points ||
- (inode_is_symlink(inode) &&
- supported_features->symlink_reparse_points);
- }
- if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
- if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
- return supported_features->encrypted_directories != 0;
- else
- return supported_features->encrypted_files != 0;
- }
- return true;
-}
-
-/* Given a WIM dentry to extract, build the path to which to extract it, in the
- * format understood by the callbacks in the apply_operations being used.
- *
- * Write the resulting path into @path, which must have room for at least
- * ctx->ops->path_max characters.
- *
- * Return %true if successful; %false if this WIM dentry doesn't actually need
- * to be extracted or if the calculated path exceeds ctx->ops->max_path
- * characters.
- *
- * This function clobbers the tmp_list member of @dentry and its ancestors up
- * until the extraction root. */
-static bool
-build_extraction_path(tchar path[], struct wim_dentry *dentry,
- const struct apply_ctx *ctx)
-{
- size_t path_nchars;
- LIST_HEAD(ancestor_list);
- tchar *p = path;
- const tchar *target_prefix;
- size_t target_prefix_nchars;
- struct wim_dentry *d;
-
- path_nchars = ctx->ops->path_prefix_nchars;
-
- if (ctx->ops->requires_realtarget_in_paths) {
- target_prefix = ctx->realtarget;
- target_prefix_nchars = ctx->realtarget_nchars;
- } else if (ctx->ops->requires_target_in_paths) {
- target_prefix = ctx->target;
- target_prefix_nchars = ctx->target_nchars;
- } else {
- target_prefix = NULL;
- target_prefix_nchars = 0;
- }
- path_nchars += target_prefix_nchars;