if (_likely_(pgsz > 0))
return pgsz;
- assert_se((r = sysconf(_SC_PAGESIZE)) > 0);
+ r = sysconf(_SC_PAGESIZE);
+ assert(r > 0);
pgsz = (size_t) r;
-
return pgsz;
}
if (sl < pl)
return false;
- for(i = 0; i < pl; ++i) {
+ for(i = 0; i < pl; ++i)
if (tolower(s[i]) != tolower(prefix[i]))
return false;
- }
return true;
}
assert(s);
assert(ret_pid);
- if ((r = safe_atolu(s, &ul)) < 0)
+ r = safe_atolu(s, &ul);
+ if (r < 0)
return r;
pid = (pid_t) ul;
assert(s);
assert(ret_uid);
- if ((r = safe_atolu(s, &ul)) < 0)
+ r = safe_atolu(s, &ul);
+ if (r < 0)
return r;
uid = (uid_t) ul;
int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
int r;
- FILE *f;
+ _cleanup_fclose_ FILE *f = NULL;
char fn[PATH_MAX], line[LINE_MAX], *p;
long unsigned ppid;
assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
char_array_0(fn);
- if (!(f = fopen(fn, "re")))
+ f = fopen(fn, "re");
+ if (!f)
return -errno;
- if (!(fgets(line, sizeof(line), f))) {
+ if (!fgets(line, sizeof(line), f)) {
r = feof(f) ? -EIO : -errno;
fclose(f);
return r;
}
- fclose(f);
-
/* Let's skip the pid and comm fields. The latter is enclosed
* in () but does not escape any () in its value, so let's
* skip over it manually */
- if (!(p = strrchr(line, ')')))
+ p = strrchr(line, ')');
+ if (!p)
return -EIO;
p++;
}
int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
- int r;
- FILE *f;
+ _cleanup_fclose_ FILE *f = NULL;
char fn[PATH_MAX], line[LINE_MAX], *p;
assert(pid > 0);
assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
char_array_0(fn);
- if (!(f = fopen(fn, "re")))
+ f = fopen(fn, "re");
+ if (!f)
return -errno;
- if (!(fgets(line, sizeof(line), f))) {
- r = feof(f) ? -EIO : -errno;
- fclose(f);
- return r;
- }
+ if (!fgets(line, sizeof(line), f)) {
+ if (ferror(f))
+ return -errno;
- fclose(f);
+ return -EIO;
+ }
/* Let's skip the pid and comm fields. The latter is enclosed
* in () but does not escape any () in its value, so let's
* skip over it manually */
- if (!(p = strrchr(line, ')')))
+ p = strrchr(line, ')');
+ if (!p)
return -EIO;
p++;
}
int write_one_line_file(const char *fn, const char *line) {
- FILE *f;
- int r;
+ _cleanup_fclose_ FILE *f = NULL;
assert(fn);
assert(line);
return -errno;
errno = 0;
- if (fputs(line, f) < 0) {
- r = -errno;
- goto finish;
- }
+ if (fputs(line, f) < 0)
+ return errno ? -errno : -EIO;
if (!endswith(line, "\n"))
fputc('\n', f);
fflush(f);
- if (ferror(f)) {
- if (errno != 0)
- r = -errno;
- else
- r = -EIO;
- } else
- r = 0;
+ if (ferror(f))
+ return errno ? -errno : -EIO;
-finish:
- fclose(f);
- return r;
+ return 0;
}
int fchmod_umask(int fd, mode_t m) {
}
int read_one_line_file(const char *fn, char **line) {
- FILE *f;
- int r;
+ _cleanup_fclose_ FILE *f = NULL;
char t[LINE_MAX], *c;
assert(fn);
if (!fgets(t, sizeof(t), f)) {
- if (ferror(f)) {
- r = -errno;
- goto finish;
- }
+ if (ferror(f))
+ return errno ? -errno : -EIO;
t[0] = 0;
}
c = strdup(t);
- if (!c) {
- r = -ENOMEM;
- goto finish;
- }
-
+ if (!c)
+ return -ENOMEM;
truncate_nl(c);
*line = c;
- r = 0;
-
-finish:
- fclose(f);
- return r;
+ return 0;
}
int read_full_file(const char *fn, char **contents, size_t *size) {
- FILE *f;
- int r;
+ _cleanup_fclose_ FILE *f = NULL;
size_t n, l;
- char *buf = NULL;
+ _cleanup_free_ char *buf = NULL;
struct stat st;
- if (!(f = fopen(fn, "re")))
+ f = fopen(fn, "re");
+ if (!f)
return -errno;
- if (fstat(fileno(f), &st) < 0) {
- r = -errno;
- goto finish;
- }
+ if (fstat(fileno(f), &st) < 0)
+ return -errno;
/* Safety check */
- if (st.st_size > 4*1024*1024) {
- r = -E2BIG;
- goto finish;
- }
+ if (st.st_size > 4*1024*1024)
+ return -E2BIG;
n = st.st_size > 0 ? st.st_size : LINE_MAX;
l = 0;
char *t;
size_t k;
- if (!(t = realloc(buf, n+1))) {
- r = -ENOMEM;
- goto finish;
- }
+ t = realloc(buf, n+1);
+ if (!t)
+ return -ENOMEM;
buf = t;
k = fread(buf + l, 1, n - l, f);
if (k <= 0) {
- if (ferror(f)) {
- r = -errno;
- goto finish;
- }
+ if (ferror(f))
+ return -errno;
break;
}
n *= 2;
/* Safety check */
- if (n > 4*1024*1024) {
- r = -E2BIG;
- goto finish;
- }
+ if (n > 4*1024*1024)
+ return -E2BIG;
}
buf[l] = 0;
if (size)
*size = l;
- r = 0;
-
-finish:
- fclose(f);
- free(buf);
-
- return r;
+ return 0;
}
int parse_env_file(
return r;
}
-int get_process_uid(pid_t pid, uid_t *uid) {
+static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
char *p;
FILE *f;
int r;
l = strstrip(line);
- if (startswith(l, "Uid:")) {
- l += 4;
+ if (startswith(l, field)) {
+ l += strlen(field);
l += strspn(l, WHITESPACE);
l[strcspn(l, WHITESPACE)] = 0;
return r;
}
+int get_process_uid(pid_t pid, uid_t *uid) {
+ return get_process_id(pid, "Uid:", uid);
+}
+
+int get_process_gid(pid_t pid, gid_t *gid) {
+ return get_process_id(pid, "Gid:", gid);
+}
+
char *strnappend(const char *s, const char *suffix, size_t b) {
size_t a;
char *r;
assert(suffix);
a = strlen(s);
+ if (b > ((size_t) -1) - a)
+ return NULL;
- if (!(r = new(char, a+b+1)))
+ r = new(char, a+b+1);
+ if (!r)
return NULL;
memcpy(r, s, a);
}
bool fstype_is_network(const char *fstype) {
- static const char * const table[] = {
- "cifs",
- "smbfs",
- "ncpfs",
- "nfs",
- "nfs4",
- "gfs",
- "gfs2"
- };
+ static const char table[] =
+ "cifs\0"
+ "smbfs\0"
+ "ncpfs\0"
+ "nfs\0"
+ "nfs4\0"
+ "gfs\0"
+ "gfs2\0";
- unsigned i;
-
- for (i = 0; i < ELEMENTSOF(table); i++)
- if (streq(table[i], fstype))
- return true;
-
- return false;
+ return nulstr_contains(table, fstype);
}
int chvt(int vt) {
- int fd, r = 0;
+ _cleanup_close_ int fd;
- if ((fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC)) < 0)
+ fd = open_terminal("/dev/tty0", O_RDWR|O_NOCTTY|O_CLOEXEC);
+ if (fd < 0)
return -errno;
if (vt < 0) {
0
};
- if (ioctl(fd, TIOCLINUX, tiocl) < 0) {
- r = -errno;
- goto fail;
- }
+ if (ioctl(fd, TIOCLINUX, tiocl) < 0)
+ return -errno;
vt = tiocl[0] <= 0 ? 1 : tiocl[0];
}
if (ioctl(fd, VT_ACTIVATE, vt) < 0)
- r = -errno;
+ return -errno;
-fail:
- close_nointr_nofail(fd);
- return r;
+ return 0;
}
int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
assert(fd >= 0);
- r = dup2(fd, STDIN_FILENO);
- s = dup2(fd, STDOUT_FILENO);
- t = dup2(fd, STDERR_FILENO);
+ r = dup3(fd, STDIN_FILENO, 0);
+ s = dup3(fd, STDOUT_FILENO, 0);
+ t = dup3(fd, STDERR_FILENO, 0);
if (fd >= 3)
close_nointr_nofail(fd);
if (r < 0 || s < 0 || t < 0)
return -errno;
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
+ /* We rely here that the new fd has O_CLOEXEC not set */
return 0;
}
}
int dir_is_empty(const char *path) {
- DIR *d;
+ _cleanup_closedir_ DIR *d;
int r;
- struct dirent buf, *de;
- if (!(d = opendir(path)))
+ d = opendir(path);
+ if (!d)
return -errno;
for (;;) {
- if ((r = readdir_r(d, &buf, &de)) > 0) {
- r = -r;
- break;
- }
+ struct dirent *de;
+ union dirent_storage buf;
- if (!de) {
- r = 1;
- break;
- }
+ r = readdir_r(d, &buf.de, &de);
+ if (r > 0)
+ return -r;
- if (!ignore_file(de->d_name)) {
- r = 0;
- break;
- }
- }
+ if (!de)
+ return 1;
- closedir(d);
- return r;
+ if (!ignore_file(de->d_name))
+ return 0;
+ }
}
unsigned long long random_ull(void) {
- int fd;
+ _cleanup_close_ int fd;
uint64_t ull;
ssize_t r;
goto fallback;
r = loop_read(fd, &ull, sizeof(ull), true);
- close_nointr_nofail(fd);
-
if (r != sizeof(ull))
goto fallback;
static char *lookup_uid(uid_t uid) {
long bufsize;
- char *buf, *name;
+ char *name;
+ _cleanup_free_ char *buf = NULL;
struct passwd pwbuf, *pw = NULL;
/* Shortcut things to avoid NSS lookups */
if (!buf)
return NULL;
- if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw) {
- name = strdup(pw->pw_name);
- free(buf);
- return name;
- }
-
- free(buf);
+ if (getpwuid_r(uid, &pwbuf, buf, bufsize, &pw) == 0 && pw)
+ return strdup(pw->pw_name);
if (asprintf(&name, "%lu", (unsigned long) uid) < 0)
return NULL;
assert(r);
- if ((k = ttyname_r(fd, path, sizeof(path))) != 0)
+ k = ttyname_r(fd, path, sizeof(path));
+ if (k != 0)
return -k;
char_array_0(path);
- if (!(c = strdup(startswith(path, "/dev/") ? path + 5 : path)))
+ c = strdup(startswith(path, "/dev/") ? path + 5 : path);
+ if (!c)
return -ENOMEM;
*r = c;
int k;
char *s;
- if ((k = getttyname_malloc(fd, &s)) < 0)
+ k = getttyname_malloc(fd, &s);
+ if (k < 0)
return k;
if (streq(s, "tty")) {
}
for (;;) {
- struct dirent buf, *de;
+ struct dirent *de;
+ union dirent_storage buf;
bool is_dir, keep_around;
struct stat st;
int r;
- r = readdir_r(d, &buf, &de);
+ r = readdir_r(d, &buf.de, &de);
if (r != 0 && ret == 0) {
ret = -r;
break;
}
}
-void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
- char *s = NULL;
+int status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
static const char status_indent[] = " "; /* "[" STATUS "] " */
- int fd = -1;
+ _cleanup_free_ char *s = NULL;
+ _cleanup_close_ int fd = -1;
struct iovec iovec[5];
int n = 0;
* optional and go exclusively to the console. */
if (vasprintf(&s, format, ap) < 0)
- goto finish;
+ return log_oom();
fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
- goto finish;
+ return fd;
if (ellipse) {
char *e;
if (c <= 0)
c = 80;
- sl = status ? strlen(status_indent) : 0;
+ sl = status ? sizeof(status_indent)-1 : 0;
emax = c - sl - 1;
if (emax < 3)
IOVEC_SET_STRING(iovec[n++], s);
IOVEC_SET_STRING(iovec[n++], "\n");
- writev(fd, iovec, n);
-
-finish:
- free(s);
+ if (writev(fd, iovec, n) < 0)
+ return -errno;
- if (fd >= 0)
- close_nointr_nofail(fd);
+ return 0;
}
-void status_printf(const char *status, bool ellipse, const char *format, ...) {
+int status_printf(const char *status, bool ellipse, const char *format, ...) {
va_list ap;
+ int r;
assert(format);
va_start(ap, format);
- status_vprintf(status, ellipse, format, ap);
+ r = status_vprintf(status, ellipse, format, ap);
va_end(ap);
+
+ return r;
}
-void status_welcome(void) {
- char *pretty_name = NULL, *ansi_color = NULL;
- const char *const_pretty = NULL, *const_color = NULL;
+int status_welcome(void) {
int r;
+ _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
- if ((r = parse_env_file("/etc/os-release", NEWLINE,
- "PRETTY_NAME", &pretty_name,
- "ANSI_COLOR", &ansi_color,
- NULL)) < 0) {
-
- if (r != -ENOENT)
- log_warning("Failed to read /etc/os-release: %s", strerror(-r));
- }
-
- if (!pretty_name && !const_pretty)
- const_pretty = "Linux";
+ r = parse_env_file("/etc/os-release", NEWLINE,
+ "PRETTY_NAME", &pretty_name,
+ "ANSI_COLOR", &ansi_color,
+ NULL);
+ if (r < 0 && r != -ENOENT)
+ log_warning("Failed to read /etc/os-release: %s", strerror(-r));
- if (!ansi_color && !const_color)
- const_color = "1";
-
- status_printf(NULL,
- false,
- "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
- const_color ? const_color : ansi_color,
- const_pretty ? const_pretty : pretty_name);
-
- free(ansi_color);
- free(pretty_name);
+ return status_printf(NULL, false,
+ "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+ isempty(ansi_color) ? "1" : ansi_color,
+ isempty(pretty_name) ? "Linux" : pretty_name);
}
char *replace_env(const char *format, char **env) {
assert(path);
- if ((fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644)) < 0)
+ /* This just opens the file for writing, ensuring it
+ * exists. It doesn't call utimensat() the way /usr/bin/touch
+ * does it. */
+
+ fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, 0644);
+ if (fd < 0)
return -errno;
close_nointr_nofail(fd);
size_t l;
assert(s);
+ /* This is rather stupid, simply removes the heading and
+ * trailing quotes if there is one. Doesn't care about
+ * escaping or anything. We should make this smarter one
+ * day...*/
+
l = strlen(s);
if (l < 2)
return strdup(s);
}
char *normalize_env_assignment(const char *s) {
- char *name, *value, *p, *r;
+ _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
+ char *eq, *r;
- p = strchr(s, '=');
+ eq = strchr(s, '=');
+ if (!eq) {
+ char *t;
- if (!p) {
- if (!(r = strdup(s)))
+ r = strdup(s);
+ if (!r)
return NULL;
- return strstrip(r);
+ t = strstrip(r);
+ if (t == r)
+ return r;
+
+ memmove(r, t, strlen(t) + 1);
+ return r;
}
- if (!(name = strndup(s, p - s)))
+ name = strndup(s, eq - s);
+ if (!name)
return NULL;
- if (!(p = strdup(p+1))) {
- free(name);
+ p = strdup(eq + 1);
+ if (!p)
return NULL;
- }
value = unquote(strstrip(p), QUOTES);
- free(p);
-
- if (!value) {
- free(name);
+ if (!value)
return NULL;
- }
- if (asprintf(&r, "%s=%s", name, value) < 0)
+ if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
r = NULL;
- free(value);
- free(name);
-
return r;
}
int nfd;
DIR *d;
- if ((nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags)) < 0)
+ nfd = openat(fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|flags);
+ if (nfd < 0)
return NULL;
- if (!(d = fdopendir(nfd))) {
+ d = fdopendir(nfd);
+ if (!d) {
close_nointr_nofail(nfd);
return NULL;
}
int signo;
assert(s);
- if ((signo = signal_from_string(s)) <= 0)
+ signo = signal_from_string(s);
+ if (signo <= 0)
if (startswith(s, "SIG"))
return signal_from_string(s+3);
}
char *fstab_node_to_udev_node(const char *p) {
+ assert(p);
+
if (startswith(p, "LABEL="))
return tag_to_udev_node(p+6, "label");
return 0;
}
-int symlink_or_copy(const char *from, const char *to) {
- char *pf = NULL, *pt = NULL;
- struct stat a, b;
- int r;
-
- assert(from);
- assert(to);
-
- if (path_get_parent(from, &pf) < 0 ||
- path_get_parent(to, &pt) < 0) {
- r = -ENOMEM;
- goto finish;
- }
-
- if (stat(pf, &a) < 0 ||
- stat(pt, &b) < 0) {
- r = -errno;
- goto finish;
- }
-
- if (a.st_dev != b.st_dev) {
- free(pf);
- free(pt);
-
- return copy_file(from, to);
- }
-
- if (symlink(from, to) < 0) {
- r = -errno;
- goto finish;
- }
-
- r = 0;
-
-finish:
- free(pf);
- free(pt);
-
- return r;
-}
-
-int symlink_or_copy_atomic(const char *from, const char *to) {
- char *t, *x;
+int symlink_atomic(const char *from, const char *to) {
+ char *x;
+ _cleanup_free_ char *t;
const char *fn;
size_t k;
unsigned long long ull;
*x = 0;
- r = symlink_or_copy(from, t);
- if (r < 0) {
- unlink(t);
- free(t);
- return r;
- }
+ if (symlink(from, t) < 0)
+ return -errno;
if (rename(t, to) < 0) {
r = -errno;
unlink(t);
- free(t);
return r;
}
- free(t);
- return r;
+ return 0;
}
bool display_is_local(const char *display) {
return -errno;
for (;;) {
- struct dirent buffer, *de;
+ struct dirent *de;
+ union dirent_storage buf;
int k;
- k = readdir_r(d, &buffer, &de);
+ k = readdir_r(d, &buf.de, &de);
if (k != 0) {
r = -k;
goto finish;
for (;;) {
const char *t;
+ size_t n;
t = va_arg(ap, const char *);
if (!t)
break;
- l += strlen(t);
+ n = strlen(t);
+ if (n > ((size_t) -1) - l)
+ return NULL;
+
+ l += n;
}
} else
l = 0;
int offset = 0;
unsigned u;
- signo =__signal_from_string(s);
+ signo = __signal_from_string(s);
if (signo > 0)
return signo;
}
int can_sleep(const char *type) {
- char *p, *w, *state;
+ char *w, *state;
size_t l, k;
- bool found = false;
int r;
+ _cleanup_free_ char *p = NULL;
assert(type);
return r == -ENOENT ? 0 : r;
k = strlen(type);
+ FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state)
+ if (l == k && memcmp(w, type, l) == 0)
+ return true;
- FOREACH_WORD_SEPARATOR(w, l, p, WHITESPACE, state) {
- if (l == k && strncmp(w, type, l) == 0) {
- found = true;
- break;
- }
- }
-
- free(p);
- return found;
+ return false;
}
bool is_valid_documentation_url(const char *url) {
}
bool in_initrd(void) {
- static int saved = -1;
+ static __thread int saved = -1;
struct statfs s;
if (saved >= 0)
}
void warn_melody(void) {
- int fd;
+ _cleanup_close_ int fd = -1;
fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY);
if (fd < 0)
return;
- /* Yeah, this is synchronous. Kinda sucks. Bute well... */
+ /* Yeah, this is synchronous. Kinda sucks. But well... */
ioctl(fd, KIOCSOUND, (int)(1193180/440));
usleep(125*USEC_PER_MSEC);
usleep(125*USEC_PER_MSEC);
ioctl(fd, KIOCSOUND, 0);
- close_nointr_nofail(fd);
}
int make_console_stdio(void) {
errno = 0;
p = getpwuid(u);
if (!p)
- return errno ? -errno : -ENOENT;
+ return errno ? -errno : -ESRCH;
if (!path_is_absolute(p->pw_dir))
return -EINVAL;
*_sh = sh;
return 0;
}
+
+void freep(void *p) {
+ free(*(void**) p);
+}
+
+void fclosep(FILE **f) {
+ if (*f)
+ fclose(*f);
+}
+
+void closep(int *fd) {
+ if (*fd >= 0)
+ close_nointr_nofail(*fd);
+}
+
+void closedirp(DIR **d) {
+ if (*d)
+ closedir(*d);
+}
+
+void umaskp(mode_t *u) {
+ umask(*u);
+}