chiark / gitweb /
Prep v231: Apply missing fixes from upstream (1/6) src/basic
authorSven Eden <yamakuzure@gmx.net>
Wed, 14 Jun 2017 15:44:53 +0000 (17:44 +0200)
committerSven Eden <yamakuzure@gmx.net>
Fri, 16 Jun 2017 08:13:01 +0000 (10:13 +0200)
22 files changed:
src/basic/cgroup-util.c
src/basic/cgroup-util.h
src/basic/fileio.c
src/basic/fileio.h
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/hashmap.c
src/basic/missing.h
src/basic/missing_syscall.h
src/basic/mkdir.c
src/basic/mount-util.c
src/basic/process-util.c
src/basic/raw-clone.h
src/basic/set.h
src/basic/strv.c
src/basic/terminal-util.c
src/basic/terminal-util.h
src/basic/time-util.c
src/basic/time-util.h
src/basic/umask-util.h
src/basic/util.c
src/basic/util.h

index c98c1c4003dff4aa18c8d7419ef3f97d2e12ad80..73134caa515d572e18cf717ba754f8440ec3b02b 100644 (file)
@@ -376,7 +376,8 @@ int cg_migrate(
 
         log_debug_elogind("Migrating \"%s\"/\"%s\" to \"%s\"/\"%s\" (%s)",
                           cfrom, pfrom, cto, pto,
-                          ignore_self ? "ignoring self" : "watching self");
+                          (flags & CGROUP_IGNORE_SELF)
+                          ? "ignoring self" : "watching self");
         do {
                 _cleanup_fclose_ FILE *f = NULL;
                 pid_t pid = 0;
@@ -1925,7 +1926,6 @@ int cg_set_attribute(const char *controller, const char *path, const char *attri
         return write_string_file(p, value, 0);
 }
 
-#if 0 /// UNNEEDED by elogind
 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret) {
         _cleanup_free_ char *p = NULL;
         int r;
@@ -1937,6 +1937,7 @@ int cg_get_attribute(const char *controller, const char *path, const char *attri
         return read_one_line_file(p, ret);
 }
 
+#if 0 /// UNNEEDED by elogind
 int cg_create_everywhere(CGroupMask supported, CGroupMask mask, const char *path) {
         CGroupController c;
         int r, unified;
index 58f0eafdca6b412f03214736bf9939a82289a443..56598d22bde8b1de244d4729ecb6ea129b1377f6 100644 (file)
@@ -170,9 +170,9 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid);
 int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
 
 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value);
-#if 0 /// UNNEEDED by elogind
 int cg_get_attribute(const char *controller, const char *path, const char *attribute, char **ret);
 
+#if 0 /// UNNEEDED by elogind
 int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
 int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid);
 #endif // 0
index 42de50dcf628b0c3473ab940f90f33a786b96dea..df432eaee4283f9c182fa01301e48cffc869fb13 100644 (file)
@@ -1361,3 +1361,44 @@ int link_tmpfile(int fd, const char *path, const char *target) {
         return 0;
 }
 #endif // 0
+
+int read_nul_string(FILE *f, char **ret) {
+        _cleanup_free_ char *x = NULL;
+        size_t allocated = 0, n = 0;
+
+        assert(f);
+        assert(ret);
+
+        /* Reads a NUL-terminated string from the specified file. */
+
+        for (;;) {
+                int c;
+
+                if (!GREEDY_REALLOC(x, allocated, n+2))
+                        return -ENOMEM;
+
+                c = fgetc(f);
+                if (c == 0) /* Terminate at NUL byte */
+                        break;
+                if (c == EOF) {
+                        if (ferror(f))
+                                return -errno;
+                        break; /* Terminate at EOF */
+                }
+
+                x[n++] = (char) c;
+        }
+
+        if (x)
+                x[n] = 0;
+        else {
+                x = new0(char, 1);
+                if (!x)
+                        return -ENOMEM;
+        }
+
+        *ret = x;
+        x = NULL;
+
+        return 0;
+}
index 3c7b9c85b0b132b6053c9e8bb7fc43e2917b4a8c..2469b4ca4d9fff3b78577c73d06015806c6fbbd2 100644 (file)
@@ -92,3 +92,5 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path);
 
 int link_tmpfile(int fd, const char *path, const char *target);
 #endif // 0
+
+int read_nul_string(FILE *f, char **ret);
index 426ad97612167c0445b0c0579d5cb4fdecb8815c..d2d7bb566f1324969997f4060a35d18a8bc9f929 100644 (file)
@@ -501,6 +501,34 @@ int get_files_in_directory(const char *path, char ***list) {
 }
 
 #if 0 /// UNNEEDED by elogind
+int var_tmp(char **ret) {
+        const char *tmp_dir = NULL;
+        const char *env_tmp_dir = NULL;
+        char *c = NULL;
+        int r;
+
+        assert(ret);
+
+        env_tmp_dir = getenv("TMPDIR");
+        if (env_tmp_dir != NULL) {
+                r = is_dir(env_tmp_dir, true);
+                if (r < 0 && r != -ENOENT)
+                        return r;
+                if (r > 0)
+                        tmp_dir = env_tmp_dir;
+        }
+
+        if (!tmp_dir)
+                tmp_dir = "/var/tmp";
+
+        c = strdup(tmp_dir);
+        if (!c)
+                return -ENOMEM;
+        *ret = c;
+
+        return 0;
+}
+
 int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
         char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
         int r;
index 2c5a65026d522b63b952894900c386f03e1617a5..ab31f061e13745fc8037ebcb51a034e48a06ab6d 100644 (file)
@@ -73,6 +73,8 @@ int mkfifo_atomic(const char *path, mode_t mode);
 int get_files_in_directory(const char *path, char ***list);
 
 #if 0 /// UNNEEDED by elogind
+int var_tmp(char **ret);
+
 #define INOTIFY_EVENT_MAX (sizeof(struct inotify_event) + NAME_MAX + 1)
 
 #define FOREACH_INOTIFY_EVENT(e, buffer, sz) \
index c89630f04ccdbf55d3cd47868974455c73cf9430..250fed5345fc47befcf09df9ea952626f1f956d2 100644 (file)
@@ -1768,6 +1768,9 @@ void *ordered_hashmap_next(OrderedHashmap *h, const void *key) {
 int set_consume(Set *s, void *value) {
         int r;
 
+        assert(s);
+        assert(value);
+
         r = set_put(s, value);
         if (r <= 0)
                 free(value);
@@ -1796,6 +1799,8 @@ int set_put_strdupv(Set *s, char **l) {
         int n = 0, r;
         char **i;
 
+        assert(s);
+
         STRV_FOREACH(i, l) {
                 r = set_put_strdup(s, *i);
                 if (r < 0)
@@ -1806,4 +1811,24 @@ int set_put_strdupv(Set *s, char **l) {
 
         return n;
 }
+
+int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags) {
+        const char *p = v;
+        int r;
+
+        assert(s);
+        assert(v);
+
+        for (;;) {
+                char *word;
+
+                r = extract_first_word(&p, &word, separators, flags);
+                if (r <= 0)
+                        return r;
+
+                r = set_consume(s, word);
+                if (r < 0)
+                        return r;
+        }
+}
 #endif // 0
index 4a3b5ecb5b8543a82d3246af47d9564125cc92ba..322cb5695b3d59c36acecb488677dc5f0cbde8a0 100644 (file)
@@ -38,6 +38,7 @@
 #include <uchar.h>
 #include <unistd.h>
 
+/// Additional includes needed by elogind
 #include "musl_missing.h"
 
 #ifdef HAVE_AUDIT
@@ -990,11 +991,13 @@ struct btrfs_ioctl_quota_ctl_args {
 #ifndef INPUT_PROP_ACCELEROMETER
 #define INPUT_PROP_ACCELEROMETER  0x06
 #endif
+#endif // 0
 
 #ifndef HAVE_KEY_SERIAL_T
 typedef int32_t key_serial_t;
 #endif
 
+#if 0 /// UNNEEDED by elogind
 #ifndef KEYCTL_READ
 #define KEYCTL_READ 11
 #endif
index 8a1c24cc560b817e119b0bfd0a146bdc3d2c3e9a..84598c05bd89b7b57481fd623350f03046cfbe68 100644 (file)
@@ -181,18 +181,6 @@ static inline int setns(int fd, int nstype) {
 /* ======================================================================= */
 
 #if 0 /// UNNEEDED by elogind
-static inline int raw_clone(unsigned long flags, void *child_stack) {
-#if defined(__s390__) || defined(__CRIS__)
-        /* On s390 and cris the order of the first and second arguments
-         * of the raw clone() system call is reversed. */
-        return (int) syscall(__NR_clone, child_stack, flags);
-#else
-        return (int) syscall(__NR_clone, flags, child_stack);
-#endif
-}
-
-/* ======================================================================= */
-
 static inline pid_t raw_getpid(void) {
 #if defined(__alpha__)
         return (pid_t) syscall(__NR_getxpid);
index 62e9b082e2015053fb22bacaebc398a0f0b4c82a..db1e8329135784309bbf60ac91e4507667ca2b61 100644 (file)
 
 #include "fs-util.h"
 #include "macro.h"
-#include "missing.h"
 #include "mkdir.h"
 #include "path-util.h"
 #include "stat-util.h"
 #include "user-util.h"
 
+/// Additional includes needed by elogind
+#include "missing.h"
+
 int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, mkdir_func_t _mkdir) {
         struct stat st;
 
index d04a49e2fef7af05a0ee7c9c6230ef8ba3785ca9..121619eed08d844c11e19fbb59b3954f1a05493d 100644 (file)
@@ -534,3 +534,28 @@ int repeat_unmount(const char *path, int flags) {
         }
 }
 #endif // 0
+
+const char* mode_to_inaccessible_node(mode_t mode) {
+        /* This function maps a node type to the correspondent inaccessible node type.
+         * Character and block inaccessible devices may not be created (because major=0 and minor=0),
+         * in such case we map character and block devices to the inaccessible node type socket. */
+        switch(mode & S_IFMT) {
+                case S_IFREG:
+                        return "/run/systemd/inaccessible/reg";
+                case S_IFDIR:
+                        return "/run/systemd/inaccessible/dir";
+                case S_IFCHR:
+                        if (access("/run/systemd/inaccessible/chr", F_OK) == 0)
+                                return "/run/systemd/inaccessible/chr";
+                        return "/run/systemd/inaccessible/sock";
+                case S_IFBLK:
+                        if (access("/run/systemd/inaccessible/blk", F_OK) == 0)
+                                return "/run/systemd/inaccessible/blk";
+                        return "/run/systemd/inaccessible/sock";
+                case S_IFIFO:
+                        return "/run/systemd/inaccessible/fifo";
+                case S_IFSOCK:
+                        return "/run/systemd/inaccessible/sock";
+        }
+        return NULL;
+}
index c976f1f6891fda039fae84296acd91acba26aa2f..cd9c0f7e5d5155abf9ea63fed1d6b7b292112ec4 100644 (file)
@@ -814,7 +814,7 @@ void valgrind_summary_hack(void) {
 #ifdef HAVE_VALGRIND_VALGRIND_H
         if (getpid() == 1 && RUNNING_ON_VALGRIND) {
                 pid_t pid;
-                pid = raw_clone(SIGCHLD, NULL);
+                pid = raw_clone(SIGCHLD);
                 if (pid < 0)
                         log_emergency_errno(errno, "Failed to fork off valgrind helper: %m");
                 else if (pid == 0)
index 1bef6f2dae0c50394483b734fce11a44e3885d7b..d4738289999f1a1550f45f032d2a037da5f505f9 100644 (file)
@@ -1,22 +1,22 @@
 #pragma once
 
 /***
-  This file is part of elogind.
+  This file is part of systemd.
 
   Copyright 2010 Lennart Poettering
   Copyright 2016 Michael Karcher
-  elogind is free software; you can redistribute it and/or modify it
+  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.
 
-  elogind is distributed in the hope that it will be useful, but
+  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 elogind; If not, see <http://www.gnu.org/licenses/>.
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
 #include <sched.h>
index 170f0c44692296bb22d5b90fce9c9744d8c1b0cd..5a5c8edb463f1b587010b61e1899bad941e10f7d 100644 (file)
@@ -125,6 +125,7 @@ int set_consume(Set *s, void *value);
 int set_put_strdup(Set *s, const char *p);
 #if 0 /// UNNEEDED by elogind
 int set_put_strdupv(Set *s, char **l);
+int set_put_strsplit(Set *s, const char *v, const char *separators, ExtractFlags flags);
 #endif // 0
 
 #define SET_FOREACH(e, s, i) \
index 251031e012c078fdb4f597f3d25d09599edaa923..baaa72e674dc98b3ca3126efc1e385019ef361d0 100644 (file)
@@ -648,6 +648,17 @@ char **strv_remove(char **l, const char *s) {
 }
 
 char **strv_parse_nulstr(const char *s, size_t l) {
+        /* l is the length of the input data, which will be split at NULs into
+         * elements of the resulting strv. Hence, the number of items in the resulting strv
+         * will be equal to one plus the number of NUL bytes in the l bytes starting at s,
+         * unless s[l-1] is NUL, in which case the final empty string is not stored in
+         * the resulting strv, and length is equal to the number of NUL bytes.
+         *
+         * Note that contrary to a normal nulstr which cannot contain empty strings, because
+         * the input data is terminated by any two consequent NUL bytes, this parser accepts
+         * empty strings in s.
+         */
+
         const char *p;
         unsigned c = 0, i = 0;
         char **v;
@@ -711,6 +722,13 @@ char **strv_split_nulstr(const char *s) {
 
 #if 0 /// UNNEEDED by elogind
 int strv_make_nulstr(char **l, char **p, size_t *q) {
+        /* A valid nulstr with two NULs at the end will be created, but
+         * q will be the length without the two trailing NULs. Thus the output
+         * string is a valid nulstr and can be iterated over using NULSTR_FOREACH,
+         * and can also be parsed by strv_parse_nulstr as long as the length
+         * is provided separately.
+         */
+
         size_t n_allocated = 0, n = 0;
         _cleanup_free_ char *m = NULL;
         char **i;
@@ -723,7 +741,7 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
 
                 z = strlen(*i);
 
-                if (!GREEDY_REALLOC(m, n_allocated, n + z + 1))
+                if (!GREEDY_REALLOC(m, n_allocated, n + z + 2))
                         return -ENOMEM;
 
                 memcpy(m + n, *i, z + 1);
@@ -734,11 +752,14 @@ int strv_make_nulstr(char **l, char **p, size_t *q) {
                 m = new0(char, 1);
                 if (!m)
                         return -ENOMEM;
-                n = 0;
-        }
+                n = 1;
+        } else
+                /* make sure there is a second extra NUL at the end of resulting nulstr */
+                m[n] = '\0';
 
+        assert(n > 0);
         *p = m;
-        *q = n;
+        *q = n - 1;
 
         m = NULL;
 
index 40e3c400f9adbb984b6369ba04481a96e76c37a1..465326cfcf1845fc808a9222b76986e2010e2bb0 100644 (file)
@@ -1203,6 +1203,19 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
 }
 #endif // 0
 
+bool terminal_is_dumb(void) {
+        const char *e;
+
+        if (!on_tty())
+                return true;
+
+        e = getenv("TERM");
+        if (!e)
+                return true;
+
+        return streq(e, "dumb");
+}
+
 bool colors_enabled(void) {
         static int enabled = -1;
 
@@ -1212,10 +1225,8 @@ bool colors_enabled(void) {
                 colors = getenv("SYSTEMD_COLORS");
                 if (colors)
                         enabled = parse_boolean(colors) != 0;
-                else if (streq_ptr(getenv("TERM"), "dumb"))
-                        enabled = false;
                 else
-                        enabled = on_tty();
+                        enabled = !terminal_is_dumb();
         }
 
         return enabled;
index 38f91514d5ee42103afabdf26a34074cf15a50e2..561045871eae411c6c877b6f828dc7d6f92b815a 100644 (file)
@@ -68,6 +68,7 @@ int vt_disallocate(const char *name);
 
 char *resolve_dev_console(char **active);
 #endif // 0
+int get_kernel_consoles(char ***consoles);
 bool tty_is_vc(const char *tty);
 #if 0 /// UNNEEDED by elogind
 bool tty_is_vc_resolve(const char *tty);
@@ -93,6 +94,7 @@ void columns_lines_cache_reset(int _unused_ signum);
 #endif // 0
 
 bool on_tty(void);
+bool terminal_is_dumb(void);
 bool colors_enabled(void);
 
 static inline const char *ansi_underline(void) {
index 97db1e2ccc659d4804acf991cbc204f10c316869..1c4999aae65d9f3cddcd0bce6792a95b5cfbeb0c 100644 (file)
@@ -91,6 +91,16 @@ dual_timestamp* dual_timestamp_get(dual_timestamp *ts) {
         return ts;
 }
 
+triple_timestamp* triple_timestamp_get(triple_timestamp *ts) {
+        assert(ts);
+
+        ts->realtime = now(CLOCK_REALTIME);
+        ts->monotonic = now(CLOCK_MONOTONIC);
+        ts->boottime = clock_boottime_supported() ? now(CLOCK_BOOTTIME) : USEC_INFINITY;
+
+        return ts;
+}
+
 dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
         int64_t delta;
         assert(ts);
@@ -109,6 +119,24 @@ dual_timestamp* dual_timestamp_from_realtime(dual_timestamp *ts, usec_t u) {
 }
 
 #if 0 /// UNNEEDED by elogind
+triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u) {
+        int64_t delta;
+
+        assert(ts);
+
+        if (u == USEC_INFINITY || u <= 0) {
+                ts->realtime = ts->monotonic = ts->boottime = u;
+                return ts;
+        }
+
+        ts->realtime = u;
+        delta = (int64_t) now(CLOCK_REALTIME) - (int64_t) u;
+        ts->monotonic = usec_sub(now(CLOCK_MONOTONIC), delta);
+        ts->boottime = clock_boottime_supported() ? usec_sub(now(CLOCK_BOOTTIME), delta) : USEC_INFINITY;
+
+        return ts;
+}
+
 dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u) {
         int64_t delta;
         assert(ts);
@@ -142,6 +170,26 @@ dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, us
 }
 #endif // 0
 
+usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock) {
+
+        switch (clock) {
+
+        case CLOCK_REALTIME:
+        case CLOCK_REALTIME_ALARM:
+                return ts->realtime;
+
+        case CLOCK_MONOTONIC:
+                return ts->monotonic;
+
+        case CLOCK_BOOTTIME:
+        case CLOCK_BOOTTIME_ALARM:
+                return ts->boottime;
+
+        default:
+                return USEC_INFINITY;
+        }
+}
+
 usec_t timespec_load(const struct timespec *ts) {
         assert(ts);
 
@@ -1125,7 +1173,33 @@ clockid_t clock_boottime_or_monotonic(void) {
         else
                 return CLOCK_MONOTONIC;
 }
+#endif // 0
+
+bool clock_supported(clockid_t clock) {
+        struct timespec ts;
 
+        switch (clock) {
+
+        case CLOCK_MONOTONIC:
+        case CLOCK_REALTIME:
+                return true;
+
+        case CLOCK_BOOTTIME:
+                return clock_boottime_supported();
+
+        case CLOCK_BOOTTIME_ALARM:
+                if (!clock_boottime_supported())
+                        return false;
+
+                /* fall through, after checking the cached value for CLOCK_BOOTTIME. */
+
+        default:
+                /* For everything else, check properly */
+                return clock_gettime(clock, &ts) >= 0;
+        }
+}
+
+#if 0 /// UNNEEDED by elogind
 int get_timezone(char **tz) {
         _cleanup_free_ char *t = NULL;
         const char *e;
index 6feb75cc7acfb2483ddcc37d5dd1c9f9424b8da4..f80b6594f54b7779c35e03e0497e55360f5fddc9 100644 (file)
@@ -39,6 +39,12 @@ typedef struct dual_timestamp {
         usec_t monotonic;
 } dual_timestamp;
 
+typedef struct triple_timestamp {
+        usec_t realtime;
+        usec_t monotonic;
+        usec_t boottime;
+} triple_timestamp;
+
 #define USEC_INFINITY ((usec_t) -1)
 #define NSEC_INFINITY ((nsec_t) -1)
 
@@ -69,7 +75,8 @@ typedef struct dual_timestamp {
 
 #define TIME_T_MAX (time_t)((UINTMAX_C(1) << ((sizeof(time_t) << 3) - 1)) - 1)
 
-#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) { 0ULL, 0ULL })
+#define DUAL_TIMESTAMP_NULL ((struct dual_timestamp) {})
+#define TRIPLE_TIMESTAMP_NULL ((struct triple_timestamp) {})
 
 usec_t now(clockid_t clock);
 #if 0 /// UNNEEDED by elogind
@@ -83,11 +90,28 @@ dual_timestamp* dual_timestamp_from_monotonic(dual_timestamp *ts, usec_t u);
 dual_timestamp* dual_timestamp_from_boottime_or_monotonic(dual_timestamp *ts, usec_t u);
 #endif // 0
 
+triple_timestamp* triple_timestamp_get(triple_timestamp *ts);
+triple_timestamp* triple_timestamp_from_realtime(triple_timestamp *ts, usec_t u);
+
+#define DUAL_TIMESTAMP_HAS_CLOCK(clock)                               \
+        IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC)
+
+#define TRIPLE_TIMESTAMP_HAS_CLOCK(clock)                               \
+        IN_SET(clock, CLOCK_REALTIME, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC, CLOCK_BOOTTIME, CLOCK_BOOTTIME_ALARM)
+
 static inline bool dual_timestamp_is_set(dual_timestamp *ts) {
         return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
                 (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY));
 }
 
+static inline bool triple_timestamp_is_set(triple_timestamp *ts) {
+        return ((ts->realtime > 0 && ts->realtime != USEC_INFINITY) ||
+                (ts->monotonic > 0 && ts->monotonic != USEC_INFINITY) ||
+                (ts->boottime > 0 && ts->boottime != USEC_INFINITY));
+}
+
+usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock);
+
 usec_t timespec_load(const struct timespec *ts) _pure_;
 struct timespec *timespec_store(struct timespec *ts, usec_t u);
 
@@ -127,6 +151,7 @@ bool timezone_is_valid(const char *name);
 
 #endif // 0
 bool clock_boottime_supported(void);
+bool clock_supported(clockid_t clock);
 #if 0 /// UNNEEDED by elogind
 clockid_t clock_boottime_or_monotonic(void);
 #endif // 0
index be90d5a3cb9188bba95d3e9ae891bc8e983bcf1e..359d87d27c2b4f70c667f1c666afc19f997ca04d 100644 (file)
@@ -31,7 +31,6 @@ static inline void umaskp(mode_t *u) {
 
 #define _cleanup_umask_ _cleanup_(umaskp)
 
-#if 0 /// UNNEEDED by elogind
 struct _umask_struct_ {
         mode_t mask;
         bool quit;
@@ -45,4 +44,3 @@ static inline void _reset_umask_(struct _umask_struct_ *s) {
         for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
              !_saved_umask_.quit ;                                      \
              _saved_umask_.quit = true)
-#endif // 0
index 12f7e1b0512a900e9335582ae1045beb82e1f6c2..f14dba9d9144e31abcd9f4a44446aac1eb060ffb 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "alloc-util.h"
 #include "build.h"
+#include "cgroup-util.h"
 //#include "def.h"
 #include "dirent-util.h"
 #include "fd-util.h"
@@ -64,6 +65,7 @@ assert_cc(EAGAIN == EWOULDBLOCK);
 
 int saved_argc = 0;
 char **saved_argv = NULL;
+static int saved_in_initrd = -1;
 
 size_t page_size(void) {
         static thread_local size_t pgsz = 0;
@@ -413,10 +415,10 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
 
                 /* Detach from stdout/stderr. and reopen
                  * /dev/tty for them. This is important to
-                 * ensure that when loginctl is started via
+                 * ensure that when systemctl is started via
                  * popen() or a similar call that expects to
                  * read EOF we actually do generate EOF and
-                 * not delay this indefinitely because we
+                 * not delay this indefinitely by because we
                  * keep an unused copy of stdin around. */
                 fd = open("/dev/tty", O_WRONLY);
                 if (fd < 0) {
@@ -458,11 +460,10 @@ int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *pa
 }
 
 bool in_initrd(void) {
-        static int saved = -1;
         struct statfs s;
 
-        if (saved >= 0)
-                return saved;
+        if (saved_in_initrd >= 0)
+                return saved_in_initrd;
 
         /* We make two checks here:
          *
@@ -474,11 +475,15 @@ bool in_initrd(void) {
          * emptying when transititioning to the main systemd.
          */
 
-        saved = access("/etc/initrd-release", F_OK) >= 0 &&
-                statfs("/", &s) >= 0 &&
-                is_temporary_fs(&s);
+        saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
+                          statfs("/", &s) >= 0 &&
+                          is_temporary_fs(&s);
 
-        return saved;
+        return saved_in_initrd;
+}
+
+void in_initrd_force(bool value) {
+        saved_in_initrd = value;
 }
 
 #if 0 /// UNNEEDED by elogind
@@ -581,48 +586,7 @@ int on_ac_power(void) {
         return found_online || !found_offline;
 }
 
-bool id128_is_valid(const char *s) {
-        size_t i, l;
-
-        l = strlen(s);
-        if (l == 32) {
-
-                /* Simple formatted 128bit hex string */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if (!(c >= '0' && c <= '9') &&
-                            !(c >= 'a' && c <= 'z') &&
-                            !(c >= 'A' && c <= 'Z'))
-                                return false;
-                }
-
-        } else if (l == 36) {
-
-                /* Formatted UUID */
-
-                for (i = 0; i < l; i++) {
-                        char c = s[i];
-
-                        if ((i == 8 || i == 13 || i == 18 || i == 23)) {
-                                if (c != '-')
-                                        return false;
-                        } else {
-                                if (!(c >= '0' && c <= '9') &&
-                                    !(c >= 'a' && c <= 'z') &&
-                                    !(c >= 'A' && c <= 'Z'))
-                                        return false;
-                        }
-                }
-
-        } else
-                return false;
-
-        return true;
-}
 #endif // 0
-
 int container_get_leader(const char *machine, pid_t *pid) {
         _cleanup_free_ char *s = NULL, *class = NULL;
         const char *p;
@@ -773,15 +737,119 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
 }
 
 uint64_t physical_memory(void) {
-        long mem;
+        _cleanup_free_ char *root = NULL, *value = NULL;
+        uint64_t mem, lim;
+        size_t ps;
+        long sc;
+
+        /* We return this as uint64_t in case we are running as 32bit process on a 64bit kernel with huge amounts of
+         * memory.
+         *
+         * In order to support containers nicely that have a configured memory limit we'll take the minimum of the
+         * physically reported amount of memory and the limit configured for the root cgroup, if there is any. */
+
+        sc = sysconf(_SC_PHYS_PAGES);
+        assert(sc > 0);
+
+        ps = page_size();
+        mem = (uint64_t) sc * (uint64_t) ps;
+
+        if (cg_get_root_path(&root) < 0)
+                return mem;
+
+        if (cg_get_attribute("memory", root, "memory.limit_in_bytes", &value))
+                return mem;
+
+        if (safe_atou64(value, &lim) < 0)
+                return mem;
+
+        /* Make sure the limit is a multiple of our own page size */
+        lim /= ps;
+        lim *= ps;
+
+        return MIN(mem, lim);
+}
+
+uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
+        uint64_t p, m, ps, r;
+
+        assert(max > 0);
+
+        /* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
+         * the result is a multiple of the page size (rounds down). */
+
+        ps = page_size();
+        assert(ps > 0);
+
+        p = physical_memory() / ps;
+        assert(p > 0);
+
+        m = p * v;
+        if (m / p != v)
+                return UINT64_MAX;
+
+        m /= max;
+
+        r = m * ps;
+        if (r / ps != m)
+                return UINT64_MAX;
+
+        return r;
+}
+
+uint64_t system_tasks_max(void) {
+
+#if SIZEOF_PID_T == 4
+#define TASKS_MAX ((uint64_t) (INT32_MAX-1))
+#elif SIZEOF_PID_T == 2
+#define TASKS_MAX ((uint64_t) (INT16_MAX-1))
+#else
+#error "Unknown pid_t size"
+#endif
+
+        _cleanup_free_ char *value = NULL, *root = NULL;
+        uint64_t a = TASKS_MAX, b = TASKS_MAX;
+
+        /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
+         * limit:
+         *
+         * a) the maximum value for the pid_t type
+         * b) the cgroups pids_max attribute for the system
+         * c) the kernel's configure maximum PID value
+         *
+         * And then pick the smallest of the three */
+
+        if (read_one_line_file("/proc/sys/kernel/pid_max", &value) >= 0)
+                (void) safe_atou64(value, &a);
+
+        if (cg_get_root_path(&root) >= 0) {
+                value = mfree(value);
+
+                if (cg_get_attribute("pids", root, "pids.max", &value) >= 0)
+                        (void) safe_atou64(value, &b);
+        }
+
+        return MIN3(TASKS_MAX,
+                    a <= 0 ? TASKS_MAX : a,
+                    b <= 0 ? TASKS_MAX : b);
+}
+
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
+        uint64_t t, m;
+
+        assert(max > 0);
+
+        /* Multiply the system's task value by the fraction v/max. Hence, if max==100 this calculates percentages
+         * relative to the system's maximum number of tasks. Returns UINT64_MAX on overflow. */
 
-        /* We return this as uint64_t in case we are running as 32bit
-         * process on a 64bit kernel with huge amounts of memory */
+        t = system_tasks_max();
+        assert(t > 0);
 
-        mem = sysconf(_SC_PHYS_PAGES);
-        assert(mem > 0);
+        m = t * v;
+        if (m / t != v) /* overflow? */
+                return UINT64_MAX;
 
-        return (uint64_t) mem * (uint64_t) page_size();
+        return m / max;
 }
 
 #if 0 /// UNNEEDED by elogind
index af5a4fc9e607fd86d4650661abaae33cb79b56bb..346221ca0c99682f055db0374d1215b05149dd41 100644 (file)
@@ -92,6 +92,7 @@ int prot_from_flags(int flags) _const_;
 int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
 
 bool in_initrd(void);
+void in_initrd_force(bool value);
 
 #if 0 /// UNNEEDED by elogind
 void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
@@ -186,15 +187,17 @@ static inline unsigned log2u_round_up(unsigned x) {
 }
 
 #if 0 /// UNNEEDED by elogind
-bool id128_is_valid(const char *s) _pure_;
 #endif // 0
-
 int container_get_leader(const char *machine, pid_t *pid);
 
 int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
 int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
 
 uint64_t physical_memory(void);
+uint64_t physical_memory_scale(uint64_t v, uint64_t max);
+
+uint64_t system_tasks_max(void);
+uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
 
 #if 0 /// UNNEEDED by elogind
 #endif // 0