static u64 __dentry_total_length(const struct dentry *dentry, u64 length)
{
- const struct inode *inode = dentry->inode;
+ const struct inode *inode = dentry->d_inode;
for (u16 i = 0; i < inode->num_ads; i++)
length += ads_entry_total_length(&inode->ads_entries[i]);
return (length + 7) & ~7;
return __dentry_total_length(dentry, dentry->length);
}
-/* Transfers file attributes from a `stat' buffer to an inode. */
+/* Transfers file attributes from a `stat' buffer to a WIM "inode". */
void stbuf_to_inode(const struct stat *stbuf, struct inode *inode)
{
if (S_ISLNK(stbuf->st_mode)) {
inode->ino = (u64)stbuf->st_ino;
else
inode->ino = (u64)stbuf->st_ino |
- ((u64)stbuf->st_dev << (sizeof(ino_t) * 8));
+ ((u64)stbuf->st_dev << ((sizeof(ino_t) * 8) & 63));
/* Set timestamps */
inode->creation_time = timespec_to_wim_timestamp(&stbuf->st_mtim);
inode->last_write_time = timespec_to_wim_timestamp(&stbuf->st_mtim);
if (ret != 0)
return ret;
- child = root->inode->children;
+ child = root->d_inode->children;
if (!child)
return 0;
if (ret != 0)
return ret;
child = child->next;
- } while (child != root->inode->children);
+ } while (child != root->d_inode->children);
return 0;
}
struct dentry *child;
struct dentry *next;
- child = root->inode->children;
+ child = root->d_inode->children;
if (child) {
do {
next = child->next;
if (ret != 0)
return ret;
child = next;
- } while (child != root->inode->children);
+ } while (child != root->d_inode->children);
}
return visitor(root, arg);
}
{
struct dentry *child;
- child = dentry->inode->children;
+ child = dentry->d_inode->children;
dentry->subdir_offset = *subdir_offset_p;
if (child) {
do {
*subdir_offset_p += dentry_correct_total_length(child);
child = child->next;
- } while (child != dentry->inode->children);
+ } while (child != dentry->d_inode->children);
/* End-of-directory dentry on disk. */
*subdir_offset_p += 8;
do {
calculate_subdir_offsets(child, subdir_offset_p);
child = child->next;
- } while (child != dentry->inode->children);
+ } while (child != dentry->d_inode->children);
} else {
/* On disk, childless directories have a valid subdir_offset
* that points to an 8-byte end-of-directory dentry. Regular
struct dentry *child;
size_t name_len;
- child = dentry->inode->children;
+ child = dentry->d_inode->children;
if (child) {
name_len = strlen(name);
do {
if (dentry_has_name(child, name, name_len))
return child;
child = child->next;
- } while (child != dentry->inode->children);
+ } while (child != dentry->d_inode->children);
}
return NULL;
}
if (*path == '\0')
return cur_dir;
- child = cur_dir->inode->children;
+ child = cur_dir->d_inode->children;
if (child) {
new_path = path_next_part(path, &base_len);
do {
if (dentry_has_name(child, path, base_len))
return get_dentry_relative_path(child, new_path);
child = child->next;
- } while (child != cur_dir->inode->children);
+ } while (child != cur_dir->d_inode->children);
}
return NULL;
}
if (!dentry)
return NULL;
else
- return dentry->inode;
+ return dentry->d_inode;
}
/* Returns the dentry that corresponds to the parent directory of @path, or NULL
{
const u8 *hash;
struct lookup_table_entry *lte;
- const struct inode *inode = dentry->inode;
+ const struct inode *inode = dentry->d_inode;
time_t time;
char *p;
puts("\"");
printf("Short Name Length = %hu\n", dentry->short_name_len);
printf("Full Path (UTF-8) = \"%s\"\n", dentry->full_path_utf8);
- lte = inode_stream_lte(dentry->inode, 0, lookup_table);
+ lte = inode_stream_lte(dentry->d_inode, 0, lookup_table);
if (lte) {
print_lookup_table_entry(lte);
} else {
static struct inode *new_timeless_inode()
{
struct inode *inode = CALLOC(1, sizeof(struct inode));
- if (!inode)
- return NULL;
- inode->security_id = -1;
- inode->link_count = 1;
- INIT_LIST_HEAD(&inode->dentry_list);
+ if (inode) {
+ inode->security_id = -1;
+ inode->link_count = 1;
+ #ifdef WITH_FUSE
+ inode->next_stream_id = 1;
+ #endif
+ INIT_LIST_HEAD(&inode->dentry_list);
+ }
return inode;
}
static struct inode *new_inode()
{
struct inode *inode = new_timeless_inode();
- if (!inode)
- return NULL;
- u64 now = get_wim_timestamp();
- inode->creation_time = now;
- inode->last_access_time = now;
- inode->last_write_time = now;
+ if (inode) {
+ u64 now = get_wim_timestamp();
+ inode->creation_time = now;
+ inode->last_access_time = now;
+ inode->last_write_time = now;
+ }
return inode;
}
dentry = new_dentry(name);
if (dentry) {
if (timeless)
- dentry->inode = new_timeless_inode();
+ dentry->d_inode = new_timeless_inode();
else
- dentry->inode = new_inode();
- if (dentry->inode) {
- inode_add_dentry(dentry, dentry->inode);
+ dentry->d_inode = new_inode();
+ if (dentry->d_inode) {
+ inode_add_dentry(dentry, dentry->d_inode);
} else {
free_dentry(dentry);
dentry = NULL;
}
+static int init_ads_entry(struct ads_entry *ads_entry, const char *name)
+{
+ int ret = 0;
+ memset(ads_entry, 0, sizeof(*ads_entry));
+ if (name && *name)
+ ret = change_ads_name(ads_entry, name);
+ return ret;
+}
+
+static void destroy_ads_entry(struct ads_entry *ads_entry)
+{
+ FREE(ads_entry->stream_name);
+ FREE(ads_entry->stream_name_utf8);
+}
+
+
/* Frees an inode. */
void free_inode(struct inode *inode)
{
if (inode) {
- inode_free_ads_entries(inode);
+ if (inode->ads_entries) {
+ for (u16 i = 0; i < inode->num_ads; i++)
+ destroy_ads_entry(&inode->ads_entries[i]);
+ FREE(inode->ads_entries);
+ }
#ifdef WITH_FUSE
wimlib_assert(inode->num_opened_fds == 0);
FREE(inode->fds);
#endif
{
free_inode(inode);
- inode = NULL;
}
}
}
FREE(dentry->file_name_utf8);
FREE(dentry->short_name);
FREE(dentry->full_path_utf8);
- put_inode(dentry->inode);
+ if (dentry->d_inode)
+ put_inode(dentry->d_inode);
FREE(dentry);
}
static int do_free_dentry(struct dentry *dentry, void *__lookup_table)
{
struct lookup_table *lookup_table = __lookup_table;
- struct lookup_table_entry *lte;
- struct inode *inode = dentry->inode;
unsigned i;
if (lookup_table) {
+ struct lookup_table_entry *lte;
+ struct inode *inode = dentry->d_inode;
wimlib_assert(inode->link_count);
for (i = 0; i <= inode->num_ads; i++) {
lte = inode_stream_lte(inode, i, lookup_table);
- lte_decrement_refcnt(lte, lookup_table);
+ if (lte)
+ lte_decrement_refcnt(lte, lookup_table);
}
}
- wimlib_assert(dentry->refcnt != 0);
- if (--dentry->refcnt == 0)
- free_dentry(dentry);
+ put_dentry(dentry);
return 0;
}
{
wimlib_assert(dentry_is_directory(parent));
dentry->parent = parent;
- if (parent->inode->children) {
+ if (parent->d_inode->children) {
/* Not an only child; link to siblings. */
- dentry->next = parent->inode->children;
- dentry->prev = parent->inode->children->prev;
+ dentry->next = parent->d_inode->children;
+ dentry->prev = parent->d_inode->children->prev;
dentry->next->prev = dentry;
dentry->prev->next = dentry;
} else {
/* Only child; link to parent. */
- parent->inode->children = dentry;
+ parent->d_inode->children = dentry;
dentry->next = dentry;
dentry->prev = dentry;
}
}
+#ifdef WITH_FUSE
/*
* Unlink a dentry from the directory tree.
*
if (dentry_is_root(dentry))
return;
if (dentry_is_only_child(dentry)) {
- dentry->parent->inode->children = NULL;
+ dentry->parent->d_inode->children = NULL;
} else {
if (dentry_is_first_sibling(dentry))
- dentry->parent->inode->children = dentry->next;
+ dentry->parent->d_inode->children = dentry->next;
dentry->next->prev = dentry->prev;
dentry->prev->next = dentry->next;
}
}
-
-
-/* Parameters for calculate_dentry_statistics(). */
-struct image_statistics {
- struct lookup_table *lookup_table;
- u64 *dir_count;
- u64 *file_count;
- u64 *total_bytes;
- u64 *hard_link_bytes;
-};
-
-static int calculate_dentry_statistics(struct dentry *dentry, void *arg)
-{
- struct image_statistics *stats;
- struct lookup_table_entry *lte;
-
- stats = arg;
-
- if (dentry_is_directory(dentry) && !dentry_is_root(dentry))
- ++*stats->dir_count;
- else
- ++*stats->file_count;
-
- for (unsigned i = 0; i <= dentry->inode->num_ads; i++) {
- lte = inode_stream_lte(dentry->inode, i, stats->lookup_table);
- if (lte) {
- *stats->total_bytes += wim_resource_size(lte);
- if (++lte->out_refcnt == 1)
- *stats->hard_link_bytes += wim_resource_size(lte);
- }
- }
- return 0;
-}
-
-/* Calculates some statistics about a dentry tree. */
-void calculate_dir_tree_statistics(struct dentry *root, struct lookup_table *table,
- u64 *dir_count_ret, u64 *file_count_ret,
- u64 *total_bytes_ret,
- u64 *hard_link_bytes_ret)
-{
- struct image_statistics stats;
- *dir_count_ret = 0;
- *file_count_ret = 0;
- *total_bytes_ret = 0;
- *hard_link_bytes_ret = 0;
- stats.lookup_table = table;
- stats.dir_count = dir_count_ret;
- stats.file_count = file_count_ret;
- stats.total_bytes = total_bytes_ret;
- stats.hard_link_bytes = hard_link_bytes_ret;
- for_lookup_table_entry(table, lte_zero_out_refcnt, NULL);
- for_dentry_in_tree(root, calculate_dentry_statistics, &stats);
-}
+#endif
static inline struct dentry *inode_first_dentry(struct inode *inode)
{
int verify_dentry(struct dentry *dentry, void *wim)
{
const WIMStruct *w = wim;
- const struct inode *inode = dentry->inode;
+ const struct inode *inode = dentry->d_inode;
int ret = WIMLIB_ERR_INVALID_DENTRY;
- if (!dentry->inode->verified) {
- ret = verify_inode(dentry->inode, w);
+ if (!dentry->d_inode->verified) {
+ ret = verify_inode(dentry->d_inode, w);
if (ret != 0)
goto out;
}
}
#endif
-
-static int init_ads_entry(struct ads_entry *ads_entry, const char *name)
-{
- int ret = 0;
- memset(ads_entry, 0, sizeof(*ads_entry));
- if (name && *name)
- ret = change_ads_name(ads_entry, name);
- return ret;
-}
-
-static void destroy_ads_entry(struct ads_entry *ads_entry)
-{
- FREE(ads_entry->stream_name);
- FREE(ads_entry->stream_name_utf8);
-}
-
-
-void inode_free_ads_entries(struct inode *inode)
-{
- if (inode->ads_entries) {
- for (u16 i = 0; i < inode->num_ads; i++)
- destroy_ads_entry(&inode->ads_entries[i]);
- FREE(inode->ads_entries);
- }
-}
-
#if defined(WITH_FUSE) || defined(WITH_NTFS_3G)
/*
* Add an alternate stream entry to an inode and return a pointer to it, or NULL
struct ads_entry *ads_entries;
struct ads_entry *new_entry;
+ DEBUG("Add alternate data stream \"%s\"", stream_name);
+
if (inode->num_ads >= 0xfffe) {
ERROR("Too many alternate data streams in one inode!");
return NULL;
#ifdef WITH_FUSE
new_entry->stream_id = inode->next_stream_id++;
#endif
+ inode->num_ads = num_ads;
return new_entry;
}
#endif
struct ads_entry *ads_entry;
struct lookup_table_entry *lte;
+ wimlib_assert(idx < inode->num_ads);
+ wimlib_assert(inode->resolved);
+
ads_entry = &inode->ads_entries[idx];
- wimlib_assert(ads_entry);
- wimlib_assert(inode->resolved);
+ DEBUG("Remove alternate data stream \"%s\"", ads_entry->stream_name_utf8);
lte = ads_entry->lte;
-
if (lte)
lte_decrement_refcnt(lte, lookup_table);
destroy_ads_entry(ads_entry);
- wimlib_assert(inode->num_ads);
memcpy(&inode->ads_entries[idx],
&inode->ads_entries[idx + 1],
(inode->num_ads - idx - 1) * sizeof(inode->ads_entries[0]));
/* We've read all the data for this dentry. Set the names and their
* lengths, and we've done. */
- dentry->inode = inode;
+ dentry->d_inode = inode;
dentry->file_name = file_name;
dentry->file_name_utf8 = file_name_utf8;
dentry->short_name = short_name;
child->parent = dentry;
prev_child = child;
- inode_add_dentry(child, child->inode);
+ inode_add_dentry(child, child->d_inode);
/* If there are children of this child, call this procedure
* recursively. */
prev_child->next = first_child;
first_child->prev = prev_child;
}
- dentry->inode->children = first_child;
+ dentry->d_inode->children = first_child;
return ret;
}
{
u8 *orig_p = p;
const u8 *hash;
- const struct inode *inode = dentry->inode;
+ const struct inode *inode = dentry->d_inode;
/* We calculate the correct length of the dentry ourselves because the
* dentry->length field may been set to an unexpected value from when we
}
/* Align to 8-byte boundary */
- wimlib_assert(length >= (p - orig_p)
- && length - (p - orig_p) <= 7);
+ wimlib_assert(length >= (p - orig_p) && length - (p - orig_p) <= 7);
p = put_zeroes(p, length - (p - orig_p));
/* Write the alternate data streams, if there are any. Please see
}
p = put_zeroes(p, (8 - (p - orig_p) % 8) % 8);
}
-#ifdef ENABLE_ASSERTIONS
wimlib_assert(p - orig_p == __dentry_total_length(dentry, length));
-#endif
return p;
}
* recursively writing the directory trees rooted at each of the child
* dentries, since the on-disk dentries for a dentry's children are
* always located at consecutive positions in the metadata resource! */
- child = parent->inode->children;
+ child = parent->d_inode->children;
if (child) {
do {
p = write_dentry(child, p);
child = child->next;
- } while (child != parent->inode->children);
+ } while (child != parent->d_inode->children);
}
/* write end of directory entry */
do {
p = write_dentry_tree_recursive(child, p);
child = child->next;
- } while (child != parent->inode->children);
+ } while (child != parent->d_inode->children);
}
return p;
}