summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-10-25 13:14:12 +0100
committerLennart Poettering <lennart@poettering.net>2015-10-25 13:19:18 +0100
commit3ffd4af22052963e7a29431721ee204e634bea75 (patch)
treefe60142dfddd37cfc02b7a135542107e772b36c3 /src/basic
parent04c0136989b7eb896bfb0fb176e11233d69e1453 (diff)
util-lib: split out fd-related operations into fd-util.[ch]
There are more than enough to deserve their own .c file, hence move them over.
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/async.c1
-rw-r--r--src/basic/audit.c7
-rw-r--r--src/basic/barrier.c1
-rw-r--r--src/basic/btrfs-util.c3
-rw-r--r--src/basic/capability.c10
-rw-r--r--src/basic/cgroup-util.c3
-rw-r--r--src/basic/clock-util.c3
-rw-r--r--src/basic/clock-util.h1
-rw-r--r--src/basic/conf-files.c3
-rw-r--r--src/basic/copy.c3
-rw-r--r--src/basic/extract-word.c1
-rw-r--r--src/basic/fd-util.c321
-rw-r--r--src/basic/fd-util.h69
-rw-r--r--src/basic/fdset.c5
-rw-r--r--src/basic/fileio.c3
-rw-r--r--src/basic/hostname-util.c3
-rw-r--r--src/basic/locale-util.c3
-rw-r--r--src/basic/lockfile-util.c5
-rw-r--r--src/basic/log.c3
-rw-r--r--src/basic/memfd-util.c3
-rw-r--r--src/basic/memfd-util.h3
-rw-r--r--src/basic/path-util.c3
-rw-r--r--src/basic/process-util.c3
-rw-r--r--src/basic/random-util.c13
-rw-r--r--src/basic/rm-rf.c3
-rw-r--r--src/basic/socket-label.c11
-rw-r--r--src/basic/terminal-util.c3
-rw-r--r--src/basic/time-util.c3
-rw-r--r--src/basic/util.c301
-rw-r--r--src/basic/util.h38
30 files changed, 455 insertions, 377 deletions
diff --git a/src/basic/async.c b/src/basic/async.c
index 7725e6d7d3..c3135f0efe 100644
--- a/src/basic/async.c
+++ b/src/basic/async.c
@@ -23,6 +23,7 @@
#include <unistd.h>
#include "async.h"
+#include "fd-util.h"
#include "log.h"
#include "util.h"
diff --git a/src/basic/audit.c b/src/basic/audit.c
index 1f593aa813..af43ec8097 100644
--- a/src/basic/audit.c
+++ b/src/basic/audit.c
@@ -22,11 +22,12 @@
#include <errno.h>
#include <stdio.h>
-#include "macro.h"
#include "audit.h"
-#include "util.h"
-#include "process-util.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "macro.h"
+#include "process-util.h"
+#include "util.h"
int audit_session_from_pid(pid_t pid, uint32_t *id) {
_cleanup_free_ char *s = NULL;
diff --git a/src/basic/barrier.c b/src/basic/barrier.c
index 436ba95989..2d55bab4ab 100644
--- a/src/basic/barrier.c
+++ b/src/basic/barrier.c
@@ -30,6 +30,7 @@
#include <unistd.h>
#include "barrier.h"
+#include "fd-util.h"
#include "macro.h"
#include "util.h"
diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c
index df7b959c12..f799f8dcc2 100644
--- a/src/basic/btrfs-util.c
+++ b/src/basic/btrfs-util.c
@@ -27,7 +27,9 @@
#endif
#include "btrfs-ctree.h"
+#include "btrfs-util.h"
#include "copy.h"
+#include "fd-util.h"
#include "fileio.h"
#include "macro.h"
#include "missing.h"
@@ -36,7 +38,6 @@
#include "smack-util.h"
#include "string-util.h"
#include "util.h"
-#include "btrfs-util.h"
/* WARNING: Be careful with file system ioctls! When we get an fd, we
* need to make sure it either refers to only a regular file or
diff --git a/src/basic/capability.c b/src/basic/capability.c
index 8dbe4da5bb..6f25b5dee9 100644
--- a/src/basic/capability.c
+++ b/src/basic/capability.c
@@ -19,18 +19,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <unistd.h>
#include <errno.h>
+#include <grp.h>
#include <stdio.h>
#include <sys/capability.h>
#include <sys/prctl.h>
-#include "grp.h"
+#include <unistd.h>
+#include "capability.h"
+#include "fileio.h"
+#include "log.h"
#include "macro.h"
#include "util.h"
-#include "log.h"
-#include "fileio.h"
-#include "capability.h"
int have_effective_cap(int value) {
_cleanup_cap_free_ cap_t cap;
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index ce21ef73eb..958497543a 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -29,7 +29,9 @@
#include <sys/types.h>
#include <unistd.h>
+#include "cgroup-util.h"
#include "extract-word.h"
+#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
#include "login-util.h"
@@ -42,7 +44,6 @@
#include "string-util.h"
#include "unit-name.h"
#include "util.h"
-#include "cgroup-util.h"
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
_cleanup_free_ char *fs = NULL;
diff --git a/src/basic/clock-util.c b/src/basic/clock-util.c
index 03ec5725ae..00ee4c2796 100644
--- a/src/basic/clock-util.c
+++ b/src/basic/clock-util.c
@@ -26,10 +26,11 @@
#include <sys/ioctl.h>
#include <sys/time.h>
+#include "clock-util.h"
+#include "fd-util.h"
#include "macro.h"
#include "string-util.h"
#include "util.h"
-#include "clock-util.h"
int clock_get_hwclock(struct tm *tm) {
_cleanup_close_ int fd = -1;
diff --git a/src/basic/clock-util.h b/src/basic/clock-util.h
index 8c2d235430..fef2d471a6 100644
--- a/src/basic/clock-util.h
+++ b/src/basic/clock-util.h
@@ -21,6 +21,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <time.h>
int clock_is_localtime(void);
int clock_set_timezone(int *min);
diff --git a/src/basic/conf-files.c b/src/basic/conf-files.c
index 0e44d1bbad..3af3fe392c 100644
--- a/src/basic/conf-files.c
+++ b/src/basic/conf-files.c
@@ -25,6 +25,8 @@
#include <stdlib.h>
#include <string.h>
+#include "conf-files.h"
+#include "fd-util.h"
#include "hashmap.h"
#include "log.h"
#include "macro.h"
@@ -33,7 +35,6 @@
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "conf-files.h"
static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
_cleanup_closedir_ DIR *dir = NULL;
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 7702d906c7..c15527df22 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -23,10 +23,11 @@
#include <sys/xattr.h>
#include "btrfs-util.h"
+#include "copy.h"
+#include "fd-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "copy.h"
#define COPY_BUFFER_SIZE (16*1024)
diff --git a/src/basic/extract-word.c b/src/basic/extract-word.c
index 52d2672390..f2b74802fa 100644
--- a/src/basic/extract-word.c
+++ b/src/basic/extract-word.c
@@ -22,7 +22,6 @@
#include "escape.h"
#include "utf8.h"
#include "util.h"
-
#include "extract-word.h"
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags) {
diff --git a/src/basic/fd-util.c b/src/basic/fd-util.c
new file mode 100644
index 0000000000..e54c104597
--- /dev/null
+++ b/src/basic/fd-util.c
@@ -0,0 +1,321 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd 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.
+
+ systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "fd-util.h"
+#include "util.h"
+
+int close_nointr(int fd) {
+ assert(fd >= 0);
+
+ if (close(fd) >= 0)
+ return 0;
+
+ /*
+ * Just ignore EINTR; a retry loop is the wrong thing to do on
+ * Linux.
+ *
+ * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
+ * https://bugzilla.gnome.org/show_bug.cgi?id=682819
+ * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
+ * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
+ */
+ if (errno == EINTR)
+ return 0;
+
+ return -errno;
+}
+
+int safe_close(int fd) {
+
+ /*
+ * Like close_nointr() but cannot fail. Guarantees errno is
+ * unchanged. Is a NOP with negative fds passed, and returns
+ * -1, so that it can be used in this syntax:
+ *
+ * fd = safe_close(fd);
+ */
+
+ if (fd >= 0) {
+ PROTECT_ERRNO;
+
+ /* The kernel might return pretty much any error code
+ * via close(), but the fd will be closed anyway. The
+ * only condition we want to check for here is whether
+ * the fd was invalid at all... */
+
+ assert_se(close_nointr(fd) != -EBADF);
+ }
+
+ return -1;
+}
+
+void safe_close_pair(int p[]) {
+ assert(p);
+
+ if (p[0] == p[1]) {
+ /* Special case pairs which use the same fd in both
+ * directions... */
+ p[0] = p[1] = safe_close(p[0]);
+ return;
+ }
+
+ p[0] = safe_close(p[0]);
+ p[1] = safe_close(p[1]);
+}
+
+void close_many(const int fds[], unsigned n_fd) {
+ unsigned i;
+
+ assert(fds || n_fd <= 0);
+
+ for (i = 0; i < n_fd; i++)
+ safe_close(fds[i]);
+}
+
+int fclose_nointr(FILE *f) {
+ assert(f);
+
+ /* Same as close_nointr(), but for fclose() */
+
+ if (fclose(f) == 0)
+ return 0;
+
+ if (errno == EINTR)
+ return 0;
+
+ return -errno;
+}
+
+FILE* safe_fclose(FILE *f) {
+
+ /* Same as safe_close(), but for fclose() */
+
+ if (f) {
+ PROTECT_ERRNO;
+
+ assert_se(fclose_nointr(f) != EBADF);
+ }
+
+ return NULL;
+}
+
+DIR* safe_closedir(DIR *d) {
+
+ if (d) {
+ PROTECT_ERRNO;
+
+ assert_se(closedir(d) >= 0 || errno != EBADF);
+ }
+
+ return NULL;
+}
+
+int fd_nonblock(int fd, bool nonblock) {
+ int flags, nflags;
+
+ assert(fd >= 0);
+
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0)
+ return -errno;
+
+ if (nonblock)
+ nflags = flags | O_NONBLOCK;
+ else
+ nflags = flags & ~O_NONBLOCK;
+
+ if (nflags == flags)
+ return 0;
+
+ if (fcntl(fd, F_SETFL, nflags) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int fd_cloexec(int fd, bool cloexec) {
+ int flags, nflags;
+
+ assert(fd >= 0);
+
+ flags = fcntl(fd, F_GETFD, 0);
+ if (flags < 0)
+ return -errno;
+
+ if (cloexec)
+ nflags = flags | FD_CLOEXEC;
+ else
+ nflags = flags & ~FD_CLOEXEC;
+
+ if (nflags == flags)
+ return 0;
+
+ if (fcntl(fd, F_SETFD, nflags) < 0)
+ return -errno;
+
+ return 0;
+}
+
+_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
+ unsigned i;
+
+ assert(n_fdset == 0 || fdset);
+
+ for (i = 0; i < n_fdset; i++)
+ if (fdset[i] == fd)
+ return true;
+
+ return false;
+}
+
+int close_all_fds(const int except[], unsigned n_except) {
+ _cleanup_closedir_ DIR *d = NULL;
+ struct dirent *de;
+ int r = 0;
+
+ assert(n_except == 0 || except);
+
+ d = opendir("/proc/self/fd");
+ if (!d) {
+ int fd;
+ struct rlimit rl;
+
+ /* When /proc isn't available (for example in chroots)
+ * the fallback is brute forcing through the fd
+ * table */
+
+ assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
+ for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
+
+ if (fd_in_set(fd, except, n_except))
+ continue;
+
+ if (close_nointr(fd) < 0)
+ if (errno != EBADF && r == 0)
+ r = -errno;
+ }
+
+ return r;
+ }
+
+ while ((de = readdir(d))) {
+ int fd = -1;
+
+ if (hidden_file(de->d_name))
+ continue;
+
+ if (safe_atoi(de->d_name, &fd) < 0)
+ /* Let's better ignore this, just in case */
+ continue;
+
+ if (fd < 3)
+ continue;
+
+ if (fd == dirfd(d))
+ continue;
+
+ if (fd_in_set(fd, except, n_except))
+ continue;
+
+ if (close_nointr(fd) < 0) {
+ /* Valgrind has its own FD and doesn't want to have it closed */
+ if (errno != EBADF && r == 0)
+ r = -errno;
+ }
+ }
+
+ return r;
+}
+
+int same_fd(int a, int b) {
+ struct stat sta, stb;
+ pid_t pid;
+ int r, fa, fb;
+
+ assert(a >= 0);
+ assert(b >= 0);
+
+ /* Compares two file descriptors. Note that semantics are
+ * quite different depending on whether we have kcmp() or we
+ * don't. If we have kcmp() this will only return true for
+ * dup()ed file descriptors, but not otherwise. If we don't
+ * have kcmp() this will also return true for two fds of the same
+ * file, created by separate open() calls. Since we use this
+ * call mostly for filtering out duplicates in the fd store
+ * this difference hopefully doesn't matter too much. */
+
+ if (a == b)
+ return true;
+
+ /* Try to use kcmp() if we have it. */
+ pid = getpid();
+ r = kcmp(pid, pid, KCMP_FILE, a, b);
+ if (r == 0)
+ return true;
+ if (r > 0)
+ return false;
+ if (errno != ENOSYS)
+ return -errno;
+
+ /* We don't have kcmp(), use fstat() instead. */
+ if (fstat(a, &sta) < 0)
+ return -errno;
+
+ if (fstat(b, &stb) < 0)
+ return -errno;
+
+ if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
+ return false;
+
+ /* We consider all device fds different, since two device fds
+ * might refer to quite different device contexts even though
+ * they share the same inode and backing dev_t. */
+
+ if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
+ return false;
+
+ if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
+ return false;
+
+ /* The fds refer to the same inode on disk, let's also check
+ * if they have the same fd flags. This is useful to
+ * distinguish the read and write side of a pipe created with
+ * pipe(). */
+ fa = fcntl(a, F_GETFL);
+ if (fa < 0)
+ return -errno;
+
+ fb = fcntl(b, F_GETFL);
+ if (fb < 0)
+ return -errno;
+
+ return fa == fb;
+}
+
+void cmsg_close_all(struct msghdr *mh) {
+ struct cmsghdr *cmsg;
+
+ assert(mh);
+
+ CMSG_FOREACH(cmsg, mh)
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
+}
diff --git a/src/basic/fd-util.h b/src/basic/fd-util.h
new file mode 100644
index 0000000000..be00d881c3
--- /dev/null
+++ b/src/basic/fd-util.h
@@ -0,0 +1,69 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2010 Lennart Poettering
+
+ systemd 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.
+
+ systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <dirent.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+
+#include "macro.h"
+
+int close_nointr(int fd);
+int safe_close(int fd);
+void safe_close_pair(int p[]);
+
+void close_many(const int fds[], unsigned n_fd);
+
+int fclose_nointr(FILE *f);
+FILE* safe_fclose(FILE *f);
+DIR* safe_closedir(DIR *f);
+
+static inline void closep(int *fd) {
+ safe_close(*fd);
+}
+
+static inline void close_pairp(int (*p)[2]) {
+ safe_close_pair(*p);
+}
+
+static inline void fclosep(FILE **f) {
+ safe_fclose(*f);
+}
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
+DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
+
+#define _cleanup_close_ _cleanup_(closep)
+#define _cleanup_fclose_ _cleanup_(fclosep)
+#define _cleanup_pclose_ _cleanup_(pclosep)
+#define _cleanup_closedir_ _cleanup_(closedirp)
+#define _cleanup_close_pair_ _cleanup_(close_pairp)
+
+int fd_nonblock(int fd, bool nonblock);
+int fd_cloexec(int fd, bool cloexec);
+
+int close_all_fds(const int except[], unsigned n_except);
+
+int same_fd(int a, int b);
+
+void cmsg_close_all(struct msghdr *mh);
diff --git a/src/basic/fdset.c b/src/basic/fdset.c
index 2882f515b5..9669110828 100644
--- a/src/basic/fdset.c
+++ b/src/basic/fdset.c
@@ -25,10 +25,11 @@
#include "sd-daemon.h"
+#include "fd-util.h"
+#include "fdset.h"
+#include "macro.h"
#include "set.h"
#include "util.h"
-#include "macro.h"
-#include "fdset.h"
#define MAKE_SET(s) ((Set*) s)
#define MAKE_FDSET(s) ((FDSet*) s)
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index f8ccf79221..5d33309ab2 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -23,11 +23,12 @@
#include "ctype.h"
#include "escape.h"
+#include "fd-util.h"
+#include "fileio.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
#include "util.h"
-#include "fileio.h"
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index 8d10615682..7d058416e5 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -22,9 +22,10 @@
#include <ctype.h>
#include <sys/utsname.h>
+#include "fd-util.h"
+#include "hostname-util.h"
#include "string-util.h"
#include "util.h"
-#include "hostname-util.h"
bool hostname_is_set(void) {
struct utsname u;
diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c
index a44daf8f5e..44e1628664 100644
--- a/src/basic/locale-util.c
+++ b/src/basic/locale-util.c
@@ -21,12 +21,13 @@
#include <sys/mman.h>
+#include "fd-util.h"
+#include "locale-util.h"
#include "set.h"
#include "string-util.h"
#include "strv.h"
#include "utf8.h"
#include "util.h"
-#include "locale-util.h"
static int add_locales_from_archive(Set *locales) {
/* Stolen from glibc... */
diff --git a/src/basic/lockfile-util.c b/src/basic/lockfile-util.c
index f3ec6a3e52..e573dcb56f 100644
--- a/src/basic/lockfile-util.c
+++ b/src/basic/lockfile-util.c
@@ -27,9 +27,10 @@
#include <limits.h>
#include <sys/file.h>
-#include "util.h"
-#include "lockfile-util.h"
+#include "fd-util.h"
#include "fileio.h"
+#include "lockfile-util.h"
+#include "util.h"
int make_lock_file(const char *p, int operation, LockFile *ret) {
_cleanup_close_ int fd = -1;
diff --git a/src/basic/log.c b/src/basic/log.c
index acc390b8d3..99dccb1f10 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -31,7 +31,9 @@
#include "sd-messages.h"
+#include "fd-util.h"
#include "formats-util.h"
+#include "log.h"
#include "macro.h"
#include "missing.h"
#include "process-util.h"
@@ -40,7 +42,6 @@
#include "string-util.h"
#include "terminal-util.h"
#include "util.h"
-#include "log.h"
#define SNDBUF_SIZE (8*1024*1024)
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c
index 4dafd69daf..9d638b27f0 100644
--- a/src/basic/memfd-util.c
+++ b/src/basic/memfd-util.c
@@ -27,11 +27,12 @@
#include <sys/mman.h>
#include <sys/prctl.h>
+#include "fd-util.h"
+#include "memfd-util.h"
#include "missing.h"
#include "string-util.h"
#include "utf8.h"
#include "util.h"
-#include "memfd-util.h"
int memfd_new(const char *name) {
_cleanup_free_ char *g = NULL;
diff --git a/src/basic/memfd-util.h b/src/basic/memfd-util.h
index 3ed551fb37..2cb404ea81 100644
--- a/src/basic/memfd-util.h
+++ b/src/basic/memfd-util.h
@@ -21,7 +21,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-
+#include <sys/types.h>
+#include <inttypes.h>
int memfd_new(const char *name);
int memfd_new_and_map(const char *name, size_t sz, void **p);
diff --git a/src/basic/path-util.c b/src/basic/path-util.c
index 31328807f4..7b01633f5f 100644
--- a/src/basic/path-util.c
+++ b/src/basic/path-util.c
@@ -27,14 +27,15 @@
#include <sys/statvfs.h>
#include <unistd.h>
+#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
+#include "path-util.h"
#include "string-util.h"
#include "strv.h"
#include "util.h"
-#include "path-util.h"
bool path_is_absolute(const char *p) {
return p[0] == '/';
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index bfde17a956..949bd1f64d 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -29,12 +29,13 @@
#include <unistd.h>
#include "escape.h"
+#include "fd-util.h"
#include "fileio.h"
#include "log.h"
+#include "process-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "util.h"
-#include "process-util.h"
int get_process_state(pid_t pid) {
const char *p;
diff --git a/src/basic/random-util.c b/src/basic/random-util.c
index b230044f50..e183165b9f 100644
--- a/src/basic/random-util.c
+++ b/src/basic/random-util.c
@@ -17,20 +17,21 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdint.h>
#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <fcntl.h>
-#include <time.h>
+#include <linux/random.h>
+#include <stdint.h>
#ifdef HAVE_SYS_AUXV_H
#include <sys/auxv.h>
#endif
-#include <linux/random.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+#include "fd-util.h"
+#include "missing.h"
#include "random-util.h"
#include "time-util.h"
-#include "missing.h"
#include "util.h"
int dev_urandom(void *p, size_t n) {
diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c
index 5a75090a6d..a5daa23f86 100644
--- a/src/basic/rm-rf.c
+++ b/src/basic/rm-rf.c
@@ -20,10 +20,11 @@
***/
#include "btrfs-util.h"
+#include "fd-util.h"
#include "path-util.h"
+#include "rm-rf.h"
#include "string-util.h"
#include "util.h"
-#include "rm-rf.h"
int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
_cleanup_closedir_ DIR *d = NULL;
diff --git a/src/basic/socket-label.c b/src/basic/socket-label.c
index 937124cc02..4099ea6f9f 100644
--- a/src/basic/socket-label.c
+++ b/src/basic/socket-label.c
@@ -19,18 +19,19 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <string.h>
-#include <unistd.h>
#include <errno.h>
-#include <sys/stat.h>
#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "fd-util.h"
#include "macro.h"
-#include "util.h"
-#include "mkdir.h"
#include "missing.h"
+#include "mkdir.h"
#include "selinux-util.h"
#include "socket-util.h"
+#include "util.h"
int socket_address_listen(
const SocketAddress *a,
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 4723653566..5949b99c95 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -31,13 +31,14 @@
#include <time.h>
#include <unistd.h>
+#include "fd-util.h"
#include "fileio.h"
#include "path-util.h"
#include "process-util.h"
#include "string-util.h"
+#include "terminal-util.h"
#include "time-util.h"
#include "util.h"
-#include "terminal-util.h"
static volatile unsigned cached_columns = 0;
static volatile unsigned cached_lines = 0;
diff --git a/src/basic/time-util.c b/src/basic/time-util.c
index a516d2807b..d117380d52 100644
--- a/src/basic/time-util.c
+++ b/src/basic/time-util.c
@@ -23,11 +23,12 @@
#include <sys/timerfd.h>
#include <sys/timex.h>
+#include "fd-util.h"
#include "path-util.h"
#include "string-util.h"
#include "strv.h"
-#include "util.h"
#include "time-util.h"
+#include "util.h"
usec_t now(clockid_t clock_id) {
struct timespec ts;
diff --git a/src/basic/util.c b/src/basic/util.c
index 233a6c2e35..05f34ea52c 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -79,6 +79,7 @@
#include "env-util.h"
#include "escape.h"
#include "exit-status.h"
+#include "fd-util.h"
#include "fileio.h"
#include "formats-util.h"
#include "gunicode.h"
@@ -98,8 +99,8 @@
#include "strv.h"
#include "terminal-util.h"
#include "utf8.h"
-#include "virt.h"
#include "util.h"
+#include "virt.h"
/* Put this test here for a lack of better place */
assert_cc(EAGAIN == EWOULDBLOCK);
@@ -121,98 +122,6 @@ size_t page_size(void) {
return pgsz;
}
-int close_nointr(int fd) {
- assert(fd >= 0);
-
- if (close(fd) >= 0)
- return 0;
-
- /*
- * Just ignore EINTR; a retry loop is the wrong thing to do on
- * Linux.
- *
- * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
- * https://bugzilla.gnome.org/show_bug.cgi?id=682819
- * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
- * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain
- */
- if (errno == EINTR)
- return 0;
-
- return -errno;
-}
-
-int safe_close(int fd) {
-
- /*
- * Like close_nointr() but cannot fail. Guarantees errno is
- * unchanged. Is a NOP with negative fds passed, and returns
- * -1, so that it can be used in this syntax:
- *
- * fd = safe_close(fd);
- */
-
- if (fd >= 0) {
- PROTECT_ERRNO;
-
- /* The kernel might return pretty much any error code
- * via close(), but the fd will be closed anyway. The
- * only condition we want to check for here is whether
- * the fd was invalid at all... */
-
- assert_se(close_nointr(fd) != -EBADF);
- }
-
- return -1;
-}
-
-void close_many(const int fds[], unsigned n_fd) {
- unsigned i;
-
- assert(fds || n_fd <= 0);
-
- for (i = 0; i < n_fd; i++)
- safe_close(fds[i]);
-}
-
-int fclose_nointr(FILE *f) {
- assert(f);
-
- /* Same as close_nointr(), but for fclose() */
-
- if (fclose(f) == 0)
- return 0;
-
- if (errno == EINTR)
- return 0;
-
- return -errno;
-}
-
-FILE* safe_fclose(FILE *f) {
-
- /* Same as safe_close(), but for fclose() */
-
- if (f) {
- PROTECT_ERRNO;
-
- assert_se(fclose_nointr(f) != EBADF);
- }
-
- return NULL;
-}
-
-DIR* safe_closedir(DIR *d) {
-
- if (d) {
- PROTECT_ERRNO;
-
- assert_se(closedir(d) >= 0 || errno != EBADF);
- }
-
- return NULL;
-}
-
int unlink_noerrno(const char *path) {
PROTECT_ERRNO;
int r;
@@ -1304,123 +1213,6 @@ bool hidden_file(const char *filename) {
return hidden_file_allow_backup(filename);
}
-int fd_nonblock(int fd, bool nonblock) {
- int flags, nflags;
-
- assert(fd >= 0);
-
- flags = fcntl(fd, F_GETFL, 0);
- if (flags < 0)
- return -errno;
-
- if (nonblock)
- nflags = flags | O_NONBLOCK;
- else
- nflags = flags & ~O_NONBLOCK;
-
- if (nflags == flags)
- return 0;
-
- if (fcntl(fd, F_SETFL, nflags) < 0)
- return -errno;
-
- return 0;
-}
-
-int fd_cloexec(int fd, bool cloexec) {
- int flags, nflags;
-
- assert(fd >= 0);
-
- flags = fcntl(fd, F_GETFD, 0);
- if (flags < 0)
- return -errno;
-
- if (cloexec)
- nflags = flags | FD_CLOEXEC;
- else
- nflags = flags & ~FD_CLOEXEC;
-
- if (nflags == flags)
- return 0;
-
- if (fcntl(fd, F_SETFD, nflags) < 0)
- return -errno;
-
- return 0;
-}
-
-_pure_ static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
- unsigned i;
-
- assert(n_fdset == 0 || fdset);
-
- for (i = 0; i < n_fdset; i++)
- if (fdset[i] == fd)
- return true;
-
- return false;
-}
-
-int close_all_fds(const int except[], unsigned n_except) {
- _cleanup_closedir_ DIR *d = NULL;
- struct dirent *de;
- int r = 0;
-
- assert(n_except == 0 || except);
-
- d = opendir("/proc/self/fd");
- if (!d) {
- int fd;
- struct rlimit rl;
-
- /* When /proc isn't available (for example in chroots)
- * the fallback is brute forcing through the fd
- * table */
-
- assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
- for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
-
- if (fd_in_set(fd, except, n_except))
- continue;
-
- if (close_nointr(fd) < 0)
- if (errno != EBADF && r == 0)
- r = -errno;
- }
-
- return r;
- }
-
- while ((de = readdir(d))) {
- int fd = -1;
-
- if (hidden_file(de->d_name))
- continue;
-
- if (safe_atoi(de->d_name, &fd) < 0)
- /* Let's better ignore this, just in case */
- continue;
-
- if (fd < 3)
- continue;
-
- if (fd == dirfd(d))
- continue;
-
- if (fd_in_set(fd, except, n_except))
- continue;
-
- if (close_nointr(fd) < 0) {
- /* Valgrind has its own FD and doesn't want to have it closed */
- if (errno != EBADF && r == 0)
- r = -errno;
- }
- }
-
- return r;
-}
-
bool fstype_is_network(const char *fstype) {
static const char table[] =
"afs\0"
@@ -1480,20 +1272,6 @@ int flush_fd(int fd) {
}
}
-void safe_close_pair(int p[]) {
- assert(p);
-
- if (p[0] == p[1]) {
- /* Special case pairs which use the same fd in both
- * directions... */
- p[0] = p[1] = safe_close(p[0]);
- return;
- }
-
- p[0] = safe_close(p[0]);
- p[1] = safe_close(p[1]);
-}
-
ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
uint8_t *p = buf;
ssize_t n = 0;
@@ -4804,71 +4582,6 @@ int fd_setcrtime(int fd, usec_t usec) {
return 0;
}
-int same_fd(int a, int b) {
- struct stat sta, stb;
- pid_t pid;
- int r, fa, fb;
-
- assert(a >= 0);
- assert(b >= 0);
-
- /* Compares two file descriptors. Note that semantics are
- * quite different depending on whether we have kcmp() or we
- * don't. If we have kcmp() this will only return true for
- * dup()ed file descriptors, but not otherwise. If we don't
- * have kcmp() this will also return true for two fds of the same
- * file, created by separate open() calls. Since we use this
- * call mostly for filtering out duplicates in the fd store
- * this difference hopefully doesn't matter too much. */
-
- if (a == b)
- return true;
-
- /* Try to use kcmp() if we have it. */
- pid = getpid();
- r = kcmp(pid, pid, KCMP_FILE, a, b);
- if (r == 0)
- return true;
- if (r > 0)
- return false;
- if (errno != ENOSYS)
- return -errno;
-
- /* We don't have kcmp(), use fstat() instead. */
- if (fstat(a, &sta) < 0)
- return -errno;
-
- if (fstat(b, &stb) < 0)
- return -errno;
-
- if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT))
- return false;
-
- /* We consider all device fds different, since two device fds
- * might refer to quite different device contexts even though
- * they share the same inode and backing dev_t. */
-
- if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode))
- return false;
-
- if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino)
- return false;
-
- /* The fds refer to the same inode on disk, let's also check
- * if they have the same fd flags. This is useful to
- * distinguish the read and write side of a pipe created with
- * pipe(). */
- fa = fcntl(a, F_GETFL);
- if (fa < 0)
- return -errno;
-
- fb = fcntl(b, F_GETFL);
- if (fb < 0)
- return -errno;
-
- return fa == fb;
-}
-
int chattr_fd(int fd, unsigned value, unsigned mask) {
unsigned old_attr, new_attr;
struct stat st;
@@ -5075,16 +4788,6 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
return -1;
}
-void cmsg_close_all(struct msghdr *mh) {
- struct cmsghdr *cmsg;
-
- assert(mh);
-
- CMSG_FOREACH(cmsg, mh)
- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
- close_many((int*) CMSG_DATA(cmsg), (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int));
-}
-
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
struct stat buf;
int ret;
diff --git a/src/basic/util.h b/src/basic/util.h
index d1da9ce106..e50fd69664 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -87,16 +87,6 @@ static inline const char* one_zero(bool b) {
return b ? "1" : "0";
}
-int close_nointr(int fd);
-int safe_close(int fd);
-void safe_close_pair(int p[]);
-
-void close_many(const int fds[], unsigned n_fd);
-
-int fclose_nointr(FILE *f);
-FILE* safe_fclose(FILE *f);
-DIR* safe_closedir(DIR *f);
-
int parse_size(const char *t, uint64_t base, uint64_t *size);
int parse_boolean(const char *v) _pure_;
@@ -245,11 +235,6 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k
} \
struct __useless_struct_to_allow_trailing_semicolon__
-int fd_nonblock(int fd, bool nonblock);
-int fd_cloexec(int fd, bool cloexec);
-
-int close_all_fds(const int except[], unsigned n_except);
-
bool fstype_is_network(const char *fstype);
int flush_fd(int fd);
@@ -410,35 +395,16 @@ static inline void freep(void *p) {
free(*(void**) p);
}
-static inline void closep(int *fd) {
- safe_close(*fd);
-}
-
static inline void umaskp(mode_t *u) {
umask(*u);
}
-static inline void close_pairp(int (*p)[2]) {
- safe_close_pair(*p);
-}
-
-static inline void fclosep(FILE **f) {
- safe_fclose(*f);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, pclose);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DIR*, closedir);
DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent);
#define _cleanup_free_ _cleanup_(freep)
-#define _cleanup_close_ _cleanup_(closep)
#define _cleanup_umask_ _cleanup_(umaskp)
#define _cleanup_globfree_ _cleanup_(globfree)
-#define _cleanup_fclose_ _cleanup_(fclosep)
-#define _cleanup_pclose_ _cleanup_(pclosep)
-#define _cleanup_closedir_ _cleanup_(closedirp)
#define _cleanup_endmntent_ _cleanup_(endmntentp)
-#define _cleanup_close_pair_ _cleanup_(close_pairp)
_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
@@ -747,8 +713,6 @@ int fd_getcrtime(int fd, usec_t *usec);
int path_getcrtime(const char *p, usec_t *usec);
int fd_getcrtime_at(int dirfd, const char *name, usec_t *usec, int flags);
-int same_fd(int a, int b);
-
int chattr_fd(int fd, unsigned value, unsigned mask);
int chattr_path(const char *p, unsigned value, unsigned mask);
@@ -764,8 +728,6 @@ void sigkill_wait(pid_t *pid);
int syslog_parse_priority(const char **p, int *priority, bool with_facility);
-void cmsg_close_all(struct msghdr *mh);
-
int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath);
int parse_mode(const char *s, mode_t *ret);