failed = 1;
continue;
}
+
if (onedev && mystat.st_dev != pdev) {
/* TODO should we be checking /proc/self/mountinfo for
* pathname and not doing this if found? */
INFO("Removed btrfs subvolume at %s\n", pathname);
continue;
}
+
if (S_ISDIR(mystat.st_mode)) {
if (_recursive_rmdir(pathname, pdev, exclude, level+1, onedev) < 0)
failed=1;
do {
dir = tmp + strspn(tmp, "/");
tmp = dir + strcspn(dir, "/");
+
makeme = strndup(orig, dir - orig);
if (*makeme) {
if (mkdir(makeme, mode) && errno != EEXIST) {
const char *homedir;
struct stat sb;
- if (stat(RUNTIME_PATH, &sb) < 0) {
+ if (stat(RUNTIME_PATH, &sb) < 0)
return NULL;
- }
if (geteuid() == sb.st_uid || getegid() == sb.st_gid) {
rundir = strdup(RUNTIME_PATH);
}
rundir = malloc(sizeof(char) * (17 + strlen(homedir)));
+ if (!rundir)
+ return NULL;
+
sprintf(rundir, "%s/.cache/lxc/run/", homedir);
return rundir;
if (ret == -1) {
if (errno == EINTR)
goto again;
+
return -1;
}
+
if (ret != pid)
goto again;
+
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
return -1;
+
return 0;
}
if (ret == -1) {
if (errno == EINTR)
goto again;
+
return -1;
}
+
if (ret != pid)
goto again;
+
return status;
}
-ssize_t lxc_write_nointr(int fd, const void* buf, size_t count)
+ssize_t lxc_write_nointr(int fd, const void *buf, size_t count)
{
ssize_t ret;
again:
ret = write(fd, buf, count);
if (ret < 0 && errno == EINTR)
goto again;
+
return ret;
}
-ssize_t lxc_read_nointr(int fd, void* buf, size_t count)
+ssize_t lxc_read_nointr(int fd, void *buf, size_t count)
{
ssize_t ret;
again:
ret = read(fd, buf, count);
if (ret < 0 && errno == EINTR)
goto again;
+
return ret;
}
-ssize_t lxc_read_nointr_expect(int fd, void* buf, size_t count, const void* expected_buf)
+ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count, const void *expected_buf)
{
ssize_t ret;
+
ret = lxc_read_nointr(fd, buf, count);
if (ret <= 0)
return ret;
+
if ((size_t)ret != count)
return -1;
+
if (expected_buf && memcmp(buf, expected_buf, count) != 0) {
errno = EINVAL;
return -1;
}
+
return ret;
}
if (!fnam)
return -1;
+
f = fopen_cloexec(fnam, "r");
if (!f) {
SYSERROR("Error opening template");
return -1;
}
+
if (fseek(f, 0, SEEK_END) < 0) {
SYSERROR("Error seeking to end of template");
fclose(f);
return -1;
}
+
if ((flen = ftell(f)) < 0) {
SYSERROR("Error telling size of template");
fclose(f);
return -1;
}
+
if (fseek(f, 0, SEEK_SET) < 0) {
SYSERROR("Error seeking to start of template");
fclose(f);
return -1;
}
+
if ((buf = malloc(flen+1)) == NULL) {
SYSERROR("Out of memory");
fclose(f);
return -1;
}
+
if (fread(buf, 1, flen, f) != flen) {
SYSERROR("Failure reading template");
free(buf);
fclose(f);
return -1;
}
+
if (fclose(f) < 0) {
SYSERROR("Failre closing template");
free(buf);
return -1;
}
+
buf[flen] = '\0';
ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, buf, flen, (void *)digest);
free(buf);
result = calloc(count, sizeof(char*));
if (!result)
return NULL;
+
count = skip;
while (1) {
char* arg = va_arg(ap, char*);
fp = malloc(sizeof(*fp));
if (!fp)
goto on_error;
+
memset(fp, 0, sizeof(*fp));
fp->child_pid = child_pid;
result = calloc(1, len + 1);
if (!result)
return NULL;
+
saved_len = len;
}
part_len = (ssize_t)(p - last_p);
if (result && part_len > 0)
memcpy(&result[len], last_p, part_len);
+
len += part_len;
+
if (result && replacement_len > 0)
memcpy(&result[len], replacement, replacement_len);
+
len += replacement_len;
p += needle_len;
}
+
part_len = strlen(last_p);
if (result && part_len > 0)
memcpy(&result[len], last_p, part_len);
+
len += part_len;
}
free(result);
return NULL;
}
+
/* make sure we didn't overwrite any buffer,
* due to calloc the string should be 0-terminated */
if (result[len] != '\0') {
for (; haystack && *haystack; haystack++)
if (!strcmp(needle, *haystack))
return true;
+
return false;
}
for (p = (char **)parts; *p; p++) {
if (p > (char **)parts)
(void)strlcat(result, sep, buf_len);
+
(void)strlcat(result, *p, buf_len);
}
components = lxc_string_split(path, '/');
if (!components)
return NULL;
+
for (p = components; *p; p++)
components_len++;
lxc_free_array((void **)parts, free);
return dup;
}
+
n = strcspn(dup, "/");
if (n == len) {
free(dup);
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++;
}
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);
r = lxc_grow_array((void ***)result, cap, 2 + *cnt, 16);
if (r < 0)
return false;
+
(*result)[*cnt] = strndup(start, end - start);
if (!(*result)[*cnt])
return false;
+
(*cnt)++;
return true;
for (; (token = strtok_r(str, sep, &saveptr)); str = NULL) {
while (token[0] == ' ' || token[0] == '\t')
token++;
+
i = strlen(token);
while (i > 0 && (token[i - 1] == ' ' || token[i - 1] == '\t')) {
token[i - 1] = '\0';
i--;
}
+
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 */
return realloc(result, (result_count + 1) * sizeof(char *));
+
error_out:
saved_errno = errno;
lxc_free_array((void **)result, free);
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)
+int lxc_grow_array(void ***array, size_t *capacity, size_t new_size, size_t capacity_increment)
{
size_t new_capacity;
void **new_array;
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;
fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, mode);
if (fd < 0)
return -1;
+
ret = lxc_write_nointr(fd, buf, count);
if (ret < 0)
goto out_error;
+
if ((size_t)ret != count)
goto out_error;
+
if (add_newline) {
ret = lxc_write_nointr(fd, "\n", 1);
if (ret != 1)
goto out_error;
}
+
close(fd);
return 0;
return -1;
}
-int lxc_read_from_file(const char *filename, void* buf, size_t count)
+int lxc_read_from_file(const char *filename, void *buf, size_t count)
{
int fd = -1, saved_errno;
ssize_t ret;
free(array);
return NULL;
}
+
array = temp;
array[count] = NULL;
}
+
return array;
}
while (getline(&line, &sz, f) != -1) {
if (sscanf(line, "%u %u %u", &nsid, &hostid, &range) != 3)
continue;
+
if (hostid <= orig && hostid + range > orig) {
nsid += orig - hostid;
goto found;
}
nsid = 0;
+
found:
fclose(f);
free(line);
if (ret < 0)
/* Could be something other than eexist, just say "no". */
return false;
+
return S_ISDIR(sb.st_mode);
}
f = fopen("/proc/self/mountinfo", "r");
if (!f)
return 0;
+
while (fgets(buf, LXC_LINELEN, f)) {
for (p = buf, i = 0; p && i < 4; i++)
p = strchr(p + 1, ' ');
if (!p)
continue;
+
p2 = strchr(p + 1, ' ');
if (!p2)
continue;
+
*p2 = '\0';
if (strcmp(p + 1, "/") == 0) {
/* This is '/'. Is it shared? */
}
}
}
+
fclose(f);
return 0;
}
close(fd);
return false;
}
+
close(fd);
return true;
}
p = strchr(p + 1, ' ');
if (!p)
continue;
+
p2 = strchr(p + 1, ' ');
if (!p2)
continue;
+
*p2 = '\0';
if (strcmp(p + 1, "/") == 0) {
/* This is '/'. Is it the ramfs? */
}
}
}
+
free(line);
fclose(f);
return false;
if (!getenv("PATH")) {
if (setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 0))
SYSERROR("Failed to setenv");
+
env_set = 1;
}
ERROR("pathname too long");
goto out1;
}
+
if (access(retv, X_OK) == 0)
return retv;
ERROR("pathname too long");
goto out1;
}
+
if (access(retv, X_OK) == 0)
return retv;
ERROR("pathname too long");
goto out1;
}
+
if (access(retv, X_OK) == 0)
return retv;
ERROR("pathname too long");
goto out1;
}
+
if (access(retv, X_OK) == 0)
return retv;
WARN("Nonsense - name /lxc.init.static too long");
goto out1;
}
+
if (access(retv, X_OK) == 0)
return retv;
f = fopen(file, "w");
if (!f)
return -1;
+
if (fprintf(f, "%s", content) != strlen(content))
ret = -1;
+
fclose(f);
return ret;
}
int is_dir(const char *path)
{
struct stat statbuf;
- int ret = stat(path, &statbuf);
+ int ret;
+
+ ret = stat(path, &statbuf);
if (ret == 0 && S_ISDIR(statbuf.st_mode))
return 1;
+
return 0;
}
}
len = strlen(LXCTEMPLATEDIR) + strlen(t) + strlen("/lxc-") + 1;
+
tpath = malloc(len);
if (!tpath)
return NULL;
+
ret = snprintf(tpath, len, "%s/lxc-%s", LXCTEMPLATEDIR, t);
if (ret < 0 || ret >= len) {
free(tpath);
return NULL;
}
+
if (access(tpath, X_OK) < 0) {
SYSERROR("bad template: %s", t);
free(tpath);
while (path[offset] != '\0' && offset < fulllen)
offset++;
+
while (path[offset] == '\0' && offset < fulllen)
offset++;
if (subdirlen < len)
return false;
+
if (strncmp(subdir, dir, len) != 0)
return false;
+
if (dir[len-1] == '/')
return true;
+
if (subdir[len] == '/' || subdirlen == len)
return true;
+
return false;
}
static int check_symlink(int fd)
{
struct stat sb;
- int ret = fstat(fd, &sb);
+ int ret;
+
+ ret = fstat(fd, &sb);
if (ret < 0)
return -ENOENT;
+
if (S_ISLNK(sb.st_mode))
return -ELOOP;
+
return 0;
}
target, prefix_skip);
return -EINVAL;
}
+
/*
* get_nextpath() expects the curlen argument to be
* on a (turned into \0) / or before it, so decrement
SYSERROR("Out of memory checking for symbolic link");
return -ENOMEM;
}
+
for (i = 0; i < fulllen; i++) {
if (dup[i] == '/')
dup[i] = '\0';
dirfd = open(prefix_skip, O_RDONLY);
if (dirfd < 0)
goto out;
+
while (1) {
int newfd, saved_errno;
char *nextpath;
if ((nextpath = get_nextpath(dup, &curlen, fulllen)) == NULL)
goto out;
+
newfd = open_if_safe(dirfd, nextpath);
saved_errno = errno;
close(dirfd);
+
dirfd = newfd;
if (newfd < 0) {
errno = saved_errno;
if (errno == ELOOP)
SYSERROR("%s in %s was a symbolic link!", nextpath, target);
+
goto out;
}
}
/* todo - allow symlinks for relative paths if 'allowsymlinks' option is passed */
if (flags & MS_BIND && src && src[0] != '/') {
INFO("this is a relative bind mount");
+
srcfd = open_without_symlink(src, NULL);
if (srcfd < 0)
return srcfd;
+
ret = snprintf(srcbuf, 50, "/proc/self/fd/%d", srcfd);
if (ret < 0 || ret > 50) {
close(srcfd);
close(srcfd);
errno = saved_errno;
}
+
return destfd;
}
if (ret < 0 || ret > 50) {
if (srcfd != -1)
close(srcfd);
+
close(destfd);
ERROR("Out of memory");
return -EINVAL;
saved_errno = errno;
if (srcfd != -1)
close(srcfd);
+
close(destfd);
if (ret < 0) {
errno = saved_errno;
if (linklen < 0) {
if (mkdir(path, 0755) && errno != EEXIST)
return -1;
+
goto domount;
} else if (linklen >= LXC_NUMSTRLEN64) {
link[linklen - 1] = '\0';
int null_stdfds(void)
{
int ret = -1;
- int fd = open_devnull();
+ int fd;
+ fd = open_devnull();
if (fd >= 0) {
ret = set_stdfds(fd);
close(fd);
while (getline(&line, &sz, f) != -1) {
n++;
}
+
free(line);
fclose(f);
return n;
*/
if (umounts != INT_MAX)
umounts++;
+
/* We succeeded in umounting. Make sure that there's no other
* mountpoint stacked underneath.
*/
if (!entry)
return NULL;
+
do {
ret = strdup(entry);
} while (!ret);