summaryrefslogtreecommitdiff
path: root/src/basic/util.c
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/util.c
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/util.c')
-rw-r--r--src/basic/util.c301
1 files changed, 2 insertions, 299 deletions
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;