main: split the code in multiple files

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2019-09-12 17:57:57 +02:00
parent 53c165e6bd
commit c2c2ac5b82
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED
6 changed files with 315 additions and 214 deletions

View File

@ -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
View 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,
};

View File

@ -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
View File

@ -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
View 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
View File

@ -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)))