static char *ovl_detect_name(void);
static int ovl_do_rsync(struct bdev *orig, struct bdev *new,
struct lxc_conf *conf);
-static int ovl_rsync(struct rsync_data *data);
-static int ovl_rsync_wrapper(void *data);
static int ovl_remount_on_enodev(const char *lower, const char *target,
const char *name, unsigned long mountflags,
const void *options);
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf)
{
- char *src;
+ int ret;
+ char *src;
if (!snap) {
- ERROR("overlay is only for snapshot clones");
+ ERROR("The overlay storage driver can only be used for "
+ "snapshots");
return -22;
}
if (!orig->src || !orig->dest)
return -1;
- new->dest = lxc_string_join(
- "/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
- if (!new->dest)
- return -1;
+ new->dest = must_make_path(lxcpath, cname, "rootfs", NULL);
- if (mkdir_p(new->dest, 0755) < 0)
+ ret = mkdir_p(new->dest, 0755);
+ if (ret < 0 && errno != EEXIST) {
+ SYSERROR("Failed to create directory \"%s\"", new->dest);
return -1;
+ }
- if (am_unpriv() && chown_mapped_root(new->dest, conf) < 0)
- WARN("Failed to update ownership of %s", new->dest);
+ if (am_unpriv()) {
+ ret = chown_mapped_root(new->dest, conf);
+ if (ret < 0)
+ WARN("Failed to update ownership of %s", new->dest);
+ }
if (strcmp(orig->type, "dir") == 0) {
char *delta, *lastslash;
char *work;
int ret, len, lastslashidx;
- /*
- * if we have
- * /var/lib/lxc/c2/rootfs
- * then delta will be
- * /var/lib/lxc/c2/delta0
+ /* If we have "/var/lib/lxc/c2/rootfs" then delta will be
+ * "/var/lib/lxc/c2/delta0".
*/
lastslash = strrchr(new->dest, '/');
- if (!lastslash)
+ if (!lastslash) {
+ ERROR("Failed to detect \"/\" in string \"%s\"",
+ new->dest);
return -22;
- if (strlen(lastslash) < 7)
+ }
+
+ if (strlen(lastslash) < (sizeof("/rootfs") - 1)) {
+ ERROR("Failed to detect \"/rootfs\" in string \"%s\"",
+ new->dest);
return -22;
+ }
+
lastslash++;
lastslashidx = lastslash - new->dest;
delta = malloc(lastslashidx + 7);
- if (!delta)
+ if (!delta) {
+ ERROR("Failed to allocate memory");
return -1;
+ }
+
strncpy(delta, new->dest, lastslashidx + 1);
- strcpy(delta + lastslashidx, "delta0");
- if ((ret = mkdir(delta, 0755)) < 0) {
- SYSERROR("error: mkdir %s", delta);
+ strncpy(delta + lastslashidx, "delta0", sizeof("delta0") - 1);
+ delta[lastslashidx + sizeof("delta0")] = '\0';
+
+ ret = mkdir(delta, 0755);
+ if (ret < 0 && errno != EEXIST) {
+ SYSERROR("Failed to create directory \"%s\"", delta);
free(delta);
return -1;
}
- if (am_unpriv() && chown_mapped_root(delta, conf) < 0)
- WARN("Failed to update ownership of %s", delta);
- /*
- * Make workdir for overlayfs.v22 or higher:
+ if (am_unpriv()) {
+ ret = chown_mapped_root(delta, conf);
+ if (ret < 0)
+ WARN("Failed to update ownership of %s", delta);
+ }
+
+ /* Make workdir for overlayfs.v22 or higher:
* The workdir will be
* /var/lib/lxc/c2/olwork
* and is used to prepare files before they are atomically
*/
work = malloc(lastslashidx + 7);
if (!work) {
+ ERROR("Failed to allocate memory");
free(delta);
return -1;
}
+
strncpy(work, new->dest, lastslashidx + 1);
- strcpy(work + lastslashidx, "olwork");
+ strncpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
+ work[lastslashidx + sizeof("olwork")] = '\0';
+
if (mkdir(work, 0755) < 0) {
SYSERROR("error: mkdir %s", work);
free(delta);
free(work);
return -1;
}
- if (am_unpriv() && chown_mapped_root(work, conf) < 0)
- WARN("Failed to update ownership of %s", work);
+
+ if (am_unpriv()) {
+ ret = chown_mapped_root(work, conf);
+ if (ret < 0)
+ WARN("Failed to update ownership of %s", work);
+ }
free(work);
+ /* strlen("overlay:") = 8
+ * +
+ * strlen(delta)
+ * +
+ * :
+ * +
+ * strlen(src)
+ * +
+ * \0
+ */
src = lxc_storage_get_path(orig->src, orig->type);
- // the src will be 'overlayfs:lowerdir:upperdir'
- len = strlen(delta) + strlen(src) + 12;
+ len = 8 + strlen(delta) + 1 + strlen(src) + 1;
new->src = malloc(len);
if (!new->src) {
+ ERROR("Failed to allocate memory");
free(delta);
return -ENOMEM;
}
+
ret = snprintf(new->src, len, "overlay:%s:%s", src, delta);
free(delta);
- if (ret < 0 || ret >= len)
+ if (ret < 0 || (size_t)ret >= len) {
+ ERROR("Failed to create string");
return -1;
- } else if (!strcmp(orig->type, "overlayfs") || !strcmp(orig->type, "overlay")) {
- /*
- * What exactly do we want to do here? I think we want to use
- * the original lowerdir, with a private delta which is
- * originally rsynced from the original delta
- */
+ }
+ } else if (!strcmp(orig->type, "overlayfs") ||
+ !strcmp(orig->type, "overlay")) {
char *osrc, *odelta, *nsrc, *ndelta, *work;
char *lastslash;
- int len, ret, lastslashidx;
+ int ret, lastslashidx;
+ size_t len;
osrc = strdup(orig->src);
if (!osrc) {
- SYSERROR("Failed to duplicate \"%s\"", orig->src);
+ ERROR("Failed to duplicate string \"%s\"", orig->src);
return -22;
- }
+ }
nsrc = strchr(osrc, ':') + 1;
if ((nsrc != osrc + 8) && (nsrc != osrc + 10)) {
free(osrc);
- ERROR("Detected \":\" in \"%s\" at wrong position", osrc);
+ ERROR("Detected \":\" in \"%s\" at wrong position",
+ osrc);
return -22;
- }
+ }
odelta = strchr(nsrc, ':');
if (!odelta) {
free(osrc);
- ERROR("Failed to find \":\" in \"%s\"", nsrc);
+ ERROR("Failed to find \":\" in \"%s\"", nsrc);
return -22;
}
*odelta = '\0';
odelta++;
- ndelta = lxc_string_join("/", (const char *[]){lxcpath, cname, "rootfs", NULL}, false);
- if (!ndelta) {
- free(osrc);
- ERROR("Failed to create new path");
- return -ENOMEM;
- }
+ ndelta = must_make_path(lxcpath, cname, "delta0", NULL);
ret = mkdir(ndelta, 0755);
if (ret < 0 && errno != EEXIST) {
free(osrc);
free(ndelta);
- SYSERROR("Failed to create \"%s\"", ndelta);
+ SYSERROR("Failed to create directory \"%s\"", ndelta);
return -1;
}
- if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
- WARN("Failed to update ownership of %s", ndelta);
+ if (am_unpriv()) {
+ ret = chown_mapped_root(ndelta, conf);
+ if (ret < 0)
+ WARN("Failed to update ownership of %s",
+ ndelta);
+ }
- /*
- * make workdir for overlayfs.v22 or higher (see comment further
- * up)
+ /* Make workdir for overlayfs.v22 or higher (See the comment
+ * further up.).
*/
lastslash = strrchr(ndelta, '/');
if (!lastslash) {
ERROR("Failed to allocate memory");
return -1;
}
+
strncpy(work, ndelta, lastslashidx + 1);
- strcpy(work + lastslashidx, "olwork");
+ strncpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
+ work[lastslashidx + sizeof("olwork")] = '\0';
+
ret = mkdir(work, 0755);
if (ret < 0 && errno != EEXIST) {
free(osrc);
free(ndelta);
free(work);
- SYSERROR("Failed to create \"%s\"", ndelta);
+ SYSERROR("Failed to create directory \"%s\"", ndelta);
return -1;
}
- if (am_unpriv() && chown_mapped_root(work, conf) < 0)
- WARN("Failed to update ownership of %s", work);
+ if (am_unpriv()) {
+ ret = chown_mapped_root(work, conf);
+ if (ret < 0)
+ WARN("Failed to update ownership of %s", work);
+ }
free(work);
- len = strlen(nsrc) + strlen(ndelta) + 10;
+ /* strlen("overlay:") = 8
+ * +
+ * strlen(delta)
+ * +
+ * :
+ * +
+ * strlen(src)
+ * +
+ * \0
+ */
+ len = 8 + strlen(ndelta) + 1 + strlen(nsrc) + 1;
new->src = malloc(len);
if (!new->src) {
free(osrc);
ret = snprintf(new->src, len, "overlay:%s:%s", nsrc, ndelta);
free(osrc);
free(ndelta);
- if (ret < 0 || ret >= len) {
+ if (ret < 0 || (size_t)ret >= len) {
ERROR("Failed to create string");
return -1;
- }
+ }
return ovl_do_rsync(orig, new, conf);
} else {
ERROR("overlay clone of %s container is not yet supported",
orig->type);
- /*
- * Note, supporting this will require ovl_mount supporting
+ /* Note, supporting this will require ovl_mount supporting
* mounting of the underlay. No big deal, just needs to be done.
*/
return -1;
return 0;
}
-/*
- * to say 'lxc-create -t ubuntu -n o1 -B overlay' means you want
- * $lxcpath/$lxcname/rootfs to have the created container, while all
- * changes after starting the container are written to
- * $lxcpath/$lxcname/delta0
+/* To say "lxc-create -t ubuntu -n o1 -B overlay" means you want
+ * "<lxcpath>/<lxcname>/rootfs" to have the created container, while all changes
+ * after starting the container are written to "<lxcpath>/<lxcname>/delta0".
*/
int ovl_create(struct bdev *bdev, const char *dest, const char *n,
- struct bdev_specs *specs)
+ struct bdev_specs *specs)
{
char *delta;
- int ret, len = strlen(dest), newlen;
+ int ret;
+ size_t len, newlen;
- if (len < 8 || strcmp(dest + len - 7, "/rootfs") != 0)
+ len = strlen(dest);
+ if (len < 8 || strcmp(dest + len - 7, "/rootfs")) {
+ ERROR("Failed to detect \"/rootfs\" in \"%s\"", dest);
return -1;
+ }
- if (!(bdev->dest = strdup(dest))) {
- ERROR("Out of memory");
+ bdev->dest = strdup(dest);
+ if (!bdev->dest) {
+ ERROR("Failed to duplicate string \"%s\"", dest);
return -1;
}
- delta = alloca(strlen(dest) + 1);
- strcpy(delta, dest);
- strcpy(delta + len - 6, "delta0");
+ delta = malloc(len + 1);
+ if (!delta) {
+ ERROR("Failed to allocate memory");
+ return -1;
+ }
+
+ strncpy(delta, dest, len);
+ strncpy(delta + len - 6, "delta0", sizeof("delta0") - 1);
+ delta[len + sizeof("delta0")] = '\0';
- if (mkdir_p(delta, 0755) < 0) {
- ERROR("Error creating %s", delta);
+ ret = mkdir_p(delta, 0755);
+ if (ret < 0) {
+ SYSERROR("Failed to create directory \"%s\"", delta);
+ free(delta);
return -1;
}
- // overlay:lower:upper
+ /* overlay:lower:upper */
newlen = (2 * len) + strlen("overlay:") + 2;
bdev->src = malloc(newlen);
if (!bdev->src) {
- ERROR("Out of memory");
+ ERROR("Failed to allocate memory");
+ free(delta);
return -1;
}
+
ret = snprintf(bdev->src, newlen, "overlay:%s:%s", dest, delta);
- if (ret < 0 || ret >= newlen)
+ if (ret < 0 || (size_t)ret >= newlen) {
+ ERROR("Failed to create string");
+ free(delta);
return -1;
+ }
- if (mkdir_p(bdev->dest, 0755) < 0) {
- ERROR("Error creating %s", bdev->dest);
+ ret = mkdir_p(bdev->dest, 0755);
+ if (ret < 0) {
+ SYSERROR("Failed to create directory \"%s\"", bdev->dest);
+ free(delta);
return -1;
}
+ free(delta);
return 0;
}
int ovl_destroy(struct bdev *orig)
{
- bool ovl;
+ bool ovl;
char *upper = orig->src;
- ovl = !strncmp(upper, "overlay:", 8);
+ ovl = !strncmp(upper, "overlay:", 8);
if (!ovl && strncmp(upper, "overlayfs:", 10))
return -22;
- if (ovl)
- upper += 8;
- else
- upper += 10;
+ if (ovl)
+ upper += 8;
+ else
+ upper += 10;
upper = strchr(upper, ':');
if (!upper)
char *tmp, *options, *dup, *lower, *upper;
char *options_work, *work, *lastslash;
int lastslashidx;
- int len, len2;
+ size_t len, len2;
unsigned long mntflags;
char *mntdata;
int ret, ret2;
if (!ovl_name)
ovl_name = ovl_detect_name();
- /*
- * separately mount it first:
- * mount -t overlayfs * -oupperdir=${upper},lowerdir=${lower} lower dest
+ /* Separately mount it first:
+ * mount -t overlay * -o upperdir=${upper},lowerdir=${lower} lower dest
*/
- dup = alloca(strlen(bdev->src) + 1);
- strcpy(dup, bdev->src);
+ dup = strdup(bdev->src);
+ if (!dup) {
+ ERROR("Failed to allocate memory");
+ return -1;
+ }
+
/* support multiple lower layers */
- if (!(lower = strstr(dup, ":/")))
- return -22;
+ lower = strstr(dup, ":/");
+ if (!lower) {
+ ERROR("Failed to detect \":/\" in string \"%s\"", dup);
+ free(dup);
+ return -22;
+ }
+
lower++;
upper = lower;
while ((tmp = strstr(++upper, ":/"))) {
upper = tmp;
}
- if (--upper == lower)
+
+ upper--;
+ if (upper == lower) {
+ free(dup);
return -22;
+ }
*upper = '\0';
upper++;
- // if delta doesn't yet exist, create it
- if (mkdir_p(upper, 0755) < 0 && errno != EEXIST)
+ /* if delta doesn't yet exist, create it */
+ ret = mkdir_p(upper, 0755) < 0;
+ if (ret < 0 && errno != EEXIST) {
+ SYSERROR("Failed to create directory \"%s\"", upper);
+ free(dup);
return -22;
+ }
- /*
- * overlayfs.v22 or higher needs workdir option:
+ /* overlayfs.v22 or higher needs workdir option:
* if upper is
* /var/lib/lxc/c2/delta0
* then workdir is
* /var/lib/lxc/c2/olwork
*/
lastslash = strrchr(upper, '/');
- if (!lastslash)
+ if (!lastslash) {
+ ERROR("Failed to detect \"/\" in string \"%s\"", upper);
+ free(dup);
return -22;
+ }
+
lastslash++;
lastslashidx = lastslash - upper;
- work = alloca(lastslashidx + 7);
- strncpy(work, upper, lastslashidx + 7);
- strcpy(work + lastslashidx, "olwork");
+ work = malloc(lastslashidx + 7);
+ if (!work) {
+ ERROR("Failed to allocate memory");
+ free(dup);
+ return -22;
+ }
- if (parse_mntopts(bdev->mntopts, &mntflags, &mntdata) < 0) {
+ strncpy(work, upper, lastslashidx + 1);
+ strncpy(work + lastslashidx, "olwork", sizeof("olwork") - 1);
+ work[lastslashidx + sizeof("olwork")] = '\0';
+
+ ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata);
+ if (ret < 0) {
+ ERROR("Failed to parse mount options");
free(mntdata);
+ free(dup);
+ free(work);
return -22;
}
- if (mkdir_p(work, 0755) < 0 && errno != EEXIST) {
+ ret = mkdir_p(work, 0755);
+ if (ret < 0 && errno != EEXIST) {
+ SYSERROR("Failed to create directory \"%s\"", work);
free(mntdata);
+ free(dup);
+ free(work);
return -22;
}
*/
if (mntdata) {
- len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
+ len = strlen(lower) + strlen(upper) +
+ strlen("upperdir=,lowerdir=,") + strlen(mntdata) + 1;
options = alloca(len);
- ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s", upper, lower, mntdata);
+ ret = snprintf(options, len, "upperdir=%s,lowerdir=%s,%s",
+ upper, lower, mntdata);
- len2 = strlen(lower) + strlen(upper) + strlen(work)
- + strlen("upperdir=,lowerdir=,workdir=") + strlen(mntdata) + 1;
+ len2 = strlen(lower) + strlen(upper) + strlen(work) +
+ strlen("upperdir=,lowerdir=,workdir=") +
+ strlen(mntdata) + 1;
options_work = alloca(len2);
- ret2 = snprintf(options, len2, "upperdir=%s,lowerdir=%s,workdir=%s,%s",
- upper, lower, work, mntdata);
+ ret2 = snprintf(options, len2,
+ "upperdir=%s,lowerdir=%s,workdir=%s,%s", upper,
+ lower, work, mntdata);
} else {
- len = strlen(lower) + strlen(upper) + strlen("upperdir=,lowerdir=") + 1;
+ len = strlen(lower) + strlen(upper) +
+ strlen("upperdir=,lowerdir=") + 1;
options = alloca(len);
- ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper, lower);
+ ret = snprintf(options, len, "upperdir=%s,lowerdir=%s", upper,
+ lower);
- len2 = strlen(lower) + strlen(upper) + strlen(work)
- + strlen("upperdir=,lowerdir=,workdir=") + 1;
+ len2 = strlen(lower) + strlen(upper) + strlen(work) +
+ strlen("upperdir=,lowerdir=,workdir=") + 1;
options_work = alloca(len2);
- ret2 = snprintf(options_work, len2, "upperdir=%s,lowerdir=%s,workdir=%s",
- upper, lower, work);
+ ret2 = snprintf(options_work, len2,
+ "upperdir=%s,lowerdir=%s,workdir=%s", upper,
+ lower, work);
}
if (ret < 0 || ret >= len || ret2 < 0 || ret2 >= len2) {
+ ERROR("Failed to create string");
free(mntdata);
+ free(dup);
+ free(work);
return -1;
}
- /* Assume we need a workdir as we are on a overlay version >= v22. */
+ /* Assume we need a workdir as we are on a overlay version >= v22. */
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
MS_MGC_VAL | mntflags, options_work);
if (ret < 0) {
- INFO("Overlay: Error mounting %s onto %s with options %s. "
- "Retrying without workdir: %s.",
+ INFO("Failed to mount \"%s\" on \"%s\" with options \"%s\". "
+ "Retrying without workdir: %s",
lower, bdev->dest, options_work, strerror(errno));
- /* Assume we cannot use a workdir as we are on a version <= v21. */
+ /* Assume we cannot use a workdir as we are on a version <= v21.
+ */
ret = ovl_remount_on_enodev(lower, bdev->dest, ovl_name,
- MS_MGC_VAL | mntflags, options);
+ MS_MGC_VAL | mntflags, options);
if (ret < 0)
- SYSERROR("Overlay: Error mounting %s onto %s with "
- "options %s: %s.",
- lower, bdev->dest, options,
- strerror(errno));
+ SYSERROR("Failed to mount \"%s\" on \"%s\" with "
+ "options \"%s\": %s",
+ lower, bdev->dest, options, strerror(errno));
else
- INFO("Overlay: Mounted %s onto %s with options %s.",
+ INFO("Mounted \"%s\" on \"%s\" with options \"%s\"",
lower, bdev->dest, options);
} else {
- INFO("Overlay: Mounted %s onto %s with options %s.", lower,
+ INFO("Mounted \"%s\" on \"%s\" with options \"%s\"", lower,
bdev->dest, options_work);
}
+
+ free(dup);
+ free(work);
return ret;
}
int ovl_umount(struct bdev *bdev)
{
+ int ret;
+
if (strcmp(bdev->type, "overlay") && strcmp(bdev->type, "overlayfs"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
- return umount(bdev->dest);
+ ret = umount(bdev->dest);
+ if (ret < 0)
+ SYSERROR("Failed to unmount \"%s\"", bdev->dest);
+ else
+ TRACE("Unmounted \"%s\"", bdev->dest);
+
+ return ret;
}
char *ovl_get_lower(const char *rootfs_path)
{
char *s1;
+
s1 = strstr(rootfs_path, ":/");
if (!s1)
return NULL;
if (!s1)
return NULL;
- if ((s2 = strstr(s1, ":/"))) {
+ s2 = strstr(s1, ":/");
+ if (s2) {
s2 = s2 + 1;
if ((s3 = strstr(s2, ":/")))
*s3 = '\0';
const char *lxc_name, const char *lxc_path)
{
char lxcpath[MAXPATHLEN];
- char *rootfs_path = NULL;
- char *rootfsdir = NULL;
- char *upperdir = NULL;
- char *workdir = NULL;
- char **opts = NULL;
+ char **opts;
+ int ret;
+ size_t arrlen, dirlen, i, len, rootfslen;
int fret = -1;
- int ret = 0;
- size_t arrlen = 0;
- size_t dirlen = 0;
- size_t i;
- size_t len = 0;
- size_t rootfslen = 0;
+ char *rootfs_dir = NULL, *rootfs_path = NULL, *upperdir = NULL,
+ *workdir = NULL;
/* When rootfs == NULL we have a container without a rootfs. */
if (rootfs && rootfs->path)
goto err;
for (i = 0; i < arrlen; i++) {
- if (strstr(opts[i], "upperdir=") && (strlen(opts[i]) > (len = strlen("upperdir="))))
+ if (strstr(opts[i], "upperdir=") &&
+ (strlen(opts[i]) > (len = strlen("upperdir="))))
upperdir = opts[i] + len;
- else if (strstr(opts[i], "workdir=") && (strlen(opts[i]) > (len = strlen("workdir="))))
+ else if (strstr(opts[i], "workdir=") &&
+ (strlen(opts[i]) > (len = strlen("workdir="))))
workdir = opts[i] + len;
}
if (rootfs_path) {
- ret = snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name);
+ ret =
+ snprintf(lxcpath, MAXPATHLEN, "%s/%s", lxc_path, lxc_name);
if (ret < 0 || ret >= MAXPATHLEN)
goto err;
- rootfsdir = ovl_get_rootfs(rootfs_path, &rootfslen);
- if (!rootfsdir)
+ rootfs_dir = ovl_get_rootfs(rootfs_path, &rootfslen);
+ if (!rootfs_dir)
goto err;
dirlen = strlen(lxcpath);
if (upperdir) {
if (!rootfs_path)
ret = mkdir_p(upperdir, 0755);
- else if ((strncmp(upperdir, lxcpath, dirlen) == 0) && (strncmp(upperdir, rootfsdir, rootfslen) != 0))
+ else if (!strncmp(upperdir, lxcpath, dirlen) &&
+ strncmp(upperdir, rootfs_dir, rootfslen))
ret = mkdir_p(upperdir, 0755);
if (ret < 0)
- WARN("Failed to create upperdir");
+ WARN("Failed to create directory \"%s\": %s", upperdir,
+ strerror(errno));
}
ret = 0;
if (workdir) {
if (!rootfs_path)
ret = mkdir_p(workdir, 0755);
- else if ((strncmp(workdir, lxcpath, dirlen) == 0) && (strncmp(workdir, rootfsdir, rootfslen) != 0))
+ else if (!strncmp(workdir, lxcpath, dirlen) &&
+ strncmp(workdir, rootfs_dir, rootfslen))
ret = mkdir_p(workdir, 0755);
if (ret < 0)
- WARN("Failed to create workdir");
+ WARN("Failed to create directory \"%s\": %s", workdir,
+ strerror(errno));
}
fret = 0;
err:
- free(rootfsdir);
+ free(rootfs_dir);
lxc_free_array((void **)opts, free);
return fret;
}
-/*
- * To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
+/* To be called from lxcapi_clone() in lxccontainer.c: When we clone a container
* with overlay lxc.mount.entry entries we need to update absolute paths for
* upper- and workdir. This update is done in two locations:
* lxc_conf->unexpanded_config and lxc_conf->mount_list. Both updates are done
- * independent of each other since lxc_conf->mountlist may container more mount
- * entries (e.g. from other included files) than lxc_conf->unexpanded_config .
+ * independent of each other since lxc_conf->mountlist may contain more mount
+ * entries (e.g. from other included files) than lxc_conf->unexpanded_config.
*/
int ovl_update_abs_paths(struct lxc_conf *lxc_conf, const char *lxc_path,
const char *lxc_name, const char *newpath,
const char *newname)
{
- char new_upper[MAXPATHLEN];
- char new_work[MAXPATHLEN];
- char old_upper[MAXPATHLEN];
- char old_work[MAXPATHLEN];
- char *cleanpath = NULL;
+ char new_upper[MAXPATHLEN], new_work[MAXPATHLEN], old_upper[MAXPATHLEN],
+ old_work[MAXPATHLEN];
size_t i;
+ struct lxc_list *iterator;
+ char *cleanpath = NULL;
int fret = -1;
int ret = 0;
- struct lxc_list *iterator;
const char *ovl_dirs[] = {"br", "upperdir", "workdir"};
cleanpath = strdup(newpath);
goto err;
}
- ret = snprintf(old_work, MAXPATHLEN, "workdir=%s/%s", lxc_path, lxc_name);
+ ret =
+ snprintf(old_work, MAXPATHLEN, "workdir=%s/%s", lxc_path, lxc_name);
if (ret < 0 || ret >= MAXPATHLEN)
goto err;
- ret = snprintf(new_work, MAXPATHLEN, "workdir=%s/%s", cleanpath, newname);
+ ret =
+ snprintf(new_work, MAXPATHLEN, "workdir=%s/%s", cleanpath, newname);
if (ret < 0 || ret >= MAXPATHLEN)
goto err;
lxc_list_for_each(iterator, &lxc_conf->mount_list) {
- char *mnt_entry = NULL;
- char *new_mnt_entry = NULL;
- char *tmp = NULL;
- char *tmp_mnt_entry = NULL;
+ char *mnt_entry = NULL, *new_mnt_entry = NULL, *tmp = NULL,
+ *tmp_mnt_entry = NULL;
+
mnt_entry = iterator->elem;
if (strstr(mnt_entry, "overlay"))
if (!tmp)
continue;
- ret = snprintf(old_upper, MAXPATHLEN, "%s=%s/%s", tmp, lxc_path, lxc_name);
+ ret = snprintf(old_upper, MAXPATHLEN, "%s=%s/%s", tmp, lxc_path,
+ lxc_name);
if (ret < 0 || ret >= MAXPATHLEN)
goto err;
- ret = snprintf(new_upper, MAXPATHLEN, "%s=%s/%s", tmp, cleanpath, newname);
+ ret = snprintf(new_upper, MAXPATHLEN, "%s=%s/%s", tmp,
+ cleanpath, newname);
if (ret < 0 || ret >= MAXPATHLEN)
goto err;
if (strstr(mnt_entry, old_upper)) {
- tmp_mnt_entry = lxc_string_replace(old_upper, new_upper, mnt_entry);
+ tmp_mnt_entry =
+ lxc_string_replace(old_upper, new_upper, mnt_entry);
}
if (strstr(mnt_entry, old_work)) {
if (tmp_mnt_entry)
- new_mnt_entry = lxc_string_replace(old_work, new_work, tmp_mnt_entry);
+ new_mnt_entry = lxc_string_replace(
+ old_work, new_work, tmp_mnt_entry);
else
- new_mnt_entry = lxc_string_replace(old_work, new_work, mnt_entry);
+ new_mnt_entry = lxc_string_replace(
+ old_work, new_work, mnt_entry);
}
if (new_mnt_entry) {
const char *name, unsigned long mountflags,
const void *options)
{
- int ret;
- ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options);
- if (ret < 0 && errno == ENODEV) /* Try other module name. */
+ int ret;
+ ret = mount(lower, target, ovl_name, MS_MGC_VAL | mountflags, options);
+ if (ret < 0 && errno == ENODEV) /* Try other module name. */
ret = mount(lower, target,
ovl_name == ovl_version[0] ? ovl_version[1]
: ovl_version[0],
MS_MGC_VAL | mountflags, options);
- return ret;
-}
-
-static int ovl_rsync(struct rsync_data *data)
-{
- int ret;
-
- if (setgid(0) < 0) {
- ERROR("Failed to setgid to 0");
- return -1;
- }
- if (setgroups(0, NULL) < 0)
- WARN("Failed to clear groups");
- if (setuid(0) < 0) {
- ERROR("Failed to setuid to 0");
- return -1;
- }
-
- if (unshare(CLONE_NEWNS) < 0) {
- SYSERROR("Unable to unshare mounts ns");
- return -1;
- }
- if (detect_shared_rootfs()) {
- if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
- SYSERROR("Failed to make / rslave");
- ERROR("Continuing...");
- }
- }
- if (ovl_mount(data->orig) < 0) {
- ERROR("Failed mounting original container fs");
- return -1;
- }
- if (ovl_mount(data->new) < 0) {
- ERROR("Failed mounting new container fs");
- return -1;
- }
- ret = do_rsync(data->orig->dest, data->new->dest);
-
- ovl_umount(data->new);
- ovl_umount(data->orig);
-
- if (ret < 0) {
- ERROR("rsyncing %s to %s", data->orig->dest, data->new->dest);
- return -1;
- }
-
- return 0;
+ return ret;
}
static char *ovl_detect_name(void)
{
+ FILE *f;
char *v = ovl_version[0];
char *line = NULL;
size_t len = 0;
- FILE *f = fopen("/proc/filesystems", "r");
+
+ f = fopen("/proc/filesystems", "r");
if (!f)
return v;
return v;
}
-static int ovl_do_rsync(struct bdev *orig, struct bdev *new, struct lxc_conf *conf)
+static int ovl_do_rsync(struct bdev *orig, struct bdev *new,
+ struct lxc_conf *conf)
{
int ret = -1;
- struct rsync_data rdata;
+ struct rsync_data rdata = {0, 0};
+ char cmd_output[MAXPATHLEN] = {0};
rdata.orig = orig;
rdata.new = new;
- if (am_unpriv())
- ret = userns_exec_1(conf, ovl_rsync_wrapper, &rdata,
- "ovl_rsync_wrapper");
- else
- ret = ovl_rsync(&rdata);
- if (ret)
- ERROR("copying overlay delta");
+ if (am_unpriv()) {
+ ret = userns_exec_1(conf, lxc_rsync_exec_wrapper, &rdata,
+ "lxc_rsync_exec_wrapper");
+ if (ret < 0)
+ ERROR("Failed to rsync from \"%s\" into \"%s\"",
+ orig->dest, new->dest);
+ } else {
+ ret = run_command(cmd_output, sizeof(cmd_output),
+ lxc_rsync_exec_wrapper, (void *)&rdata);
+ if (ret < 0)
+ ERROR("Failed to rsync from \"%s\" into \"%s\": %s",
+ orig->dest, new->dest, cmd_output);
+ }
return ret;
}
-
-static int ovl_rsync_wrapper(void *data)
-{
- struct rsync_data *arg = data;
- return ovl_rsync(arg);
-}
-