]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/storage/dir.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
13 #include "memory_utils.h"
14 #include "mount_utils.h"
18 lxc_log_define(dir
, lxc
);
21 * For a simple directory bind mount, we substitute the old container name and
24 int dir_clonepaths(struct lxc_storage
*orig
, struct lxc_storage
*new,
25 const char *oldname
, const char *cname
, const char *oldpath
,
26 const char *lxcpath
, int snap
, uint64_t newsize
,
27 struct lxc_conf
*conf
)
29 const char *src_no_prefix
;
34 return log_error_errno(-EINVAL
, EINVAL
, "Directories cannot be snapshotted");
36 if (!orig
->dest
|| !orig
->src
)
37 return ret_errno(EINVAL
);
39 len
= STRLITERALLEN("dir:") + strlen(lxcpath
) + STRLITERALLEN("/") +
40 strlen(cname
) + STRLITERALLEN("/rootfs") + 1;
41 new->src
= malloc(len
);
43 return ret_errno(ENOMEM
);
45 ret
= snprintf(new->src
, len
, "dir:%s/%s/rootfs", lxcpath
, cname
);
46 if (ret
< 0 || (size_t)ret
>= len
)
47 return ret_errno(EIO
);
49 src_no_prefix
= lxc_storage_get_path(new->src
, new->type
);
50 new->dest
= strdup(src_no_prefix
);
52 return log_error_errno(-ENOMEM
, ENOMEM
, "Failed to duplicate string \"%s\"", new->src
);
54 TRACE("Created new path \"%s\" for dir storage driver", new->dest
);
58 int dir_create(struct lxc_storage
*bdev
, const char *dest
, const char *n
,
59 struct bdev_specs
*specs
, const struct lxc_conf
*conf
)
61 __do_free
char *bdev_src
= NULL
, *bdev_dest
= NULL
;
66 len
= STRLITERALLEN("dir:");
67 if (specs
&& specs
->dir
)
72 len
+= strlen(src
) + 1;
73 bdev_src
= malloc(len
);
75 return ret_errno(ENOMEM
);
77 ret
= snprintf(bdev_src
, len
, "dir:%s", src
);
78 if (ret
< 0 || (size_t)ret
>= len
)
79 return ret_errno(EIO
);
81 bdev_dest
= strdup(dest
);
83 return ret_errno(ENOMEM
);
85 ret
= mkdir_p(dest
, 0755);
87 return log_error_errno(-errno
, errno
, "Failed to create directory \"%s\"", dest
);
89 TRACE("Created directory \"%s\"", dest
);
90 bdev
->src
= move_ptr(bdev_src
);
91 bdev
->dest
= move_ptr(bdev_dest
);
96 int dir_destroy(struct lxc_storage
*orig
)
101 src
= lxc_storage_get_path(orig
->src
, orig
->src
);
103 ret
= lxc_rmdir_onedev(src
, NULL
);
105 return log_error_errno(ret
, errno
, "Failed to delete \"%s\"", src
);
110 bool dir_detect(const char *path
)
115 if (!strncmp(path
, "dir:", 4))
118 ret
= stat(path
, &statbuf
);
119 if (ret
== -1 && errno
== EPERM
)
120 return log_error_errno(false, errno
, "dir_detect: failed to look at \"%s\"", path
);
122 if (ret
== 0 && S_ISDIR(statbuf
.st_mode
))
128 int dir_mount(struct lxc_storage
*bdev
)
130 struct lxc_rootfs
*rootfs
= bdev
->rootfs
;
131 struct lxc_mount_options
*mnt_opts
= &rootfs
->mnt_opts
;
133 const char *source
, *target
;
135 if (!strequal(bdev
->type
, "dir"))
136 return syserror_set(-EINVAL
, "Invalid storage driver");
138 if (is_empty_string(bdev
->src
))
139 return syserror_set(-EINVAL
, "Missing rootfs path");
141 if (is_empty_string(bdev
->dest
))
142 return syserror_set(-EINVAL
, "Missing target mountpoint");
144 if (rootfs
->dfd_idmapped
>= 0 && !can_use_bind_mounts())
145 return syserror_set(-EOPNOTSUPP
, "Idmapped mount requested but kernel doesn't support new mount API");
147 source
= lxc_storage_get_path(bdev
->src
, bdev
->type
);
150 if (can_use_bind_mounts()) {
151 __do_close
int fd_source
= -EBADF
, fd_target
= -EBADF
;
153 fd_target
= open_at(-EBADF
, target
, PROTECT_OPATH_DIRECTORY
, 0, 0);
155 return syserror("Failed to open \"%s\"", target
);
157 if (rootfs
->dfd_idmapped
>= 0) {
158 ret
= move_detached_mount(rootfs
->dfd_idmapped
, fd_target
, "",
159 PROTECT_OPATH_DIRECTORY
,
160 PROTECT_LOOKUP_BENEATH
);
162 fd_source
= open_at(-EBADF
, source
, PROTECT_OPATH_DIRECTORY
, 0, 0);
164 return syserror("Failed to open \"%s\"", source
);
166 ret
= fd_bind_mount(fd_source
, "",
167 PROTECT_OPATH_DIRECTORY
,
168 PROTECT_LOOKUP_BENEATH
, fd_target
,
169 "", PROTECT_OPATH_DIRECTORY
,
170 PROTECT_LOOKUP_BENEATH
, 0, true);
173 ret
= mount(source
, target
, "bind", MS_BIND
| MS_REC
| mnt_opts
->mnt_flags
| mnt_opts
->prop_flags
, mnt_opts
->data
);
174 if (!ret
&& (mnt_opts
->mnt_flags
& MS_RDONLY
)) {
175 unsigned long mflags
;
177 mflags
= add_required_remount_flags(source
, target
,
180 mnt_opts
->mnt_flags
|
183 ret
= mount(source
, target
, "bind", mflags
, mnt_opts
->data
);
185 SYSERROR("Failed to remount \"%s\" on \"%s\" read-only", source
, target
);
187 TRACE("Remounted \"%s\" on \"%s\" read-only", source
, target
);
191 return syserror_set(ret
, "Failed to mount \"%s\" onto \"%s\"", source
, target
);
193 TRACE("Mounted \"%s\" onto \"%s\"", source
, target
);
197 int dir_umount(struct lxc_storage
*bdev
)
199 if (strcmp(bdev
->type
, "dir"))
200 return ret_errno(EINVAL
);
202 if (!bdev
->src
|| !bdev
->dest
)
203 return ret_errno(EINVAL
);
205 return umount2(bdev
->dest
, MNT_DETACH
);