X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=55de83023d53c1e6c34226e532df505418473561;hp=ba035caed064315363af1f2358fb6a5b16f246ad;hb=f85ef957e647c5182acf5e64298f68e4b7fbfe8f;hpb=9cad100eca602aa33c2f56475c30fccf14abea1a diff --git a/src/shared/util.c b/src/shared/util.c index ba035caed..55de83023 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -19,12 +19,13 @@ along with systemd; If not, see . ***/ -#include #include #include #include #include #include +#include +#include #include #include #include @@ -46,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -74,13 +74,13 @@ #include #endif +#include "config.h" #include "macro.h" #include "util.h" #include "ioprio.h" #include "missing.h" #include "log.h" #include "strv.h" -#include "label.h" #include "mkdir.h" #include "path-util.h" #include "exit-status.h" @@ -1689,6 +1689,7 @@ bool chars_intersect(const char *a, const char *b) { bool fstype_is_network(const char *fstype) { static const char table[] = + "afs\0" "cifs\0" "smbfs\0" "sshfs\0" @@ -2325,6 +2326,17 @@ ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) { return n; } +int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) { + ssize_t n; + + n = loop_read(fd, buf, nbytes, do_poll); + if (n < 0) + return n; + if ((size_t) n != nbytes) + return -EIO; + return 0; +} + int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { const uint8_t *p = buf; @@ -2579,8 +2591,9 @@ char* dirname_malloc(const char *path) { int dev_urandom(void *p, size_t n) { static int have_syscall = -1; - int r, fd; - ssize_t k; + + _cleanup_close_ int fd = -1; + int r; /* Gathers some randomness from the kernel. This call will * never block, and will always return some data from the @@ -2615,22 +2628,14 @@ int dev_urandom(void *p, size_t n) { return -errno; } else /* too short read? */ - return -EIO; + return -ENODATA; } fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return errno == ENOENT ? -ENOSYS : -errno; - k = loop_read(fd, p, n, true); - safe_close(fd); - - if (k < 0) - return (int) k; - if ((size_t) k != n) - return -EIO; - - return 0; + return loop_read_exact(fd, p, n, true); } void initialize_srand(void) { @@ -5782,6 +5787,11 @@ void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size, return NULL; } +void init_gettext(void) { + setlocale(LC_ALL, ""); + textdomain(GETTEXT_PACKAGE); +} + bool is_locale_utf8(void) { const char *set; static int cached_answer = -1; @@ -5993,7 +6003,7 @@ int on_ac_power(void) { d = opendir("/sys/class/power_supply"); if (!d) - return -errno; + return errno == ENOENT ? true : -errno; for (;;) { struct dirent *de; @@ -8102,3 +8112,54 @@ 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); + + for (cmsg = CMSG_FIRSTHDR(mh); cmsg; cmsg = CMSG_NXTHDR(mh, cmsg)) + 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; + + ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE); + if (ret >= 0) + return 0; + + /* Even though renameat2() exists since Linux 3.15, btrfs added + * support for it later. If it is not implemented, fallback to another + * method. */ + if (errno != EINVAL) + return -errno; + + /* The link()/unlink() fallback does not work on directories. But + * renameat() without RENAME_NOREPLACE gives the same semantics on + * directories, except when newpath is an *empty* directory. This is + * good enough. */ + ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW); + if (ret >= 0 && S_ISDIR(buf.st_mode)) { + ret = renameat(olddirfd, oldpath, newdirfd, newpath); + return ret >= 0 ? 0 : -errno; + } + + /* If it is not a directory, use the link()/unlink() fallback. */ + ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0); + if (ret < 0) + return -errno; + + ret = unlinkat(olddirfd, oldpath, 0); + if (ret < 0) { + /* backup errno before the following unlinkat() alters it */ + ret = errno; + (void) unlinkat(newdirfd, newpath, 0); + errno = ret; + return -errno; + } + + return 0; +}