mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-09 15:24:54 -04:00
main: split the code in multiple files
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
53c165e6bd
commit
c2c2ac5b82
@ -11,7 +11,7 @@ CLEANFILES = fuse-overlayfs.1
|
||||
fuse_overlayfs_CFLAGS = -I . -I $(abs_srcdir)/lib $(FUSE_CFLAGS)
|
||||
fuse_overlayfs_LDFLAGS =
|
||||
fuse_overlayfs_LDADD = lib/libgnu.a $(FUSE_LIBS)
|
||||
fuse_overlayfs_SOURCES = main.c
|
||||
fuse_overlayfs_SOURCES = main.c direct.c utils.c
|
||||
|
||||
WD := $(shell pwd)
|
||||
|
||||
|
170
direct.c
Normal file
170
direct.c
Normal file
@ -0,0 +1,170 @@
|
||||
/* fuse-overlayfs: Overlay Filesystem in Userspace
|
||||
|
||||
Copyright (C) 2018 Giuseppe Scrivano <giuseppe@scrivano.org>
|
||||
Copyright (C) 2018-2019 Red Hat Inc.
|
||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "fuse-overlayfs.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/xattr.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
static int
|
||||
direct_file_exists (struct ovl_layer *l, const char *pathname)
|
||||
{
|
||||
return file_exists_at (l->fd, pathname);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_listxattr (struct ovl_layer *l, const char *path, char *buf, size_t size)
|
||||
{
|
||||
cleanup_close int fd = -1;
|
||||
char full_path[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
full_path[0] = '\0';
|
||||
ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (fd >= 0)
|
||||
return flistxattr (fd, buf, size);
|
||||
|
||||
return llistxattr (full_path, buf, size);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_getxattr (struct ovl_layer *l, const char *path, const char *name, char *buf, size_t size)
|
||||
{
|
||||
cleanup_close int fd = -1;
|
||||
char full_path[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
full_path[0] = '\0';
|
||||
ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (fd >= 0)
|
||||
return fgetxattr (fd, name, buf, size);
|
||||
|
||||
return lgetxattr (full_path, name, buf, size);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_fstat (struct ovl_layer *l, int fd, const char *path, struct stat *st)
|
||||
{
|
||||
return fstat (fd, st);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_statat (struct ovl_layer *l, const char *path, struct stat *st, int flags)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY (fstatat (l->fd, path, st, flags));
|
||||
}
|
||||
|
||||
static struct dirent *
|
||||
direct_readdir (void *dirp)
|
||||
{
|
||||
return readdir (dirp);
|
||||
}
|
||||
|
||||
static void *
|
||||
direct_opendir (struct ovl_layer *l, const char *path)
|
||||
{
|
||||
cleanup_close int cleanup_fd = -1;
|
||||
DIR *dp = NULL;
|
||||
|
||||
cleanup_fd = TEMP_FAILURE_RETRY (openat (l->fd, path, O_DIRECTORY));
|
||||
if (cleanup_fd < 0)
|
||||
return NULL;
|
||||
|
||||
dp = fdopendir (cleanup_fd);
|
||||
if (dp == NULL)
|
||||
return NULL;
|
||||
|
||||
cleanup_fd = -1;
|
||||
|
||||
return dp;
|
||||
}
|
||||
|
||||
static int
|
||||
direct_closedir (void *dirp)
|
||||
{
|
||||
return closedir (dirp);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_openat (struct ovl_layer *l, const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY (openat (l->fd, path, flags, mode));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
direct_readlinkat (struct ovl_layer *l, const char *path, char *buf, size_t bufsiz)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY (readlinkat (l->fd, path, buf, bufsiz));
|
||||
}
|
||||
|
||||
static int
|
||||
direct_load_data_source (struct ovl_layer *l, const char *opaque)
|
||||
{
|
||||
l->path = realpath (opaque, NULL);
|
||||
if (l->path == NULL)
|
||||
return -1;
|
||||
|
||||
l->fd = open (l->path, O_DIRECTORY);
|
||||
if (l->fd < 0)
|
||||
{
|
||||
free (l->path);
|
||||
l->path = NULL;
|
||||
return l->fd;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
direct_cleanup (struct ovl_layer *l)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct data_source direct_access_ds =
|
||||
{
|
||||
.load_data_source = direct_load_data_source,
|
||||
.cleanup = direct_cleanup,
|
||||
.file_exists = direct_file_exists,
|
||||
.statat = direct_statat,
|
||||
.fstat = direct_fstat,
|
||||
.opendir = direct_opendir,
|
||||
.readdir = direct_readdir,
|
||||
.closedir = direct_closedir,
|
||||
.openat = direct_openat,
|
||||
.getxattr = direct_getxattr,
|
||||
.listxattr = direct_listxattr,
|
||||
.readlinkat = direct_readlinkat,
|
||||
};
|
@ -109,6 +109,8 @@ struct ovl_layer
|
||||
/* a data_source defines the methods for accessing a lower layer. */
|
||||
struct data_source
|
||||
{
|
||||
int (*load_data_source)(struct ovl_layer *l, const char *opaque);
|
||||
int (*cleanup)(struct ovl_layer *l);
|
||||
int (*file_exists)(struct ovl_layer *l, const char *pathname);
|
||||
int (*statat)(struct ovl_layer *l, const char *path, struct stat *st, int flags);
|
||||
int (*fstat)(struct ovl_layer *l, int fd, const char *path, struct stat *st);
|
||||
|
191
main.c
191
main.c
@ -141,12 +141,6 @@ open_by_handle_at (int mount_fd, struct file_handle *handle, int flags)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
file_exists_at (int dirfd, const char *pathname)
|
||||
{
|
||||
return faccessat (dirfd, pathname, F_OK, AT_SYMLINK_NOFOLLOW|AT_EACCESS);
|
||||
}
|
||||
|
||||
#ifndef RENAME_EXCHANGE
|
||||
# define RENAME_EXCHANGE (1 << 1)
|
||||
# define RENAME_NOREPLACE (1 << 2)
|
||||
@ -274,52 +268,6 @@ inode_to_node (struct ovl_data *lo, ino_t n)
|
||||
return lookup_inode (lo, n)->node;
|
||||
}
|
||||
|
||||
static int
|
||||
strconcat3 (char *dest, size_t size, const char *s1, const char *s2, const char *s3)
|
||||
{
|
||||
size_t t;
|
||||
char *current = dest;
|
||||
|
||||
size--;
|
||||
|
||||
if (s1)
|
||||
{
|
||||
t = strlen (s1);
|
||||
if (t > size)
|
||||
t = size;
|
||||
|
||||
memcpy (current, s1, t);
|
||||
current += t;
|
||||
|
||||
size -= t;
|
||||
}
|
||||
if (s2)
|
||||
{
|
||||
t = strlen (s2);
|
||||
if (t > size)
|
||||
t = size;
|
||||
|
||||
memcpy (current, s2, t);
|
||||
current += t;
|
||||
|
||||
size -= t;
|
||||
}
|
||||
if (s3)
|
||||
{
|
||||
t = strlen (s3);
|
||||
if (t > size)
|
||||
t = size;
|
||||
|
||||
memcpy (current, s3, t);
|
||||
current += t;
|
||||
|
||||
size -= t;
|
||||
}
|
||||
*current = '\0';
|
||||
|
||||
return current - dest;
|
||||
}
|
||||
|
||||
static void
|
||||
check_can_mknod (struct ovl_data *lo)
|
||||
{
|
||||
@ -1602,14 +1550,10 @@ read_dirs (struct ovl_data *lo, char *path, bool low, struct ovl_layer *layers)
|
||||
|
||||
l->ovl_data = lo;
|
||||
|
||||
l->path = NULL;
|
||||
l->fd = -1;
|
||||
|
||||
l->path = realpath (it, NULL);
|
||||
if (l->path == NULL)
|
||||
return NULL;
|
||||
|
||||
l->fd = open (l->path, O_DIRECTORY);
|
||||
if (l->fd < 0)
|
||||
if (l->ds->load_data_source (l, it) < 0)
|
||||
return NULL;
|
||||
|
||||
l->low = low;
|
||||
@ -2912,23 +2856,6 @@ ovl_rmdir (fuse_req_t req, fuse_ino_t parent, const char *name)
|
||||
do_rm (req, parent, name, true);
|
||||
}
|
||||
|
||||
static int
|
||||
open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *fd, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
out[0] = '\0';
|
||||
|
||||
*fd = l->ds->openat (l, path, O_NONBLOCK|O_NOFOLLOW|flags, 0755);
|
||||
if (*fd < 0 && (errno == ELOOP || errno == EISDIR))
|
||||
{
|
||||
strconcat3 (out, PATH_MAX, l->path, "/", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *fd;
|
||||
}
|
||||
|
||||
static int
|
||||
direct_setxattr (struct ovl_layer *l, const char *path, const char *name, const char *buf, size_t size, int flags)
|
||||
{
|
||||
@ -4789,117 +4716,6 @@ ovl_copy_file_range (fuse_req_t req, fuse_ino_t ino_in, off_t off_in, struct fus
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
direct_file_exists (struct ovl_layer *l, const char *pathname)
|
||||
{
|
||||
return file_exists_at (l->fd, pathname);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_listxattr (struct ovl_layer *l, const char *path, char *buf, size_t size)
|
||||
{
|
||||
cleanup_close int fd = -1;
|
||||
char full_path[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
full_path[0] = '\0';
|
||||
ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (fd >= 0)
|
||||
return flistxattr (fd, buf, size);
|
||||
|
||||
return llistxattr (full_path, buf, size);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_getxattr (struct ovl_layer *l, const char *path, const char *name, char *buf, size_t size)
|
||||
{
|
||||
cleanup_close int fd = -1;
|
||||
char full_path[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
full_path[0] = '\0';
|
||||
ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (fd >= 0)
|
||||
return fgetxattr (fd, name, buf, size);
|
||||
|
||||
return lgetxattr (full_path, name, buf, size);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_fstat (struct ovl_layer *l, int fd, const char *path, struct stat *st)
|
||||
{
|
||||
return fstat (fd, st);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_statat (struct ovl_layer *l, const char *path, struct stat *st, int flags)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY (fstatat (l->fd, path, st, flags));
|
||||
}
|
||||
|
||||
static struct dirent *
|
||||
direct_readdir (void *dirp)
|
||||
{
|
||||
return readdir (dirp);
|
||||
}
|
||||
|
||||
static void *
|
||||
direct_opendir (struct ovl_layer *l, const char *path)
|
||||
{
|
||||
cleanup_close int cleanup_fd = -1;
|
||||
DIR *dp = NULL;
|
||||
|
||||
cleanup_fd = TEMP_FAILURE_RETRY (openat (l->fd, path, O_DIRECTORY));
|
||||
if (cleanup_fd < 0)
|
||||
return NULL;
|
||||
|
||||
dp = fdopendir (cleanup_fd);
|
||||
if (dp == NULL)
|
||||
return NULL;
|
||||
|
||||
cleanup_fd = -1;
|
||||
|
||||
return dp;
|
||||
}
|
||||
|
||||
static int
|
||||
direct_closedir (void *dirp)
|
||||
{
|
||||
return closedir (dirp);
|
||||
}
|
||||
|
||||
static int
|
||||
direct_openat (struct ovl_layer *l, const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY (openat (l->fd, path, flags, mode));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
direct_readlinkat (struct ovl_layer *l, const char *path, char *buf, size_t bufsiz)
|
||||
{
|
||||
return TEMP_FAILURE_RETRY (readlinkat (l->fd, path, buf, bufsiz));
|
||||
}
|
||||
|
||||
struct data_source direct_access_ds =
|
||||
{
|
||||
.file_exists = direct_file_exists,
|
||||
.statat = direct_statat,
|
||||
.fstat = direct_fstat,
|
||||
.opendir = direct_opendir,
|
||||
.readdir = direct_readdir,
|
||||
.closedir = direct_closedir,
|
||||
.openat = direct_openat,
|
||||
.getxattr = direct_getxattr,
|
||||
.listxattr = direct_listxattr,
|
||||
.readlinkat = direct_readlinkat,
|
||||
};
|
||||
|
||||
static struct fuse_lowlevel_ops ovl_oper =
|
||||
{
|
||||
.statfs = ovl_statfs,
|
||||
@ -5228,6 +5044,9 @@ err_out2:
|
||||
fuse_session_destroy (se);
|
||||
err_out1:
|
||||
|
||||
for (tmp_layer = lo.layers; tmp_layer; tmp_layer = tmp_layer->next)
|
||||
tmp_layer->ds->cleanup (tmp_layer);
|
||||
|
||||
node_mark_all_free (lo.root);
|
||||
|
||||
hash_free (lo.inodes);
|
||||
|
124
utils.c
Normal file
124
utils.c
Normal file
@ -0,0 +1,124 @@
|
||||
/* fuse-overlayfs: Overlay Filesystem in Userspace
|
||||
|
||||
Copyright (C) 2019 Red Hat Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
|
||||
int
|
||||
file_exists_at (int dirfd, const char *pathname)
|
||||
{
|
||||
return faccessat (dirfd, pathname, F_OK, AT_SYMLINK_NOFOLLOW|AT_EACCESS);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
strconcat3 (char *dest, size_t size, const char *s1, const char *s2, const char *s3)
|
||||
{
|
||||
size_t t;
|
||||
char *current = dest;
|
||||
|
||||
size--;
|
||||
|
||||
if (s1)
|
||||
{
|
||||
t = strlen (s1);
|
||||
if (t > size)
|
||||
t = size;
|
||||
|
||||
memcpy (current, s1, t);
|
||||
current += t;
|
||||
|
||||
size -= t;
|
||||
}
|
||||
if (s2)
|
||||
{
|
||||
t = strlen (s2);
|
||||
if (t > size)
|
||||
t = size;
|
||||
|
||||
memcpy (current, s2, t);
|
||||
current += t;
|
||||
|
||||
size -= t;
|
||||
}
|
||||
if (s3)
|
||||
{
|
||||
t = strlen (s3);
|
||||
if (t > size)
|
||||
t = size;
|
||||
|
||||
memcpy (current, s3, t);
|
||||
current += t;
|
||||
|
||||
size -= t;
|
||||
}
|
||||
*current = '\0';
|
||||
|
||||
return current - dest;
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_freep (void *p)
|
||||
{
|
||||
void **pp = (void **) p;
|
||||
free (*pp);
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_filep (FILE **f)
|
||||
{
|
||||
FILE *file = *f;
|
||||
if (file)
|
||||
(void) fclose (file);
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_closep (void *p)
|
||||
{
|
||||
int *pp = p;
|
||||
if (*pp >= 0)
|
||||
close (*pp);
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_dirp (DIR **p)
|
||||
{
|
||||
DIR *dir = *p;
|
||||
if (dir)
|
||||
closedir (dir);
|
||||
}
|
||||
|
||||
int
|
||||
open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *fd, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
out[0] = '\0';
|
||||
|
||||
*fd = l->ds->openat (l, path, O_NONBLOCK|O_NOFOLLOW|flags, 0755);
|
||||
if (*fd < 0 && (errno == ELOOP || errno == EISDIR))
|
||||
{
|
||||
strconcat3 (out, PATH_MAX, l->path, "/", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return *fd;
|
||||
}
|
40
utils.h
40
utils.h
@ -18,36 +18,22 @@
|
||||
#ifndef UTILS_H
|
||||
# define UTILS_H
|
||||
|
||||
void
|
||||
cleanup_freep (void *p)
|
||||
{
|
||||
void **pp = (void **) p;
|
||||
free (*pp);
|
||||
}
|
||||
# include <unistd.h>
|
||||
# include <stdio.h>
|
||||
# include <sys/types.h>
|
||||
# include <dirent.h>
|
||||
# include <stdlib.h>
|
||||
# include "fuse-overlayfs.h"
|
||||
|
||||
void
|
||||
cleanup_filep (FILE **f)
|
||||
{
|
||||
FILE *file = *f;
|
||||
if (file)
|
||||
(void) fclose (file);
|
||||
}
|
||||
void cleanup_freep (void *p);
|
||||
void cleanup_filep (FILE **f);
|
||||
void cleanup_closep (void *p);
|
||||
void cleanup_dirp (DIR **p);
|
||||
|
||||
void
|
||||
cleanup_closep (void *p)
|
||||
{
|
||||
int *pp = p;
|
||||
if (*pp >= 0)
|
||||
close (*pp);
|
||||
}
|
||||
int file_exists_at (int dirfd, const char *pathname);
|
||||
|
||||
void
|
||||
cleanup_dirp (DIR **p)
|
||||
{
|
||||
DIR *dir = *p;
|
||||
if (dir)
|
||||
closedir (dir);
|
||||
}
|
||||
int strconcat3 (char *dest, size_t size, const char *s1, const char *s2, const char *s3);
|
||||
int open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *fd, int flags);
|
||||
|
||||
# define cleanup_file __attribute__((cleanup (cleanup_filep)))
|
||||
# define cleanup_free __attribute__((cleanup (cleanup_freep)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user