tools: move lxc-copy to API symbols only

Closes #2073. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 8d313ae1
/*
* 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;
}
#ifndef _GETSUBOPT_H
#define _GETSUBOPT_H
int getsubopt (char **optionp, char *const *tokens, char **valuep);
#endif
......@@ -17,37 +17,29 @@
*/
#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);
......
......@@ -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;
}
......@@ -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 */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment