close(pipes[1]);
- pipe_f = fdopen(pipes[0], "r");
+ pipe_f = fdopen(pipes[0], "re");
if (!pipe_f) {
close(pipes[0]);
goto reap_child;
if (ret < 0 || ret >= LXC_PROC_STATUS_LEN)
return;
- proc_file = fopen(proc_fn, "r");
+ proc_file = fopen(proc_fn, "re");
if (!proc_file)
return;
char *buf = NULL;
size_t len = 0, fulllen = 0;
- f = fopen(fnam, "r");
+ f = fopen(fnam, "re");
if (!f)
return NULL;
while ((linelen = getline(&line, &len, f)) != -1) {
__do_fclose FILE *f = NULL;
size_t len = 0;
- f = fopen("/proc/self/cgroup", "r");
+ f = fopen("/proc/self/cgroup", "re");
if (!f)
return -1;
if (ret < 0)
return log_error_errno(-1, errno, "Failed to retrieve available legacy cgroup controllers");
- f = fopen("/proc/self/mountinfo", "r");
+ f = fopen("/proc/self/mountinfo", "re");
if (!f)
return log_error_errno(-1, errno, "Failed to open \"/proc/self/mountinfo\"");
char path[PATH_MAX];
size_t len = 0;
- f = fopen("/proc/self/cgroup", "r");
+ f = fopen("/proc/self/cgroup", "re");
if (!f)
return;
return;
}
- f = fopen(path, "r");
+ f = fopen(path, "re");
if (!f) {
if (my_args.quiet)
fprintf(stderr, "Failed to open %s\n", path);
int count = 0;
size_t len = 0;
- fin = fopen(LXC_USERNIC_CONF, "r");
+ fin = fopen(LXC_USERNIC_CONF, "re");
if (!fin) {
CMD_SYSERROR("Failed to open \"%s\"\n", LXC_USERNIC_CONF);
return -1;
int ret = -1;
size_t sz = 0;
- fin = fopen(fnam, "r");
+ fin = fopen(fnam, "re");
if (!fin)
return -1;
int progress = 0;
size_t len = 0;
- f = fopen("./proc/self/mountinfo", "r");
+ f = fopen("./proc/self/mountinfo", "re");
if (!f) {
SYSERROR("Failed to open \"/proc/self/mountinfo\"");
return -1;
bool include_nesting_helpers)
{
__do_close_prot_errno int fd = -EBADF;
+ FILE *f;
int ret;
char *mount_entry;
struct lxc_list *iterator;
if (ret < 0)
return NULL;
- return fdopen(move_fd(fd), "r+");
+ f = fdopen(fd, "re+");
+ if (f)
+ move_fd(fd); /* Transfer ownership of fd. */
+ return f;
}
static int setup_mount_entries(const struct lxc_conf *conf,
return;
}
- f = fdopen(memfd, "r");
+ f = fdopen(memfd, "re");
if (!f) {
SYSERROR("Failed to open copy of \"/proc/self/mountinfo\" to mark all shared. Continuing");
return;
if (!gname)
return;
- subuid_f = fopen(subuidfile, "r");
+ subuid_f = fopen(subuidfile, "re");
if (!subuid_f) {
ERROR("Your system is not configured with subuids");
return;
WARN("Could not parse UID range");
}
- subgid_f = fopen(subgidfile, "r");
+ subgid_f = fopen(subgidfile, "re");
if (!subgid_f) {
ERROR("Your system is not configured with subgids");
return;
/*
* Important Note:
- * If a new config option is added to this table, be aware that
+ * If a new config option is added to this table, be aware that
* the order in which the options are places into the table matters.
* That means that more specific options of a namespace have to be
* placed above more generic ones.
static int do_includedir(const char *dirp, struct lxc_conf *lxc_conf)
{
+ __do_closedir DIR *dir = NULL;
struct dirent *direntp;
- DIR *dir;
char path[PATH_MAX];
int len;
int ret = -1;
continue;
len = snprintf(path, PATH_MAX, "%s/%s", dirp, fnam);
- if (len < 0 || len >= PATH_MAX) {
- ret = -1;
- goto out;
- }
+ if (len < 0 || len >= PATH_MAX)
+ return -1;
ret = lxc_config_read(path, lxc_conf, true);
if (ret < 0)
- goto out;
+ return -1;
}
- ret = 0;
-out:
- closedir(dir);
-
- return ret;
+ return 0;
}
static int set_config_includefiles(const char *key, const char *value,
return -1;
}
- f = fopen(path, "r");
+ f = fopen(path, "re");
if (!f) {
/* This means we're coming from a liblxc which didn't export
* the tty info. In this case they had to have lxc.console.path
return false;
}
- f = fdopen(pipes[0], "r");
+ f = fdopen(pipes[0], "re");
if (!f) {
close(pipes[0]);
return false;
goto out_fini_handler;
}
- FILE *f = fopen(buf, "r");
+ FILE *f = fopen(buf, "re");
if (!f) {
SYSERROR("couldn't read restore's children file %s", buf);
goto out_fini_handler;
return -1;
}
- f = fopen(path, "w");
+ f = fopen(path, "we");
if (!f) {
SYSERROR("failed to open %s", path);
return -1;
FILE *f;
int ret = 0;
- f = fopen(file, "w");
+ f = fopen(file, "we");
if (!f)
return -1;
return ret;
}
-char *file_to_buf(char *path, size_t *length)
-{
- int fd;
- char buf[PATH_MAX];
- char *copy = NULL;
-
- if (!length)
- return NULL;
-
- fd = open(path, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- return NULL;
-
- *length = 0;
- for (;;) {
- int n;
- char *old = copy;
-
- n = lxc_read_nointr(fd, buf, sizeof(buf));
- if (n < 0)
- goto on_error;
- if (!n)
- break;
-
- copy = must_realloc(old, (*length + n) * sizeof(*old));
- memcpy(copy + *length, buf, n);
- *length += n;
- }
-
- close(fd);
- return copy;
-
-on_error:
- close(fd);
- free(copy);
-
- return NULL;
-}
-
int fd_to_fd(int from, int to)
{
for (;;) {
return 0;
}
+
+static char *fd_to_buf(int fd, size_t *length)
+{
+ __do_free char *copy = NULL;
+
+ if (!length)
+ return NULL;
+
+ *length = 0;
+ for (;;) {
+ ssize_t bytes_read;
+ char buf[4096];
+ char *old = copy;
+
+ bytes_read = lxc_read_nointr(fd, buf, sizeof(buf));
+ if (bytes_read < 0)
+ return NULL;
+
+ if (!bytes_read)
+ break;
+
+ copy = must_realloc(old, (*length + bytes_read) * sizeof(*old));
+ memcpy(copy + *length, buf, bytes_read);
+ *length += bytes_read;
+ }
+
+ return move_ptr(copy);
+}
+
+char *file_to_buf(const char *path, size_t *length)
+{
+ __do_close_prot_errno int fd = -EBADF;
+
+ if (!length)
+ return NULL;
+
+ fd = open(path, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ return NULL;
+
+ return fd_to_buf(fd, length);
+}
+
+FILE *fopen_cached(const char *path, const char *mode, void **caller_freed_buffer)
+{
+ __do_free char *buf = NULL;
+ size_t len = 0;
+ FILE *f;
+
+ buf = file_to_buf(path, &len);
+ if (!buf)
+ return NULL;
+
+ f = fmemopen(buf, len, mode);
+ if (!f)
+ return NULL;
+ *caller_freed_buffer = move_ptr(buf);
+ return f;
+}
+
+FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer)
+{
+ __do_free char *buf = NULL;
+ size_t len = 0;
+ FILE *f;
+
+ buf = fd_to_buf(fd, &len);
+ if (!buf)
+ return NULL;
+
+ f = fmemopen(buf, len, mode);
+ if (!f)
+ return NULL;
+
+ *caller_freed_buffer = move_ptr(buf);
+ return f;
+}
extern FILE *fopen_cloexec(const char *path, const char *mode);
extern ssize_t lxc_sendfile_nointr(int out_fd, int in_fd, off_t *offset,
size_t count);
-extern char *file_to_buf(char *path, size_t *length);
+extern char *file_to_buf(const char *path, size_t *length);
extern int fd_to_fd(int from, int to);
extern int lxc_open_dirfd(const char *dir);
+extern FILE *fdopen_cached(int fd, const char *mode, void **caller_freed_buffer);
+extern FILE *fopen_cached(const char *path, const char *mode,
+ void **caller_freed_buffer);
#endif /* __LXC_FILE_UTILS_H */
static bool am_single_threaded(void)
{
- DIR *dir;
+ __do_closedir DIR *dir = NULL;
struct dirent *direntp;
int count = 0;
if (count > 1)
break;
}
- closedir(dir);
return count == 1;
}
char *tpath;
#endif
- f = fopen(path, "r");
+ f = fopen(path, "re");
if (f == NULL)
return false;
free(tpath);
#endif
- f = fopen(path, "w");
+ f = fopen(path, "we");
if (f == NULL) {
SYSERROR("Reopening config for writing");
free(contents);
/* If we find an lxc-snapshot file using the old format only listing the
* number of snapshots we will keep using it. */
- f1 = fopen(path, "r");
+ f1 = fopen(path, "re");
if (f1) {
n = fscanf(f1, "%d", &v);
fclose(f1);
if (n == 1) {
v += inc ? 1 : -1;
- f1 = fopen(path, "w");
+ f1 = fopen(path, "we");
if (!f1)
goto out;
/* Here we know that we have or can use an lxc-snapshot file
* using the new format. */
if (inc) {
- f1 = fopen(path, "a");
+ f1 = fopen(path, "ae");
if (!f1)
goto out;
return;
}
- f = fopen(path, "r");
+ f = fopen(path, "re");
if (f == NULL)
return;
v = fbuf.st_size;
if (v != 0) {
- f = fopen(path, "r");
+ f = fopen(path, "re");
if (!f)
goto out;
static bool has_snapshots(struct lxc_container *c)
{
+ __do_closedir DIR *dir = NULL;
char path[PATH_MAX];
struct dirent *direntp;
- int count=0;
- DIR *dir;
+ int count = 0;
if (!get_snappath_dir(c, path))
return false;
break;
}
- closedir(dir);
return count > 0;
}
if (ret < 0 || ret >= PATH_MAX)
return false;
- f = fopen(path, "a");
+ f = fopen(path, "ae");
if (!f)
return false;
if (!file_exists(path))
return 0;
- if (!(fout = fopen(path, "w"))) {
+ if (!(fout = fopen(path, "we"))) {
SYSERROR("unable to open %s: ignoring", path);
return 0;
}
len = strlen(snappath) + 1 + strlen(newname) + 1 + strlen(LXC_TIMESTAMP_FNAME) + 1;
dfnam = must_realloc(NULL, len);
snprintf(dfnam, len, "%s/%s/%s", snappath, newname, LXC_TIMESTAMP_FNAME);
- f = fopen(dfnam, "w");
+ f = fopen(dfnam, "we");
if (!f) {
ERROR("Failed to open %s", dfnam);
return -1;
if (ret < 0 || ret >= PATH_MAX)
return NULL;
- fin = fopen(path, "r");
+ fin = fopen(path, "re");
if (!fin)
return NULL;
static int do_lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **ret_snaps)
{
+ __do_closedir DIR *dir = NULL;
char snappath[PATH_MAX], path2[PATH_MAX];
int count = 0, ret;
struct dirent *direntp;
struct lxc_snapshot *snaps =NULL, *nsnaps;
- DIR *dir;
if (!c || !lxcapi_is_defined(c))
return -1;
out_free:
if (snaps) {
- int i;
-
- for (i=0; i<count; i++)
+ for (int i = 0; i < count; i++)
lxcsnap_free(&snaps[i]);
free(snaps);
}
- if (closedir(dir))
- WARN("Failed to close directory");
-
return -1;
}
static bool remove_all_snapshots(const char *path)
{
- DIR *dir;
+ __do_closedir DIR *dir = NULL;
struct dirent *direntp;
bool bret = true;
}
}
- closedir(dir);
-
if (rmdir(path))
SYSERROR("Error removing directory %s", path);
*/
int list_defined_containers(const char *lxcpath, char ***names, struct lxc_container ***cret)
{
- DIR *dir;
+ __do_closedir DIR *dir = NULL;
int i, cfound = 0, nfound = 0;
struct dirent *direntp;
struct lxc_container *c;
nfound++;
}
- closedir(dir);
return nfound;
free_bad:
if (names && *names) {
- for (i=0; i<cfound; i++)
+ for (i = 0; i < cfound; i++)
free((*names)[i]);
free(*names);
}
if (cret && *cret) {
- for (i=0; i<nfound; i++)
+ for (i = 0; i < nfound; i++)
lxc_container_put((*cret)[i]);
free(*cret);
}
- closedir(dir);
return -1;
}
if (nret)
*nret = NULL;
- FILE *f = fopen("/proc/net/unix", "r");
+ FILE *f = fopen("/proc/net/unix", "re");
if (!f)
return -1;
#define PHYSNAME "/sys/class/net/%s/phy80211/name"
char *is_wlan(const char *ifname)
{
- __do_free char *path = NULL;
+ __do_fclose FILE *f = NULL;
+ __do_free char *path = NULL, *physname = NULL;
int i, ret;
long physlen;
size_t len;
- FILE *f;
- char *physname = NULL;
len = strlen(ifname) + strlen(PHYSNAME) - 1;
path = must_realloc(NULL, len + 1);
ret = snprintf(path, len, PHYSNAME, ifname);
if (ret < 0 || (size_t)ret >= len)
- goto bad;
+ return NULL;
- f = fopen(path, "r");
+ f = fopen(path, "re");
if (!f)
- goto bad;
+ return NULL;
/* Feh - sb.st_size is always 4096. */
fseek(f, 0, SEEK_END);
physlen = ftell(f);
fseek(f, 0, SEEK_SET);
- if (physlen < 0) {
- fclose(f);
- goto bad;
- }
+ if (physlen < 0)
+ return NULL;
physname = malloc(physlen + 1);
- if (!physname) {
- fclose(f);
- goto bad;
- }
+ if (!physname)
+ return NULL;
memset(physname, 0, physlen + 1);
ret = fread(physname, 1, physlen, f);
- fclose(f);
if (ret < 0)
- goto bad;
+ return NULL;
for (i = 0; i < physlen; i++) {
if (physname[i] == '\n')
break;
}
- return physname;
-
-bad:
- free(physname);
- return NULL;
+ return move_ptr(physname);
}
static int lxc_netdev_rename_by_name_in_netns(pid_t pid, const char *old,
/* Recursively remove directory and its parents. */
static int recursive_rmdir(char *dirname)
{
+ __do_closedir DIR *dir = NULL;
struct dirent *direntp;
- DIR *dir;
int r = 0;
dir = opendir(dirname);
r = -1;
}
- if (closedir(dir) < 0) {
- if (!r)
- pam_cgfs_debug("Failed to delete %s: %s\n", dirname, strerror(errno));
- r = -1;
- }
-
return r;
}
int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data)
{
- FILE *f;
+ __do_fclose FILE *f = NULL;
+ __do_free char *line = NULL;
int err = 0;
- char *line = NULL;
size_t len = 0;
- f = fopen(file, "r");
+ f = fopen(file, "re");
if (!f) {
SYSERROR("Failed to open \"%s\"", file);
return -1;
}
}
- free(line);
- fclose(f);
return err;
}
*/
static bool use_seccomp(const struct lxc_conf *conf)
{
+ __do_free char *line = NULL;
+ __do_fclose FILE *f = NULL;
int ret, v;
- FILE *f;
size_t line_bufsz = 0;
- char *line = NULL;
bool already_enabled = false, found = false;
if (conf->seccomp.allow_nesting > 0)
return true;
- f = fopen("/proc/self/status", "r");
+ f = fopen("/proc/self/status", "re");
if (!f)
return true;
break;
}
}
- free(line);
- fclose(f);
if (!found) {
INFO("Seccomp is not enabled in the kernel");
int lxc_read_seccomp_config(struct lxc_conf *conf)
{
+ __do_fclose FILE *f = NULL;
int ret;
- FILE *f;
if (!conf->seccomp.seccomp)
return 0;
}
#endif
- f = fopen(conf->seccomp.seccomp, "r");
+ f = fopen(conf->seccomp.seccomp, "re");
if (!f) {
SYSERROR("Failed to open seccomp policy file %s", conf->seccomp.seccomp);
return -1;
}
- ret = parse_config(f, conf);
- fclose(f);
-
- return ret;
+ return parse_config(f, conf);
}
int lxc_seccomp_load(struct lxc_conf *conf)
int randseed(bool srand_it)
{
- FILE *f;
+ __do_fclose FILE *f = NULL;
/*
* srand pre-seed function based on /dev/urandom
*/
unsigned int seed = time(NULL) + getpid();
- f = fopen("/dev/urandom", "r");
+ f = fopen("/dev/urandom", "re");
if (f) {
int ret = fread(&seed, sizeof(seed), 1, f);
if (ret != 1)
SYSDEBUG("Unable to fread /dev/urandom, fallback to time+pid rand seed");
-
- fclose(f);
}
if (srand_it)
uid_t get_ns_uid(uid_t orig)
{
- char *line = NULL;
+ __do_free char *line = NULL;
+ __do_fclose FILE *f = NULL;
size_t sz = 0;
uid_t nsid, hostid, range;
- FILE *f;
- f = fopen("/proc/self/uid_map", "r");
+ f = fopen("/proc/self/uid_map", "re");
if (!f) {
SYSERROR("Failed to open uid_map");
return 0;
if (sscanf(line, "%u %u %u", &nsid, &hostid, &range) != 3)
continue;
- if (hostid <= orig && hostid + range > orig) {
- nsid += orig - hostid;
- goto found;
- }
+ if (hostid <= orig && hostid + range > orig)
+ return nsid += orig - hostid;
}
- nsid = LXC_INVALID_UID;
-
-found:
- fclose(f);
- free(line);
- return nsid;
+ return LXC_INVALID_UID;
}
gid_t get_ns_gid(gid_t orig)
{
- char *line = NULL;
+ __do_free char *line = NULL;
+ __do_fclose FILE *f = NULL;
size_t sz = 0;
gid_t nsid, hostid, range;
- FILE *f;
- f = fopen("/proc/self/gid_map", "r");
+ f = fopen("/proc/self/gid_map", "re");
if (!f) {
SYSERROR("Failed to open gid_map");
return 0;
if (sscanf(line, "%u %u %u", &nsid, &hostid, &range) != 3)
continue;
- if (hostid <= orig && hostid + range > orig) {
- nsid += orig - hostid;
- goto found;
- }
+ if (hostid <= orig && hostid + range > orig)
+ return nsid += orig - hostid;
}
- nsid = LXC_INVALID_GID;
-
-found:
- fclose(f);
- free(line);
- return nsid;
+ return LXC_INVALID_GID;
}
bool dir_exists(const char *path)
int i;
size_t len = 0;
- f = fopen("/proc/self/mountinfo", "r");
+ f = fopen("/proc/self/mountinfo", "re");
if (!f)
return 0;
*/
bool detect_ramfs_rootfs(void)
{
- FILE *f;
- char *p, *p2;
- char *line = NULL;
+ __do_free char *line = NULL;
+ __do_free void *fopen_cache = NULL;
+ __do_fclose FILE *f = NULL;
size_t len = 0;
- int i;
- f = fopen("/proc/self/mountinfo", "r");
- if (!f) {
- SYSERROR("Failed to open mountinfo");
+ f = fopen_cached("/proc/self/mountinfo", "re", &fopen_cache);
+ if (!f)
return false;
- }
while (getline(&line, &len, f) != -1) {
+ int i;
+ char *p, *p2;
+
for (p = line, i = 0; p && i < 4; i++)
p = strchr(p + 1, ' ');
if (!p)
p2 = strchr(p + 1, ' ');
if (!p2)
continue;
-
*p2 = '\0';
if (strcmp(p + 1, "/") == 0) {
/* This is '/'. Is it the ramfs? */
p = strchr(p2 + 1, '-');
- if (p && strncmp(p, "- rootfs rootfs ", 16) == 0) {
- free(line);
- fclose(f);
- INFO("Rootfs is located on ramfs");
+ if (p && strncmp(p, "- rootfs rootfs ", 16) == 0)
return true;
- }
}
}
- free(line);
- fclose(f);
return false;
}
#define __PROC_STATUS_LEN (6 + INTTYPE_TO_STRLEN(pid_t) + 7 + 1)
bool task_blocks_signal(pid_t pid, int signal)
{
+ __do_free char *line = NULL;
+ __do_fclose FILE *f = NULL;
int ret;
char status[__PROC_STATUS_LEN] = {0};
- FILE *f;
uint64_t sigblk = 0, one = 1;
size_t n = 0;
bool bret = false;
- char *line = NULL;
ret = snprintf(status, __PROC_STATUS_LEN, "/proc/%d/status", pid);
if (ret < 0 || ret >= __PROC_STATUS_LEN)
return bret;
- f = fopen(status, "r");
+ f = fopen(status, "re");
if (!f)
- return bret;
+ return false;
while (getline(&line, &n, f) != -1) {
char *numstr;
numstr = lxc_trim_whitespace_in_place(line + 7);
ret = lxc_safe_uint64(numstr, &sigblk, 16);
if (ret < 0)
- goto out;
+ return false;
break;
}
if (sigblk & (one << (signal - 1)))
bret = true;
-out:
- free(line);
- fclose(f);
return bret;
}
if (fd_cloexec(dupfd, true) < 0)
return -1;
- /* transfer ownership of fd */
f = fdopen(dupfd, "re");
if (!f)
return -1;
+
+ /* Transfer ownership of fd. */
move_fd(dupfd);
ret = 0;
#include "file_utils.h"
#include "initutils.h"
#include "macro.h"
+#include "memory_utils.h"
#include "raw_syscalls.h"
#include "string_utils.h"
/* are we unprivileged with respect to init_user_ns */
inline static bool am_host_unpriv(void)
{
- FILE *f;
+ __do_fclose FILE *f = NULL;
uid_t user, host, count;
int ret;
/* Now: are we in a user namespace? Because then we're also
* unprivileged.
*/
- f = fopen("/proc/self/uid_map", "r");
- if (!f) {
+ f = fopen("/proc/self/uid_map", "re");
+ if (!f)
return false;
- }
ret = fscanf(f, "%u %u %u", &user, &host, &count);
- fclose(f);
- if (ret != 3) {
+ if (ret != 3)
return false;
- }
- if (user != 0 || host != 0 || count != UINT32_MAX)
- return true;
- return false;
+ return user != 0 || host != 0 || count != UINT32_MAX;
}
/*