mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-09 23:34:57 -04:00
fuse-overlayfs: implement mknod
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
b8f90ec1f6
commit
4d34e45e37
109
main.c
109
main.c
@ -586,8 +586,8 @@ make_ovl_node (const char *path, struct ovl_layer *layer, const char *name, ino_
|
|||||||
ret->layer = layer;
|
ret->layer = layer;
|
||||||
ret->ino = ino;
|
ret->ino = ino;
|
||||||
ret->present_lowerdir = 0;
|
ret->present_lowerdir = 0;
|
||||||
|
ret->hidden_dirfd = -1;
|
||||||
ret->name = strdup (name);
|
ret->name = strdup (name);
|
||||||
ret->hidden_dirfd = 0;
|
|
||||||
if (ret->name == NULL)
|
if (ret->name == NULL)
|
||||||
{
|
{
|
||||||
free (ret);
|
free (ret);
|
||||||
@ -632,7 +632,7 @@ make_ovl_node (const char *path, struct ovl_layer *layer, const char *name, ino_
|
|||||||
for (it = layer; it; it = it->next)
|
for (it = layer; it; it = it->next)
|
||||||
{
|
{
|
||||||
ssize_t s;
|
ssize_t s;
|
||||||
int fd = TEMP_FAILURE_RETRY (openat (it->fd, path, O_RDONLY));
|
int fd = TEMP_FAILURE_RETRY (openat (it->fd, path, O_PATH|O_RDONLY));
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -777,10 +777,10 @@ load_dir (struct ovl_data *lo, struct ovl_node *n, struct ovl_layer *layer, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (insert_node (n, child, false) == NULL)
|
if (insert_node (n, child, false) == NULL)
|
||||||
{
|
{
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir (dp);
|
closedir (dp);
|
||||||
}
|
}
|
||||||
@ -2637,6 +2637,102 @@ hide_all (struct ovl_data *lo, struct ovl_node *node)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ovl_mknod (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev)
|
||||||
|
{
|
||||||
|
struct ovl_node *node;
|
||||||
|
struct ovl_data *lo = ovl_data (req);
|
||||||
|
struct ovl_node *pnode;
|
||||||
|
int ret = 0;
|
||||||
|
char path[PATH_MAX + 10];
|
||||||
|
struct fuse_entry_param e;
|
||||||
|
const struct fuse_ctx *ctx = fuse_req_ctx (req);
|
||||||
|
char wd_tmp_file_name[32];
|
||||||
|
|
||||||
|
if (ovl_debug (req))
|
||||||
|
fprintf (stderr, "ovl_mknod(ino=%" PRIu64 ", name=%s, mode=%d, rdev=%lu)\n",
|
||||||
|
parent, name, mode, rdev);
|
||||||
|
|
||||||
|
node = do_lookup_file (lo, parent, name);
|
||||||
|
if (node != NULL)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, EEXIST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pnode = do_lookup_file (lo, parent, NULL);
|
||||||
|
if (pnode == NULL)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, ENOENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pnode = get_node_up (lo, pnode);
|
||||||
|
if (pnode == NULL)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sprintf (wd_tmp_file_name, "%lu", get_next_wd_counter ());
|
||||||
|
ret = mknodat (lo->workdir_fd, wd_tmp_file_name, mode, rdev);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fchownat (lo->workdir_fd, wd_tmp_file_name, get_uid (lo, ctx->uid), get_gid (lo, ctx->gid), 0) < 0)
|
||||||
|
{
|
||||||
|
unlinkat (lo->workdir_fd, wd_tmp_file_name, 0);
|
||||||
|
fuse_reply_err (req, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf (path, "%s/%s", pnode->path, name);
|
||||||
|
ret = renameat (lo->workdir_fd, wd_tmp_file_name, get_upper_layer (lo)->fd, path);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
unlinkat (lo->workdir_fd, wd_tmp_file_name, 0);
|
||||||
|
fuse_reply_err (req, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = make_ovl_node (path, get_upper_layer (lo), name, 0, false);
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = insert_node (pnode, node, true);
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, ENOMEM);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delete_whiteout (lo, -1, pnode, name) < 0)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&e, 0, sizeof (e));
|
||||||
|
|
||||||
|
ret = rpl_stat (req, node, &e.attr);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
fuse_reply_err (req, errno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.ino = NODE_TO_INODE (node);
|
||||||
|
e.attr_timeout = ATTR_TIMEOUT;
|
||||||
|
e.entry_timeout = ENTRY_TIMEOUT;
|
||||||
|
node->lookups++;
|
||||||
|
fuse_reply_entry (req, &e);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
|
ovl_mkdir (fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
|
||||||
{
|
{
|
||||||
@ -2766,6 +2862,7 @@ static struct fuse_lowlevel_ops ovl_oper =
|
|||||||
.symlink = ovl_symlink,
|
.symlink = ovl_symlink,
|
||||||
.rename = ovl_rename,
|
.rename = ovl_rename,
|
||||||
.mkdir = ovl_mkdir,
|
.mkdir = ovl_mkdir,
|
||||||
|
.mknod = ovl_mknod,
|
||||||
.link = ovl_link,
|
.link = ovl_link,
|
||||||
.fsync = ovl_fsync,
|
.fsync = ovl_fsync,
|
||||||
.flock = ovl_flock,
|
.flock = ovl_flock,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user