/* Name of the directory on which the WIM file is mounted. */
static const char *mount_dir;
+/* Next hard link group ID to be assigned. These are also used as the inode
+ * numbers. */
+static u64 next_link_group_id;
+
static inline int get_lookup_flags()
{
if (close(fd->staging_fd) != 0)
return -errno;
}
- if (--lte->num_opened_fds == 0 && lte->refcnt == 0)
+ if (--lte->num_opened_fds == 0 && lte->refcnt == 0) {
+ if (lte->staging_file_name)
+ unlink(lte->staging_file_name);
free_lookup_table_entry(lte);
+ }
lte->fds[fd->idx] = NULL;
FREE(fd);
return 0;
struct lookup_table_entry *old_lte, *new_lte;
size_t link_group_size;
+ DEBUG("Extracting resource `%s' to staging directory", dentry->full_path_utf8);
+
old_lte = *lte;
fd = create_staging_file(&staging_file_name, O_WRONLY);
if (fd == -1)
if (link_group_size == old_lte->refcnt) {
/* This hard link group is the only user of the lookup
* table entry, so we can re-use it. */
+ DEBUG("Re-using lookup table entry");
lookup_table_remove(w->lookup_table, old_lte);
new_lte = old_lte;
} else {
+ DEBUG("Splitting lookup table entry "
+ "(link_group_size = %u, lte refcnt = %u)",
+ link_group_size, old_lte->refcnt);
/* Split a hard link group away from the "lookup table
* entry" hard link group (i.e. we had two hard link
* groups that were identical, but now we are changing
num_transferred_fds++;
}
}
+ DEBUG("Transferring %u file descriptors",
+ num_transferred_fds);
new_lte->fds = MALLOC(num_transferred_fds *
sizeof(new_lte->fds[0]));
if (!new_lte->fds) {
- free_lookup_table_entry(new_lte);
+ FREE(new_lte);
ret = -ENOMEM;
goto out_delete_staging_file;
}
- u16 j = 0;
- for (u16 i = 0; i < old_lte->num_allocated_fds; i++) {
+ for (u16 i = 0, j = 0; ; i++) {
if (old_lte->fds[i] &&
old_lte->fds[i]->dentry->hard_link ==
dentry->hard_link)
fd->lte = new_lte;
fd->idx = j;
new_lte->fds[j] = fd;
+ if (++j == num_transferred_fds)
+ break;
}
}
old_lte->refcnt -= link_group_size;
- old_lte->num_opened_fds -= j;
- new_lte->num_opened_fds = j;
-
+ old_lte->num_opened_fds -= num_transferred_fds;
+ new_lte->num_opened_fds = num_transferred_fds;
+ new_lte->num_allocated_fds = num_transferred_fds;
}
} else {
new_lte = new_lookup_table_entry();
struct fuse_file_info *fi)
{
struct wimlib_fd *fd = (struct wimlib_fd*)fi->fh;
- dentry_to_stbuf(fd->dentry, stbuf, w->lookup_table);
- return 0;
+ return dentry_to_stbuf(fd->dentry, stbuf, w->lookup_table);
}
static int wimfs_ftruncate(const char *path, off_t size,
struct dentry *dentry = get_dentry(w, path);
if (!dentry)
return -ENOENT;
- dentry_to_stbuf(dentry, stbuf, w->lookup_table);
- return 0;
+ return dentry_to_stbuf(dentry, stbuf, w->lookup_table);
}
/* Create a hard link */
list_add(&from_dentry->link_group_list, &to_dentry->link_group_list);
link_dentry(from_dentry, from_dentry_parent);
dentry_increment_lookup_table_refcnts(from_dentry, w->lookup_table);
+ from_dentry->link_group_master_status = GROUP_SLAVE;
return 0;
}
dentry = new_dentry(basename);
if (!dentry)
return -ENOMEM;
+ dentry->hard_link = next_link_group_id++;
link_dentry(dentry, parent);
}
return 0;
if (ret != 0)
return ret;
- if (lte && lte->staging_file_name)
- if (unlink(lte->staging_file_name) != 0)
- return -errno;
-
if (dentry_hash == dentry->hash) {
/* We are removing the full dentry including all alternate data
* streams. */
wimlib_assert(fd->lte->staging_file_name);
wimlib_assert(fd->staging_fd != -1);
+ /* Seek to the requested position */
+ if (lseek(fd->staging_fd, offset, SEEK_SET) == -1)
+ return -errno;
+
/* Write the data. */
ret = write(fd->staging_fd, buf, size);
if (ret == -1)
int flags)
{
int argc = 0;
- char *argv[6];
+ char *argv[16];
int ret;
char *p;
if (ret != 0)
return ret;
+ DEBUG("Selected image %d", image);
+
+ next_link_group_id = assign_link_groups(wim->image_metadata[image - 1].lgt);
+
if (flags & WIMLIB_MOUNT_FLAG_READWRITE)
wim_get_current_image_metadata(wim)->modified = true;
if (flags & WIMLIB_MOUNT_FLAG_DEBUG) {
argv[argc++] = "-d";
}
- if (!(flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
- argv[argc++] = "-o";
- argv[argc++] = "ro";
- } else {
+ char optstring[256] = "use_ino";
+ argv[argc++] = "-o";
+ argv[argc++] = optstring;
+ if ((flags & WIMLIB_MOUNT_FLAG_READWRITE)) {
make_staging_dir();
if (!staging_dir_name) {
FREE(p);
return WIMLIB_ERR_MKDIR;
}
+ } else {
+ strcat(optstring, ",ro");
}
+ argv[argc] = NULL;
#ifdef ENABLE_DEBUG
{