mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-23 02:51:55 +00:00
transfused: introduce automatic mount point preparation
Mount points are now made dynamically if either the leaf doesn't exist or the leaf has no children. Any proper prefix of the target mount point may or may not exist prior to mounting. Signed-off-by: David Sheets <dsheets@docker.com>
This commit is contained in:
parent
0e89621f76
commit
0d0413b264
@ -4,10 +4,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pthread.h>
|
||||
@ -438,6 +440,82 @@ void start_writer(connection_t * connection, int fuse) {
|
||||
connection->mount_point);
|
||||
}
|
||||
|
||||
char * alloc_dirname(connection_t * conn, char * path) {
|
||||
size_t len = strlen(path) + 1;
|
||||
char * input = must_malloc("alloc_dirname input", len);
|
||||
char * output = must_malloc("alloc_dirname output", len);
|
||||
char * dir;
|
||||
strlcpy(input, path, len);
|
||||
|
||||
dir = dirname(input);
|
||||
if (dir == NULL)
|
||||
die(1, conn->params, "", "Couldn't get dirname of %s: ", path);
|
||||
strcpy(output, dir);
|
||||
|
||||
free(input);
|
||||
return output;
|
||||
}
|
||||
|
||||
void mkdir_p(connection_t * conn, char * path) {
|
||||
char * parent;
|
||||
|
||||
if (mkdir(path, 0700)) switch (errno) {
|
||||
case ENOENT:
|
||||
parent = alloc_dirname(conn, path);
|
||||
mkdir_p(conn, parent);
|
||||
free(parent);
|
||||
if (mkdir(path, 0700))
|
||||
die(1, conn->params, "", "Couldn't create directory %s: ", path);
|
||||
break;
|
||||
default:
|
||||
die(1, conn->params, "", "Couldn't create directory %s: ", path);
|
||||
}
|
||||
}
|
||||
|
||||
int is_next_child_ok(connection_t * conn, DIR * dir) {
|
||||
struct dirent * child;
|
||||
|
||||
errno = 0;
|
||||
child = readdir(dir);
|
||||
if (child == NULL) {
|
||||
if (errno != 0)
|
||||
die(1, conn->params, "", "Couldn't read mount point %s: ",
|
||||
conn->mount_point);
|
||||
else return 0;
|
||||
} else
|
||||
if (strcmp(".", child->d_name) != 0 && strcmp("..", child->d_name) != 0)
|
||||
die(1, conn->params, NULL, "Couldn't mount on %s: %s exists",
|
||||
conn->mount_point, child->d_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// The leaf may exist but must be empty. Any proper path prefix may exist.
|
||||
void prepare_mount_point(connection_t * conn) {
|
||||
DIR * dir;
|
||||
char * mount_point = conn->mount_point;
|
||||
|
||||
dir = opendir(mount_point);
|
||||
if (dir != NULL) {
|
||||
if (is_next_child_ok(conn, dir))
|
||||
if (is_next_child_ok(conn, dir)) {
|
||||
if (is_next_child_ok(conn, dir))
|
||||
die(1, conn->params, "", "Couldn't mount on %s: not empty",
|
||||
mount_point);
|
||||
else return;
|
||||
}
|
||||
if (closedir(dir))
|
||||
die(1, conn->params, "", "Couldn't close mount point %s: ", mount_point);
|
||||
} else {
|
||||
switch (errno) {
|
||||
case ENOENT: break;
|
||||
default:
|
||||
die(1, conn->params, "", "Couldn't open mount point %s: ", mount_point);
|
||||
}
|
||||
}
|
||||
|
||||
mkdir_p(conn, mount_point);
|
||||
}
|
||||
|
||||
void * mount_connection(connection_t * conn) {
|
||||
int optc;
|
||||
char ** optv;
|
||||
@ -451,6 +529,8 @@ void * mount_connection(connection_t * conn) {
|
||||
|
||||
optv = read_opts(conn, buf);
|
||||
|
||||
prepare_mount_point(conn);
|
||||
|
||||
for (optc = 0; optv[optc] != NULL; optc++) {}
|
||||
|
||||
fuse = get_fuse_sock(conn, optc, optv);
|
||||
|
Loading…
Reference in New Issue
Block a user