From: Christian Brauner Date: Fri, 12 Jan 2018 13:27:23 +0000 (+0100) Subject: tools: move lxc-copy to API symbols only X-Git-Tag: lxc-3.0.0.beta1~36^2~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0cb3e3a6ddbe9de3817546870e6481ddd51694aa;p=thirdparty%2Flxc.git tools: move lxc-copy to API symbols only Closes #2073. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/tools/include/getsubopt.c b/src/lxc/tools/include/getsubopt.c new file mode 100644 index 000000000..b75497b1a --- /dev/null +++ b/src/lxc/tools/include/getsubopt.c @@ -0,0 +1,89 @@ +/* + * Android c-library does not have getsubopt, + * so code lifted from uClibc + * http://git.uclibc.org/uClibc/tree/libc/unistd/getsubopt.c + */ + +/* Parse comma separate list into words. + Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#include + +char *strchrnul(const char *s, int c) +{ + char *result; + + result = strchr( s, c ); + + if( !result ) + { + result = (char *)s + strlen( s ); + } + + return( result ); +} + +/* Parse comma separated suboption from *OPTIONP and match against + strings in TOKENS. If found return index and set *VALUEP to + optional value introduced by an equal sign. If the suboption is + not part of TOKENS return in *VALUEP beginning of unknown + suboption. On exit *OPTIONP is set to the beginning of the next + token or at the terminating NUL character. */ +int +getsubopt (char **optionp, char *const *tokens, char **valuep) +{ + char *endp, *vstart; + int cnt; + + if (**optionp == '\0') + return -1; + + /* Find end of next token. */ + endp = strchrnul (*optionp, ','); + + /* Find start of value. */ + vstart = memchr (*optionp, '=', endp - *optionp); + if (vstart == NULL) + vstart = endp; + + /* Try to match the characters between *OPTIONP and VSTART against + one of the TOKENS. */ + for (cnt = 0; tokens[cnt] != NULL; ++cnt) + if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0 + && tokens[cnt][vstart - *optionp] == '\0') + { + /* We found the current option in TOKENS. */ + *valuep = vstart != endp ? vstart + 1 : NULL; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return cnt; + } + + /* The current suboption does not match any option. */ + *valuep = *optionp; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return -1; +} diff --git a/src/lxc/tools/include/getsubopt.h b/src/lxc/tools/include/getsubopt.h new file mode 100644 index 000000000..e45cf66b0 --- /dev/null +++ b/src/lxc/tools/include/getsubopt.h @@ -0,0 +1,4 @@ +#ifndef _GETSUBOPT_H +#define _GETSUBOPT_H +int getsubopt (char **optionp, char *const *tokens, char **valuep); +#endif diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c index 1718f84a7..ae8b81021 100644 --- a/src/lxc/tools/lxc_copy.c +++ b/src/lxc/tools/lxc_copy.c @@ -17,37 +17,29 @@ */ #define _GNU_SOURCE -#include "config.h" - -#include +#include +#include +#include #include #include -#include -#include +#include #include -#include +#include #include -#include -#include -#include -#include +#include #include -#include +#include +#include +#include +#include #include -#include "attach.h" -#include "log.h" -#include "confile.h" #include "arguments.h" -#include "lxc.h" -#include "conf.h" -#include "state.h" -#include "storage.h" -#include "utils.h" +#include "tool_utils.h" #ifndef HAVE_GETSUBOPT -#include <../include/getsubopt.h> +#include "include/getsubopt.h" #endif enum mnttype { @@ -186,7 +178,6 @@ int main(int argc, char *argv[]) if (lxc_log_init(&log)) exit(ret); - lxc_log_options_no_override(); /* REMOVE IN LXC 3.0 */ setenv("LXC_UPDATE_CONFIG_FORMAT", "1", 0); @@ -273,17 +264,17 @@ static struct mnts *add_mnt(struct mnts **mnts, unsigned int *num, enum mnttype static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_arguments *arg) { - char upperdir[MAXPATHLEN]; - char workdir[MAXPATHLEN]; + char upperdir[TOOL_MAXPATHLEN]; + char workdir[TOOL_MAXPATHLEN]; unsigned int i; int ret; struct mnts *m = NULL; for (i = 0, m = mnts; i < num; i++, m++) { if ((m->mnt_type == LXC_MNT_OVL) || (m->mnt_type == LXC_MNT_AUFS)) { - ret = snprintf(upperdir, MAXPATHLEN, "%s/%s/delta#XXXXXX", + ret = snprintf(upperdir, TOOL_MAXPATHLEN, "%s/%s/delta#XXXXXX", arg->newpath, arg->newname); - if (ret < 0 || ret >= MAXPATHLEN) + if (ret < 0 || ret >= TOOL_MAXPATHLEN) return -1; if (!mkdtemp(upperdir)) return -1; @@ -293,9 +284,9 @@ static int mk_rand_ovl_dirs(struct mnts *mnts, unsigned int num, struct lxc_argu } if (m->mnt_type == LXC_MNT_OVL) { - ret = snprintf(workdir, MAXPATHLEN, "%s/%s/work#XXXXXX", + ret = snprintf(workdir, TOOL_MAXPATHLEN, "%s/%s/work#XXXXXX", arg->newpath, arg->newname); - if (ret < 0 || ret >= MAXPATHLEN) + if (ret < 0 || ret >= TOOL_MAXPATHLEN) return -1; if (!mkdtemp(workdir)) return -1; @@ -400,19 +391,19 @@ static int do_clone(struct lxc_container *c, char *newname, char *newpath, static int do_clone_ephemeral(struct lxc_container *c, struct lxc_arguments *arg, char **args, int flags) { - char *bdev; char *premount; - char randname[MAXPATHLEN]; + char randname[TOOL_MAXPATHLEN]; unsigned int i; int ret = 0; bool bret = true, started = false; + char *tmp_buf = randname; struct lxc_container *clone; lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT; attach_options.env_policy = LXC_ATTACH_CLEAR_ENV; if (!arg->newname) { - ret = snprintf(randname, MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name); - if (ret < 0 || ret >= MAXPATHLEN) + ret = snprintf(randname, TOOL_MAXPATHLEN, "%s/%s_XXXXXX", arg->newpath, arg->name); + if (ret < 0 || ret >= TOOL_MAXPATHLEN) return -1; if (!mkdtemp(randname)) return -1; @@ -429,12 +420,6 @@ static int do_clone_ephemeral(struct lxc_container *c, return -1; if (arg->tmpfs) { - bdev = c->lxc_conf->rootfs.bdev_type; - if (bdev && strcmp(bdev, "dir")) { - fprintf(stderr, "Cannot currently use tmpfs with %s storage backend.\n", bdev); - goto destroy_and_put; - } - premount = mount_tmpfs(arg->name, arg->newname, arg->newpath, arg); if (!premount) goto destroy_and_put; @@ -501,7 +486,8 @@ static int do_clone_ephemeral(struct lxc_container *c, destroy_and_put: if (started) clone->shutdown(clone, -1); - if (!started || clone->lxc_conf->ephemeral != 1) + ret = clone->get_config_item(clone, "lxc.ephemeral", tmp_buf, TOOL_MAXPATHLEN); + if (ret > 0 && strcmp(tmp_buf, "0")) clone->destroy(clone); free_mnts(); lxc_container_put(clone); diff --git a/src/lxc/tools/tool_utils.c b/src/lxc/tools/tool_utils.c index 00181ab65..29adc6776 100644 --- a/src/lxc/tools/tool_utils.c +++ b/src/lxc/tools/tool_utils.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -380,3 +381,161 @@ int lxc_safe_long(const char *numstr, long int *converted) *converted = sli; return 0; } + +void lxc_free_array(void **array, lxc_free_fn element_free_fn) +{ + void **p; + for (p = array; p && *p; p++) + element_free_fn(*p); + free((void*)array); +} + +int lxc_grow_array(void ***array, size_t* capacity, size_t new_size, size_t capacity_increment) +{ + size_t new_capacity; + void **new_array; + + /* first time around, catch some trivial mistakes of the user + * only initializing one of these */ + if (!*array || !*capacity) { + *array = NULL; + *capacity = 0; + } + + new_capacity = *capacity; + while (new_size + 1 > new_capacity) + new_capacity += capacity_increment; + if (new_capacity != *capacity) { + /* we have to reallocate */ + new_array = realloc(*array, new_capacity * sizeof(void *)); + if (!new_array) + return -1; + memset(&new_array[*capacity], 0, (new_capacity - (*capacity)) * sizeof(void *)); + *array = new_array; + *capacity = new_capacity; + } + + /* array has sufficient elements */ + return 0; +} + +char **lxc_string_split(const char *string, char _sep) +{ + char *token, *str, *saveptr = NULL; + char sep[2] = {_sep, '\0'}; + char **tmp = NULL, **result = NULL; + size_t result_capacity = 0; + size_t result_count = 0; + int r, saved_errno; + + if (!string) + return calloc(1, sizeof(char *)); + + str = alloca(strlen(string) + 1); + strcpy(str, string); + for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) { + r = lxc_grow_array((void ***)&result, &result_capacity, result_count + 1, 16); + if (r < 0) + goto error_out; + result[result_count] = strdup(token); + if (!result[result_count]) + goto error_out; + result_count++; + } + + /* if we allocated too much, reduce it */ + tmp = realloc(result, (result_count + 1) * sizeof(char *)); + if (!tmp) + goto error_out; + result = tmp; + /* Make sure we don't return uninitialized memory. */ + if (result_count == 0) + *result = NULL; + return result; +error_out: + saved_errno = errno; + lxc_free_array((void **)result, free); + errno = saved_errno; + return NULL; +} + +char **lxc_normalize_path(const char *path) +{ + char **components; + char **p; + size_t components_len = 0; + size_t pos = 0; + + components = lxc_string_split(path, '/'); + if (!components) + return NULL; + for (p = components; *p; p++) + components_len++; + + /* resolve '.' and '..' */ + for (pos = 0; pos < components_len; ) { + if (!strcmp(components[pos], ".") || (!strcmp(components[pos], "..") && pos == 0)) { + /* eat this element */ + free(components[pos]); + memmove(&components[pos], &components[pos+1], sizeof(char *) * (components_len - pos)); + components_len--; + } else if (!strcmp(components[pos], "..")) { + /* eat this and the previous element */ + free(components[pos - 1]); + free(components[pos]); + memmove(&components[pos-1], &components[pos+1], sizeof(char *) * (components_len - pos)); + components_len -= 2; + pos--; + } else { + pos++; + } + } + + return components; +} + +char *lxc_string_join(const char *sep, const char **parts, bool use_as_prefix) +{ + char *result; + char **p; + size_t sep_len = strlen(sep); + size_t result_len = use_as_prefix * sep_len; + + /* calculate new string length */ + for (p = (char **)parts; *p; p++) + result_len += (p > (char **)parts) * sep_len + strlen(*p); + + result = calloc(result_len + 1, 1); + if (!result) + return NULL; + + if (use_as_prefix) + strcpy(result, sep); + for (p = (char **)parts; *p; p++) { + if (p > (char **)parts) + strcat(result, sep); + strcat(result, *p); + } + + return result; +} + +int is_dir(const char *path) +{ + struct stat statbuf; + int ret = stat(path, &statbuf); + if (ret == 0 && S_ISDIR(statbuf.st_mode)) + return 1; + return 0; +} + +size_t lxc_array_len(void **array) +{ + void **p; + size_t result = 0; + + for (p = array; p && *p; p++) + result++; + + return result; +} diff --git a/src/lxc/tools/tool_utils.h b/src/lxc/tools/tool_utils.h index b122e3ea1..2453e3d61 100644 --- a/src/lxc/tools/tool_utils.h +++ b/src/lxc/tools/tool_utils.h @@ -129,4 +129,16 @@ extern int lxc_safe_uint(const char *numstr, unsigned int *converted); extern int lxc_safe_int(const char *numstr, int *converted); extern int lxc_safe_long(const char *numstr, long int *converted); +typedef void (*lxc_free_fn)(void *); +extern void lxc_free_array(void **array, lxc_free_fn element_free_fn); +extern size_t lxc_array_len(void **array); +extern int lxc_grow_array(void ***array, size_t *capacity, size_t new_size, + size_t capacity_increment); +extern char **lxc_string_split(const char *string, char _sep); +extern char **lxc_normalize_path(const char *path); +extern char *lxc_string_join(const char *sep, const char **parts, + bool use_as_prefix); + +extern int is_dir(const char *path); + #endif /* __LXC_UTILS_H */