return ret;
}
+static int ensure_dir(const char *dest) {
+ struct stat sb;
+ int ret = -1;
+
+ if (stat(dest, &sb) == 0) {
+ if ((sb.st_mode & S_IFMT) == S_IFDIR)
+ return 0;
+ ret = unlink(dest);
+ if (ret < 0) {
+ SYSERROR("Failed to remove old \"%s\"", dest);
+ return ret;
+ }
+ }
+
+ ret = mkdir(dest, 0755);
+ if (ret < 0) {
+ SYSERROR("Failed to mkdir \"%s\"", dest);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ensure_file(const char *dest) {
+ struct stat sb;
+ int fd, ret;
+
+ if (stat(dest, &sb) == 0) {
+ if ((sb.st_mode & S_IFMT) != S_IFDIR)
+ return 0;
+ ret = rmdir(dest);
+ if (ret < 0) {
+ SYSERROR("Failed to remove old \"%s\"", dest);
+ return ret;
+ }
+ }
+
+ fd = creat(dest, 0755);
+ if (fd < 0) {
+ SYSERROR("Failed to mkdir \"%s\"", dest);
+ return ret;
+ }
+ close(fd);
+
+ return 0;
+}
+
+/* @st_mode is the st_mode field of the stat(source) return struct */
+static int create_mount_target(mode_t st_mode, const char *dest) {
+ char *dirdup, *destdirname;
+ int ret = -1;
+
+ dirdup = strdup(dest);
+ if (!dirdup) {
+ SYSERROR("Failed to duplicate target name");
+ return ret;
+ }
+
+ destdirname = dirname(dirdup);
+
+ ret = mkdir_p(destdirname, 0755);
+ if (ret < 0) {
+ SYSERROR("failed to create path: %s", destdirname);
+ free(dirdup);
+ return ret;
+ }
+ free(dirdup);
+
+ switch (st_mode & S_IFMT) {
+ case S_IFDIR:
+ ensure_dir(dest);
+ return 0;
+ default:
+ ensure_file(dest);
+ return 0;
+ }
+}
+
#define WRAP_API(rettype, fnname) \
static rettype fnname(struct lxc_container *c) \
{ \
char template[MAXPATHLEN], path[MAXPATHLEN];
pid_t pid, init_pid;
size_t len;
+ struct stat sb;
int ret = -1, fd = -EBADF;
if (!c || !c->lxc_conf) {
goto out;
}
- /* Create a temporary dir under the shared mountpoint */
- sret = mkdtemp(template);
- if (!sret) {
- SYSERROR("Could not create shmounts temporary dir");
- goto out;
+ /* Create a temporary file / dir under the shared mountpoint */
+ if (!source || strcmp(source, "") == 0) {
+ /* If source is not specified, maybe we want to mount a filesystem? */
+ sb.st_mode = S_IFDIR;
+ } else {
+ ret = stat(source, &sb);
+ if (ret < 0) {
+ SYSERROR("Error getting stat info about the source \"%s\"", source);
+ goto out;
+ }
+ }
+
+ if ((sb.st_mode & S_IFMT) == S_IFDIR) {
+ sret = mkdtemp(template);
+ if (!sret) {
+ SYSERROR("Could not create shmounts temporary dir");
+ goto out;
+ }
+ ret = chmod(template, 0);
+ if (ret < 0) {
+ SYSERROR("Could not chmod shmounts temporary dir \"%s\"", template);
+ goto out;
+ }
+ } else {
+ fd = lxc_make_tmpfile(template, false);
+ if (fd < 0) {
+ SYSERROR("Could not create shmounts temporary file");
+ goto out;
+ }
+ ret = fchmod(fd, 0);
+ if (ret < 0) {
+ SYSERROR("Could not chmod shmounts temporary file");
+ goto out;
+ }
}
/* Do the fork */
/* Do the mount */
ret = mount(source, template, filesystemtype, mountflags, data);
if (ret < 0) {
- SYSERROR("Failed to mount \"%s\" onto \"%s\"", source, template);
+ SYSERROR("Failed to mount onto \"%s\"", template);
_exit(EXIT_FAILURE);
}
_exit(EXIT_FAILURE);
}
+ ret = create_mount_target(sb.st_mode, target);
+ if (ret < 0)
+ _exit(EXIT_FAILURE);
+
suff = strrchr(template, '/');
if (!suff)
_exit(EXIT_FAILURE);
_exit(EXIT_FAILURE);
}
- ret = mkdir_p(target, 0700);
- if (ret < 0) {
- ERROR("Failed to create container temp mountpoint");
- _exit(EXIT_FAILURE);
- }
-
ret = mount(path, target, NULL, MS_REC | MS_MOVE, NULL);
if (ret < 0) {
SYSERROR("Failed to move the mount from \"%s\" to \"%s\"", path, target);