#include "xml.h"
#include "io.h"
#include "timestamp.h"
+#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
inode->num_opened_fds++;
if (lte)
lte->num_opened_fds++;
- DEBUG("Allocated fd");
+ DEBUG("Allocated fd (idx = %u)", fd->idx);
return 0;
}
}
static void inode_put_fd(struct inode *inode, struct wimlib_fd *fd)
{
- wimlib_assert(fd);
- wimlib_assert(inode);
+ wimlib_assert(fd != NULL);
+ wimlib_assert(inode != NULL);
wimlib_assert(fd->f_inode == inode);
- wimlib_assert(inode->num_opened_fds);
- wimlib_assert(fd->idx < inode->num_opened_fds);
+ wimlib_assert(inode->num_opened_fds != 0);
+ wimlib_assert(fd->idx < inode->num_allocated_fds);
wimlib_assert(inode->fds[fd->idx] == fd);
inode->fds[fd->idx] = NULL;
}
-/* Simple function that returns the concatenation of 4 strings. */
-static char *strcat_dup(const char *s1, const char *s2, const char *s3,
- const char *s4)
+/* Simple function that returns the concatenation of 2 strings. */
+static char *strcat_dup(const char *s1, const char *s2, size_t max_len)
{
- size_t len = strlen(s1) + strlen(s2) + strlen(s3) + strlen(s4) + 1;
- char *p = MALLOC(len);
+ size_t len = strlen(s1) + strlen(s2);
+ if (len > max_len)
+ len = max_len;
+ char *p = MALLOC(len + 1);
if (!p)
return NULL;
- p = strcpy(p, s1);
- p = strcat(p, s2);
- p = strcat(p, s3);
- return strcat(p, s4);
+ snprintf(p, len + 1, "%s%s", s1, s2);
+ return p;
}
-/* Removes trailing forward slashes in a string. */
-static void remove_trailing_slashes(char *s)
+static int set_message_queue_names(struct wimfs_context *ctx,
+ const char *mount_dir)
{
- long len = strlen(s);
- for (long i = len - 1; i >= 1; i--) {
- if (s[i] == '/')
- s[i] = '\0';
- else
- break;
- }
-}
+ static const char *u2d_prefix = "/wimlib-unmount-to-daemon-mq";
+ static const char *d2u_prefix = "/wimlib-daemon-to-unmount-mq";
+ char *dir_path;
+ char *p;
+ int ret;
-/* Changes forward slashes to underscores in a string. */
-static void s_slashes_underscores_g(char *s)
-{
- while (*s) {
- if (*s == '/')
- *s = '_';
- s++;
+ dir_path = realpath(mount_dir, NULL);
+ if (!dir_path) {
+ ERROR_WITH_ERRNO("Failed to resolve path \"%s\"", mount_dir);
+ return WIMLIB_ERR_NOTDIR;
}
-}
-static int set_message_queue_names(struct wimfs_context *ctx,
- const char *mount_dir)
-{
- static const char *slash = "/";
- static const char *prefix = "wimlib-";
- static const char *u2d_suffix = "unmount-to-daemon-mq";
- static const char *d2u_suffix = "daemon-to-unmount-mq";
+ DEBUG("Using absolute dir_path = `%s'", dir_path);
- const char *mount_dir_basename = path_basename(mount_dir);
- ctx->unmount_to_daemon_mq_name = strcat_dup(slash, mount_dir_basename,
- prefix, u2d_suffix);
+ p = dir_path;
+ while (*p) {
+ if (*p == '/')
+ *p = 0xff;
+ p++;
+ }
+
+ ctx->unmount_to_daemon_mq_name = strcat_dup(u2d_prefix, dir_path,
+ NAME_MAX);
if (!ctx->unmount_to_daemon_mq_name) {
- ERROR("Out of memory");
- return WIMLIB_ERR_NOMEM;
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_dir_path;
}
- ctx->daemon_to_unmount_mq_name = strcat_dup(slash, mount_dir_basename,
- prefix, d2u_suffix);
+ ctx->daemon_to_unmount_mq_name = strcat_dup(d2u_prefix, dir_path,
+ NAME_MAX);
if (!ctx->daemon_to_unmount_mq_name) {
- ERROR("Out of memory");
- FREE(ctx->unmount_to_daemon_mq_name);
- ctx->unmount_to_daemon_mq_name = NULL;
- return WIMLIB_ERR_NOMEM;
+ ret = WIMLIB_ERR_NOMEM;
+ goto out_free_unmount_to_daemon_mq_name;
}
- remove_trailing_slashes(ctx->unmount_to_daemon_mq_name);
- remove_trailing_slashes(ctx->daemon_to_unmount_mq_name);
- s_slashes_underscores_g(ctx->unmount_to_daemon_mq_name + 1);
- s_slashes_underscores_g(ctx->daemon_to_unmount_mq_name + 1);
- return 0;
+ ret = 0;
+ goto out_free_dir_path;
+out_free_unmount_to_daemon_mq_name:
+ FREE(ctx->unmount_to_daemon_mq_name);
+ ctx->unmount_to_daemon_mq_name = NULL;
+out_free_dir_path:
+ FREE(dir_path);
+ return ret;
}
static void free_message_queue_names(struct wimfs_context *ctx)
else
flags = O_WRONLY | O_CREAT;
+ DEBUG("Opening message queue \"%s\"", ctx->unmount_to_daemon_mq_name);
ctx->unmount_to_daemon_mq = mq_open(ctx->unmount_to_daemon_mq_name,
flags, 0700, NULL);
else
flags = O_RDONLY | O_CREAT;
+ DEBUG("Opening message queue \"%s\"", ctx->daemon_to_unmount_mq_name);
ctx->daemon_to_unmount_mq = mq_open(ctx->daemon_to_unmount_mq_name,
flags, 0700, NULL);
return 0;
}
+static int wimfs_chmod(const char *path, mode_t mask)
+{
+ struct dentry *dentry;
+ struct wimfs_context *ctx = wimfs_get_context();
+ struct inode *inode;
+ struct stat stbuf;
+ int ret;
+
+ ret = lookup_resource(ctx->wim, path,
+ get_lookup_flags(ctx) | LOOKUP_FLAG_DIRECTORY_OK,
+ &dentry, NULL, NULL);
+ if (ret != 0)
+ return ret;
+ inode = dentry->d_inode;
+ inode_to_stbuf(inode, NULL, &stbuf);
+ if (mask == stbuf.st_mode)
+ return 0;
+ else
+ return -EPERM;
+
+}
+
static void inode_update_lte_ptr(struct inode *inode,
struct lookup_table_entry *old_lte,
struct lookup_table_entry *new_lte)
struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
int ret = ftruncate(fd->staging_fd, size);
if (ret != 0)
- return ret;
+ return -errno;
if (fd->f_lte && size < fd->f_lte->resource_entry.original_size)
fd->f_lte->resource_entry.original_size = size;
return 0;
lte->refcnt++;
}
- link_dentry(from_dentry, from_dentry_parent);
+ dentry_add_child(from_dentry_parent, from_dentry);
return 0;
}
newdir->d_inode->attributes |= FILE_ATTRIBUTE_DIRECTORY;
newdir->d_inode->resolved = true;
newdir->d_inode->ino = ctx->next_ino++;
- link_dentry(newdir, parent);
+ dentry_add_child(parent, newdir);
return 0;
}
return -ENOMEM;
dentry->d_inode->resolved = true;
dentry->d_inode->ino = ctx->next_ino++;
- link_dentry(dentry, parent);
+ dentry_add_child(parent, dentry);
}
return 0;
}
struct inode *inode;
int ret;
struct wimlib_fd *fd = NULL;
- struct wimfs_context *ctx = wimfs_get_context();
+ WIMStruct *w = wimfs_get_WIMStruct();
- inode = wim_pathname_to_inode(ctx->wim, path);
+ inode = wim_pathname_to_inode(w, path);
if (!inode)
return -ENOENT;
if (!inode_is_directory(inode))
}
}
+struct fill_params {
+ void *buf;
+ fuse_fill_dir_t filler;
+};
+
+static int dentry_fuse_fill(struct dentry *dentry, void *arg)
+{
+ struct fill_params *fill_params = arg;
+ return fill_params->filler(fill_params->buf, dentry->file_name_utf8,
+ NULL, 0);
+}
+
/* Fills in the entries of the directory specified by @path using the
* FUSE-provided function @filler. */
static int wimfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
{
struct wimlib_fd *fd = (struct wimlib_fd*)(uintptr_t)fi->fh;
struct inode *inode;
- struct dentry *child;
if (!fd)
return -EBADF;
inode = fd->f_inode;
+ struct fill_params fill_params = {
+ .buf = buf,
+ .filler = filler,
+ };
+
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
- child = inode->children;
-
- if (!child)
- return 0;
-
- do {
- if (filler(buf, child->file_name_utf8, NULL, 0))
- return 0;
- child = child->next;
- } while (child != inode->children);
- return 0;
+ return for_dentry_in_rbtree(inode->children.rb_node,
+ dentry_fuse_fill, &fill_params);
}
* directory */
if (!dentry_is_directory(dst))
return -ENOTDIR;
- if (dst->d_inode->children != NULL)
+ if (inode_has_children(dst->d_inode))
return -ENOTEMPTY;
}
parent_of_dst = dst->parent;
src->file_name_utf8_len = file_name_utf8_len;
unlink_dentry(src);
- link_dentry(src, parent_of_dst);
+ dentry_add_child(parent_of_dst, src);
return 0;
}
if (inode_set_symlink(inode, to, ctx->wim->lookup_table, NULL) != 0)
goto out_free_dentry;
- link_dentry(dentry, dentry_parent);
+ dentry_add_child(dentry_parent, dentry);
return 0;
out_free_dentry:
free_dentry(dentry);
{
struct dentry *dentry;
struct inode *inode;
+ WIMStruct *w = wimfs_get_WIMStruct();
+
dentry = get_dentry(w, path);
if (!dentry)
return -ENOENT;
static struct fuse_operations wimfs_operations = {
.access = wimfs_access,
+ .chmod = wimfs_chmod,
.destroy = wimfs_destroy,
#if 0
.fallocate = wimfs_fallocate,
ctx.wim = wim;
ctx.mount_flags = flags;
+ DEBUG("Calling fuse_main()");
+
ret = fuse_main(argc, argv, &wimfs_operations, &ctx);
+
+ DEBUG("Returned from fuse_main() (ret = %d)", ret);
if (ret)
ret = WIMLIB_ERR_FUSE;
out_free_dir_copy: