]> git.proxmox.com Git - mirror_lxc.git/commitdiff
tools: move lxc-copy to API symbols only
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 12 Jan 2018 13:27:23 +0000 (14:27 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 6 Feb 2018 20:03:34 +0000 (21:03 +0100)
Closes #2073.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/tools/include/getsubopt.c [new file with mode: 0644]
src/lxc/tools/include/getsubopt.h [new file with mode: 0644]
src/lxc/tools/lxc_copy.c
src/lxc/tools/tool_utils.c
src/lxc/tools/tool_utils.h

diff --git a/src/lxc/tools/include/getsubopt.c b/src/lxc/tools/include/getsubopt.c
new file mode 100644 (file)
index 0000000..b75497b
--- /dev/null
@@ -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 <drepper@cygnus.com>, 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 <stdlib.h>
+#include <string.h>
+
+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 (file)
index 0000000..e45cf66
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef _GETSUBOPT_H
+#define _GETSUBOPT_H
+int getsubopt (char **optionp, char *const *tokens, char **valuep);
+#endif
index 1718f84a748b5c25363a89b726ecb2feb599382d..ae8b810213d3fdbb2379f7220f3a10c4a53bd3de 100644 (file)
  */
 
 #define _GNU_SOURCE
-#include "config.h"
-
-#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <getopt.h>
 #include <signal.h>
-#include <stdio.h>
-#include <sys/types.h>
+#include <stdbool.h>
 #include <stdint.h>
-#include <sys/wait.h>
+#include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include <string.h>
 #include <time.h>
-#include <stdbool.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 #include <lxc/lxccontainer.h>
 
-#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);
index 00181ab6501e94de813d541b860efee642febb7d..29adc67763f70ecad69021e7a0e11ea9c4831470 100644 (file)
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <linux/sched.h>
 #include <sys/prctl.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -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;
+}
index b122e3ea16bb6326d5d50becf3efd9ac24078d9e..2453e3d612cdc244c0854fb5d8367d993825ea22 100644 (file)
@@ -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 */