-#ifdef ENABLE_DEBUG
- if (lte_spec) {
- char sha1_str[100];
- char *p = sha1_str;
- for (unsigned i = 0; i < SHA1_HASH_SIZE; i++)
- p += sprintf(p, "%02x", lte_override->hash[i]);
- DEBUG("Extracting stream SHA1=%s to \"%"TS"\"",
- sha1_str, path, inode->i_ino);
- } else {
- DEBUG("Extracting streams to \"%"TS"\"", path, inode->i_ino);
- }
-#endif
-
- if (ctx->ops->uses_cookies)
- file_spec.cookie = inode->extract_cookie;
- else
- file_spec.path = path;
-
- /* Unnamed data stream. */
- lte = inode_unnamed_lte_resolved(inode);
- if (lte && (!lte_spec || lte == lte_spec)) {
- if (lte_spec)
- lte = lte_override;
- if (!(inode->i_attributes & (FILE_ATTRIBUTE_DIRECTORY |
- FILE_ATTRIBUTE_REPARSE_POINT)))
- {
- if (inode->i_attributes & FILE_ATTRIBUTE_ENCRYPTED &&
- ctx->supported_features.encrypted_files) {
- if (!ctx->ops->extract_encrypted_stream_creates_file) {
- ret = ctx->ops->extract_encrypted_stream(
- path, lte, ctx);
- if (ret)
- goto error;
- }
- } else {
- ret = ctx->ops->extract_unnamed_stream(
- file_spec, lte, ctx);
- if (ret)
- goto error;
- }
- update_extract_progress(ctx, lte);
- }
- else if (inode->i_attributes & FILE_ATTRIBUTE_REPARSE_POINT)
- {
- ret = 0;
- if (ctx->supported_features.reparse_points)
- ret = extract_reparse_data(path, ctx, inode, lte);
- #ifndef __WIN32__
- else if ((inode_is_symlink(inode) &&
- ctx->supported_features.symlink_reparse_points))
- ret = extract_symlink(path, ctx, inode, lte);
- #endif
- if (ret)
- return ret;
- }
- }
-
- /* Named data streams. */
- if (can_extract_named_data_streams(ctx)) {
- for (u16 i = 0; i < inode->i_num_ads; i++) {
- struct wim_ads_entry *entry = &inode->i_ads_entries[i];
-
- if (!ads_entry_is_named_stream(entry))
- continue;
- lte = entry->lte;
- if (!lte)
- continue;
- if (lte_spec && lte_spec != lte)
- continue;
- if (lte_spec)
- lte = lte_override;
- ret = ctx->ops->extract_named_stream(file_spec, entry->stream_name,
- entry->stream_name_nbytes / 2,
- lte, ctx);
- if (ret)
- goto error;
- update_extract_progress(ctx, lte);
- }
- }
- return 0;
-
-error:
- ERROR_WITH_ERRNO("Failed to extract data of \"%"TS"\"", path);
- return ret;
-}
-
-/* Set attributes on an extracted file or directory if supported by the
- * extraction mode. */
-static int
-extract_file_attributes(const tchar *path, struct apply_ctx *ctx,
- struct wim_dentry *dentry, unsigned pass)
-{
- int ret;
-
- if (ctx->ops->set_file_attributes &&
- !(ctx->extract_flags & WIMLIB_EXTRACT_FLAG_NO_ATTRIBUTES) &&
- !(dentry == ctx->target_dentry && ctx->root_dentry_is_special)) {
- u32 attributes = dentry->d_inode->i_attributes;
-
- /* Clear unsupported attributes. */
- attributes &= ctx->supported_attributes_mask;
-
- if ((attributes & FILE_ATTRIBUTE_DIRECTORY &&
- !ctx->supported_features.encrypted_directories) ||
- (!(attributes & FILE_ATTRIBUTE_DIRECTORY) &&
- !ctx->supported_features.encrypted_files))
- {
- attributes &= ~FILE_ATTRIBUTE_ENCRYPTED;
- }
-
- if (attributes == 0)
- attributes = FILE_ATTRIBUTE_NORMAL;
-
- ret = ctx->ops->set_file_attributes(path, attributes, ctx, pass);
- if (ret) {
- ERROR_WITH_ERRNO("Failed to set attributes on "
- "\"%"TS"\"", path);
- return ret;
- }
- }
- return 0;
-}
-
-
-/* Set or remove the short (DOS) name on an extracted file or directory if
- * supported by the extraction mode. Since DOS names are unimportant and it's
- * easy to run into problems setting them on Windows (SetFileShortName()
- * requires SE_RESTORE privilege, which only the Administrator can request, and
- * also requires DELETE access to the file), failure is ignored unless
- * WIMLIB_EXTRACT_FLAG_STRICT_SHORT_NAMES is set. */
-static int
-extract_short_name(const tchar *path, struct apply_ctx *ctx,
- struct wim_dentry *dentry)
-{
- int ret;
-
- /* 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.