Merge pull request #94 from giuseppe/free-wd

main: make sure the work directory is empty
This commit is contained in:
Daniel J Walsh 2019-07-29 10:18:59 -04:00 committed by GitHub
commit 95120c05a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 28 deletions

View File

@ -1215,7 +1215,6 @@ hash_print (const Hash_table *table)
for (cursor = bucket; cursor; cursor = cursor->next) for (cursor = bucket; cursor; cursor = cursor->next)
{ {
char const *s = cursor->data; char const *s = cursor->data;
/* FIXME */
if (s) if (s)
printf (" %s\n", s); printf (" %s\n", s);
} }

113
main.c
View File

@ -1095,11 +1095,11 @@ safe_read_xattr (char **ret, int sfd, const char *name, size_t initial_size)
buffer = tmp; buffer = tmp;
} }
buffer[s] == '\0';
if (s <= 0) if (s <= 0)
return s; return s;
buffer[s] = '\0';
/* Change owner. */ /* Change owner. */
*ret = buffer; *ret = buffer;
buffer = NULL; buffer = NULL;
@ -1148,27 +1148,40 @@ make_ovl_node (const char *path, struct ovl_layer *layer, const char *name, ino_
{ {
struct stat st; struct stat st;
struct ovl_layer *it; struct ovl_layer *it;
cleanup_free char *path = NULL; cleanup_free char *npath = NULL;
path = strdup (ret->path); npath = strdup (ret->path);
if (path == NULL) if (npath == NULL)
return NULL; return NULL;
for (it = layer; it; it = it->next) for (it = layer; it; it = it->next)
{ {
ssize_t s; ssize_t s;
bool stat_only = false;
cleanup_free char *val = NULL; cleanup_free char *val = NULL;
cleanup_free char *origin = NULL; cleanup_free char *origin = NULL;
cleanup_close int fd = TEMP_FAILURE_RETRY (openat (it->fd, path, O_RDONLY|O_NONBLOCK|O_NOFOLLOW|O_PATH)); cleanup_close int fd = TEMP_FAILURE_RETRY (openat (it->fd, npath, O_RDONLY|O_NONBLOCK|O_NOFOLLOW));
if (fd < 0) if (fd < 0)
continue; {
/* It is a symlink, read only the ino. */
if (errno == ELOOP && fstatat (it->fd, npath, &st, AT_SYMLINK_NOFOLLOW) == 0)
{
ret->ino = st.st_ino;
ret->last_layer = it;
}
goto no_fd;
}
/* It is an open FD, stat the file and read the origin xattrs. */
if (fstat (fd, &st) == 0) if (fstat (fd, &st) == 0)
{ {
ret->ino = st.st_ino; ret->ino = st.st_ino;
ret->last_layer = it; ret->last_layer = it;
} }
if (stat_only)
goto no_fd;
s = safe_read_xattr (&val, fd, PRIVILEGED_ORIGIN_XATTR, PATH_MAX); s = safe_read_xattr (&val, fd, PRIVILEGED_ORIGIN_XATTR, PATH_MAX);
if (s > 0) if (s > 0)
{ {
@ -1206,11 +1219,12 @@ make_ovl_node (const char *path, struct ovl_layer *layer, const char *name, ino_
s = safe_read_xattr (&origin, fd, ORIGIN_XATTR, PATH_MAX); s = safe_read_xattr (&origin, fd, ORIGIN_XATTR, PATH_MAX);
if (s > 0) if (s > 0)
{ {
free (path); free (npath);
path = origin; npath = origin;
origin = NULL; origin = NULL;
} }
no_fd:
if (parent && parent->last_layer == it) if (parent && parent->last_layer == it)
break; break;
if (fast_ino_check) if (fast_ino_check)
@ -2567,27 +2581,22 @@ update_paths (struct ovl_node *node)
} }
static int static int
empty_dir (struct ovl_data *lo, struct ovl_node *node) empty_dirfd (int fd)
{ {
cleanup_dir DIR *dp = NULL; cleanup_dir DIR *dp = NULL;
cleanup_close int cleanup_fd = -1;
struct dirent *dent; struct dirent *dent;
cleanup_fd = TEMP_FAILURE_RETRY (openat (get_upper_layer (lo)->fd, node->path, O_DIRECTORY)); dp = fdopendir (fd);
if (cleanup_fd < 0)
return -1;
if (set_fd_opaque (cleanup_fd) < 0)
return -1;
dp = fdopendir (cleanup_fd);
if (dp == NULL) if (dp == NULL)
return -1; {
close (fd);
cleanup_fd = -1; /* It is not owned by dp. */ return -1;
}
for (;;) for (;;)
{ {
int ret;
errno = 0; errno = 0;
dent = readdir (dp); dent = readdir (dp);
if (dent == NULL) if (dent == NULL)
@ -2601,13 +2610,59 @@ empty_dir (struct ovl_data *lo, struct ovl_node *node)
continue; continue;
if (strcmp (dent->d_name, "..") == 0) if (strcmp (dent->d_name, "..") == 0)
continue; continue;
if (unlinkat (dirfd (dp), dent->d_name, 0) < 0)
unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR); ret = unlinkat (dirfd (dp), dent->d_name, 0);
if (ret < 0 && errno == EISDIR)
{
ret = unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
if (ret < 0 && errno == ENOTEMPTY)
{
int dfd;
dfd = openat (dirfd (dp), dent->d_name, O_DIRECTORY);
if (dfd < 0)
return -1;
ret = empty_dirfd (dfd);
if (ret < 0)
return -1;
ret = unlinkat (dirfd (dp), dent->d_name, AT_REMOVEDIR);
if (ret < 0)
return -1;
continue;
}
}
if (ret < 0)
return ret;
} }
return 0; return 0;
} }
static int
empty_dir (struct ovl_data *lo, struct ovl_node *node)
{
cleanup_dir DIR *dp = NULL;
cleanup_close int cleanup_fd = -1;
struct dirent *dent;
int ret;
cleanup_fd = TEMP_FAILURE_RETRY (openat (get_upper_layer (lo)->fd, node->path, O_DIRECTORY));
if (cleanup_fd < 0)
return -1;
if (set_fd_opaque (cleanup_fd) < 0)
return -1;
ret = empty_dirfd (cleanup_fd);
cleanup_fd = -1;
return ret;
}
static void static void
do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp) do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
{ {
@ -3120,6 +3175,7 @@ ovl_create (fuse_req_t req, fuse_ino_t parent, const char *name,
fuse_reply_err (req, errno); fuse_reply_err (req, errno);
return; return;
} }
fi->fh = fd; fi->fh = fd;
fd = -1; /* Do not clean it up. */ fd = -1; /* Do not clean it up. */
@ -4355,8 +4411,7 @@ ovl_ioctl (fuse_req_t req, fuse_ino_t ino, unsigned int cmd, void *arg,
{ {
case FS_IOC_GETVERSION: case FS_IOC_GETVERSION:
case FS_IOC_GETFLAGS: case FS_IOC_GETFLAGS:
if (fi->fh >= 0) fd = fi->fh;
fd = fi->fh;
break; break;
case FS_IOC_SETVERSION: case FS_IOC_SETVERSION:
@ -4478,7 +4533,7 @@ ovl_copy_file_range (fuse_req_t req, fuse_ino_t ino_in, off_t off_in, struct fus
} }
fd_dest = TEMP_FAILURE_RETRY (openat (node_dirfd (dnode), dnode->path, O_NONBLOCK|O_NOFOLLOW|O_WRONLY)); fd_dest = TEMP_FAILURE_RETRY (openat (node_dirfd (dnode), dnode->path, O_NONBLOCK|O_NOFOLLOW|O_WRONLY));
if (fd < 0) if (fd_dest < 0)
{ {
fuse_reply_err (req, errno); fuse_reply_err (req, errno);
return; return;
@ -4763,6 +4818,7 @@ main (int argc, char *argv[])
error (EXIT_FAILURE, 0, "workdir not specified"); error (EXIT_FAILURE, 0, "workdir not specified");
else else
{ {
int dfd;
cleanup_free char *path = NULL; cleanup_free char *path = NULL;
path = realpath (lo.workdir, NULL); path = realpath (lo.workdir, NULL);
@ -4777,6 +4833,9 @@ main (int argc, char *argv[])
lo.workdir_fd = open (lo.workdir, O_DIRECTORY); lo.workdir_fd = open (lo.workdir, O_DIRECTORY);
if (lo.workdir_fd < 0) if (lo.workdir_fd < 0)
error (EXIT_FAILURE, errno, "cannot open workdir"); error (EXIT_FAILURE, errno, "cannot open workdir");
dfd = dup (lo.workdir_fd);
empty_dirfd (dfd);
} }
umask (0); umask (0);