/* Load the streams from a file or reparse point in the NTFS volume into the WIM
* lookup table */
static int
-capture_ntfs_streams(struct wim_dentry *dentry,
+capture_ntfs_streams(struct wim_inode *inode,
ntfs_inode *ni,
- mbchar *path,
+ char *path,
size_t path_len,
struct wim_lookup_table *lookup_table,
ntfs_volume **ntfs_vol_p,
goto out_put_actx;
if (type == AT_REPARSE_POINT)
- dentry->d_inode->i_reparse_tag = reparse_tag;
+ inode->i_reparse_tag = reparse_tag;
/* Make a lookup table entry for the stream, or use an existing
* one if there's already an identical stream. */
if (name_length == 0) {
/* Unnamed data stream. Put the reference to it in the
* dentry's inode. */
- if (dentry->d_inode->i_lte) {
+ if (inode->i_lte) {
WARNING("Found two un-named data streams for "
"`%s'", path);
free_lookup_table_entry(lte);
} else {
- dentry->d_inode->i_lte = lte;
+ inode->i_lte = lte;
}
} else {
/* Named data stream. Put the reference to it in the
* alternate data stream entries */
struct wim_ads_entry *new_ads_entry;
- new_ads_entry = inode_add_ads_utf16le(dentry->d_inode,
+ new_ads_entry = inode_add_ads_utf16le(inode,
attr_record_name(actx->attr),
name_length * 2);
if (!new_ads_entry)
struct readdir_ctx {
struct wim_dentry *parent;
ntfs_inode *dir_ni;
- mbchar *path;
+ char *path;
size_t path_len;
struct wim_lookup_table *lookup_table;
+ struct wim_inode_table *inode_table;
struct sd_set *sd_set;
struct dos_name_map *dos_name_map;
- const struct capture_config *config;
+ const struct wimlib_capture_config *config;
ntfs_volume **ntfs_vol_p;
int add_image_flags;
wimlib_progress_func_t progress_func;
build_dentry_tree_ntfs_recursive(struct wim_dentry **root_p,
ntfs_inode *dir_ni,
ntfs_inode *ni,
- mbchar *path,
+ char *path,
size_t path_len,
int name_type,
struct wim_lookup_table *lookup_table,
+ struct wim_inode_table *inode_table,
struct sd_set *sd_set,
- const struct capture_config *config,
+ const struct wimlib_capture_config *config,
ntfs_volume **ntfs_vol_p,
int add_image_flags,
wimlib_progress_func_t progress_func);
{
struct readdir_ctx *ctx;
size_t mbs_name_nbytes;
- mbchar *mbs_name;
+ char *mbs_name;
struct wim_dentry *child;
int ret;
size_t path_len;
if (ret != 0 || name_type == FILE_NAME_DOS)
goto out;
}
- ret = utf16le_to_mbs(name, name_nbytes,
- &mbs_name, &mbs_name_nbytes);
+ ret = utf16le_to_tstr(name, name_nbytes,
+ &mbs_name, &mbs_name_nbytes);
if (ret)
goto out;
child = NULL;
ret = build_dentry_tree_ntfs_recursive(&child, ctx->dir_ni,
ni, ctx->path, path_len, name_type,
- ctx->lookup_table, ctx->sd_set,
+ ctx->lookup_table,
+ ctx->inode_table,
+ ctx->sd_set,
ctx->config, ctx->ntfs_vol_p,
ctx->add_image_flags,
ctx->progress_func);
* the NTFS streams, and build an array of security descriptors.
*/
static int
-build_dentry_tree_ntfs_recursive(struct wim_dentry **root_p,
+build_dentry_tree_ntfs_recursive(struct wim_dentry **root_ret,
ntfs_inode *dir_ni,
ntfs_inode *ni,
- mbchar *path,
+ char *path,
size_t path_len,
int name_type,
struct wim_lookup_table *lookup_table,
+ struct wim_inode_table *inode_table,
struct sd_set *sd_set,
- const struct capture_config *config,
+ const struct wimlib_capture_config *config,
ntfs_volume **ntfs_vol_p,
int add_image_flags,
wimlib_progress_func_t progress_func)
u32 attributes;
int ret;
struct wim_dentry *root;
+ struct wim_inode *inode;
- if (exclude_path(path, config, false)) {
+ if (exclude_path(path, path_len, config, false)) {
/* Exclude a file or directory tree based on the capture
* configuration file */
- if ((add_image_flags & WIMLIB_ADD_IMAGE_FLAG_VERBOSE)
+ if ((add_image_flags & WIMLIB_ADD_IMAGE_FLAG_EXCLUDE_VERBOSE)
&& progress_func)
{
union wimlib_progress_info info;
info.scan.excluded = true;
progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY, &info);
}
- *root_p = NULL;
- return 0;
+ root = NULL;
+ ret = 0;
+ goto out;
}
/* Get file attributes */
progress_func(WIMLIB_PROGRESS_MSG_SCAN_DENTRY, &info);
}
- /* Create the new WIM dentry */
- ret = new_dentry_with_timeless_inode(path_basename(path), &root);
+ /* Create a WIM dentry with an associated inode, which may be shared */
+ ret = inode_table_new_dentry(inode_table,
+ path_basename_with_len(path, path_len),
+ ni->mft_no,
+ 0,
+ &root);
if (ret)
return ret;
- *root_p = root;
+ inode = root->d_inode;
+
+ if (inode->i_nlink > 1) /* Shared inode; nothing more to do */
+ goto out;
if (name_type & FILE_NAME_WIN32) /* Win32 or Win32+DOS name */
root->is_win32_name = 1;
- root->d_inode->i_creation_time = le64_to_cpu(ni->creation_time);
- root->d_inode->i_last_write_time = le64_to_cpu(ni->last_data_change_time);
- root->d_inode->i_last_access_time = le64_to_cpu(ni->last_access_time);
- root->d_inode->i_attributes = le32_to_cpu(attributes);
- root->d_inode->i_ino = ni->mft_no;
- root->d_inode->i_resolved = 1;
+ inode->i_creation_time = le64_to_cpu(ni->creation_time);
+ inode->i_last_write_time = le64_to_cpu(ni->last_data_change_time);
+ inode->i_last_access_time = le64_to_cpu(ni->last_access_time);
+ inode->i_attributes = le32_to_cpu(attributes);
+ inode->i_resolved = 1;
if (attributes & FILE_ATTR_REPARSE_POINT) {
/* Junction point, symbolic link, or other reparse point */
- ret = capture_ntfs_streams(root, ni, path, path_len,
- lookup_table, ntfs_vol_p,
- AT_REPARSE_POINT);
+ ret = capture_ntfs_streams(inode, ni, path,
+ path_len, lookup_table,
+ ntfs_vol_p, AT_REPARSE_POINT);
} else if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
/* Normal directory */
.path = path,
.path_len = path_len,
.lookup_table = lookup_table,
+ .inode_table = inode_table,
.sd_set = sd_set,
.dos_name_map = &dos_name_map,
.config = config,
destroy_dos_name_map(&dos_name_map);
} else {
/* Normal file */
- ret = capture_ntfs_streams(root, ni, path, path_len,
- lookup_table, ntfs_vol_p,
- AT_DATA);
+ ret = capture_ntfs_streams(inode, ni, path,
+ path_len, lookup_table,
+ ntfs_vol_p, AT_DATA);
}
- if (ret != 0)
- return ret;
+ if (ret)
+ goto out;
- /* Get security descriptor */
- char _sd[1];
- char *sd = _sd;
- errno = 0;
- ret = ntfs_xattr_system_getxattr(&ctx, XATTR_NTFS_ACL,
- ni, dir_ni, sd,
- sizeof(sd));
- if (ret > sizeof(sd)) {
- sd = alloca(ret);
+ if (!(add_image_flags & WIMLIB_ADD_IMAGE_FLAG_NO_ACLS)) {
+ /* Get security descriptor */
+ char _sd[1];
+ char *sd = _sd;
+ errno = 0;
ret = ntfs_xattr_system_getxattr(&ctx, XATTR_NTFS_ACL,
- ni, dir_ni, sd, ret);
- }
- if (ret > 0) {
- root->d_inode->i_security_id = sd_set_add_sd(sd_set, sd, ret);
- if (root->d_inode->i_security_id == -1) {
- ERROR("Out of memory");
- return WIMLIB_ERR_NOMEM;
+ ni, dir_ni, sd,
+ sizeof(sd));
+ if (ret > sizeof(sd)) {
+ sd = alloca(ret);
+ ret = ntfs_xattr_system_getxattr(&ctx, XATTR_NTFS_ACL,
+ ni, dir_ni, sd, ret);
+ }
+ if (ret > 0) {
+ inode->i_security_id = sd_set_add_sd(sd_set, sd, ret);
+ if (inode->i_security_id == -1) {
+ ERROR("Out of memory");
+ ret = WIMLIB_ERR_NOMEM;
+ goto out;
+ }
+ DEBUG("Added security ID = %u for `%s'",
+ inode->i_security_id, path);
+ ret = 0;
+ } else if (ret < 0) {
+ ERROR_WITH_ERRNO("Failed to get security information from "
+ "`%s'", path);
+ ret = WIMLIB_ERR_NTFS_3G;
+ } else {
+ inode->i_security_id = -1;
+ DEBUG("No security ID for `%s'", path);
}
- DEBUG("Added security ID = %u for `%s'",
- root->d_inode->i_security_id, path);
- ret = 0;
- } else if (ret < 0) {
- ERROR_WITH_ERRNO("Failed to get security information from "
- "`%s'", path);
- ret = WIMLIB_ERR_NTFS_3G;
- } else {
- root->d_inode->i_security_id = -1;
- DEBUG("No security ID for `%s'", path);
}
+out:
+ if (ret == 0)
+ *root_ret = root;
+ else
+ free_dentry_tree(root, lookup_table);
return ret;
}
int
build_dentry_tree_ntfs(struct wim_dentry **root_p,
- const mbchar *device,
+ const char *device,
struct wim_lookup_table *lookup_table,
- struct wim_security_data *sd,
- const struct capture_config *config,
+ struct wim_inode_table *inode_table,
+ struct sd_set *sd_set,
+ const struct wimlib_capture_config *config,
int add_image_flags,
wimlib_progress_func_t progress_func,
void *extra_arg)
ntfs_volume *vol;
ntfs_inode *root_ni;
int ret;
- struct sd_set sd_set = {
- .sd = sd,
- .rb_root = {NULL},
- };
ntfs_volume **ntfs_vol_p = extra_arg;
DEBUG("Mounting NTFS volume `%s' read-only", device);
/* Currently we assume that all the paths fit into this length and there
* is no check for overflow. */
- mbchar *path = MALLOC(32768);
+ char *path = MALLOC(32768);
if (!path) {
ERROR("Could not allocate memory for NTFS pathname");
ret = WIMLIB_ERR_NOMEM;
path[1] = '\0';
ret = build_dentry_tree_ntfs_recursive(root_p, NULL, root_ni, path, 1,
FILE_NAME_POSIX, lookup_table,
- &sd_set,
+ inode_table,
+ sd_set,
config, ntfs_vol_p,
add_image_flags,
progress_func);
out_cleanup:
FREE(path);
ntfs_inode_close(root_ni);
- destroy_sd_set(&sd_set);
out:
ntfs_index_ctx_put(vol->secure_xsii);
ntfs_index_ctx_put(vol->secure_xsdh);