mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-09 15:24:54 -04:00
fuse-overlayfs: support running without upper layer
when there is no upper layer specified, fail every read operation with EROFS. Closes: https://github.com/containers/fuse-overlayfs/issues/100 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
3bc0aa6427
commit
c9bbc94ab6
@ -3,12 +3,6 @@ fuse-overlayfs
|
||||
|
||||
An implementation of overlay+shiftfs in FUSE for rootless containers.
|
||||
|
||||
Limitations:
|
||||
=======================================================
|
||||
|
||||
Read-only mode is not supported, so it is always required to specify
|
||||
an upperdir and a workingdir.
|
||||
|
||||
Usage:
|
||||
=======================================================
|
||||
|
||||
|
56
main.c
56
main.c
@ -544,15 +544,27 @@ ovl_init (void *userdata, struct fuse_conn_info *conn)
|
||||
conn->want |= FUSE_CAP_WRITEBACK_CACHE;
|
||||
}
|
||||
|
||||
static struct ovl_layer *
|
||||
get_first_layer (struct ovl_data *lo)
|
||||
{
|
||||
return lo->layers;
|
||||
}
|
||||
|
||||
static struct ovl_layer *
|
||||
get_upper_layer (struct ovl_data *lo)
|
||||
{
|
||||
if (lo->upperdir == NULL)
|
||||
return NULL;
|
||||
|
||||
return lo->layers;
|
||||
}
|
||||
|
||||
static struct ovl_layer *
|
||||
get_lower_layers (struct ovl_data *lo)
|
||||
{
|
||||
if (lo->upperdir == NULL)
|
||||
return lo->layers;
|
||||
|
||||
return lo->layers->next;
|
||||
}
|
||||
|
||||
@ -2719,6 +2731,12 @@ get_node_up (struct ovl_data *lo, struct ovl_node *node)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (lo->upperdir == NULL)
|
||||
{
|
||||
errno = EROFS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node->layer == get_upper_layer (lo))
|
||||
return node;
|
||||
|
||||
@ -2936,7 +2954,7 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
|
||||
pnode = get_node_up (lo, pnode);
|
||||
if (pnode == NULL)
|
||||
{
|
||||
fuse_reply_err (req, ENOENT);
|
||||
fuse_reply_err (req, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4204,14 +4222,19 @@ ovl_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
|
||||
static void
|
||||
ovl_statfs (fuse_req_t req, fuse_ino_t ino)
|
||||
{
|
||||
int ret;
|
||||
int ret, fd;
|
||||
struct statvfs sfs;
|
||||
struct ovl_data *lo = ovl_data (req);
|
||||
|
||||
if (UNLIKELY (ovl_debug (req)))
|
||||
fprintf (stderr, "ovl_statfs(ino=%" PRIu64 "s)\n", ino);
|
||||
|
||||
ret = fstatvfs (get_upper_layer (lo)->fd, &sfs);
|
||||
fd = get_first_layer (lo)->fd;
|
||||
|
||||
if (fd >= 0)
|
||||
ret = fstatvfs (fd, &sfs);
|
||||
else
|
||||
ret = statvfs (lo->mountpoint, &sfs);
|
||||
if (ret < 0)
|
||||
{
|
||||
fuse_reply_err (req, errno);
|
||||
@ -4991,9 +5014,7 @@ main (int argc, char *argv[])
|
||||
if (lo.redirect_dir && strcmp (lo.redirect_dir, "off"))
|
||||
error (EXIT_FAILURE, 0, "fuse-overlayfs only supports redirect_dir=off");
|
||||
|
||||
if (lo.upperdir == NULL)
|
||||
error (EXIT_FAILURE, 0, "upperdir not specified");
|
||||
else
|
||||
if (lo.upperdir != NULL)
|
||||
{
|
||||
cleanup_free char *full_path = NULL;
|
||||
|
||||
@ -5013,8 +5034,8 @@ main (int argc, char *argv[])
|
||||
{
|
||||
fprintf (stderr, "uid=%s\n", lo.uid_str ? : "unchanged");
|
||||
fprintf (stderr, "uid=%s\n", lo.gid_str ? : "unchanged");
|
||||
fprintf (stderr, "upperdir=%s\n", lo.upperdir);
|
||||
fprintf (stderr, "workdir=%s\n", lo.workdir);
|
||||
fprintf (stderr, "upperdir=%s\n", lo.upperdir ? lo.upperdir : "NOT USED");
|
||||
fprintf (stderr, "workdir=%s\n", lo.workdir ? lo.workdir : "NOT USED");
|
||||
fprintf (stderr, "lowerdir=%s\n", lo.lowerdir);
|
||||
fprintf (stderr, "mountpoint=%s\n", lo.mountpoint);
|
||||
}
|
||||
@ -5036,21 +5057,26 @@ main (int argc, char *argv[])
|
||||
error (EXIT_FAILURE, errno, "cannot read lower dirs");
|
||||
}
|
||||
|
||||
tmp_layer = read_dirs (lo.upperdir, false, layers);
|
||||
if (tmp_layer == NULL)
|
||||
error (EXIT_FAILURE, errno, "cannot read upper dir");
|
||||
lo.layers = layers = tmp_layer;
|
||||
if (lo.upperdir != NULL)
|
||||
{
|
||||
tmp_layer = read_dirs (lo.upperdir, false, layers);
|
||||
if (tmp_layer == NULL)
|
||||
error (EXIT_FAILURE, errno, "cannot read upper dir");
|
||||
layers = tmp_layer;
|
||||
}
|
||||
lo.layers = layers;
|
||||
|
||||
lo.inodes = hash_initialize (2048, NULL, node_inode_hasher, node_inode_compare, inode_free);
|
||||
|
||||
lo.root = load_dir (&lo, NULL, get_upper_layer (&lo), ".", "");
|
||||
lo.root = load_dir (&lo, NULL, lo.layers, ".", "");
|
||||
if (lo.root == NULL)
|
||||
error (EXIT_FAILURE, errno, "cannot read upper dir");
|
||||
lo.root->ino->lookups = 2;
|
||||
|
||||
if (lo.workdir == NULL)
|
||||
if (lo.workdir == NULL && lo.upperdir != NULL)
|
||||
error (EXIT_FAILURE, 0, "workdir not specified");
|
||||
else
|
||||
|
||||
if (lo.workdir)
|
||||
{
|
||||
int dfd;
|
||||
cleanup_free char *path = NULL;
|
||||
|
@ -67,3 +67,19 @@ getfattr --only-values -n user.foo merged/a-directory | grep bar
|
||||
getfattr --only-values -n user.foo upper/a-directory | grep bar
|
||||
|
||||
umount merged
|
||||
|
||||
touch lower/file-lower-layer
|
||||
|
||||
# no upper layer
|
||||
fuse-overlayfs -o lowerdir=lower merged
|
||||
|
||||
tar -c --to-stdout $(pwd)/merged > /dev/null
|
||||
|
||||
set +o pipefail
|
||||
|
||||
touch merged/a 2>&1 | grep Read-only
|
||||
touch merged/file-lower-layer 2>&1 | grep Read-only
|
||||
touch merged/usr 2>&1 | grep Read-only
|
||||
mkdir merged/abcd12345 2>&1 | grep Read-only
|
||||
ln merged/file-lower-layer merged/file-lower-layer-link 2>&1 | grep Read-only
|
||||
ln -s merged/file-lower-layer merged/a-symlink 2>&1 | grep Read-only
|
||||
|
Loading…
x
Reference in New Issue
Block a user