[systemd-commits] 10 commits - TODO src/core src/cryptsetup src/debug-generator src/fsck src/fstab-generator src/gpt-auto-generator src/hibernate-resume src/journal src/modules-load src/quotacheck src/shared src/systemctl src/test src/udev

Lennart Poettering lennart at kemper.freedesktop.org
Thu Nov 6 16:21:25 PST 2014


 TODO                                              |    4 
 src/core/kmod-setup.c                             |    2 
 src/core/main.c                                   |    8 -
 src/core/timer.c                                  |    6 
 src/cryptsetup/cryptsetup-generator.c             |    7 -
 src/debug-generator/debug-generator.c             |    5 
 src/fsck/fsck.c                                   |    5 
 src/fstab-generator/fstab-generator.c             |    5 
 src/gpt-auto-generator/gpt-auto-generator.c       |    5 
 src/hibernate-resume/hibernate-resume-generator.c |   12 +
 src/journal/coredump.c                            |    2 
 src/journal/journald-server.c                     |    4 
 src/modules-load/modules-load.c                   |    5 
 src/quotacheck/quotacheck.c                       |   10 +
 src/shared/condition.c                            |    4 
 src/shared/copy.c                                 |   87 ++++++++----
 src/shared/copy.h                                 |    1 
 src/shared/fileio.c                               |   91 -------------
 src/shared/fileio.h                               |    1 
 src/shared/util.c                                 |  148 ++++++++++------------
 src/shared/util.h                                 |    4 
 src/systemctl/systemctl.c                         |    5 
 src/test/test-copy.c                              |   26 +++
 src/test/test-fileio.c                            |   25 ---
 src/test/test-util.c                              |   41 ++++--
 src/udev/net/link-config.c                        |    7 -
 src/udev/udevd.c                                  |    4 
 27 files changed, 253 insertions(+), 271 deletions(-)

New commits:
commit f4934dfaaac70c6d0d49463af62cbd089bfa64c8
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Nov 7 01:19:48 2014 +0100

    util: simplify normalize_env_assignment() a bit

diff --git a/src/shared/util.c b/src/shared/util.c
index 3eb8a0f..3411cea 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -2783,7 +2783,7 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) {
         if (k < 0)
                 return k;
 
-        snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
+        sprintf(fn, "/dev/char/%u:%u", major(devnr), minor(devnr));
 
         k = readlink_malloc(fn, &s);
         if (k < 0) {
@@ -3591,41 +3591,33 @@ char *unquote(const char *s, const char* quotes) {
 }
 
 char *normalize_env_assignment(const char *s) {
-        _cleanup_free_ char *name = NULL, *value = NULL, *p = NULL;
-        char *eq, *r;
+        _cleanup_free_ char *value = NULL;
+        const char *eq;
+        char *p, *name;
 
         eq = strchr(s, '=');
         if (!eq) {
-                char *t;
+                char *r, *t;
 
                 r = strdup(s);
                 if (!r)
                         return NULL;
 
                 t = strstrip(r);
-                if (t == r)
-                        return r;
+                if (t != r)
+                        memmove(r, t, strlen(t) + 1);
 
-                memmove(r, t, strlen(t) + 1);
                 return r;
         }
 
-        name = strndup(s, eq - s);
-        if (!name)
-                return NULL;
-
-        p = strdup(eq + 1);
-        if (!p)
-                return NULL;
+        name = strndupa(s, eq - s);
+        p = strdupa(eq + 1);
 
         value = unquote(strstrip(p), QUOTES);
         if (!value)
                 return NULL;
 
-        if (asprintf(&r, "%s=%s", strstrip(name), value) < 0)
-                r = NULL;
-
-        return r;
+        return strjoin(strstrip(name), "=", value, NULL);
 }
 
 int wait_for_terminate(pid_t pid, siginfo_t *status) {

commit b5e1fad5b1b9d29694e8c51245821a732fc22f93
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Nov 7 01:19:14 2014 +0100

    util: file_is_priv_sticky() is used internally in util.c only nowadays, make it static

diff --git a/src/shared/util.c b/src/shared/util.c
index ba86d20..3eb8a0f 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -2941,6 +2941,19 @@ int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root
         return rm_rf_children_dangerous(fd, only_dirs, honour_sticky, root_dev);
 }
 
+static int file_is_priv_sticky(const char *p) {
+        struct stat st;
+
+        assert(p);
+
+        if (lstat(p, &st) < 0)
+                return -errno;
+
+        return
+                (st.st_uid == 0 || st.st_uid == getuid()) &&
+                (st.st_mode & S_ISVTX);
+}
+
 static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bool honour_sticky, bool dangerous) {
         int fd, r;
         struct statfs s;
@@ -4829,19 +4842,6 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
         return -ENOENT;
 }
 
-int file_is_priv_sticky(const char *p) {
-        struct stat st;
-
-        assert(p);
-
-        if (lstat(p, &st) < 0)
-                return -errno;
-
-        return
-                (st.st_uid == 0 || st.st_uid == getuid()) &&
-                (st.st_mode & S_ISVTX);
-}
-
 static const char *const ioprio_class_table[] = {
         [IOPRIO_CLASS_NONE] = "none",
         [IOPRIO_CLASS_RT] = "realtime",
diff --git a/src/shared/util.h b/src/shared/util.h
index 4997225..24480be 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -582,8 +582,6 @@ static inline bool _pure_ in_charset(const char *s, const char* charset) {
 
 int block_get_whole_disk(dev_t d, dev_t *ret);
 
-int file_is_priv_sticky(const char *p);
-
 #define NULSTR_FOREACH(i, l)                                    \
         for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)
 

commit 25e14499c4c5b02229d05a5bc26c3693ade5f987
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Nov 7 01:10:57 2014 +0100

    update TODO

diff --git a/TODO b/TODO
index 8a1241f..f26aae8 100644
--- a/TODO
+++ b/TODO
@@ -37,6 +37,8 @@ External:
 
 Features:
 
+* code cleanup: retire FOREACH_WORD_QUOTED, port to unquote_first_word() loops instead
+
 * logind: when the power button is pressed short, just popup a logout dialog. If it is pressed for 1s, do the usual shutdown. Inspiration are Macs here.
 
 * optionally support running journald from the command line for testing purposes in external projects
@@ -60,8 +62,6 @@ Features:
 
 * maybe provide an API to allow migration of foreign PIDs into existing scopes.
 
-* kdbus: maybe rename "connection name" concept to something that doesn't reuse the word "name"?
-
 * PID 1 doesn't apply nspawns devices cgroup policy
 
 * maybe support a new very "soft" reboot mode, that simply kills all processes, disassembles everything, flushes /run and sysvipc, and then reexecs systemd again

commit 779042e772d2459f7649b34a164902dc456f1bab
Author: Michael Chapman <mike at very.puzzling.org>
Date:   Thu Nov 6 19:47:02 2014 +1100

    timer: reenable TIMER_ACTIVE timers when restarted
    
    A timer configured with OnActiveSec will start its associated unit again
    if the timer is stopped, then started. However, if the timer unit is
    restarted -- with "systemctl restart", say -- this does not occur.
    
    This commit ensures that TIMER_ACTIVE timers are re-enabled whenever the
    timer is started, even if that's within a restart job.

diff --git a/src/core/timer.c b/src/core/timer.c
index a3713e2..5c4e9f9 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -521,6 +521,7 @@ fail:
 
 static int timer_start(Unit *u) {
         Timer *t = TIMER(u);
+        TimerValue *v;
 
         assert(t);
         assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
@@ -530,6 +531,11 @@ static int timer_start(Unit *u) {
 
         t->last_trigger = DUAL_TIMESTAMP_NULL;
 
+        /* Reenable all timers that depend on unit activation time */
+        LIST_FOREACH(value, v, t->values)
+                if (v->base == TIMER_ACTIVE)
+                        v->disabled = false;
+
         if (t->stamp_path) {
                 struct stat st;
 

commit f32d2db140150b9d38684a699c9875b6e24ca27c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Nov 7 00:10:24 2014 +0100

    util: rework /proc/cmdline parser to use unquote_first_word()

diff --git a/src/shared/condition.c b/src/shared/condition.c
index ae23599..c5a3caa 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -101,7 +101,7 @@ static int condition_test_kernel_command_line(Condition *c) {
                 _cleanup_free_ char *word = NULL;
                 bool found;
 
-                r = unquote_first_word(&p, &word);
+                r = unquote_first_word(&p, &word, true);
                 if (r < 0)
                         return r;
                 if (r == 0)
diff --git a/src/shared/util.c b/src/shared/util.c
index 6401aaf..ba86d20 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -6146,8 +6146,7 @@ int split_pair(const char *s, const char *sep, char **l, char **r) {
 
 int shall_restore_state(void) {
         _cleanup_free_ char *line = NULL;
-        const char *word, *state;
-        size_t l;
+        const char *p;
         int r;
 
         r = proc_cmdline(&line);
@@ -6155,15 +6154,20 @@ int shall_restore_state(void) {
                 return r;
 
         r = 1;
-        FOREACH_WORD_QUOTED(word, l, line, state) {
+        p = line;
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
                 const char *e;
-                char n[l+1];
                 int k;
 
-                memcpy(n, word, l);
-                n[l] = 0;
+                k = unquote_first_word(&p, &word, true);
+                if (k < 0)
+                        return k;
+                if (k == 0)
+                        break;
 
-                e = startswith(n, "systemd.restore_state=");
+                e = startswith(word, "systemd.restore_state=");
                 if (!e)
                         continue;
 
@@ -6186,8 +6190,7 @@ int proc_cmdline(char **ret) {
 
 int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
         _cleanup_free_ char *line = NULL;
-        const char *w, *state;
-        size_t l;
+        const char *p;
         int r;
 
         assert(parse_item);
@@ -6196,11 +6199,16 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
         if (r < 0)
                 return r;
 
-        FOREACH_WORD_QUOTED(w, l, line, state) {
-                char word[l+1], *value;
+        p = line;
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
+                char *value = NULL;
 
-                memcpy(word, w, l);
-                word[l] = 0;
+                r = unquote_first_word(&p, &word, true);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        break;
 
                 /* Filter out arguments that are intended only for the
                  * initrd */
@@ -6976,7 +6984,7 @@ int is_dir(const char* path, bool follow) {
         return !!S_ISDIR(st.st_mode);
 }
 
-int unquote_first_word(const char **p, char **ret) {
+int unquote_first_word(const char **p, char **ret, bool relax) {
         _cleanup_free_ char *s = NULL;
         size_t allocated = 0, sz = 0;
 
@@ -7035,8 +7043,11 @@ int unquote_first_word(const char **p, char **ret) {
                         break;
 
                 case VALUE_ESCAPE:
-                        if (c == 0)
+                        if (c == 0) {
+                                if (relax)
+                                        goto finish;
                                 return -EINVAL;
+                        }
 
                         if (!GREEDY_REALLOC(s, allocated, sz+2))
                                 return -ENOMEM;
@@ -7047,9 +7058,11 @@ int unquote_first_word(const char **p, char **ret) {
                         break;
 
                 case SINGLE_QUOTE:
-                        if (c == 0)
+                        if (c == 0) {
+                                if (relax)
+                                        goto finish;
                                 return -EINVAL;
-                        else if (c == '\'')
+                        } else if (c == '\'')
                                 state = VALUE;
                         else if (c == '\\')
                                 state = SINGLE_QUOTE_ESCAPE;
@@ -7063,8 +7076,11 @@ int unquote_first_word(const char **p, char **ret) {
                         break;
 
                 case SINGLE_QUOTE_ESCAPE:
-                        if (c == 0)
+                        if (c == 0) {
+                                if (relax)
+                                        goto finish;
                                 return -EINVAL;
+                        }
 
                         if (!GREEDY_REALLOC(s, allocated, sz+2))
                                 return -ENOMEM;
@@ -7090,8 +7106,11 @@ int unquote_first_word(const char **p, char **ret) {
                         break;
 
                 case DOUBLE_QUOTE_ESCAPE:
-                        if (c == 0)
+                        if (c == 0) {
+                                if (relax)
+                                        goto finish;
                                 return -EINVAL;
+                        }
 
                         if (!GREEDY_REALLOC(s, allocated, sz+2))
                                 return -ENOMEM;
@@ -7151,7 +7170,7 @@ int unquote_many_words(const char **p, ...) {
         l = newa0(char*, n);
         for (c = 0; c < n; c++) {
 
-                r = unquote_first_word(p, &l[c]);
+                r = unquote_first_word(p, &l[c], false);
                 if (r < 0) {
                         int j;
 
diff --git a/src/shared/util.h b/src/shared/util.h
index af589b6..4997225 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -1018,7 +1018,7 @@ int take_password_lock(const char *root);
 int is_symlink(const char *path);
 int is_dir(const char *path, bool follow);
 
-int unquote_first_word(const char **p, char **ret);
+int unquote_first_word(const char **p, char **ret, bool relax);
 int unquote_many_words(const char **p, ...) _sentinel_;
 
 int free_and_strdup(char **p, const char *s);
diff --git a/src/test/test-util.c b/src/test/test-util.c
index de6a2a0..01b0192 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -1173,51 +1173,60 @@ static void test_unquote_first_word(void) {
         char *t;
 
         p = original = "foobar waldo";
-        assert_se(unquote_first_word(&p, &t) > 0);
+        assert_se(unquote_first_word(&p, &t, false) > 0);
         assert_se(streq(t, "foobar"));
         free(t);
         assert_se(p == original + 7);
 
-        assert_se(unquote_first_word(&p, &t) > 0);
+        assert_se(unquote_first_word(&p, &t, false) > 0);
         assert_se(streq(t, "waldo"));
         free(t);
         assert_se(p == original + 12);
 
-        assert_se(unquote_first_word(&p, &t) == 0);
+        assert_se(unquote_first_word(&p, &t, false) == 0);
         assert_se(!t);
         assert_se(p == original + 12);
 
         p = original = "\"foobar\" \'waldo\'";
-        assert_se(unquote_first_word(&p, &t) > 0);
+        assert_se(unquote_first_word(&p, &t, false) > 0);
         assert_se(streq(t, "foobar"));
         free(t);
         assert_se(p == original + 9);
 
-        assert_se(unquote_first_word(&p, &t) > 0);
+        assert_se(unquote_first_word(&p, &t, false) > 0);
         assert_se(streq(t, "waldo"));
         free(t);
         assert_se(p == original + 16);
 
-        assert_se(unquote_first_word(&p, &t) == 0);
+        assert_se(unquote_first_word(&p, &t, false) == 0);
         assert_se(!t);
         assert_se(p == original + 16);
 
         p = original = "\"";
-        assert_se(unquote_first_word(&p, &t) == -EINVAL);
+        assert_se(unquote_first_word(&p, &t, false) == -EINVAL);
         assert_se(p == original + 1);
 
         p = original = "\'";
-        assert_se(unquote_first_word(&p, &t) == -EINVAL);
+        assert_se(unquote_first_word(&p, &t, false) == -EINVAL);
         assert_se(p == original + 1);
 
+        p = original = "\'fooo";
+        assert_se(unquote_first_word(&p, &t, false) == -EINVAL);
+        assert_se(p == original + 5);
+
+        p = original = "\'fooo";
+        assert_se(unquote_first_word(&p, &t, true) > 0);
+        assert_se(streq(t, "fooo"));
+        assert_se(p == original + 5);
+
         p = original = "yay\'foo\'bar";
-        assert_se(unquote_first_word(&p, &t) > 0);
+        assert_se(unquote_first_word(&p, &t, false) > 0);
         assert_se(streq(t, "yayfoobar"));
         free(t);
         assert_se(p == original + 11);
 
         p = original = "   foobar   ";
-        assert_se(unquote_first_word(&p, &t) > 0);
+        assert_se(unquote_first_word(&p, &t, false) > 0);
         assert_se(streq(t, "foobar"));
         free(t);
         assert_se(p == original + 12);
@@ -1277,6 +1286,17 @@ static void test_unquote_many_words(void) {
         free(a);
 }
 
+static int parse_item(const char *key, const char *value) {
+        assert_se(key);
+
+        log_info("kernel cmdline option <%s> = <%s>", key, strna(value));
+        return 0;
+}
+
+static void test_parse_proc_cmdline(void) {
+        assert_se(parse_proc_cmdline(parse_item) >= 0);
+}
+
 int main(int argc, char *argv[]) {
         log_parse_environment();
         log_open();
@@ -1348,6 +1368,7 @@ int main(int argc, char *argv[]) {
         test_execute_directory();
         test_unquote_first_word();
         test_unquote_many_words();
+        test_parse_proc_cmdline();
 
         return 0;
 }

commit b5884878a2874447b2a9f07f324a7cd909d96d48
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Nov 6 21:53:34 2014 +0100

    util: simplify proc_cmdline() to reuse get_process_cmdline()
    
    Also, make all parsing of the kernel cmdline non-fatal.

diff --git a/src/core/kmod-setup.c b/src/core/kmod-setup.c
index 2f3f608..38e1726 100644
--- a/src/core/kmod-setup.c
+++ b/src/core/kmod-setup.c
@@ -47,7 +47,7 @@ static void systemd_kmod_log(
 static bool cmdline_check_kdbus(void) {
         _cleanup_free_ char *line = NULL;
 
-        if (proc_cmdline(&line) <= 0)
+        if (proc_cmdline(&line) < 0)
                 return false;
 
         return strstr(line, "kdbus") != NULL;
diff --git a/src/core/main.c b/src/core/main.c
index d48604e..56a1f61 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1402,9 +1402,11 @@ int main(int argc, char *argv[]) {
         if (parse_config_file() < 0)
                 goto finish;
 
-        if (arg_running_as == SYSTEMD_SYSTEM)
-                if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
-                        goto finish;
+        if (arg_running_as == SYSTEMD_SYSTEM) {
+                r = parse_proc_cmdline(parse_proc_cmdline_item);
+                if (r < 0)
+                        log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-r));
+        }
 
         /* Note that this also parses bits from the kernel command
          * line, including "debug". */
diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c
index 20dca84..7c79ca3 100644
--- a/src/cryptsetup/cryptsetup-generator.c
+++ b/src/cryptsetup/cryptsetup-generator.c
@@ -308,7 +308,7 @@ int main(int argc, char *argv[]) {
         _cleanup_strv_free_ char **disks_done = NULL;
         _cleanup_fclose_ FILE *f = NULL;
         unsigned n = 0;
-        int r = EXIT_FAILURE, r2 = EXIT_FAILURE;
+        int r = EXIT_FAILURE, r2 = EXIT_FAILURE, z;
         char **i;
 
         if (argc > 1 && argc != 4) {
@@ -325,8 +325,9 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
-                goto cleanup;
+        z = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (z < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-z));
 
         if (!arg_enabled) {
                 r = r2 = EXIT_SUCCESS;
diff --git a/src/debug-generator/debug-generator.c b/src/debug-generator/debug-generator.c
index fd7c29d..5bbcd8f 100644
--- a/src/debug-generator/debug-generator.c
+++ b/src/debug-generator/debug-generator.c
@@ -150,8 +150,9 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
-                return EXIT_FAILURE;
+        r = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (r < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-r));
 
         if (arg_debug_shell) {
                 r = strv_extend(&arg_wants, "debug-shell.service");
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
index 70a5918..5562217 100644
--- a/src/fsck/fsck.c
+++ b/src/fsck/fsck.c
@@ -236,7 +236,10 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        parse_proc_cmdline(parse_proc_cmdline_item);
+        q = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (q < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-q));
+
         test_files();
 
         if (!arg_force && arg_skip)
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
index 94cbc3a..af45c25 100644
--- a/src/fstab-generator/fstab-generator.c
+++ b/src/fstab-generator/fstab-generator.c
@@ -593,8 +593,9 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
-                return EXIT_FAILURE;
+        r = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (r < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-r));
 
         /* Always honour root= and usr= in the kernel command line if we are in an initrd */
         if (in_initrd()) {
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 539e2e6..d4cfe37 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -772,8 +772,9 @@ int main(int argc, char *argv[]) {
                 return EXIT_SUCCESS;
         }
 
-        if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
-                return EXIT_FAILURE;
+        r = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (r < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-r));
 
         if (!arg_enabled) {
                 log_debug("Disabled, exiting.");
diff --git a/src/hibernate-resume/hibernate-resume-generator.c b/src/hibernate-resume/hibernate-resume-generator.c
index f407216..41f65d9 100644
--- a/src/hibernate-resume/hibernate-resume-generator.c
+++ b/src/hibernate-resume/hibernate-resume-generator.c
@@ -45,6 +45,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value) {
 static int process_resume(void) {
         _cleanup_free_ char *name = NULL, *lnk = NULL;
 
+        if (!arg_resume_dev)
+                return 0;
+
         name = unit_name_from_path_instance("systemd-hibernate-resume", arg_resume_dev, ".service");
         if (!name)
                 return log_oom();
@@ -83,12 +86,11 @@ int main(int argc, char *argv[]) {
         if (!in_initrd())
                 return EXIT_SUCCESS;
 
-        if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
-                return EXIT_FAILURE;
-
-        if (arg_resume_dev != NULL)
-                r = process_resume();
+        r = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (r < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-r));
 
+        r = process_resume();
         free(arg_resume_dev);
 
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c
index 2f782f2..62ae79a 100644
--- a/src/journal/journald-server.c
+++ b/src/journal/journald-server.c
@@ -1310,10 +1310,10 @@ static int server_parse_proc_cmdline(Server *s) {
         int r;
 
         r = proc_cmdline(&line);
-        if (r < 0)
+        if (r < 0) {
                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
-        if (r <= 0)
                 return 0;
+        }
 
         FOREACH_WORD_QUOTED(w, l, line, state) {
                 _cleanup_free_ char *word;
diff --git a/src/modules-load/modules-load.c b/src/modules-load/modules-load.c
index c77b092..08de5e0 100644
--- a/src/modules-load/modules-load.c
+++ b/src/modules-load/modules-load.c
@@ -243,8 +243,9 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
-                return EXIT_FAILURE;
+        r = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (r < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-r));
 
         ctx = kmod_new(NULL, NULL);
         if (!ctx) {
diff --git a/src/quotacheck/quotacheck.c b/src/quotacheck/quotacheck.c
index ed95b48..6f39dae 100644
--- a/src/quotacheck/quotacheck.c
+++ b/src/quotacheck/quotacheck.c
@@ -74,6 +74,7 @@ int main(int argc, char *argv[]) {
         };
 
         pid_t pid;
+        int r;
 
         if (argc > 1) {
                 log_error("This program takes no arguments.");
@@ -86,7 +87,10 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        parse_proc_cmdline(parse_proc_cmdline_item);
+        r = parse_proc_cmdline(parse_proc_cmdline_item);
+        if (r < 0)
+                log_warning("Failed to parse kernel command line, ignoring: %s", strerror(-r));
+
         test_files();
 
         if (!arg_force) {
@@ -107,5 +111,7 @@ int main(int argc, char *argv[]) {
                 _exit(1); /* Operational error */
         }
 
-        return wait_for_terminate_and_warn("quotacheck", pid) >= 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+        r = wait_for_terminate_and_warn("quotacheck", pid);
+
+        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
diff --git a/src/shared/condition.c b/src/shared/condition.c
index 08bebee..ae23599 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -93,8 +93,6 @@ static int condition_test_kernel_command_line(Condition *c) {
         r = proc_cmdline(&line);
         if (r < 0)
                 return r;
-        if (r == 0)
-                return false;
 
         equal = !!strchr(c->parameter, '=');
         p = line;
diff --git a/src/shared/util.c b/src/shared/util.c
index dc1bc39..6401aaf 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -6153,11 +6153,8 @@ int shall_restore_state(void) {
         r = proc_cmdline(&line);
         if (r < 0)
                 return r;
-        if (r == 0) /* Container ... */
-                return 1;
 
         r = 1;
-
         FOREACH_WORD_QUOTED(word, l, line, state) {
                 const char *e;
                 char n[l+1];
@@ -6179,30 +6176,12 @@ int shall_restore_state(void) {
 }
 
 int proc_cmdline(char **ret) {
-        int r;
-
-        if (detect_container(NULL) > 0) {
-                char *buf = NULL, *p;
-                size_t sz = 0;
-
-                r = read_full_file("/proc/1/cmdline", &buf, &sz);
-                if (r < 0)
-                        return r;
-
-                for (p = buf; p + 1 < buf + sz; p++)
-                        if (*p == 0)
-                                *p = ' ';
-
-                *p = 0;
-                *ret = buf;
-                return 1;
-        }
-
-        r = read_one_line_file("/proc/cmdline", ret);
-        if (r < 0)
-                return r;
+        assert(ret);
 
-        return 1;
+        if (detect_container(NULL) > 0)
+                return get_process_cmdline(1, 0, false, ret);
+        else
+                return read_one_line_file("/proc/cmdline", ret);
 }
 
 int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
@@ -6215,9 +6194,7 @@ int parse_proc_cmdline(int (*parse_item)(const char *key, const char *value)) {
 
         r = proc_cmdline(&line);
         if (r < 0)
-                log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
-        if (r <= 0)
-                return 0;
+                return r;
 
         FOREACH_WORD_QUOTED(w, l, line, state) {
                 char word[l+1], *value;
diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c
index 428a71d..5aefb7d 100644
--- a/src/udev/net/link-config.c
+++ b/src/udev/net/link-config.c
@@ -174,11 +174,10 @@ static bool enable_name_policy(void) {
         size_t l;
 
         r = proc_cmdline(&line);
-        if (r < 0)
-                log_warning("Failed to read /proc/cmdline, ignoring: %s",
-                            strerror(-r));
-        if (r <= 0)
+        if (r < 0) {
+                log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
                 return true;
+        }
 
         FOREACH_WORD_QUOTED(word, l, line, state)
                 if (strneq(word, "net.ifnames=0", l))
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 305ce86..a040529 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -961,10 +961,10 @@ static void kernel_cmdline_options(struct udev *udev) {
         int r;
 
         r = proc_cmdline(&line);
-        if (r < 0)
+        if (r < 0) {
                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
-        if (r <= 0)
                 return;
+        }
 
         FOREACH_WORD_QUOTED(word, l, line, state) {
                 char *s, *opt, *value;

commit f2997962ff8aeea577bed878d3bc4e4f64784e45
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Nov 6 21:21:39 2014 +0100

    fileio: simplify write_string_file_atomic() by reusing write_string_stream()

diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index f4efc4c..ff6b1a7 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -66,7 +66,7 @@ int write_string_file_no_create(const char *fn, const char *line) {
         assert(line);
 
         /* We manually build our own version of fopen(..., "we") that
-         * without O_CREAT */
+         * works without O_CREAT */
         fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY);
         if (fd < 0)
                 return -errno;
@@ -94,20 +94,10 @@ int write_string_file_atomic(const char *fn, const char *line) {
 
         fchmod_umask(fileno(f), 0644);
 
-        errno = 0;
-        fputs(line, f);
-        if (!endswith(line, "\n"))
-                fputc('\n', f);
-
-        fflush(f);
-
-        if (ferror(f))
-                r = errno ? -errno : -EIO;
-        else {
+        r = write_string_stream(f, line);
+        if (r >= 0) {
                 if (rename(p, fn) < 0)
                         r = -errno;
-                else
-                        r = 0;
         }
 
         if (r < 0)

commit 84ee0960443b795936026239f8c0ff8429aed699
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Nov 6 21:20:32 2014 +0100

    copy: change error code when hitting copy limit to EFBIG
    
    After all, this is about files, not arguments, hence EFBIG is more
    appropriate than E2BIG

diff --git a/src/journal/coredump.c b/src/journal/coredump.c
index f423fa2..26a2010 100644
--- a/src/journal/coredump.c
+++ b/src/journal/coredump.c
@@ -329,7 +329,7 @@ static int save_external_coredump(
         }
 
         r = copy_bytes(STDIN_FILENO, fd, arg_process_size_max);
-        if (r == -E2BIG) {
+        if (r == -EFBIG) {
                 log_error("Coredump of %s (%s) is larger than configured processing limit, refusing.", info[INFO_PID], info[INFO_COMM]);
                 goto fail;
         } else if (IN_SET(r, -EDQUOT, -ENOSPC)) {
diff --git a/src/shared/copy.c b/src/shared/copy.c
index a863246..abb7fbc 100644
--- a/src/shared/copy.c
+++ b/src/shared/copy.c
@@ -37,7 +37,7 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes) {
                 if (max_bytes != (off_t) -1) {
 
                         if (max_bytes <= 0)
-                                return -E2BIG;
+                                return -EFBIG;
 
                         if ((off_t) m > max_bytes)
                                 m = (size_t) max_bytes;

commit cda134ab1eac84f874aacf8e885a07112a7fd5ce
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Nov 6 21:19:20 2014 +0100

    copy: teach copy_bytes() sendfile() support, and then replace sendfile_full() by it

diff --git a/src/shared/copy.c b/src/shared/copy.c
index 3744797..a863246 100644
--- a/src/shared/copy.c
+++ b/src/shared/copy.c
@@ -19,17 +19,20 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sys/sendfile.h>
+
 #include "util.h"
 #include "copy.h"
 
 int copy_bytes(int fdf, int fdt, off_t max_bytes) {
+        bool try_sendfile = true;
+
         assert(fdf >= 0);
         assert(fdt >= 0);
 
         for (;;) {
-                char buf[PIPE_BUF];
-                ssize_t n, k;
-                size_t m = sizeof(buf);
+                size_t m = PIPE_BUF;
+                ssize_t n;
 
                 if (max_bytes != (off_t) -1) {
 
@@ -40,19 +43,44 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes) {
                                 m = (size_t) max_bytes;
                 }
 
-                n = read(fdf, buf, m);
-                if (n < 0)
-                        return -errno;
-                if (n == 0)
-                        break;
+                /* First try sendfile(), unless we already tried */
+                if (try_sendfile) {
+
+                        n = sendfile(fdt, fdf, NULL, m);
+                        if (n < 0) {
+                                if (errno != EINVAL && errno != ENOSYS)
+                                        return -errno;
+
+                                try_sendfile = false;
+                                /* use fallback below */
+                        } else if (n == 0) /* EOF */
+                                break;
+                        else if (n > 0)
+                                /* Succcess! */
+                                goto next;
+                }
+
+                /* As a fallback just copy bits by hand */
+                {
+                        char buf[m];
+                        ssize_t k;
 
-                errno = 0;
-                k = loop_write(fdt, buf, n, false);
-                if (k < 0)
-                        return k;
-                if (k != n)
-                        return errno ? -errno : -EIO;
+                        n = read(fdf, buf, m);
+                        if (n < 0)
+                                return -errno;
+                        if (n == 0) /* EOF */
+                                break;
+
+                        errno = 0;
+                        k = loop_write(fdt, buf, n, false);
+                        if (k < 0)
+                                return k;
+                        if (k != n)
+                                return errno ? -errno : -EIO;
+
+                }
 
+        next:
                 if (max_bytes != (off_t) -1) {
                         assert(max_bytes >= n);
                         max_bytes -= n;
@@ -262,34 +290,39 @@ int copy_tree(const char *from, const char *to, bool merge) {
                 return -ENOTSUP;
 }
 
-int copy_file(const char *from, const char *to, int flags, mode_t mode) {
-        _cleanup_close_ int fdf = -1, fdt = -1;
-        int r;
+int copy_file_fd(const char *from, int fdt) {
+        _cleanup_close_ int fdf = -1;
 
         assert(from);
-        assert(to);
+        assert(fdt >= 0);
 
         fdf = open(from, O_RDONLY|O_CLOEXEC|O_NOCTTY);
         if (fdf < 0)
                 return -errno;
 
+        return copy_bytes(fdf, fdt, (off_t) -1);
+}
+
+int copy_file(const char *from, const char *to, int flags, mode_t mode) {
+        int fdt, r;
+
+        assert(from);
+        assert(to);
+
         fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode);
         if (fdt < 0)
                 return -errno;
 
-        r = copy_bytes(fdf, fdt, (off_t) -1);
+        r = copy_file_fd(from, fdt);
         if (r < 0) {
+                close(fdt);
                 unlink(to);
                 return r;
         }
 
-        r = close(fdt);
-        fdt = -1;
-
-        if (r < 0) {
-                r = -errno;
-                unlink(to);
-                return r;
+        if (close(fdt) < 0) {
+                unlink_noerrno(to);
+                return -errno;
         }
 
         return 0;
diff --git a/src/shared/copy.h b/src/shared/copy.h
index 6b93107..6293211 100644
--- a/src/shared/copy.h
+++ b/src/shared/copy.h
@@ -24,6 +24,7 @@
 #include <stdbool.h>
 #include <sys/types.h>
 
+int copy_file_fd(const char *from, int to);
 int copy_file(const char *from, const char *to, int flags, mode_t mode);
 int copy_tree(const char *from, const char *to, bool merge);
 int copy_bytes(int fdf, int fdt, off_t max_bytes);
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 38028b9..f4efc4c 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -20,12 +20,12 @@
 ***/
 
 #include <unistd.h>
-#include <sys/sendfile.h>
-#include "fileio.h"
+
 #include "util.h"
 #include "strv.h"
 #include "utf8.h"
 #include "ctype.h"
+#include "fileio.h"
 
 int write_string_stream(FILE *f, const char *line) {
         assert(f);
@@ -144,77 +144,6 @@ int read_one_line_file(const char *fn, char **line) {
         return 0;
 }
 
-ssize_t sendfile_full(int out_fd, const char *fn) {
-        _cleanup_fclose_ FILE *f;
-        struct stat st;
-        int r;
-        ssize_t s;
-
-        size_t n, l;
-        _cleanup_free_ char *buf = NULL;
-
-        assert(out_fd > 0);
-        assert(fn);
-
-        f = fopen(fn, "re");
-        if (!f)
-                return -errno;
-
-        r = fstat(fileno(f), &st);
-        if (r < 0)
-                return -errno;
-
-        s = sendfile(out_fd, fileno(f), NULL, st.st_size);
-        if (s < 0)
-                if (errno == EINVAL || errno == ENOSYS) {
-                        /* continue below */
-                } else
-                        return -errno;
-        else
-                return s;
-
-        /* sendfile() failed, fall back to read/write */
-
-        /* Safety check */
-        if (st.st_size > 4*1024*1024)
-                return -E2BIG;
-
-        n = st.st_size > 0 ? st.st_size : LINE_MAX;
-        l = 0;
-
-        while (true) {
-                char *t;
-                size_t k;
-
-                t = realloc(buf, n);
-                if (!t)
-                        return -ENOMEM;
-
-                buf = t;
-                k = fread(buf + l, 1, n - l, f);
-
-                if (k <= 0) {
-                        if (ferror(f))
-                                return -errno;
-
-                        break;
-                }
-
-                l += k;
-                n *= 2;
-
-                /* Safety check */
-                if (n > 4*1024*1024)
-                        return -E2BIG;
-        }
-
-        r = write(out_fd, buf, l);
-        if (r < 0)
-                return -errno;
-
-        return (ssize_t) l;
-}
-
 int read_full_stream(FILE *f, char **contents, size_t *size) {
         size_t n, l;
         _cleanup_free_ char *buf = NULL;
diff --git a/src/shared/fileio.h b/src/shared/fileio.h
index c256915..5ae51c1 100644
--- a/src/shared/fileio.h
+++ b/src/shared/fileio.h
@@ -33,7 +33,6 @@ int write_string_file_atomic(const char *fn, const char *line);
 int read_one_line_file(const char *fn, char **line);
 int read_full_file(const char *fn, char **contents, size_t *size);
 int read_full_stream(FILE *f, char **contents, size_t *size);
-ssize_t sendfile_full(int out_fd, const char *fn);
 
 int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
 int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index d9e9c2a..c903c54 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -67,6 +67,7 @@
 #include "logs-show.h"
 #include "socket-util.h"
 #include "fileio.h"
+#include "copy.h"
 #include "env-util.h"
 #include "bus-util.h"
 #include "bus-message.h"
@@ -4647,7 +4648,7 @@ static int cat(sd_bus *bus, char **args) {
                                ansi_highlight_off());
                         fflush(stdout);
 
-                        r = sendfile_full(STDOUT_FILENO, fragment_path);
+                        r = copy_file_fd(fragment_path, STDOUT_FILENO);
                         if (r < 0) {
                                 log_warning("Failed to cat %s: %s", fragment_path, strerror(-r));
                                 continue;
@@ -4662,7 +4663,7 @@ static int cat(sd_bus *bus, char **args) {
                                ansi_highlight_off());
                         fflush(stdout);
 
-                        r = sendfile_full(STDOUT_FILENO, *path);
+                        r = copy_file_fd(*path, STDOUT_FILENO);
                         if (r < 0) {
                                 log_warning("Failed to cat %s: %s", *path, strerror(-r));
                                 continue;
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 6aa86a0..d2cad08 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -48,11 +48,36 @@ static void test_copy_file(void) {
 
         assert_se(read_full_file(fn_copy, &buf, &sz) == 0);
         assert_se(streq(buf, "foo bar bar bar foo\n"));
+        assert_se(sz == 20);
 
         unlink(fn);
         unlink(fn_copy);
 }
 
+static void test_copy_file_fd(void) {
+        char in_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
+        char out_fn[] = "/tmp/test-copy-file-fd-XXXXXX";
+        _cleanup_close_ int in_fd = -1, out_fd = -1;
+        char text[] = "boohoo\nfoo\n\tbar\n";
+        char buf[64] = {0};
+
+        in_fd = mkostemp_safe(in_fn, O_RDWR);
+        assert_se(in_fd >= 0);
+        out_fd = mkostemp_safe(out_fn, O_RDWR);
+        assert_se(out_fd >= 0);
+
+        assert_se(write_string_file(in_fn, text) == 0);
+        assert_se(copy_file_fd("/a/file/which/does/not/exist/i/guess", out_fd) < 0);
+        assert_se(copy_file_fd(in_fn, out_fd) >= 0);
+        assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
+
+        assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
+        assert_se(streq(buf, text));
+
+        unlink(in_fn);
+        unlink(out_fn);
+}
+
 static void test_copy_tree(void) {
         char original_dir[] = "/tmp/test-copy_tree/";
         char copy_dir[] = "/tmp/test-copy_tree-copy/";
@@ -109,6 +134,7 @@ static void test_copy_tree(void) {
 
 int main(int argc, char *argv[]) {
         test_copy_file();
+        test_copy_file_fd();
         test_copy_tree();
 
         return 0;
diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c
index c26a6fa..cdf1973 100644
--- a/src/test/test-fileio.c
+++ b/src/test/test-fileio.c
@@ -348,30 +348,6 @@ static void test_write_string_file_no_create(void) {
         unlink(fn);
 }
 
-static void test_sendfile_full(void) {
-        char in_fn[] = "/tmp/test-sendfile_full-XXXXXX";
-        char out_fn[] = "/tmp/test-sendfile_full-XXXXXX";
-        _cleanup_close_ int in_fd, out_fd;
-        char text[] = "boohoo\nfoo\n\tbar\n";
-        char buf[64] = {0};
-
-        in_fd = mkostemp_safe(in_fn, O_RDWR);
-        assert_se(in_fd >= 0);
-        out_fd = mkostemp_safe(out_fn, O_RDWR);
-        assert_se(out_fd >= 0);
-
-        assert_se(write_string_file(in_fn, text) == 0);
-        assert_se(sendfile_full(out_fd, "/a/file/which/does/not/exist/i/guess") < 0);
-        assert_se(sendfile_full(out_fd, in_fn) == sizeof(text) - 1);
-        assert_se(lseek(out_fd, SEEK_SET, 0) == 0);
-
-        assert_se(read(out_fd, buf, sizeof(buf)) == sizeof(text) - 1);
-        assert_se(streq(buf, text));
-
-        unlink(in_fn);
-        unlink(out_fn);
-}
-
 static void test_load_env_file_pairs(void) {
         char fn[] = "/tmp/test-load_env_file_pairs-XXXXXX";
         int fd;
@@ -428,7 +404,6 @@ int main(int argc, char *argv[]) {
         test_write_string_stream();
         test_write_string_file();
         test_write_string_file_no_create();
-        test_sendfile_full();
         test_load_env_file_pairs();
 
         return 0;

commit 0c2576ef74a9f9b96519cdcb7f9c01742d8255e2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Nov 6 21:11:10 2014 +0100

    util: make use of isempty() where appropriate

diff --git a/src/shared/util.c b/src/shared/util.c
index 39ce46a..dc1bc39 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -695,7 +695,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
         }
 
         /* Kernel threads have no argv[] */
-        if (r == NULL || r[0] == 0) {
+        if (isempty(r)) {
                 _cleanup_free_ char *t = NULL;
                 int h;
 



More information about the systemd-commits mailing list