return 0;
}
-#define MAX_OPEN_ATTRS 1024
-
struct ntfs_3g_apply_ctx {
/* Extract flags, the pointer to the WIMStruct, etc. */
struct apply_ctx common;
/* Pointer to the open NTFS volume */
ntfs_volume *vol;
- ntfs_attr *open_attrs[MAX_OPEN_ATTRS];
+ ntfs_attr *open_attrs[MAX_OPEN_STREAMS];
unsigned num_open_attrs;
- ntfs_inode *open_inodes[MAX_OPEN_ATTRS];
+ ntfs_inode *open_inodes[MAX_OPEN_STREAMS];
unsigned num_open_inodes;
struct reparse_buffer_disk rpbuf;
u64 offset;
unsigned num_reparse_inodes;
- ntfs_inode *ntfs_reparse_inodes[MAX_OPEN_ATTRS];
- struct wim_inode *wim_reparse_inodes[MAX_OPEN_ATTRS];
+ ntfs_inode *ntfs_reparse_inodes[MAX_OPEN_STREAMS];
+ struct wim_inode *wim_reparse_inodes[MAX_OPEN_STREAMS];
};
static size_t
goto out_close;
if (!dir_ni)
- dir_ni = ntfs_inode_open(vol, dentry->parent->d_inode->i_mft_no);
+ dir_ni = ntfs_inode_open(vol, dentry->d_parent->d_inode->i_mft_no);
if (!ni)
ni = ntfs_inode_open(vol, dentry->d_inode->i_mft_no);
if (dir_ni && ni) {
/* Unlike most other NTFS-3g functions, ntfs_set_ntfs_dos_name()
* changes the directory's last modification timestamp...
* Change it back. */
- return ntfs_3g_restore_timestamps(vol, dentry->parent->d_inode);
+ return ntfs_3g_restore_timestamps(vol, dentry->d_parent->d_inode);
out_close:
/* ntfs_inode_close() can take a NULL argument, but it's probably best
ERROR_WITH_ERRNO("Failed to set security descriptor "
"on \"%s\" in NTFS volume",
dentry_full_path(one_dentry));
- fprintf(stderr, "The security descriptor is: ");
- print_byte_field(desc, desc_size, stderr);
- fprintf(stderr, "\n");
+ fprintf(wimlib_error_file,
+ "The security descriptor is: ");
+ print_byte_field(desc, desc_size, wimlib_error_file);
+ fprintf(wimlib_error_file, "\n");
}
return ret;
}
* the NTFS inode @dir_ni. */
static int
ntfs_3g_create_dirs_recursive(ntfs_inode *dir_ni, struct wim_dentry *dir,
- const struct ntfs_3g_apply_ctx *ctx)
+ struct ntfs_3g_apply_ctx *ctx)
{
struct wim_dentry *child;
child->d_inode->i_mft_no = ni->mft_no;
- ret = ntfs_3g_set_metadata(ni, child->d_inode, ctx);
+ ret = report_file_created(&ctx->common);
+ if (!ret)
+ ret = ntfs_3g_set_metadata(ni, child->d_inode, ctx);
if (!ret)
ret = ntfs_3g_create_any_empty_ads(ni, child->d_inode, ctx);
if (!ret)
static int
ntfs_3g_create_directories(struct wim_dentry *root,
struct list_head *dentry_list,
- const struct ntfs_3g_apply_ctx *ctx)
+ struct ntfs_3g_apply_ctx *ctx)
{
ntfs_inode *root_ni;
int ret;
ret = ntfs_3g_restore_dos_name(NULL, NULL, dentry, ctx->vol);
if (ret)
return ret;
+ ret = report_file_created(&ctx->common);
+ if (ret)
+ return ret;
}
return 0;
}
int res;
/* Open the inode of the parent directory. */
- dir_ni = ntfs_inode_open(ni->vol, dentry->parent->d_inode->i_mft_no);
+ dir_ni = ntfs_inode_open(ni->vol, dentry->d_parent->d_inode->i_mft_no);
if (!dir_ni)
goto fail;
/* Create first link. */
- dir_ni = ntfs_inode_open(ctx->vol, first_dentry->parent->d_inode->i_mft_no);
+ dir_ni = ntfs_inode_open(ctx->vol, first_dentry->d_parent->d_inode->i_mft_no);
if (!dir_ni) {
ERROR_WITH_ERRNO("Can't open \"%s\" in NTFS volume",
- dentry_full_path(first_dentry->parent));
+ dentry_full_path(first_dentry->d_parent));
return WIMLIB_ERR_NTFS_3G;
}
/* Close the directory in which the first link was created. */
if (ntfs_inode_close(dir_ni)) {
ERROR_WITH_ERRNO("Failed to close \"%s\" in NTFS volume",
- dentry_full_path(first_dentry->parent));
+ dentry_full_path(first_dentry->d_parent));
ret = WIMLIB_ERR_NTFS_3G;
goto out_close_ni;
}
/* Create additional links if present. */
next = inode->i_extraction_aliases.next;
- ret = 0;
do {
dentry = list_entry(next, struct wim_dentry,
d_extraction_alias_node);
* Directories must have already been created. */
static int
ntfs_3g_create_nondirectories(struct list_head *dentry_list,
- const struct ntfs_3g_apply_ctx *ctx)
+ struct ntfs_3g_apply_ctx *ctx)
{
struct wim_dentry *dentry;
struct wim_inode *inode;
inode = dentry->d_inode;
if (inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
- if (dentry != inode_first_extraction_dentry(inode))
- continue;
- ret = ntfs_3g_create_nondirectory(inode, ctx);
+ if (dentry == inode_first_extraction_dentry(inode)) {
+ ret = ntfs_3g_create_nondirectory(inode, ctx);
+ if (ret)
+ return ret;
+ }
+ ret = report_file_created(&ctx->common);
if (ret)
return ret;
}
return WIMLIB_ERR_NTFS_3G;
}
+ /* This should be ensured by extract_stream_list() */
+ wimlib_assert(ctx->num_open_attrs < MAX_OPEN_STREAMS);
+
attr = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_nchars);
if (!attr) {
ERROR_WITH_ERRNO("Failed to open data stream of \"%s\"",
}
static int
-ntfs_3g_begin_extract_stream(struct wim_lookup_table_entry *stream,
- u32 flags, void *_ctx)
+ntfs_3g_begin_extract_stream(struct wim_lookup_table_entry *stream, void *_ctx)
{
struct ntfs_3g_apply_ctx *ctx = _ctx;
const struct stream_owner *owners = stream_owners(stream);
return ret;
}
+static uint64_t
+ntfs_3g_count_dentries(const struct list_head *dentry_list)
+{
+ const struct wim_dentry *dentry;
+ uint64_t count = 0;
+
+ list_for_each_entry(dentry, dentry_list, d_extraction_list_node) {
+ count++;
+ if ((dentry->d_inode->i_attributes & FILE_ATTRIBUTE_DIRECTORY) &&
+ dentry_has_short_name(dentry))
+ {
+ count++;
+ }
+
+ }
+
+ return count;
+}
+
static int
ntfs_3g_extract(struct list_head *dentry_list, struct apply_ctx *_ctx)
{
/* Create all inodes and aliases, including short names, and set
* metadata (attributes, security descriptors, and timestamps). */
+ ret = start_file_structure_phase(&ctx->common,
+ ntfs_3g_count_dentries(dentry_list));
+ if (ret)
+ goto out_unmount;
+
ret = ntfs_3g_create_directories(root, dentry_list, ctx);
if (ret)
goto out_unmount;
if (ret)
goto out_unmount;
+ ret = end_file_structure_phase(&ctx->common);
+ if (ret)
+ goto out_unmount;
+
/* Extract streams. */
struct read_stream_list_callbacks cbs = {
.begin_stream = ntfs_3g_begin_extract_stream,