~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/journal/journal-send.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl, Michael Biebl, Michael Stapelberg, Daniel Schaal, Ondrej Balaz
  • Date: 2013-09-12 00:13:11 UTC
  • mfrom: (1.1.11) (9.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 53.
  • Revision ID: package-import@ubuntu.com-20130912001311-dz35it34wr2lbday
Tags: 204-3
[ Michael Biebl ]
* Upload to unstable.
* Use /bin/bash in debug-shell.service as Debian doesn't have /sbin/sushell.
* Only import net.ifaces cmdline property for network devices.
* Generate strict dependencies between the binary packages using a
  shlibs.local file and add an explicit versioned dependency on
  libsystemd-login0 to systemd to ensure packages are upgraded in sync.
  Closes: #719444
* Drop obsolete Replaces: libudev0 from udev package.
* Use correct paths for various binaries, like /sbin/quotaon, which are
  installed in / and not /usr in Debian.  Closes: #721347
* Don't install kernel-install(8) man page since we don't install the
  corresponding binary either.  Closes: #722180
* Cherry-pick upstream fixes to make switching runlevels and starting
  reboot via ctrl-alt-del more robust.
* Cherry-pick upstream fix to properly apply ACLs to Journal files.

[ Michael Stapelberg ]
* Make systemctl enable|disable call update-rc.d for SysV init scripts.
  Closes: #709780
* Don't mount /tmp as tmpfs by default and make it possible to enable this
  feature via "systemctl enable tmp.mount".

[ Daniel Schaal ]
* Add bug-script to systemd and udev.  Closes: #711245

[ Ondrej Balaz ]
* Recognize discard option in /etc/crypttab.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
  Copyright 2011 Lennart Poettering
7
7
 
8
8
  systemd is free software; you can redistribute it and/or modify it
9
 
  under the terms of the GNU General Public License as published by
10
 
  the Free Software Foundation; either version 2 of the License, or
 
9
  under the terms of the GNU Lesser General Public License as published by
 
10
  the Free Software Foundation; either version 2.1 of the License, or
11
11
  (at your option) any later version.
12
12
 
13
13
  systemd is distributed in the hope that it will be useful, but
14
14
  WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
 
  General Public License for more details.
 
16
  Lesser General Public License for more details.
17
17
 
18
 
  You should have received a copy of the GNU General Public License
 
18
  You should have received a copy of the GNU Lesser General Public License
19
19
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
20
20
***/
21
21
 
25
25
#include <stddef.h>
26
26
#include <unistd.h>
27
27
#include <fcntl.h>
 
28
#include <printf.h>
 
29
 
 
30
#define SD_JOURNAL_SUPPRESS_LOCATION
28
31
 
29
32
#include "sd-journal.h"
30
33
#include "util.h"
32
35
 
33
36
#define SNDBUF_SIZE (8*1024*1024)
34
37
 
 
38
#define ALLOCA_CODE_FUNC(f, func)                 \
 
39
        do {                                      \
 
40
                size_t _fl;                       \
 
41
                const char *_func = (func);       \
 
42
                char **_f = &(f);                 \
 
43
                _fl = strlen(_func) + 1;          \
 
44
                *_f = alloca(_fl + 10);           \
 
45
                memcpy(*_f, "CODE_FUNC=", 10);    \
 
46
                memcpy(*_f + 10, _func, _fl);     \
 
47
        } while(false)
 
48
 
35
49
/* We open a single fd, and we'll share it with the current process,
36
50
 * all its threads, and all its subprocesses. This means we need to
37
51
 * initialize it atomically, and need to operate on it atomically
71
85
}
72
86
 
73
87
_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
74
 
        char buffer[8 + LINE_MAX], p[11];
75
 
        struct iovec iov[2];
 
88
 
 
89
        /* FIXME: Instead of limiting things to LINE_MAX we could do a
 
90
           C99 variable-length array on the stack here in a loop. */
 
91
 
 
92
        char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
76
93
 
77
94
        if (priority < 0 || priority > 7)
78
95
                return -EINVAL;
94
111
        return sd_journal_sendv(iov, 2);
95
112
}
96
113
 
97
 
_public_ int sd_journal_send(const char *format, ...) {
 
114
_printf_attr_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
 
115
        PROTECT_ERRNO;
98
116
        int r, n = 0, i = 0, j;
99
 
        va_list ap;
100
117
        struct iovec *iov = NULL;
101
118
 
102
 
        va_start(ap, format);
 
119
        assert(_iov);
 
120
 
 
121
        if (extra > 0) {
 
122
                n = MAX(extra * 2, extra + 4);
 
123
                iov = malloc0(n * sizeof(struct iovec));
 
124
                if (!iov) {
 
125
                        r = -ENOMEM;
 
126
                        goto fail;
 
127
                }
 
128
 
 
129
                i = extra;
 
130
        }
 
131
 
103
132
        while (format) {
104
133
                struct iovec *c;
105
134
                char *buffer;
 
135
                va_list aq;
106
136
 
107
137
                if (i >= n) {
108
138
                        n = MAX(i*2, 4);
115
145
                        iov = c;
116
146
                }
117
147
 
118
 
                if (vasprintf(&buffer, format, ap) < 0) {
 
148
                va_copy(aq, ap);
 
149
                if (vasprintf(&buffer, format, aq) < 0) {
 
150
                        va_end(aq);
119
151
                        r = -ENOMEM;
120
152
                        goto fail;
121
153
                }
 
154
                va_end(aq);
 
155
 
 
156
                VA_FORMAT_ADVANCE(format, ap);
122
157
 
123
158
                IOVEC_SET_STRING(iov[i++], buffer);
124
159
 
125
160
                format = va_arg(ap, char *);
126
161
        }
127
 
        va_end(ap);
128
 
 
129
 
        r = sd_journal_sendv(iov, i);
 
162
 
 
163
        *_iov = iov;
 
164
 
 
165
        return i;
130
166
 
131
167
fail:
132
168
        for (j = 0; j < i; j++)
137
173
        return r;
138
174
}
139
175
 
 
176
_public_ int sd_journal_send(const char *format, ...) {
 
177
        int r, i, j;
 
178
        va_list ap;
 
179
        struct iovec *iov = NULL;
 
180
 
 
181
        va_start(ap, format);
 
182
        i = fill_iovec_sprintf(format, ap, 0, &iov);
 
183
        va_end(ap);
 
184
 
 
185
        if (_unlikely_(i < 0)) {
 
186
                r = i;
 
187
                goto finish;
 
188
        }
 
189
 
 
190
        r = sd_journal_sendv(iov, i);
 
191
 
 
192
finish:
 
193
        for (j = 0; j < i; j++)
 
194
                free(iov[j].iov_base);
 
195
 
 
196
        free(iov);
 
197
 
 
198
        return r;
 
199
}
 
200
 
140
201
_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
 
202
        PROTECT_ERRNO;
141
203
        int fd, buffer_fd;
142
204
        struct iovec *w;
143
205
        uint64_t *l;
154
216
         * be a tmpfs, and one that is available from early boot on
155
217
         * and where unprivileged users can create files. */
156
218
        char path[] = "/dev/shm/journal.XXXXXX";
157
 
 
158
 
        if (!iov || n <= 0)
159
 
                return -EINVAL;
160
 
 
161
 
        w = alloca(sizeof(struct iovec) * n * 5);
 
219
        bool have_syslog_identifier = false;
 
220
 
 
221
        if (_unlikely_(!iov))
 
222
                return -EINVAL;
 
223
 
 
224
        if (_unlikely_(n <= 0))
 
225
                return -EINVAL;
 
226
 
 
227
        w = alloca(sizeof(struct iovec) * n * 5 + 3);
162
228
        l = alloca(sizeof(uint64_t) * n);
163
229
 
164
230
        for (i = 0; i < n; i++) {
165
231
                char *c, *nl;
166
232
 
167
 
                if (!iov[i].iov_base ||
168
 
                    iov[i].iov_len <= 1)
 
233
                if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
169
234
                        return -EINVAL;
170
235
 
171
236
                c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
172
 
                if (!c || c == iov[i].iov_base)
 
237
                if (_unlikely_(!c || c == iov[i].iov_base))
173
238
                        return -EINVAL;
174
239
 
 
240
                have_syslog_identifier = have_syslog_identifier ||
 
241
                        (c == (char *) iov[i].iov_base + 17 &&
 
242
                         memcmp(iov[i].iov_base, "SYSLOG_IDENTIFIER", 17) == 0);
 
243
 
175
244
                nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
176
245
                if (nl) {
177
 
                        if (nl < c)
 
246
                        if (_unlikely_(nl < c))
178
247
                                return -EINVAL;
179
248
 
180
249
                        /* Already includes a newline? Bummer, then
205
274
                IOVEC_SET_STRING(w[j++], "\n");
206
275
        }
207
276
 
 
277
        if (!have_syslog_identifier &&
 
278
            string_is_safe(program_invocation_short_name)) {
 
279
 
 
280
                /* Implicitly add program_invocation_short_name, if it
 
281
                 * is not set explicitly. We only do this for
 
282
                 * program_invocation_short_name, and nothing else
 
283
                 * since everything else is much nicer to retrieve
 
284
                 * from the outside. */
 
285
 
 
286
                IOVEC_SET_STRING(w[j++], "SYSLOG_IDENTIFIER=");
 
287
                IOVEC_SET_STRING(w[j++], program_invocation_short_name);
 
288
                IOVEC_SET_STRING(w[j++], "\n");
 
289
        }
 
290
 
208
291
        fd = journal_fd();
209
 
        if (fd < 0)
 
292
        if (_unlikely_(fd < 0))
210
293
                return fd;
211
294
 
212
295
        zero(sa);
240
323
        }
241
324
 
242
325
        n = writev(buffer_fd, w, j);
243
 
        if (n < 0)  {
 
326
        if (n < 0) {
244
327
                close_nointr_nofail(buffer_fd);
245
328
                return -errno;
246
329
        }
269
352
        return 0;
270
353
}
271
354
 
 
355
static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
 
356
        PROTECT_ERRNO;
 
357
        size_t n, k;
 
358
 
 
359
        k = isempty(message) ? 0 : strlen(message) + 2;
 
360
        n = 8 + k + 256 + 1;
 
361
 
 
362
        for (;;) {
 
363
                char buffer[n];
 
364
                char* j;
 
365
 
 
366
                errno = 0;
 
367
                j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
 
368
                if (errno == 0) {
 
369
                        char error[6 + 10 + 1]; /* for a 32bit value */
 
370
 
 
371
                        if (j != buffer + 8 + k)
 
372
                                memmove(buffer + 8 + k, j, strlen(j)+1);
 
373
 
 
374
                        memcpy(buffer, "MESSAGE=", 8);
 
375
 
 
376
                        if (k > 0) {
 
377
                                memcpy(buffer + 8, message, k - 2);
 
378
                                memcpy(buffer + 8 + k - 2, ": ", 2);
 
379
                        }
 
380
 
 
381
                        snprintf(error, sizeof(error), "ERRNO=%u", _saved_errno_);
 
382
                        char_array_0(error);
 
383
 
 
384
                        IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
 
385
                        IOVEC_SET_STRING(iov[skip+1], buffer);
 
386
                        IOVEC_SET_STRING(iov[skip+2], error);
 
387
 
 
388
                        return sd_journal_sendv(iov, skip + 3);
 
389
                }
 
390
 
 
391
                if (errno != ERANGE)
 
392
                        return -errno;
 
393
 
 
394
                n *= 2;
 
395
        }
 
396
}
 
397
 
 
398
_public_ int sd_journal_perror(const char *message) {
 
399
        struct iovec iovec[3];
 
400
 
 
401
        return fill_iovec_perror_and_send(message, 0, iovec);
 
402
}
 
403
 
272
404
_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
273
405
        union sockaddr_union sa;
274
406
        int fd;
304
436
                identifier = "";
305
437
 
306
438
        l = strlen(identifier);
307
 
        header = alloca(l + 1 + 2 + 2 + 2 + 2 + 2);
 
439
        header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
308
440
 
309
441
        memcpy(header, identifier, l);
310
442
        header[l++] = '\n';
 
443
        header[l++] = '\n'; /* unit id */
311
444
        header[l++] = '0' + priority;
312
445
        header[l++] = '\n';
313
446
        header[l++] = '0' + !!level_prefix;
332
465
 
333
466
        return fd;
334
467
}
 
468
 
 
469
_public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
 
470
        int r;
 
471
        va_list ap;
 
472
 
 
473
        va_start(ap, format);
 
474
        r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
 
475
        va_end(ap);
 
476
 
 
477
        return r;
 
478
}
 
479
 
 
480
_public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
 
481
        char buffer[8 + LINE_MAX], p[11];
 
482
        struct iovec iov[5];
 
483
        char *f;
 
484
 
 
485
        if (priority < 0 || priority > 7)
 
486
                return -EINVAL;
 
487
 
 
488
        if (_unlikely_(!format))
 
489
                return -EINVAL;
 
490
 
 
491
        snprintf(p, sizeof(p), "PRIORITY=%i", priority & LOG_PRIMASK);
 
492
        char_array_0(p);
 
493
 
 
494
        memcpy(buffer, "MESSAGE=", 8);
 
495
        vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
 
496
        char_array_0(buffer);
 
497
 
 
498
        /* func is initialized from __func__ which is not a macro, but
 
499
         * a static const char[], hence cannot easily be prefixed with
 
500
         * CODE_FUNC=, hence let's do it manually here. */
 
501
        ALLOCA_CODE_FUNC(f, func);
 
502
 
 
503
        zero(iov);
 
504
        IOVEC_SET_STRING(iov[0], buffer);
 
505
        IOVEC_SET_STRING(iov[1], p);
 
506
        IOVEC_SET_STRING(iov[2], file);
 
507
        IOVEC_SET_STRING(iov[3], line);
 
508
        IOVEC_SET_STRING(iov[4], f);
 
509
 
 
510
        return sd_journal_sendv(iov, ELEMENTSOF(iov));
 
511
}
 
512
 
 
513
_public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
 
514
        int r, i, j;
 
515
        va_list ap;
 
516
        struct iovec *iov = NULL;
 
517
        char *f;
 
518
 
 
519
        va_start(ap, format);
 
520
        i = fill_iovec_sprintf(format, ap, 3, &iov);
 
521
        va_end(ap);
 
522
 
 
523
        if (_unlikely_(i < 0)) {
 
524
                r = i;
 
525
                goto finish;
 
526
        }
 
527
 
 
528
        ALLOCA_CODE_FUNC(f, func);
 
529
 
 
530
        IOVEC_SET_STRING(iov[0], file);
 
531
        IOVEC_SET_STRING(iov[1], line);
 
532
        IOVEC_SET_STRING(iov[2], f);
 
533
 
 
534
        r = sd_journal_sendv(iov, i);
 
535
 
 
536
finish:
 
537
        for (j = 3; j < i; j++)
 
538
                free(iov[j].iov_base);
 
539
 
 
540
        free(iov);
 
541
 
 
542
        return r;
 
543
}
 
544
 
 
545
_public_ int sd_journal_sendv_with_location(
 
546
                const char *file, const char *line,
 
547
                const char *func,
 
548
                const struct iovec *iov, int n) {
 
549
 
 
550
        struct iovec *niov;
 
551
        char *f;
 
552
 
 
553
        if (_unlikely_(!iov))
 
554
                return -EINVAL;
 
555
 
 
556
        if (_unlikely_(n <= 0))
 
557
                return -EINVAL;
 
558
 
 
559
        niov = alloca(sizeof(struct iovec) * (n + 3));
 
560
        memcpy(niov, iov, sizeof(struct iovec) * n);
 
561
 
 
562
        ALLOCA_CODE_FUNC(f, func);
 
563
 
 
564
        IOVEC_SET_STRING(niov[n++], file);
 
565
        IOVEC_SET_STRING(niov[n++], line);
 
566
        IOVEC_SET_STRING(niov[n++], f);
 
567
 
 
568
        return sd_journal_sendv(niov, n);
 
569
}
 
570
 
 
571
_public_ int sd_journal_perror_with_location(
 
572
                const char *file, const char *line,
 
573
                const char *func,
 
574
                const char *message) {
 
575
 
 
576
        struct iovec iov[6];
 
577
        char *f;
 
578
 
 
579
        ALLOCA_CODE_FUNC(f, func);
 
580
 
 
581
        IOVEC_SET_STRING(iov[0], file);
 
582
        IOVEC_SET_STRING(iov[1], line);
 
583
        IOVEC_SET_STRING(iov[2], f);
 
584
 
 
585
        return fill_iovec_perror_and_send(message, 3, iov);
 
586
}