~ubuntu-branches/debian/jessie/systemd/jessie

« back to all changes in this revision

Viewing changes to src/util.c

  • Committer: Package Import Robot
  • Author(s): Tollef Fog Heen, Tollef Fog Heen, Michael Biebl
  • Date: 2012-04-03 19:59:17 UTC
  • mfrom: (1.1.10) (6.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20120403195917-l532urrbg4pkreas
Tags: 44-1
[ Tollef Fog Heen ]
* New upstream version.
  - Backport 3492207: journal: PAGE_SIZE is not known on ppc and other
    archs
  - Backport 5a2a2a1: journal: react with immediate rotation to a couple
    of more errors
  - Backport 693ce21: util: never follow symlinks in rm_rf_children()
    Fixes CVE-2012-1174, closes: #664364
* Drop output message from init-functions hook, it's pointless.
* Only rmdir /lib/init/rw if it exists.
* Explicitly order debian-fixup before sysinit.target to prevent a
  possible race condition with the creation of sockets.  Thanks to
  Michael Biebl for debugging this.
* Always restart the initctl socket on upgrades, to mask sysvinit
  removing it.

[ Michael Biebl ]
* Remove workaround for non-interactive sessions from pam config again.
* Create compat /dev/initctl symlink in case we are upgrading from a system
  running a newer version of sysvinit (using /run/initctl) and sysvinit is
  replaced with systemd-sysv during the upgrade. Closes: #663219
* Install new man pages.
* Build-Depend on valac (>= 0.12) instead of valac-0.12. Closes: #663323

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
#include <linux/rtc.h>
56
56
#include <glob.h>
57
57
#include <grp.h>
 
58
#include <sys/mman.h>
58
59
 
59
60
#include "macro.h"
60
61
#include "util.h"
73
74
        static __thread size_t pgsz = 0;
74
75
        long r;
75
76
 
76
 
        if (_likely_(pgsz))
 
77
        if (_likely_(pgsz > 0))
77
78
                return pgsz;
78
79
 
79
80
        assert_se((r = sysconf(_SC_PAGESIZE)) > 0);
516
517
                return -errno;
517
518
 
518
519
        if (!(fgets(line, sizeof(line), f))) {
519
 
                r = -errno;
 
520
                r = feof(f) ? -EIO : -errno;
520
521
                fclose(f);
521
522
                return r;
522
523
        }
561
562
                return -errno;
562
563
 
563
564
        if (!(fgets(line, sizeof(line), f))) {
564
 
                r = -errno;
 
565
                r = feof(f) ? -EIO : -errno;
565
566
                fclose(f);
566
567
                return r;
567
568
        }
704
705
        assert(fn);
705
706
        assert(line);
706
707
 
707
 
        if (!(f = fopen(fn, "re")))
 
708
        f = fopen(fn, "re");
 
709
        if (!f)
708
710
                return -errno;
709
711
 
710
 
        if (!(fgets(t, sizeof(t), f))) {
711
 
                r = -errno;
712
 
                goto finish;
 
712
        if (!fgets(t, sizeof(t), f)) {
 
713
 
 
714
                if (ferror(f)) {
 
715
                        r = -errno;
 
716
                        goto finish;
 
717
                }
 
718
 
 
719
                t[0] = 0;
713
720
        }
714
721
 
715
 
        if (!(c = strdup(t))) {
 
722
        c = strdup(t);
 
723
        if (!c) {
716
724
                r = -ENOMEM;
717
725
                goto finish;
718
726
        }
884
892
                char ***rl) {
885
893
 
886
894
        FILE *f;
887
 
        char **m = 0;
 
895
        char **m = NULL;
888
896
        int r;
889
897
 
890
898
        assert(fname);
993
1001
        return s;
994
1002
}
995
1003
 
996
 
int get_process_name(pid_t pid, char **name) {
997
 
        char *p;
 
1004
int get_process_comm(pid_t pid, char **name) {
998
1005
        int r;
999
1006
 
1000
 
        assert(pid >= 1);
1001
1007
        assert(name);
1002
1008
 
1003
 
        if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
1004
 
                return -ENOMEM;
1005
 
 
1006
 
        r = read_one_line_file(p, name);
1007
 
        free(p);
1008
 
 
1009
 
        if (r < 0)
1010
 
                return r;
1011
 
 
1012
 
        return 0;
 
1009
        if (pid == 0)
 
1010
                r = read_one_line_file("/proc/self/comm", name);
 
1011
        else {
 
1012
                char *p;
 
1013
                if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
 
1014
                        return -ENOMEM;
 
1015
 
 
1016
                r = read_one_line_file(p, name);
 
1017
                free(p);
 
1018
        }
 
1019
 
 
1020
        return r;
1013
1021
}
1014
1022
 
1015
 
int get_process_cmdline(pid_t pid, size_t max_length, char **line) {
1016
 
        char *p, *r, *k;
 
1023
int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
 
1024
        char *r, *k;
1017
1025
        int c;
1018
1026
        bool space = false;
1019
1027
        size_t left;
1020
1028
        FILE *f;
1021
1029
 
1022
 
        assert(pid >= 1);
1023
1030
        assert(max_length > 0);
1024
1031
        assert(line);
1025
1032
 
1026
 
        if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
1027
 
                return -ENOMEM;
 
1033
        if (pid == 0)
 
1034
                f = fopen("/proc/self/cmdline", "re");
 
1035
        else {
 
1036
                char *p;
 
1037
                if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
 
1038
                        return -ENOMEM;
1028
1039
 
1029
 
        f = fopen(p, "re");
1030
 
        free(p);
 
1040
                f = fopen(p, "re");
 
1041
                free(p);
 
1042
        }
1031
1043
 
1032
1044
        if (!f)
1033
1045
                return -errno;
1034
1046
 
1035
 
        if (!(r = new(char, max_length))) {
 
1047
        r = new(char, max_length);
 
1048
        if (!r) {
1036
1049
                fclose(f);
1037
1050
                return -ENOMEM;
1038
1051
        }
1076
1089
 
1077
1090
                free(r);
1078
1091
 
1079
 
                if ((h = get_process_name(pid, &t)) < 0)
 
1092
                if (!comm_fallback)
 
1093
                        return -ENOENT;
 
1094
 
 
1095
                h = get_process_comm(pid, &t);
 
1096
                if (h < 0)
1080
1097
                        return h;
1081
1098
 
1082
 
                h = asprintf(&r, "[%s]", t);
 
1099
                r = join("[", t, "]", NULL);
1083
1100
                free(t);
1084
1101
 
1085
 
                if (h < 0)
 
1102
                if (!r)
1086
1103
                        return -ENOMEM;
1087
1104
        }
1088
1105
 
1090
1107
        return 0;
1091
1108
}
1092
1109
 
 
1110
int is_kernel_thread(pid_t pid) {
 
1111
        char *p;
 
1112
        size_t count;
 
1113
        char c;
 
1114
        bool eof;
 
1115
        FILE *f;
 
1116
 
 
1117
        if (pid == 0)
 
1118
                return 0;
 
1119
 
 
1120
        if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
 
1121
                return -ENOMEM;
 
1122
 
 
1123
        f = fopen(p, "re");
 
1124
        free(p);
 
1125
 
 
1126
        if (!f)
 
1127
                return -errno;
 
1128
 
 
1129
        count = fread(&c, 1, 1, f);
 
1130
        eof = feof(f);
 
1131
        fclose(f);
 
1132
 
 
1133
        /* Kernel threads have an empty cmdline */
 
1134
 
 
1135
        if (count <= 0)
 
1136
                return eof ? 1 : -errno;
 
1137
 
 
1138
        return 0;
 
1139
}
 
1140
 
 
1141
int get_process_exe(pid_t pid, char **name) {
 
1142
        int r;
 
1143
 
 
1144
        assert(name);
 
1145
 
 
1146
        if (pid == 0)
 
1147
                r = readlink_malloc("/proc/self/exe", name);
 
1148
        else {
 
1149
                char *p;
 
1150
                if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
 
1151
                        return -ENOMEM;
 
1152
 
 
1153
                r = readlink_malloc(p, name);
 
1154
                free(p);
 
1155
        }
 
1156
 
 
1157
        return r;
 
1158
}
 
1159
 
 
1160
int get_process_uid(pid_t pid, uid_t *uid) {
 
1161
        char *p;
 
1162
        FILE *f;
 
1163
        int r;
 
1164
 
 
1165
        assert(uid);
 
1166
 
 
1167
        if (pid == 0)
 
1168
                return getuid();
 
1169
 
 
1170
        if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
 
1171
                return -ENOMEM;
 
1172
 
 
1173
        f = fopen(p, "re");
 
1174
        free(p);
 
1175
 
 
1176
        if (!f)
 
1177
                return -errno;
 
1178
 
 
1179
        while (!feof(f)) {
 
1180
                char line[LINE_MAX], *l;
 
1181
 
 
1182
                if (!fgets(line, sizeof(line), f)) {
 
1183
                        if (feof(f))
 
1184
                                break;
 
1185
 
 
1186
                        r = -errno;
 
1187
                        goto finish;
 
1188
                }
 
1189
 
 
1190
                l = strstrip(line);
 
1191
 
 
1192
                if (startswith(l, "Uid:")) {
 
1193
                        l += 4;
 
1194
                        l += strspn(l, WHITESPACE);
 
1195
 
 
1196
                        l[strcspn(l, WHITESPACE)] = 0;
 
1197
 
 
1198
                        r = parse_uid(l, uid);
 
1199
                        goto finish;
 
1200
                }
 
1201
        }
 
1202
 
 
1203
        r = -EIO;
 
1204
 
 
1205
finish:
 
1206
        fclose(f);
 
1207
 
 
1208
        return r;
 
1209
}
 
1210
 
1093
1211
char *strnappend(const char *s, const char *suffix, size_t b) {
1094
1212
        size_t a;
1095
1213
        char *r;
1715
1833
 
1716
1834
        /* Undoes C style string escaping */
1717
1835
 
1718
 
        if (!(r = new(char, length+1)))
 
1836
        r = new(char, length+1);
 
1837
        if (!r)
1719
1838
                return r;
1720
1839
 
1721
1840
        for (f = s, t = r; f < s + length; f++) {
1769
1888
                        /* hexadecimal encoding */
1770
1889
                        int a, b;
1771
1890
 
1772
 
                        if ((a = unhexchar(f[1])) < 0 ||
1773
 
                            (b = unhexchar(f[2])) < 0) {
 
1891
                        a = unhexchar(f[1]);
 
1892
                        b = unhexchar(f[2]);
 
1893
 
 
1894
                        if (a < 0 || b < 0) {
1774
1895
                                /* Invalid escape code, let's take it literal then */
1775
1896
                                *(t++) = '\\';
1776
1897
                                *(t++) = 'x';
1793
1914
                        /* octal encoding */
1794
1915
                        int a, b, c;
1795
1916
 
1796
 
                        if ((a = unoctchar(f[0])) < 0 ||
1797
 
                            (b = unoctchar(f[1])) < 0 ||
1798
 
                            (c = unoctchar(f[2])) < 0) {
 
1917
                        a = unoctchar(f[0]);
 
1918
                        b = unoctchar(f[1]);
 
1919
                        c = unoctchar(f[2]);
 
1920
 
 
1921
                        if (a < 0 || b < 0 || c < 0) {
1799
1922
                                /* Invalid escape code, let's take it literal then */
1800
1923
                                *(t++) = '\\';
1801
1924
                                *(t++) = f[0];
2084
2207
        return 0;
2085
2208
}
2086
2209
 
 
2210
static bool fd_in_set(int fd, const int fdset[], unsigned n_fdset) {
 
2211
        unsigned i;
 
2212
 
 
2213
        assert(n_fdset == 0 || fdset);
 
2214
 
 
2215
        for (i = 0; i < n_fdset; i++)
 
2216
                if (fdset[i] == fd)
 
2217
                        return true;
 
2218
 
 
2219
        return false;
 
2220
}
 
2221
 
2087
2222
int close_all_fds(const int except[], unsigned n_except) {
2088
2223
        DIR *d;
2089
2224
        struct dirent *de;
2090
2225
        int r = 0;
2091
2226
 
2092
 
        if (!(d = opendir("/proc/self/fd")))
2093
 
                return -errno;
 
2227
        assert(n_except == 0 || except);
 
2228
 
 
2229
        d = opendir("/proc/self/fd");
 
2230
        if (!d) {
 
2231
                int fd;
 
2232
                struct rlimit rl;
 
2233
 
 
2234
                /* When /proc isn't available (for example in chroots)
 
2235
                 * the fallback is brute forcing through the fd
 
2236
                 * table */
 
2237
 
 
2238
                assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
 
2239
                for (fd = 3; fd < (int) rl.rlim_max; fd ++) {
 
2240
 
 
2241
                        if (fd_in_set(fd, except, n_except))
 
2242
                                continue;
 
2243
 
 
2244
                        if (close_nointr(fd) < 0)
 
2245
                                if (errno != EBADF && r == 0)
 
2246
                                        r = -errno;
 
2247
                }
 
2248
 
 
2249
                return r;
 
2250
        }
2094
2251
 
2095
2252
        while ((de = readdir(d))) {
2096
2253
                int fd = -1;
2108
2265
                if (fd == dirfd(d))
2109
2266
                        continue;
2110
2267
 
2111
 
                if (except) {
2112
 
                        bool found;
2113
 
                        unsigned i;
2114
 
 
2115
 
                        found = false;
2116
 
                        for (i = 0; i < n_except; i++)
2117
 
                                if (except[i] == fd) {
2118
 
                                        found = true;
2119
 
                                        break;
2120
 
                                }
2121
 
 
2122
 
                        if (found)
2123
 
                                continue;
2124
 
                }
 
2268
                if (fd_in_set(fd, except, n_except))
 
2269
                        continue;
2125
2270
 
2126
2271
                if (close_nointr(fd) < 0) {
2127
2272
                        /* Valgrind has its own FD and doesn't want to have it closed */
2323
2468
        return r;
2324
2469
}
2325
2470
 
2326
 
int read_one_char(FILE *f, char *ret, bool *need_nl) {
 
2471
int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) {
2327
2472
        struct termios old_termios, new_termios;
2328
2473
        char c;
2329
2474
        char line[LINE_MAX];
2341
2486
                if (tcsetattr(fileno(f), TCSADRAIN, &new_termios) >= 0) {
2342
2487
                        size_t k;
2343
2488
 
 
2489
                        if (t != (usec_t) -1) {
 
2490
                                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) {
 
2491
                                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);
 
2492
                                        return -ETIMEDOUT;
 
2493
                                }
 
2494
                        }
 
2495
 
2344
2496
                        k = fread(&c, 1, 1, f);
2345
2497
 
2346
2498
                        tcsetattr(fileno(f), TCSADRAIN, &old_termios);
2356
2508
                }
2357
2509
        }
2358
2510
 
2359
 
        if (!(fgets(line, sizeof(line), f)))
 
2511
        if (t != (usec_t) -1)
 
2512
                if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0)
 
2513
                        return -ETIMEDOUT;
 
2514
 
 
2515
        if (!fgets(line, sizeof(line), f))
2360
2516
                return -EIO;
2361
2517
 
2362
2518
        truncate_nl(line);
2387
2543
                bool need_nl = true;
2388
2544
 
2389
2545
                if (on_tty)
2390
 
                        fputs("\x1B[1m", stdout);
 
2546
                        fputs(ANSI_HIGHLIGHT_ON, stdout);
2391
2547
 
2392
2548
                va_start(ap, text);
2393
2549
                vprintf(text, ap);
2394
2550
                va_end(ap);
2395
2551
 
2396
2552
                if (on_tty)
2397
 
                        fputs("\x1B[0m", stdout);
 
2553
                        fputs(ANSI_HIGHLIGHT_OFF, stdout);
2398
2554
 
2399
2555
                fflush(stdout);
2400
2556
 
2401
 
                if ((r = read_one_char(stdin, &c, &need_nl)) < 0) {
 
2557
                r = read_one_char(stdin, &c, (usec_t) -1, &need_nl);
 
2558
                if (r < 0) {
2402
2559
 
2403
2560
                        if (r == -EBADMSG) {
2404
2561
                                puts("Bad input, please try again.");
2421
2578
        }
2422
2579
}
2423
2580
 
2424
 
int reset_terminal_fd(int fd) {
 
2581
int reset_terminal_fd(int fd, bool switch_to_text) {
2425
2582
        struct termios termios;
2426
2583
        int r = 0;
2427
 
        long arg;
2428
2584
 
2429
2585
        /* Set terminal to some sane defaults */
2430
2586
 
2437
2593
        /* Disable exclusive mode, just in case */
2438
2594
        ioctl(fd, TIOCNXCL);
2439
2595
 
 
2596
        /* Switch to text mode */
 
2597
        if (switch_to_text)
 
2598
                ioctl(fd, KDSETMODE, KD_TEXT);
 
2599
 
2440
2600
        /* Enable console unicode mode */
2441
 
        arg = K_UNICODE;
2442
 
        ioctl(fd, KDSKBMODE, &arg);
 
2601
        ioctl(fd, KDSKBMODE, K_UNICODE);
2443
2602
 
2444
2603
        if (tcgetattr(fd, &termios) < 0) {
2445
2604
                r = -errno;
2490
2649
        if (fd < 0)
2491
2650
                return fd;
2492
2651
 
2493
 
        r = reset_terminal_fd(fd);
 
2652
        r = reset_terminal_fd(fd, true);
2494
2653
        close_nointr_nofail(fd);
2495
2654
 
2496
2655
        return r;
2645
2804
                        ssize_t l;
2646
2805
                        struct inotify_event *e;
2647
2806
 
2648
 
                        if ((l = read(notify, &inotify_buffer, sizeof(inotify_buffer))) < 0) {
 
2807
                        if ((l = read(notify, inotify_buffer, sizeof(inotify_buffer))) < 0) {
2649
2808
 
2650
2809
                                if (errno == EINTR)
2651
2810
                                        continue;
2684
2843
        if (notify >= 0)
2685
2844
                close_nointr_nofail(notify);
2686
2845
 
2687
 
        if ((r = reset_terminal_fd(fd)) < 0)
 
2846
        r = reset_terminal_fd(fd, true);
 
2847
        if (r < 0)
2688
2848
                log_warning("Failed to reset terminal: %s", strerror(-r));
2689
2849
 
2690
2850
        return fd;
2856
3016
        while (nbytes > 0) {
2857
3017
                ssize_t k;
2858
3018
 
2859
 
                if ((k = write(fd, p, nbytes)) <= 0) {
 
3019
                k = write(fd, p, nbytes);
 
3020
                if (k <= 0) {
2860
3021
 
2861
3022
                        if (k < 0 && errno == EINTR)
2862
3023
                                continue;
2995
3156
                { "M", 1024ULL*1024ULL },
2996
3157
                { "G", 1024ULL*1024ULL*1024ULL },
2997
3158
                { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
 
3159
                { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
 
3160
                { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
2998
3161
                { "", 1 },
2999
3162
        };
3000
3163
 
3134
3297
void rename_process(const char name[8]) {
3135
3298
        assert(name);
3136
3299
 
 
3300
        /* This is a like a poor man's setproctitle(). It changes the
 
3301
         * comm field, argv[0], and also the glibc's internally used
 
3302
         * name of the process. For the first one a limit of 16 chars
 
3303
         * applies, to the second one usually one of 10 (i.e. length
 
3304
         * of "/sbin/init"), to the third one one of 7 (i.e. length of
 
3305
         * "systemd"). If you pass a longer string it will be
 
3306
         * truncated */
 
3307
 
3137
3308
        prctl(PR_SET_NAME, name);
3138
3309
 
3139
 
        /* This is a like a poor man's setproctitle(). The string
3140
 
         * passed should fit in 7 chars (i.e. the length of
3141
 
         * "systemd") */
3142
 
 
3143
3310
        if (program_invocation_name)
3144
3311
                strncpy(program_invocation_name, name, strlen(program_invocation_name));
3145
3312
 
3266
3433
                return -errno;
3267
3434
 
3268
3435
        if (!fgets(line, sizeof(line), f)) {
3269
 
                k = -errno;
 
3436
                k = feof(f) ? -EIO : -errno;
3270
3437
                fclose(f);
3271
3438
                return k;
3272
3439
        }
3399
3566
                        }
3400
3567
 
3401
3568
                        if (honour_sticky)
3402
 
                                keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
 
3569
                                keep_around =
 
3570
                                        (st.st_uid == 0 || st.st_uid == getuid()) &&
 
3571
                                        (st.st_mode & S_ISVTX);
3403
3572
 
3404
3573
                        is_dir = S_ISDIR(st.st_mode);
3405
3574
 
3413
3582
                                        continue;
3414
3583
                                }
3415
3584
 
3416
 
                                keep_around = st.st_uid == 0 && (st.st_mode & S_ISVTX);
 
3585
                                keep_around =
 
3586
                                        (st.st_uid == 0 || st.st_uid == getuid()) &&
 
3587
                                        (st.st_mode & S_ISVTX);
3417
3588
                        }
3418
3589
 
3419
3590
                        is_dir = de->d_type == DT_DIR;
3422
3593
                if (is_dir) {
3423
3594
                        int subdir_fd;
3424
3595
 
3425
 
                        if ((subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC)) < 0) {
 
3596
                        subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
 
3597
                        if (subdir_fd < 0) {
3426
3598
                                if (ret == 0 && errno != ENOENT)
3427
3599
                                        ret = -errno;
3428
3600
                                continue;
3475
3647
 
3476
3648
        if (delete_root) {
3477
3649
 
3478
 
                if (honour_sticky && file_is_sticky(path) > 0)
 
3650
                if (honour_sticky && file_is_priv_sticky(path) > 0)
3479
3651
                        return r;
3480
3652
 
3481
3653
                if (rmdir(path) < 0 && errno != ENOENT) {
3494
3666
         * first change the access mode and only then hand out
3495
3667
         * ownership to avoid a window where access is too open. */
3496
3668
 
3497
 
        if (chmod(path, mode) < 0)
 
3669
        if (mode != (mode_t) -1)
 
3670
                if (chmod(path, mode) < 0)
 
3671
                        return -errno;
 
3672
 
 
3673
        if (uid != (uid_t) -1 || gid != (gid_t) -1)
 
3674
                if (chown(path, uid, gid) < 0)
 
3675
                        return -errno;
 
3676
 
 
3677
        return 0;
 
3678
}
 
3679
 
 
3680
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
 
3681
        assert(fd >= 0);
 
3682
 
 
3683
        /* Under the assumption that we are running privileged we
 
3684
         * first change the access mode and only then hand out
 
3685
         * ownership to avoid a window where access is too open. */
 
3686
 
 
3687
        if (fchmod(fd, mode) < 0)
3498
3688
                return -errno;
3499
3689
 
3500
 
        if (chown(path, uid, gid) < 0)
 
3690
        if (fchown(fd, uid, gid) < 0)
3501
3691
                return -errno;
3502
3692
 
3503
3693
        return 0;
3531
3721
        }
3532
3722
}
3533
3723
 
3534
 
void status_vprintf(const char *format, va_list ap) {
3535
 
        char *s = NULL;
3536
 
        int fd = -1;
 
3724
void status_vprintf(const char *status, bool ellipse, const char *format, va_list ap) {
 
3725
        char *s = NULL, *spaces = NULL, *e;
 
3726
        int fd = -1, c;
 
3727
        size_t emax, sl, left;
 
3728
        struct iovec iovec[5];
 
3729
        int n = 0;
3537
3730
 
3538
3731
        assert(format);
3539
3732
 
3543
3736
        if (vasprintf(&s, format, ap) < 0)
3544
3737
                goto finish;
3545
3738
 
3546
 
        if ((fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0)
 
3739
        fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
 
3740
        if (fd < 0)
3547
3741
                goto finish;
3548
3742
 
3549
 
        write(fd, s, strlen(s));
 
3743
        if (ellipse) {
 
3744
                c = fd_columns(fd);
 
3745
                if (c <= 0)
 
3746
                        c = 80;
 
3747
 
 
3748
                if (status) {
 
3749
                        sl = 2 + 6 + 1; /* " [" status "]" */
 
3750
                        emax = (size_t) c > sl ? c - sl - 1 : 0;
 
3751
                } else
 
3752
                        emax = c - 1;
 
3753
 
 
3754
                e = ellipsize(s, emax, 75);
 
3755
                if (e) {
 
3756
                        free(s);
 
3757
                        s = e;
 
3758
                }
 
3759
        }
 
3760
 
 
3761
        zero(iovec);
 
3762
        IOVEC_SET_STRING(iovec[n++], s);
 
3763
 
 
3764
        if (ellipse) {
 
3765
                sl = strlen(s);
 
3766
                left = emax > sl ? emax - sl : 0;
 
3767
                if (left > 0) {
 
3768
                        spaces = malloc(left);
 
3769
                        if (spaces) {
 
3770
                                memset(spaces, ' ', left);
 
3771
                                iovec[n].iov_base = spaces;
 
3772
                                iovec[n].iov_len = left;
 
3773
                                n++;
 
3774
                        }
 
3775
                }
 
3776
        }
 
3777
 
 
3778
        if (status) {
 
3779
                IOVEC_SET_STRING(iovec[n++], " [");
 
3780
                IOVEC_SET_STRING(iovec[n++], status);
 
3781
                IOVEC_SET_STRING(iovec[n++], "]\n");
 
3782
        } else
 
3783
                IOVEC_SET_STRING(iovec[n++], "\n");
 
3784
 
 
3785
        writev(fd, iovec, n);
3550
3786
 
3551
3787
finish:
3552
3788
        free(s);
 
3789
        free(spaces);
3553
3790
 
3554
3791
        if (fd >= 0)
3555
3792
                close_nointr_nofail(fd);
3556
3793
}
3557
3794
 
3558
 
void status_printf(const char *format, ...) {
 
3795
void status_printf(const char *status, bool ellipse, const char *format, ...) {
3559
3796
        va_list ap;
3560
3797
 
3561
3798
        assert(format);
3562
3799
 
3563
3800
        va_start(ap, format);
3564
 
        status_vprintf(format, ap);
 
3801
        status_vprintf(status, ellipse, format, ap);
3565
3802
        va_end(ap);
3566
3803
}
3567
3804
 
3579
3816
                        log_warning("Failed to read /etc/os-release: %s", strerror(-r));
3580
3817
        }
3581
3818
 
3582
 
#if defined(TARGET_FEDORA)
3583
 
        if (!pretty_name) {
3584
 
                if ((r = read_one_line_file("/etc/system-release", &pretty_name)) < 0) {
3585
 
 
3586
 
                        if (r != -ENOENT)
3587
 
                                log_warning("Failed to read /etc/system-release: %s", strerror(-r));
3588
 
                }
3589
 
        }
3590
 
 
3591
 
        if (!ansi_color && pretty_name) {
3592
 
 
3593
 
                /* This tries to mimic the color magic the old Red Hat sysinit
3594
 
                 * script did. */
3595
 
 
3596
 
                if (startswith(pretty_name, "Red Hat"))
3597
 
                        const_color = "0;31"; /* Red for RHEL */
3598
 
                else if (startswith(pretty_name, "Fedora"))
3599
 
                        const_color = "0;34"; /* Blue for Fedora */
3600
 
        }
3601
 
 
3602
 
#elif defined(TARGET_SUSE)
3603
 
 
3604
 
        if (!pretty_name) {
3605
 
                if ((r = read_one_line_file("/etc/SuSE-release", &pretty_name)) < 0) {
3606
 
 
3607
 
                        if (r != -ENOENT)
3608
 
                                log_warning("Failed to read /etc/SuSE-release: %s", strerror(-r));
3609
 
                }
3610
 
        }
3611
 
 
3612
 
        if (!ansi_color)
3613
 
                const_color = "0;32"; /* Green for openSUSE */
3614
 
 
3615
 
#elif defined(TARGET_GENTOO)
3616
 
 
3617
 
        if (!pretty_name) {
3618
 
                if ((r = read_one_line_file("/etc/gentoo-release", &pretty_name)) < 0) {
3619
 
 
3620
 
                        if (r != -ENOENT)
3621
 
                                log_warning("Failed to read /etc/gentoo-release: %s", strerror(-r));
3622
 
                }
3623
 
        }
3624
 
 
3625
 
        if (!ansi_color)
3626
 
                const_color = "1;34"; /* Light Blue for Gentoo */
3627
 
 
3628
 
#elif defined(TARGET_ALTLINUX)
3629
 
 
3630
 
        if (!pretty_name) {
3631
 
                if ((r = read_one_line_file("/etc/altlinux-release", &pretty_name)) < 0) {
3632
 
 
3633
 
                        if (r != -ENOENT)
3634
 
                                log_warning("Failed to read /etc/altlinux-release: %s", strerror(-r));
3635
 
                }
3636
 
        }
3637
 
 
3638
 
        if (!ansi_color)
3639
 
                const_color = "0;36"; /* Cyan for ALTLinux */
3640
 
 
3641
 
 
3642
 
#elif defined(TARGET_DEBIAN)
3643
 
 
3644
 
        if (!pretty_name) {
3645
 
                char *version;
3646
 
 
3647
 
                if ((r = read_one_line_file("/etc/debian_version", &version)) < 0) {
3648
 
 
3649
 
                        if (r != -ENOENT)
3650
 
                                log_warning("Failed to read /etc/debian_version: %s", strerror(-r));
3651
 
                } else {
3652
 
                        pretty_name = strappend("Debian ", version);
3653
 
                        free(version);
3654
 
 
3655
 
                        if (!pretty_name)
3656
 
                                log_warning("Failed to allocate Debian version string.");
3657
 
                }
3658
 
        }
3659
 
 
3660
 
        if (!ansi_color)
3661
 
                const_color = "1;31"; /* Light Red for Debian */
3662
 
 
3663
 
#elif defined(TARGET_UBUNTU)
3664
 
 
3665
 
        if ((r = parse_env_file("/etc/lsb-release", NEWLINE,
3666
 
                                "DISTRIB_DESCRIPTION", &pretty_name,
3667
 
                                NULL)) < 0) {
3668
 
 
3669
 
                if (r != -ENOENT)
3670
 
                        log_warning("Failed to read /etc/lsb-release: %s", strerror(-r));
3671
 
        }
3672
 
 
3673
 
        if (!ansi_color)
3674
 
                const_color = "0;33"; /* Orange/Brown for Ubuntu */
3675
 
 
3676
 
#elif defined(TARGET_MANDRIVA)
3677
 
 
3678
 
        if (!pretty_name) {
3679
 
                char *s, *p;
3680
 
 
3681
 
                if ((r = read_one_line_file("/etc/mandriva-release", &s) < 0)) {
3682
 
                        if (r != -ENOENT)
3683
 
                                log_warning("Failed to read /etc/mandriva-release: %s", strerror(-r));
3684
 
                } else {
3685
 
                        p = strstr(s, " release ");
3686
 
                        if (p) {
3687
 
                                *p = '\0';
3688
 
                                p += 9;
3689
 
                                p[strcspn(p, " ")] = '\0';
3690
 
 
3691
 
                                /* This corresponds to standard rc.sysinit */
3692
 
                                if (asprintf(&pretty_name, "%s\x1B[0;39m %s", s, p) > 0)
3693
 
                                        const_color = "1;36";
3694
 
                                else
3695
 
                                        log_warning("Failed to allocate Mandriva version string.");
3696
 
                        } else
3697
 
                                log_warning("Failed to parse /etc/mandriva-release");
3698
 
                        free(s);
3699
 
                }
3700
 
        }
3701
 
#elif defined(TARGET_MEEGO)
3702
 
 
3703
 
        if (!pretty_name) {
3704
 
                if ((r = read_one_line_file("/etc/meego-release", &pretty_name)) < 0) {
3705
 
 
3706
 
                        if (r != -ENOENT)
3707
 
                                log_warning("Failed to read /etc/meego-release: %s", strerror(-r));
3708
 
                }
3709
 
        }
3710
 
 
3711
 
       if (!ansi_color)
3712
 
               const_color = "1;35"; /* Bright Magenta for MeeGo */
3713
 
#endif
3714
 
 
3715
3819
        if (!pretty_name && !const_pretty)
3716
3820
                const_pretty = "Linux";
3717
3821
 
3718
3822
        if (!ansi_color && !const_color)
3719
3823
                const_color = "1";
3720
3824
 
3721
 
        status_printf("\nWelcome to \x1B[%sm%s\x1B[0m!\n\n",
 
3825
        status_printf(NULL,
 
3826
                      false,
 
3827
                      "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
3722
3828
                      const_color ? const_color : ansi_color,
3723
3829
                      const_pretty ? const_pretty : pretty_name);
3724
3830
 
3860
3966
        return r;
3861
3967
}
3862
3968
 
3863
 
int columns(void) {
 
3969
int fd_columns(int fd) {
 
3970
        struct winsize ws;
 
3971
        zero(ws);
 
3972
 
 
3973
        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
 
3974
                return -errno;
 
3975
 
 
3976
        if (ws.ws_col <= 0)
 
3977
                return -EIO;
 
3978
 
 
3979
        return ws.ws_col;
 
3980
}
 
3981
 
 
3982
unsigned columns(void) {
3864
3983
        static __thread int parsed_columns = 0;
3865
3984
        const char *e;
3866
3985
 
3867
3986
        if (_likely_(parsed_columns > 0))
3868
3987
                return parsed_columns;
3869
3988
 
3870
 
        if ((e = getenv("COLUMNS")))
 
3989
        e = getenv("COLUMNS");
 
3990
        if (e)
3871
3991
                parsed_columns = atoi(e);
3872
3992
 
3873
 
        if (parsed_columns <= 0) {
3874
 
                struct winsize ws;
3875
 
                zero(ws);
3876
 
 
3877
 
                if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
3878
 
                        parsed_columns = ws.ws_col;
3879
 
        }
 
3993
        if (parsed_columns <= 0)
 
3994
                parsed_columns = fd_columns(STDOUT_FILENO);
3880
3995
 
3881
3996
        if (parsed_columns <= 0)
3882
3997
                parsed_columns = 80;
3884
3999
        return parsed_columns;
3885
4000
}
3886
4001
 
 
4002
int fd_lines(int fd) {
 
4003
        struct winsize ws;
 
4004
        zero(ws);
 
4005
 
 
4006
        if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
 
4007
                return -errno;
 
4008
 
 
4009
        if (ws.ws_row <= 0)
 
4010
                return -EIO;
 
4011
 
 
4012
        return ws.ws_row;
 
4013
}
 
4014
 
 
4015
unsigned lines(void) {
 
4016
        static __thread int parsed_lines = 0;
 
4017
        const char *e;
 
4018
 
 
4019
        if (_likely_(parsed_lines > 0))
 
4020
                return parsed_lines;
 
4021
 
 
4022
        e = getenv("LINES");
 
4023
        if (e)
 
4024
                parsed_lines = atoi(e);
 
4025
 
 
4026
        if (parsed_lines <= 0)
 
4027
                parsed_lines = fd_lines(STDOUT_FILENO);
 
4028
 
 
4029
        if (parsed_lines <= 0)
 
4030
                parsed_lines = 25;
 
4031
 
 
4032
        return parsed_lines;
 
4033
}
 
4034
 
3887
4035
int running_in_chroot(void) {
3888
4036
        struct stat a, b;
3889
4037
 
3903
4051
                a.st_ino != b.st_ino;
3904
4052
}
3905
4053
 
3906
 
char *ellipsize(const char *s, unsigned length, unsigned percent) {
3907
 
        size_t l, x;
 
4054
char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) {
 
4055
        size_t x;
3908
4056
        char *r;
3909
4057
 
3910
4058
        assert(s);
3911
4059
        assert(percent <= 100);
3912
 
        assert(length >= 3);
3913
 
 
3914
 
        l = strlen(s);
3915
 
 
3916
 
        if (l <= 3 || l <= length)
3917
 
                return strdup(s);
3918
 
 
3919
 
        if (!(r = new0(char, length+1)))
 
4060
        assert(new_length >= 3);
 
4061
 
 
4062
        if (old_length <= 3 || old_length <= new_length)
 
4063
                return strndup(s, old_length);
 
4064
 
 
4065
        r = new0(char, new_length+1);
 
4066
        if (!r)
3920
4067
                return r;
3921
4068
 
3922
 
        x = (length * percent) / 100;
 
4069
        x = (new_length * percent) / 100;
3923
4070
 
3924
 
        if (x > length - 3)
3925
 
                x = length - 3;
 
4071
        if (x > new_length - 3)
 
4072
                x = new_length - 3;
3926
4073
 
3927
4074
        memcpy(r, s, x);
3928
4075
        r[x] = '.';
3929
4076
        r[x+1] = '.';
3930
4077
        r[x+2] = '.';
3931
4078
        memcpy(r + x + 3,
3932
 
               s + l - (length - x - 3),
3933
 
               length - x - 3);
 
4079
               s + old_length - (new_length - x - 3),
 
4080
               new_length - x - 3);
3934
4081
 
3935
4082
        return r;
3936
4083
}
3937
4084
 
 
4085
char *ellipsize(const char *s, size_t length, unsigned percent) {
 
4086
        return ellipsize_mem(s, strlen(s), length, percent);
 
4087
}
 
4088
 
3938
4089
int touch(const char *path) {
3939
4090
        int fd;
3940
4091
 
3951
4102
        size_t l;
3952
4103
        assert(s);
3953
4104
 
3954
 
        if ((l = strlen(s)) < 2)
 
4105
        l = strlen(s);
 
4106
        if (l < 2)
3955
4107
                return strdup(s);
3956
4108
 
3957
4109
        if (strchr(quotes, s[0]) && s[l-1] == s[0])
4053
4205
 
4054
4206
}
4055
4207
 
4056
 
void freeze(void) {
 
4208
_noreturn_ void freeze(void) {
4057
4209
 
4058
4210
        /* Make sure nobody waits for us on a socket anymore */
4059
4211
        close_all_fds(NULL, 0);
4243
4395
        return i;
4244
4396
}
4245
4397
 
4246
 
const char *default_term_for_tty(const char *tty) {
 
4398
bool tty_is_vc_resolve(const char *tty) {
4247
4399
        char *active = NULL;
4248
 
        const char *term;
 
4400
        bool b;
4249
4401
 
4250
4402
        assert(tty);
4251
4403
 
4252
4404
        if (startswith(tty, "/dev/"))
4253
4405
                tty += 5;
4254
4406
 
4255
 
        /* Resolve where /dev/console is pointing when determining
4256
 
         * TERM */
 
4407
        /* Resolve where /dev/console is pointing to */
4257
4408
        if (streq(tty, "console"))
4258
4409
                if (read_one_line_file("/sys/class/tty/console/active", &active) >= 0) {
4259
4410
                        /* If multiple log outputs are configured the
4260
4411
                         * last one is what /dev/console points to */
4261
 
                        if ((tty = strrchr(active, ' ')))
 
4412
                        tty = strrchr(active, ' ');
 
4413
                        if (tty)
4262
4414
                                tty++;
4263
4415
                        else
4264
4416
                                tty = active;
4265
4417
                }
4266
4418
 
4267
 
        term = tty_is_vc(tty) ? "TERM=linux" : "TERM=vt100";
 
4419
        b = tty_is_vc(tty);
4268
4420
        free(active);
4269
4421
 
4270
 
        return term;
4271
 
}
4272
 
 
4273
 
bool dirent_is_file(struct dirent *de) {
 
4422
        return b;
 
4423
}
 
4424
 
 
4425
const char *default_term_for_tty(const char *tty) {
 
4426
        assert(tty);
 
4427
 
 
4428
        return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt100";
 
4429
}
 
4430
 
 
4431
bool dirent_is_file(const struct dirent *de) {
4274
4432
        assert(de);
4275
4433
 
4276
4434
        if (ignore_file(de->d_name))
4284
4442
        return true;
4285
4443
}
4286
4444
 
 
4445
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
 
4446
        assert(de);
 
4447
 
 
4448
        if (!dirent_is_file(de))
 
4449
                return false;
 
4450
 
 
4451
        return endswith(de->d_name, suffix);
 
4452
}
 
4453
 
4287
4454
void execute_directory(const char *directory, DIR *d, char *argv[]) {
4288
4455
        DIR *_d = NULL;
4289
4456
        struct dirent *de;
4358
4525
        }
4359
4526
 
4360
4527
        while (!hashmap_isempty(pids)) {
 
4528
                pid_t pid = PTR_TO_UINT(hashmap_first_key(pids));
4361
4529
                siginfo_t si;
4362
4530
                char *path;
4363
4531
 
4364
4532
                zero(si);
4365
 
                if (waitid(P_ALL, 0, &si, WEXITED) < 0) {
 
4533
                if (waitid(P_PID, pid, &si, WEXITED) < 0) {
4366
4534
 
4367
4535
                        if (errno == EINTR)
4368
4536
                                continue;
4456
4624
        *p += k;
4457
4625
}
4458
4626
 
 
4627
void skip_syslog_pid(char **buf) {
 
4628
        char *p;
 
4629
 
 
4630
        assert(buf);
 
4631
        assert(*buf);
 
4632
 
 
4633
        p = *buf;
 
4634
 
 
4635
        if (*p != '[')
 
4636
                return;
 
4637
 
 
4638
        p++;
 
4639
        p += strspn(p, "0123456789");
 
4640
 
 
4641
        if (*p != ']')
 
4642
                return;
 
4643
 
 
4644
        p++;
 
4645
 
 
4646
        *buf = p;
 
4647
}
 
4648
 
 
4649
void skip_syslog_date(char **buf) {
 
4650
        enum {
 
4651
                LETTER,
 
4652
                SPACE,
 
4653
                NUMBER,
 
4654
                SPACE_OR_NUMBER,
 
4655
                COLON
 
4656
        } sequence[] = {
 
4657
                LETTER, LETTER, LETTER,
 
4658
                SPACE,
 
4659
                SPACE_OR_NUMBER, NUMBER,
 
4660
                SPACE,
 
4661
                SPACE_OR_NUMBER, NUMBER,
 
4662
                COLON,
 
4663
                SPACE_OR_NUMBER, NUMBER,
 
4664
                COLON,
 
4665
                SPACE_OR_NUMBER, NUMBER,
 
4666
                SPACE
 
4667
        };
 
4668
 
 
4669
        char *p;
 
4670
        unsigned i;
 
4671
 
 
4672
        assert(buf);
 
4673
        assert(*buf);
 
4674
 
 
4675
        p = *buf;
 
4676
 
 
4677
        for (i = 0; i < ELEMENTSOF(sequence); i++, p++) {
 
4678
 
 
4679
                if (!*p)
 
4680
                        return;
 
4681
 
 
4682
                switch (sequence[i]) {
 
4683
 
 
4684
                case SPACE:
 
4685
                        if (*p != ' ')
 
4686
                                return;
 
4687
                        break;
 
4688
 
 
4689
                case SPACE_OR_NUMBER:
 
4690
                        if (*p == ' ')
 
4691
                                break;
 
4692
 
 
4693
                        /* fall through */
 
4694
 
 
4695
                case NUMBER:
 
4696
                        if (*p < '0' || *p > '9')
 
4697
                                return;
 
4698
 
 
4699
                        break;
 
4700
 
 
4701
                case LETTER:
 
4702
                        if (!(*p >= 'A' && *p <= 'Z') &&
 
4703
                            !(*p >= 'a' && *p <= 'z'))
 
4704
                                return;
 
4705
 
 
4706
                        break;
 
4707
 
 
4708
                case COLON:
 
4709
                        if (*p != ':')
 
4710
                                return;
 
4711
                        break;
 
4712
 
 
4713
                }
 
4714
        }
 
4715
 
 
4716
        *buf = p;
 
4717
}
 
4718
 
4459
4719
int have_effective_cap(int value) {
4460
4720
        cap_t cap;
4461
4721
        cap_flag_value_t fv;
4544
4804
        return pollfd.revents & POLLHUP;
4545
4805
}
4546
4806
 
 
4807
int fd_wait_for_event(int fd, int event, usec_t t) {
 
4808
        struct pollfd pollfd;
 
4809
        int r;
 
4810
 
 
4811
        zero(pollfd);
 
4812
        pollfd.fd = fd;
 
4813
        pollfd.events = event;
 
4814
 
 
4815
        r = poll(&pollfd, 1, t == (usec_t) -1 ? -1 : (int) (t / USEC_PER_MSEC));
 
4816
        if (r < 0)
 
4817
                return -errno;
 
4818
 
 
4819
        if (r == 0)
 
4820
                return 0;
 
4821
 
 
4822
        return pollfd.revents;
 
4823
}
 
4824
 
4547
4825
int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
4548
4826
        FILE *f;
4549
4827
        char *t;
4675
4953
        return 0;
4676
4954
}
4677
4955
 
4678
 
 
4679
 
static int file_is_conf(const struct dirent *d, const char *suffix) {
4680
 
        assert(d);
4681
 
 
4682
 
        if (ignore_file(d->d_name))
4683
 
                return 0;
4684
 
 
4685
 
        if (d->d_type != DT_REG &&
4686
 
            d->d_type != DT_LNK &&
4687
 
            d->d_type != DT_UNKNOWN)
4688
 
                return 0;
4689
 
 
4690
 
        return endswith(d->d_name, suffix);
4691
 
}
4692
 
 
4693
4956
static int files_add(Hashmap *h, const char *path, const char *suffix) {
4694
4957
        DIR *dir;
4695
4958
        struct dirent buffer, *de;
4715
4978
                if (!de)
4716
4979
                        break;
4717
4980
 
4718
 
                if (!file_is_conf(de, suffix))
 
4981
                if (!dirent_is_file_with_suffix(de, suffix))
4719
4982
                        continue;
4720
4983
 
4721
4984
                if (asprintf(&p, "%s/%s", path, de->d_name) < 0) {
4877
5140
        return 0;
4878
5141
}
4879
5142
 
 
5143
int rtc_open(int flags) {
 
5144
        int fd;
 
5145
        DIR *d;
 
5146
 
 
5147
        /* First, we try to make use of the /dev/rtc symlink. If that
 
5148
         * doesn't exist, we open the first RTC which has hctosys=1
 
5149
         * set. If we don't find any we just take the first RTC that
 
5150
         * exists at all. */
 
5151
 
 
5152
        fd = open("/dev/rtc", flags);
 
5153
        if (fd >= 0)
 
5154
                return fd;
 
5155
 
 
5156
        d = opendir("/sys/class/rtc");
 
5157
        if (!d)
 
5158
                goto fallback;
 
5159
 
 
5160
        for (;;) {
 
5161
                char *p, *v;
 
5162
                struct dirent buf, *de;
 
5163
                int r;
 
5164
 
 
5165
                r = readdir_r(d, &buf, &de);
 
5166
                if (r != 0)
 
5167
                        goto fallback;
 
5168
 
 
5169
                if (!de)
 
5170
                        goto fallback;
 
5171
 
 
5172
                if (ignore_file(de->d_name))
 
5173
                        continue;
 
5174
 
 
5175
                p = join("/sys/class/rtc/", de->d_name, "/hctosys", NULL);
 
5176
                if (!p) {
 
5177
                        closedir(d);
 
5178
                        return -ENOMEM;
 
5179
                }
 
5180
 
 
5181
                r = read_one_line_file(p, &v);
 
5182
                free(p);
 
5183
 
 
5184
                if (r < 0)
 
5185
                        continue;
 
5186
 
 
5187
                r = parse_boolean(v);
 
5188
                free(v);
 
5189
 
 
5190
                if (r <= 0)
 
5191
                        continue;
 
5192
 
 
5193
                p = strappend("/dev/", de->d_name);
 
5194
                fd = open(p, flags);
 
5195
                free(p);
 
5196
 
 
5197
                if (fd >= 0) {
 
5198
                        closedir(d);
 
5199
                        return fd;
 
5200
                }
 
5201
        }
 
5202
 
 
5203
fallback:
 
5204
        if (d)
 
5205
                closedir(d);
 
5206
 
 
5207
        fd = open("/dev/rtc0", flags);
 
5208
        if (fd < 0)
 
5209
                return -errno;
 
5210
 
 
5211
        return fd;
 
5212
}
 
5213
 
4880
5214
int hwclock_get_time(struct tm *tm) {
4881
5215
        int fd;
4882
5216
        int err = 0;
4883
5217
 
4884
5218
        assert(tm);
4885
5219
 
4886
 
        fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC);
 
5220
        fd = rtc_open(O_RDONLY|O_CLOEXEC);
4887
5221
        if (fd < 0)
4888
5222
                return -errno;
4889
5223
 
4907
5241
 
4908
5242
        assert(tm);
4909
5243
 
4910
 
        fd = open("/dev/rtc0", O_RDONLY|O_CLOEXEC);
 
5244
        fd = rtc_open(O_RDONLY|O_CLOEXEC);
4911
5245
        if (fd < 0)
4912
5246
                return -errno;
4913
5247
 
5066
5400
}
5067
5401
 
5068
5402
int audit_session_from_pid(pid_t pid, uint32_t *id) {
5069
 
        char *p, *s;
 
5403
        char *s;
5070
5404
        uint32_t u;
5071
5405
        int r;
5072
5406
 
5073
 
        assert(pid >= 1);
5074
5407
        assert(id);
5075
5408
 
5076
5409
        if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
5077
5410
                return -ENOENT;
5078
5411
 
5079
 
        if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
5080
 
                return -ENOMEM;
5081
 
 
5082
 
        r = read_one_line_file(p, &s);
5083
 
        free(p);
 
5412
        if (pid == 0)
 
5413
                r = read_one_line_file("/proc/self/sessionid", &s);
 
5414
        else {
 
5415
                char *p;
 
5416
 
 
5417
                if (asprintf(&p, "/proc/%lu/sessionid", (unsigned long) pid) < 0)
 
5418
                        return -ENOMEM;
 
5419
 
 
5420
                r = read_one_line_file(p, &s);
 
5421
                free(p);
 
5422
        }
 
5423
 
5084
5424
        if (r < 0)
5085
5425
                return r;
5086
5426
 
5097
5437
        return 0;
5098
5438
}
5099
5439
 
 
5440
int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
 
5441
        char *s;
 
5442
        uid_t u;
 
5443
        int r;
 
5444
 
 
5445
        assert(uid);
 
5446
 
 
5447
        /* Only use audit login uid if we are executed with sufficient
 
5448
         * capabilities so that pam_loginuid could do its job. If we
 
5449
         * are lacking the CAP_AUDIT_CONTROL capabality we most likely
 
5450
         * are being run in a container and /proc/self/loginuid is
 
5451
         * useless since it probably contains a uid of the host
 
5452
         * system. */
 
5453
 
 
5454
        if (have_effective_cap(CAP_AUDIT_CONTROL) <= 0)
 
5455
                return -ENOENT;
 
5456
 
 
5457
        if (pid == 0)
 
5458
                r = read_one_line_file("/proc/self/loginuid", &s);
 
5459
        else {
 
5460
                char *p;
 
5461
 
 
5462
                if (asprintf(&p, "/proc/%lu/loginuid", (unsigned long) pid) < 0)
 
5463
                        return -ENOMEM;
 
5464
 
 
5465
                r = read_one_line_file(p, &s);
 
5466
                free(p);
 
5467
        }
 
5468
 
 
5469
        if (r < 0)
 
5470
                return r;
 
5471
 
 
5472
        r = parse_uid(s, &u);
 
5473
        free(s);
 
5474
 
 
5475
        if (r < 0)
 
5476
                return r;
 
5477
 
 
5478
        if (u == (uid_t) -1)
 
5479
                return -ENOENT;
 
5480
 
 
5481
        *uid = (uid_t) u;
 
5482
        return 0;
 
5483
}
 
5484
 
5100
5485
bool display_is_local(const char *display) {
5101
5486
        assert(display);
5102
5487
 
5224
5609
        return 0;
5225
5610
}
5226
5611
 
 
5612
int in_group(const char *name) {
 
5613
        gid_t gid, *gids;
 
5614
        int ngroups_max, r, i;
 
5615
 
 
5616
        r = get_group_creds(&name, &gid);
 
5617
        if (r < 0)
 
5618
                return r;
 
5619
 
 
5620
        if (getgid() == gid)
 
5621
                return 1;
 
5622
 
 
5623
        if (getegid() == gid)
 
5624
                return 1;
 
5625
 
 
5626
        ngroups_max = sysconf(_SC_NGROUPS_MAX);
 
5627
        assert(ngroups_max > 0);
 
5628
 
 
5629
        gids = alloca(sizeof(gid_t) * ngroups_max);
 
5630
 
 
5631
        r = getgroups(ngroups_max, gids);
 
5632
        if (r < 0)
 
5633
                return -errno;
 
5634
 
 
5635
        for (i = 0; i < r; i++)
 
5636
                if (gids[i] == gid)
 
5637
                        return 1;
 
5638
 
 
5639
        return 0;
 
5640
}
 
5641
 
5227
5642
int glob_exists(const char *path) {
5228
5643
        glob_t g;
5229
5644
        int r, k;
5488
5903
        return -ENOENT;
5489
5904
}
5490
5905
 
5491
 
int file_is_sticky(const char *p) {
 
5906
int file_is_priv_sticky(const char *p) {
5492
5907
        struct stat st;
5493
5908
 
5494
5909
        assert(p);
5497
5912
                return -errno;
5498
5913
 
5499
5914
        return
5500
 
                st.st_uid == 0 &&
 
5915
                (st.st_uid == 0 || st.st_uid == getuid()) &&
5501
5916
                (st.st_mode & S_ISVTX);
5502
5917
}
5503
5918
 
5703
6118
        *b = c;
5704
6119
        return 0;
5705
6120
}
 
6121
 
 
6122
int prot_from_flags(int flags) {
 
6123
 
 
6124
        switch (flags & O_ACCMODE) {
 
6125
 
 
6126
        case O_RDONLY:
 
6127
                return PROT_READ;
 
6128
 
 
6129
        case O_WRONLY:
 
6130
                return PROT_WRITE;
 
6131
 
 
6132
        case O_RDWR:
 
6133
                return PROT_READ|PROT_WRITE;
 
6134
 
 
6135
        default:
 
6136
                return -EINVAL;
 
6137
        }
 
6138
}
 
6139
 
 
6140
unsigned long cap_last_cap(void) {
 
6141
        static __thread unsigned long saved;
 
6142
        static __thread bool valid = false;
 
6143
        unsigned long p;
 
6144
 
 
6145
        if (valid)
 
6146
                return saved;
 
6147
 
 
6148
        p = (unsigned long) CAP_LAST_CAP;
 
6149
 
 
6150
        if (prctl(PR_CAPBSET_READ, p) < 0) {
 
6151
 
 
6152
                /* Hmm, look downwards, until we find one that
 
6153
                 * works */
 
6154
                for (p--; p > 0; p --)
 
6155
                        if (prctl(PR_CAPBSET_READ, p) >= 0)
 
6156
                                break;
 
6157
 
 
6158
        } else {
 
6159
 
 
6160
                /* Hmm, look upwards, until we find one that doesn't
 
6161
                 * work */
 
6162
                for (;; p++)
 
6163
                        if (prctl(PR_CAPBSET_READ, p+1) < 0)
 
6164
                                break;
 
6165
        }
 
6166
 
 
6167
        saved = p;
 
6168
        valid = true;
 
6169
 
 
6170
        return p;
 
6171
}
 
6172
 
 
6173
char *format_bytes(char *buf, size_t l, off_t t) {
 
6174
        unsigned i;
 
6175
 
 
6176
        static const struct {
 
6177
                const char *suffix;
 
6178
                off_t factor;
 
6179
        } table[] = {
 
6180
                { "E", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
 
6181
                { "P", 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL },
 
6182
                { "T", 1024ULL*1024ULL*1024ULL*1024ULL },
 
6183
                { "G", 1024ULL*1024ULL*1024ULL },
 
6184
                { "M", 1024ULL*1024ULL },
 
6185
                { "K", 1024ULL },
 
6186
        };
 
6187
 
 
6188
        for (i = 0; i < ELEMENTSOF(table); i++) {
 
6189
 
 
6190
                if (t >= table[i].factor) {
 
6191
                        snprintf(buf, l,
 
6192
                                 "%llu.%llu%s",
 
6193
                                 (unsigned long long) (t / table[i].factor),
 
6194
                                 (unsigned long long) (((t*10ULL) / table[i].factor) % 10ULL),
 
6195
                                 table[i].suffix);
 
6196
 
 
6197
                        goto finish;
 
6198
                }
 
6199
        }
 
6200
 
 
6201
        snprintf(buf, l, "%lluB", (unsigned long long) t);
 
6202
 
 
6203
finish:
 
6204
        buf[l-1] = 0;
 
6205
        return buf;
 
6206
 
 
6207
}
 
6208
 
 
6209
void* memdup(const void *p, size_t l) {
 
6210
        void *r;
 
6211
 
 
6212
        assert(p);
 
6213
 
 
6214
        r = malloc(l);
 
6215
        if (!r)
 
6216
                return NULL;
 
6217
 
 
6218
        memcpy(r, p, l);
 
6219
        return r;
 
6220
}
 
6221
 
 
6222
int fd_inc_sndbuf(int fd, size_t n) {
 
6223
        int r, value;
 
6224
        socklen_t l = sizeof(value);
 
6225
 
 
6226
        r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
 
6227
        if (r >= 0 &&
 
6228
            l == sizeof(value) &&
 
6229
            (size_t) value >= n*2)
 
6230
                return 0;
 
6231
 
 
6232
        value = (int) n;
 
6233
        r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value));
 
6234
        if (r < 0)
 
6235
                return -errno;
 
6236
 
 
6237
        return 1;
 
6238
}
 
6239
 
 
6240
int fd_inc_rcvbuf(int fd, size_t n) {
 
6241
        int r, value;
 
6242
        socklen_t l = sizeof(value);
 
6243
 
 
6244
        r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
 
6245
        if (r >= 0 &&
 
6246
            l == sizeof(value) &&
 
6247
            (size_t) value >= n*2)
 
6248
                return 0;
 
6249
 
 
6250
        value = (int) n;
 
6251
        r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value));
 
6252
        if (r < 0)
 
6253
                return -errno;
 
6254
 
 
6255
        return 1;
 
6256
}