diff options
Diffstat (limited to 'src')
55 files changed, 387 insertions, 242 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c index a5920e7d36..1cfb7a98f5 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1043,7 +1043,7 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { if (r < 0) return r; - fd = mkostemp_safe(t, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(t); if (fd < 0) { free(t); return -errno; @@ -1076,7 +1076,7 @@ int fflush_and_check(FILE *f) { } /* This is much like mkostemp() but is subject to umask(). */ -int mkostemp_safe(char *pattern, int flags) { +int mkostemp_safe(char *pattern) { _cleanup_umask_ mode_t u = 0; int fd; @@ -1084,7 +1084,7 @@ int mkostemp_safe(char *pattern, int flags) { u = umask(077); - fd = mkostemp(pattern, flags); + fd = mkostemp(pattern, O_CLOEXEC); if (fd < 0) return -errno; @@ -1289,7 +1289,7 @@ int open_tmpfile_unlinkable(const char *directory, int flags) { /* Fall back to unguessable name + unlinking */ p = strjoina(directory, "/systemd-tmp-XXXXXX"); - fd = mkostemp_safe(p, flags); + fd = mkostemp_safe(p); if (fd < 0) return fd; diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 9ac497d9eb..b58c83e64a 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -71,7 +71,7 @@ int search_and_fopen_nulstr(const char *path, const char *mode, const char *root int fflush_and_check(FILE *f); int fopen_temporary(const char *path, FILE **_f, char **_temp_path); -int mkostemp_safe(char *pattern, int flags); +int mkostemp_safe(char *pattern); int tempfn_xxxxxx(const char *p, const char *extra, char **ret); int tempfn_random(const char *p, const char *extra, char **ret); diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 5d4510e1b3..dc7de5dab8 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -443,7 +443,7 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le if (old_length <= 3 || old_length <= new_length) return strndup(s, old_length); - r = new0(char, new_length+1); + r = new0(char, new_length+3); if (!r) return NULL; @@ -453,12 +453,12 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le x = new_length - 3; memcpy(r, s, x); - r[x] = '.'; - r[x+1] = '.'; - r[x+2] = '.'; + r[x] = 0xe2; /* tri-dot ellipsis: … */ + r[x+1] = 0x80; + r[x+2] = 0xa6; memcpy(r + x + 3, - s + old_length - (new_length - x - 3), - new_length - x - 3); + s + old_length - (new_length - x - 1), + new_length - x - 1); return r; } diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 0ef1f6393e..fedff1362c 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -40,8 +40,6 @@ #include "strv.h" #include "time-util.h" -static nsec_t timespec_load_nsec(const struct timespec *ts); - static clockid_t map_clock_id(clockid_t c) { /* Some more exotic archs (s390, ppc, …) lack the "ALARM" flavour of the clocks. Thus, clock_gettime() will @@ -198,7 +196,7 @@ usec_t timespec_load(const struct timespec *ts) { (usec_t) ts->tv_nsec / NSEC_PER_USEC; } -static nsec_t timespec_load_nsec(const struct timespec *ts) { +nsec_t timespec_load_nsec(const struct timespec *ts) { assert(ts); if (ts->tv_sec == (time_t) -1 && ts->tv_nsec == (long) -1) diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 99be5ce6ee..558b0b5b7f 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -111,6 +111,7 @@ static inline bool triple_timestamp_is_set(triple_timestamp *ts) { usec_t triple_timestamp_by_clock(triple_timestamp *ts, clockid_t clock); usec_t timespec_load(const struct timespec *ts) _pure_; +nsec_t timespec_load_nsec(const struct timespec *ts) _pure_; struct timespec *timespec_store(struct timespec *ts, usec_t u); usec_t timeval_load(const struct timeval *tv) _pure_; diff --git a/src/coredump/coredumpctl.c b/src/coredump/coredumpctl.c index bbf8793e57..8ba7c08eed 100644 --- a/src/coredump/coredumpctl.c +++ b/src/coredump/coredumpctl.c @@ -620,7 +620,7 @@ static int save_core(sd_journal *j, int fd, char **path, bool *unlink_temp) { if (!temp) return log_oom(); - fdt = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); + fdt = mkostemp_safe(temp); if (fdt < 0) return log_error_errno(fdt, "Failed to create temporary file: %m"); log_debug("Created temporary file %s", temp); diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 080a2cd138..197f905b7d 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -451,7 +451,7 @@ static int method_set_hostname(sd_bus_message *m, void *userdata, sd_bus_error * r = context_update_kernel_hostname(c); if (r < 0) { log_error_errno(r, "Failed to set host name: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m"); } log_info("Changed host name to '%s'", strna(c->data[PROP_HOSTNAME])); @@ -512,13 +512,13 @@ static int method_set_static_hostname(sd_bus_message *m, void *userdata, sd_bus_ r = context_update_kernel_hostname(c); if (r < 0) { log_error_errno(r, "Failed to set host name: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %m"); } r = context_write_data_static_hostname(c); if (r < 0) { log_error_errno(r, "Failed to write static host name: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %m"); } log_info("Changed static host name to '%s'", strna(c->data[PROP_STATIC_HOSTNAME])); @@ -593,7 +593,7 @@ static int set_machine_info(Context *c, sd_bus_message *m, int prop, sd_bus_mess r = context_write_data_machine_info(c); if (r < 0) { log_error_errno(r, "Failed to write machine info: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %m"); } log_info("Changed %s to '%s'", diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c index c2b5a5f205..54f42b8bf3 100644 --- a/src/journal-remote/journal-gatewayd.c +++ b/src/journal-remote/journal-gatewayd.c @@ -475,20 +475,20 @@ static int request_handler_entries( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); if (request_parse_accept(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header."); if (request_parse_range(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Range header."); if (request_parse_arguments(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments."); if (m->discrete) { if (!m->cursor) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification."); m->n_entries = 1; m->n_entries_set = true; @@ -501,7 +501,7 @@ static int request_handler_entries( else if (m->n_skip < 0) r = sd_journal_seek_tail(m->journal); if (r < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to seek in journal."); response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_entries, m, NULL); if (!response) @@ -633,14 +633,14 @@ static int request_handler_fields( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); if (request_parse_accept(m, connection) < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse Accept header."); r = sd_journal_query_unique(m->journal, field); if (r < 0) - return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields.\n"); + return mhd_respond(connection, MHD_HTTP_BAD_REQUEST, "Failed to query unique fields."); response = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN, 4*1024, request_reader_fields, m, NULL); if (!response) @@ -699,10 +699,10 @@ static int request_handler_file( fd = open(path, O_RDONLY|O_CLOEXEC); if (fd < 0) - return mhd_respondf(connection, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m\n", path); + return mhd_respondf(connection, errno, MHD_HTTP_NOT_FOUND, "Failed to open file %s: %m", path); if (fstat(fd, &st) < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m\n"); + return mhd_respondf(connection, errno, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to stat file: %m"); response = MHD_create_response_from_fd_at_offset64(st.st_size, fd, 0); if (!response) @@ -766,15 +766,15 @@ static int request_handler_machine( r = open_journal(m); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to open journal: %m"); r = sd_id128_get_machine(&mid); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine machine ID: %m"); r = sd_id128_get_boot(&bid); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine boot ID: %m"); hostname = gethostname_malloc(); if (!hostname) @@ -782,11 +782,11 @@ static int request_handler_machine( r = sd_journal_get_usage(m->journal, &usage); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s"); r = sd_journal_get_cutoff_realtime_usec(m->journal, &cutoff_from, &cutoff_to); if (r < 0) - return mhd_respondf(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s\n", strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "Failed to determine disk usage: %s"); if (parse_env_file("/etc/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL) == -ENOENT) (void) parse_env_file("/usr/lib/os-release", NEWLINE, "PRETTY_NAME", &os_name, NULL); @@ -844,8 +844,7 @@ static int request_handler( assert(method); if (!streq(method, "GET")) - return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, - "Unsupported method.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method."); if (!*connection_cls) { @@ -875,7 +874,7 @@ static int request_handler( if (streq(url, "/machine")) return request_handler_machine(connection, *connection_cls); - return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found."); } static void help(void) { diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c index 220c71754a..a9009cfefe 100644 --- a/src/journal-remote/journal-remote.c +++ b/src/journal-remote/journal-remote.c @@ -524,13 +524,12 @@ static int process_http_upload( log_warning("Failed to process data for connection %p", connection); if (r == -E2BIG) return mhd_respondf(connection, - MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, - "Entry is too large, maximum is %u bytes.\n", - DATA_SIZE_MAX); + r, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, + "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes."); else return mhd_respondf(connection, - MHD_HTTP_UNPROCESSABLE_ENTITY, - "Processing failed: %s.", strerror(-r)); + r, MHD_HTTP_UNPROCESSABLE_ENTITY, + "Processing failed: %m."); } } @@ -541,13 +540,14 @@ static int process_http_upload( remaining = source_non_empty(source); if (remaining > 0) { - log_warning("Premature EOFbyte. %zu bytes lost.", remaining); - return mhd_respondf(connection, MHD_HTTP_EXPECTATION_FAILED, + log_warning("Premature EOF byte. %zu bytes lost.", remaining); + return mhd_respondf(connection, + 0, MHD_HTTP_EXPECTATION_FAILED, "Premature EOF. %zu bytes of trailing data not processed.", remaining); } - return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK.\n"); + return mhd_respond(connection, MHD_HTTP_ACCEPTED, "OK."); }; static int request_handler( @@ -577,19 +577,16 @@ static int request_handler( *connection_cls); if (!streq(method, "POST")) - return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, - "Unsupported method.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_ACCEPTABLE, "Unsupported method."); if (!streq(url, "/upload")) - return mhd_respond(connection, MHD_HTTP_NOT_FOUND, - "Not found.\n"); + return mhd_respond(connection, MHD_HTTP_NOT_FOUND, "Not found."); header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Content-Type"); if (!header || !streq(header, "application/vnd.fdo.journal")) return mhd_respond(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE, - "Content-Type: application/vnd.fdo.journal" - " is required.\n"); + "Content-Type: application/vnd.fdo.journal is required."); { const union MHD_ConnectionInfo *ci; @@ -599,7 +596,7 @@ static int request_handler( if (!ci) { log_error("MHD_get_connection_info failed: cannot get remote fd"); return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - "Cannot check remote address"); + "Cannot check remote address."); } fd = ci->connect_fd; @@ -614,7 +611,7 @@ static int request_handler( r = getpeername_pretty(fd, false, &hostname); if (r < 0) return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - "Cannot check remote hostname"); + "Cannot check remote hostname."); } assert(hostname); @@ -623,8 +620,7 @@ static int request_handler( if (r == -ENOMEM) return respond_oom(connection); else if (r < 0) - return mhd_respond(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, - strerror(-r)); + return mhd_respondf(connection, r, MHD_HTTP_INTERNAL_SERVER_ERROR, "%m"); hostname = NULL; return MHD_YES; diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c index 2f16b02e9a..cae10203c6 100644 --- a/src/journal-remote/microhttpd-util.c +++ b/src/journal-remote/microhttpd-util.c @@ -48,7 +48,7 @@ void microhttpd_logger(void *arg, const char *fmt, va_list ap) { static int mhd_respond_internal(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, - char *buffer, + const char *buffer, size_t size, enum MHD_ResponseMemoryMode mode) { struct MHD_Response *response; @@ -56,7 +56,7 @@ static int mhd_respond_internal(struct MHD_Connection *connection, assert(connection); - response = MHD_create_response_from_buffer(size, buffer, mode); + response = MHD_create_response_from_buffer(size, (char*) buffer, mode); if (!response) return MHD_NO; @@ -72,19 +72,25 @@ int mhd_respond(struct MHD_Connection *connection, enum MHD_RequestTerminationCode code, const char *message) { + const char *fmt; + + fmt = strjoina(message, "\n"); + return mhd_respond_internal(connection, code, - (char*) message, strlen(message), + fmt, strlen(message) + 1, MHD_RESPMEM_PERSISTENT); } int mhd_respond_oom(struct MHD_Connection *connection) { - return mhd_respond(connection, MHD_HTTP_SERVICE_UNAVAILABLE, "Out of memory.\n"); + return mhd_respond(connection, MHD_HTTP_SERVICE_UNAVAILABLE, "Out of memory."); } int mhd_respondf(struct MHD_Connection *connection, + int error, enum MHD_RequestTerminationCode code, const char *format, ...) { + const char *fmt; char *m; int r; va_list ap; @@ -92,8 +98,12 @@ int mhd_respondf(struct MHD_Connection *connection, assert(connection); assert(format); + if (error < 0) + error = -error; + errno = -error; + fmt = strjoina(format, "\n"); va_start(ap, format); - r = vasprintf(&m, format, ap); + r = vasprintf(&m, fmt, ap); va_end(ap); if (r < 0) diff --git a/src/journal-remote/microhttpd-util.h b/src/journal-remote/microhttpd-util.h index ea160f212b..af26ab69fe 100644 --- a/src/journal-remote/microhttpd-util.h +++ b/src/journal-remote/microhttpd-util.h @@ -39,8 +39,9 @@ void microhttpd_logger(void *arg, const char *fmt, va_list ap) _printf_(2, 0); #define respond_oom(connection) log_oom(), mhd_respond_oom(connection) int mhd_respondf(struct MHD_Connection *connection, + int error, unsigned code, - const char *format, ...) _printf_(3,4); + const char *format, ...) _printf_(4,5); int mhd_respond(struct MHD_Connection *connection, unsigned code, diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 4105abfccc..9e4d8a28a5 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -118,6 +118,11 @@ static void flush_progress(void) { log_error(OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \ } while (0) +#define error_errno(_offset, error, _fmt, ...) do { \ + flush_progress(); \ + log_error_errno(error, OFSfmt": " _fmt, (uint64_t)_offset, ##__VA_ARGS__); \ + } while (0) + static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o) { uint64_t i; @@ -168,8 +173,8 @@ static int journal_file_object_verify(JournalFile *f, uint64_t offset, Object *o le64toh(o->object.size) - offsetof(Object, data.payload), &b, &alloc, &b_size, 0); if (r < 0) { - error(offset, "%s decompression failed: %s", - object_compressed_to_string(compression), strerror(-r)); + error_errno(offset, r, "%s decompression failed: %m", + object_compressed_to_string(compression)); return r; } @@ -912,7 +917,7 @@ int journal_file_verify( r = journal_file_object_verify(f, p, o); if (r < 0) { - error(p, "Invalid object contents: %s", strerror(-r)); + error_errno(p, r, "Invalid object contents: %m"); goto fail; } diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 381e219390..4350925fb0 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -1632,7 +1632,7 @@ static int setup_keys(void) { n /= arg_interval; safe_close(fd); - fd = mkostemp_safe(k, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(k); if (fd < 0) { r = log_error_errno(fd, "Failed to open %s: %m", k); goto finish; @@ -1684,9 +1684,9 @@ static int setup_keys(void) { "at a safe location and should not be saved locally on disk.\n" "\n\t%s", ansi_highlight(), ansi_normal(), + p, ansi_highlight(), ansi_normal(), - ansi_highlight_red(), - p); + ansi_highlight_red()); fflush(stderr); } for (i = 0; i < seed_size; i++) { diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c index 898c876450..b7d9e7bffa 100644 --- a/src/journal/test-catalog.c +++ b/src/journal/test-catalog.c @@ -55,7 +55,7 @@ static Hashmap * test_import(const char* contents, ssize_t size, int code) { assert_se(h = hashmap_new(&catalog_hash_ops)); - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, contents, size) == size); @@ -182,7 +182,7 @@ static void test_catalog_update(void) { static char name[] = "/tmp/test-catalog.XXXXXX"; int r; - r = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + r = mkostemp_safe(name); assert_se(r >= 0); database = name; diff --git a/src/journal/test-compress.c b/src/journal/test-compress.c index 68c9a4d76c..00e5222a1c 100644 --- a/src/journal/test-compress.c +++ b/src/journal/test-compress.c @@ -167,7 +167,7 @@ static void test_compress_stream(int compression, log_debug("/* test compression */"); - assert_se((dst = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC)) >= 0); + assert_se((dst = mkostemp_safe(pattern)) >= 0); assert_se(compress(src, dst, -1) == 0); @@ -178,7 +178,7 @@ static void test_compress_stream(int compression, log_debug("/* test decompression */"); - assert_se((dst2 = mkostemp_safe(pattern2, O_RDWR|O_CLOEXEC)) >= 0); + assert_se((dst2 = mkostemp_safe(pattern2)) >= 0); assert_se(stat(srcfile, &st) == 0); diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c index 5e063f4d04..35cae23bf8 100644 --- a/src/journal/test-journal-interleaving.c +++ b/src/journal/test-journal-interleaving.c @@ -36,10 +36,9 @@ static bool arg_keep = false; -noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) { - log_internal(LOG_CRIT, 0, file, line, func, - "'%s' failed at %s:%u (%s): %s.", - text, file, line, func, strerror(eno)); +noreturn static void log_assert_errno(const char *text, int error, const char *file, int line, const char *func) { + log_internal(LOG_CRIT, error, file, line, func, + "'%s' failed at %s:%u (%s): %m", text, file, line, func); abort(); } diff --git a/src/journal/test-mmap-cache.c b/src/journal/test-mmap-cache.c index 009aabf55e..0ad49aeb5f 100644 --- a/src/journal/test-mmap-cache.c +++ b/src/journal/test-mmap-cache.c @@ -36,15 +36,15 @@ int main(int argc, char *argv[]) { assert_se(m = mmap_cache_new()); - x = mkostemp_safe(px, O_RDWR|O_CLOEXEC); + x = mkostemp_safe(px); assert_se(x >= 0); unlink(px); - y = mkostemp_safe(py, O_RDWR|O_CLOEXEC); + y = mkostemp_safe(py); assert_se(y >= 0); unlink(py); - z = mkostemp_safe(pz, O_RDWR|O_CLOEXEC); + z = mkostemp_safe(pz); assert_se(z >= 0); unlink(pz); diff --git a/src/kernel-install/kernel-install b/src/kernel-install/kernel-install index c66bcfc092..f37c023c6a 100644 --- a/src/kernel-install/kernel-install +++ b/src/kernel-install/kernel-install @@ -61,6 +61,13 @@ for i in "$@"; do fi done +# KERNEL_INSTALL_NOOP may be used by programs like lorax and rpm-ostree which +# want to install a kernel (indirectly via RPM), but control generation of the +# initramfs. In general, OSTree takes over kernel management too. +if test -n "${KERNEL_INSTALL_NOOP:-}"; then + exit 0 +fi + if [[ "${0##*/}" == 'installkernel' ]]; then COMMAND='add' else diff --git a/src/libsystemd/sd-bus/test-bus-chat.c b/src/libsystemd/sd-bus/test-bus-chat.c index 048c0d19e2..fc60830059 100644 --- a/src/libsystemd/sd-bus/test-bus-chat.c +++ b/src/libsystemd/sd-bus/test-bus-chat.c @@ -351,7 +351,7 @@ finish: static int quit_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { bool *x = userdata; - log_error("Quit callback: %s", strerror(sd_bus_message_get_errno(m))); + log_error_errno(sd_bus_message_get_errno(m), "Quit callback: %m"); *x = 1; return 1; diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 566a050432..1c10dd55a7 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -21,6 +21,7 @@ #include <sys/socket.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> +#include <linux/can/netlink.h> #include <linux/in6.h> #include <linux/veth.h> #include <linux/if_bridge.h> @@ -303,49 +304,48 @@ static const char* const nl_union_link_info_data_table[] = { [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = "vti6", [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl", [NL_UNION_LINK_INFO_DATA_VRF] = "vrf", + [NL_UNION_LINK_INFO_DATA_VCAN] = "vcan", }; DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData); static const NLTypeSystem rtnl_link_info_data_type_systems[] = { - [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), - .types = rtnl_link_info_data_bond_types }, - [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), - .types = rtnl_link_info_data_bridge_types }, - [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), - .types = rtnl_link_info_data_vlan_types }, - [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), - .types = rtnl_link_info_data_veth_types }, - [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), - .types = rtnl_link_info_data_macvlan_types }, - [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), - .types = rtnl_link_info_data_macvlan_types }, - [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), - .types = rtnl_link_info_data_ipvlan_types }, - [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), - .types = rtnl_link_info_data_vxlan_types }, - [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), - .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types), + .types = rtnl_link_info_data_bond_types }, + [NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types), + .types = rtnl_link_info_data_bridge_types }, + [NL_UNION_LINK_INFO_DATA_VLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vlan_types), + .types = rtnl_link_info_data_vlan_types }, + [NL_UNION_LINK_INFO_DATA_VETH] = { .count = ELEMENTSOF(rtnl_link_info_data_veth_types), + .types = rtnl_link_info_data_veth_types }, + [NL_UNION_LINK_INFO_DATA_MACVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), + .types = rtnl_link_info_data_macvlan_types }, + [NL_UNION_LINK_INFO_DATA_MACVTAP] = { .count = ELEMENTSOF(rtnl_link_info_data_macvlan_types), + .types = rtnl_link_info_data_macvlan_types }, + [NL_UNION_LINK_INFO_DATA_IPVLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types), + .types = rtnl_link_info_data_ipvlan_types }, + [NL_UNION_LINK_INFO_DATA_VXLAN] = { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types), + .types = rtnl_link_info_data_vxlan_types }, + [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), + .types = rtnl_link_info_data_iptun_types }, + [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), - .types = rtnl_link_info_data_ipgre_types }, - [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), - .types = rtnl_link_info_data_iptun_types }, - [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), - .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), - .types = rtnl_link_info_data_ipvti_types }, - [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), - .types = rtnl_link_info_data_ip6tnl_types }, - - [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types), - .types = rtnl_link_info_data_vrf_types }, - + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipgre_types), + .types = rtnl_link_info_data_ipgre_types }, + [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types), + .types = rtnl_link_info_data_iptun_types }, + [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), + .types = rtnl_link_info_data_ipvti_types }, + [NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ipvti_types), + .types = rtnl_link_info_data_ipvti_types }, + [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = { .count = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types), + .types = rtnl_link_info_data_ip6tnl_types }, + [NL_UNION_LINK_INFO_DATA_VRF] = { .count = ELEMENTSOF(rtnl_link_info_data_vrf_types), + .types = rtnl_link_info_data_vrf_types }, }; static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = { diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h index 7c0e598b26..42e96173de 100644 --- a/src/libsystemd/sd-netlink/netlink-types.h +++ b/src/libsystemd/sd-netlink/netlink-types.h @@ -87,6 +87,7 @@ typedef enum NLUnionLinkInfoData { NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL, NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL, NL_UNION_LINK_INFO_DATA_VRF, + NL_UNION_LINK_INFO_DATA_VCAN, _NL_UNION_LINK_INFO_DATA_MAX, _NL_UNION_LINK_INFO_DATA_INVALID = -1 } NLUnionLinkInfoData; diff --git a/src/locale/localed.c b/src/locale/localed.c index 298f176e40..1cb049e74a 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -334,7 +334,7 @@ static int method_set_locale(sd_bus_message *m, void *userdata, sd_bus_error *er r = locale_write_data(c, &settings); if (r < 0) { log_error_errno(r, "Failed to set locale: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set locale: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set locale: %m"); } locale_update_system_manager(c, sd_bus_message_get_bus(m)); @@ -403,7 +403,7 @@ static int method_set_vc_keyboard(sd_bus_message *m, void *userdata, sd_bus_erro r = vconsole_write_data(c); if (r < 0) { log_error_errno(r, "Failed to set virtual console keymap: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set virtual console keymap: %m"); } log_info("Changed virtual console keymap to '%s' toggle '%s'", @@ -592,7 +592,7 @@ static int method_set_x11_keyboard(sd_bus_message *m, void *userdata, sd_bus_err r = x11_write_data(c); if (r < 0) { log_error_errno(r, "Failed to set X11 keyboard layout: %m"); - return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %s", strerror(-r)); + return sd_bus_error_set_errnof(error, r, "Failed to set X11 keyboard layout: %m"); } log_info("Changed X11 keyboard layout to '%s' model '%s' variant '%s' options '%s'", diff --git a/src/login/logind-user.c b/src/login/logind-user.c index e0e73b034d..2dc5fa7665 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -354,14 +354,12 @@ static int user_mkdir_runtime_path(User *u) { r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t); if (r < 0) { - if (errno != EPERM) { + if (errno != EPERM && errno != EACCES) { r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path); goto fail; } - /* Lacking permissions, maybe - * CAP_SYS_ADMIN-less container? In this case, - * just use a normal directory. */ + log_debug_errno(errno, "Failed to mount per-user tmpfs directory %s, assuming containerized execution, ignoring: %m", u->runtime_path); r = chmod_and_chown(u->runtime_path, 0700, u->uid, u->gid); if (r < 0) { diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 5e2462cba2..e40f40a263 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -444,7 +444,9 @@ static int method_register_machine_internal(sd_bus_message *message, bool read_n r = cg_pid_get_unit(m->leader, &m->unit); if (r < 0) { - r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r)); + r = sd_bus_error_set_errnof(error, r, + "Failed to determine unit of process "PID_FMT" : %m", + m->leader); goto fail; } diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index aab40a0eb1..1687d9bf31 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1787,6 +1787,31 @@ static int link_down(Link *link) { return 0; } +static int link_up_can(Link *link) { + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; + int r; + + assert(link); + + log_link_debug(link, "Bringing CAN link up"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + static int link_handle_bound_to_list(Link *link) { Link *l; Iterator i; @@ -2431,6 +2456,19 @@ static int link_configure(Link *link) { assert(link->network); assert(link->state == LINK_STATE_PENDING); + if (streq_ptr(link->kind, "vcan")) { + + if (!(link->flags & IFF_UP)) { + r = link_up_can(link); + if (r < 0) { + link_enter_failed(link); + return r; + } + } + + return 0; + } + /* Drop foreign config, but ignore loopback or critical devices. * We do not want to remove loopback address or addresses used for root NFS. */ if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) { diff --git a/src/network/networkd-netdev-vcan.c b/src/network/networkd-netdev-vcan.c new file mode 100644 index 0000000000..bfce6e1962 --- /dev/null +++ b/src/network/networkd-netdev-vcan.c @@ -0,0 +1,25 @@ +/*** + This file is part of systemd. + + Copyright 2016 Susant Sahani + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include "networkd-netdev-vcan.h" + +const NetDevVTable vcan_vtable = { + .object_size = sizeof(VCan), + .create_type = NETDEV_CREATE_INDEPENDENT, +}; diff --git a/src/network/networkd-netdev-vcan.h b/src/network/networkd-netdev-vcan.h new file mode 100644 index 0000000000..6ba47fd70e --- /dev/null +++ b/src/network/networkd-netdev-vcan.h @@ -0,0 +1,34 @@ +#pragma once + +/*** + This file is part of systemd. + + Copyright 2016 Susant Sahani + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +typedef struct VCan VCan; + +#include <linux/can/netlink.h> + +#include "networkd-netdev.h" + +struct VCan { + NetDev meta; +}; + +DEFINE_NETDEV_CAST(VCAN, VCan); + +extern const NetDevVTable vcan_vtable; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index ece4ea2e64..a210ba1242 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -34,7 +34,6 @@ #include "string-util.h" const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { - [NETDEV_KIND_BRIDGE] = &bridge_vtable, [NETDEV_KIND_BOND] = &bond_vtable, [NETDEV_KIND_VLAN] = &vlan_vtable, @@ -56,7 +55,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { [NETDEV_KIND_TAP] = &tap_vtable, [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable, [NETDEV_KIND_VRF] = &vrf_vtable, - + [NETDEV_KIND_VCAN] = &vcan_vtable, }; static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { @@ -81,7 +80,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { [NETDEV_KIND_TAP] = "tap", [NETDEV_KIND_IP6TNL] = "ip6tnl", [NETDEV_KIND_VRF] = "vrf", - + [NETDEV_KIND_VCAN] = "vcan", }; DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); @@ -516,7 +515,7 @@ static int netdev_create(NetDev *netdev, Link *link, r = sd_netlink_message_close_container(m); if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); r = sd_netlink_message_close_container(m); if (r < 0) diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index 09863e72b4..31b55e2791 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -56,6 +56,7 @@ typedef enum NetDevKind { NETDEV_KIND_TUN, NETDEV_KIND_TAP, NETDEV_KIND_VRF, + NETDEV_KIND_VCAN, _NETDEV_KIND_MAX, _NETDEV_KIND_INVALID = -1 } NetDevKind; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 58e19e542a..313abca762 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -482,9 +482,10 @@ int config_parse_netdev(const char *unit, case NETDEV_KIND_MACVTAP: case NETDEV_KIND_IPVLAN: case NETDEV_KIND_VXLAN: + case NETDEV_KIND_VCAN: r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Can not add NetDev '%s' to network: %m", rvalue); return 0; } diff --git a/src/network/networkd.h b/src/network/networkd.h index c4bd712147..cb1b73145e 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -43,6 +43,7 @@ #include "networkd-netdev-vlan.h" #include "networkd-netdev-vrf.h" #include "networkd-netdev-vxlan.h" +#include "networkd-netdev-vcan.h" #include "networkd-network.h" #include "networkd-util.h" diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 6d0420965a..6f4a33cd96 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1219,7 +1219,13 @@ static int setup_timezone(const char *dest) { /* Fix the timezone, if possible */ r = readlink_malloc("/etc/localtime", &p); if (r < 0) { - log_warning("/etc/localtime is not a symlink, not updating container timezone."); + log_warning("host's /etc/localtime is not a symlink, not updating container timezone."); + /* to handle warning, delete /etc/localtime and replace it + * it /w a symbolic link to a time zone data file. + * + * Example: + * ln -s /etc/localtime /usr/share/zoneinfo/UTC + */ return 0; } diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 65151b19a6..2597cfc648 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -484,7 +484,7 @@ int ask_password_agent( (void) mkdir_p_label("/run/systemd/ask-password", 0755); - fd = mkostemp_safe(temp, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(temp); if (fd < 0) { r = fd; goto finish; diff --git a/src/shared/condition.c b/src/shared/condition.c index 6bb42c0692..f13fa6a9fd 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -37,6 +37,7 @@ #include "condition.h" #include "extract-word.h" #include "fd-util.h" +#include "fileio.h" #include "glob-util.h" #include "hostname-util.h" #include "ima-util.h" @@ -309,8 +310,45 @@ static int condition_test_needs_update(Condition *c) { if (lstat("/usr/", &usr) < 0) return true; - return usr.st_mtim.tv_sec > other.st_mtim.tv_sec || - (usr.st_mtim.tv_sec == other.st_mtim.tv_sec && usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec); + /* + * First, compare seconds as they are always accurate... + */ + if (usr.st_mtim.tv_sec != other.st_mtim.tv_sec) + return usr.st_mtim.tv_sec > other.st_mtim.tv_sec; + + /* + * ...then compare nanoseconds. + * + * A false positive is only possible when /usr's nanoseconds > 0 + * (otherwise /usr cannot be strictly newer than the target file) + * AND the target file's nanoseconds == 0 + * (otherwise the filesystem supports nsec timestamps, see stat(2)). + */ + if (usr.st_mtim.tv_nsec > 0 && other.st_mtim.tv_nsec == 0) { + _cleanup_free_ char *timestamp_str = NULL; + uint64_t timestamp; + int r; + + r = parse_env_file(p, NULL, "TimestampNSec", ×tamp_str, NULL); + if (r < 0) { + log_error_errno(-r, "Failed to parse timestamp file '%s', using mtime: %m", p); + return true; + } else if (r == 0) { + log_debug("No data in timestamp file '%s', using mtime", p); + return true; + } + + r = safe_atou64(timestamp_str, ×tamp); + if (r < 0) { + log_error_errno(-r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", + timestamp_str, p); + return true; + } + + other.st_mtim.tv_nsec = timestamp % NSEC_PER_SEC; + } + + return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec; } static int condition_test_first_boot(Condition *c) { diff --git a/src/shared/install.c b/src/shared/install.c index 11770d887f..5f12fb447f 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -403,6 +403,9 @@ static bool chroot_symlinks_same(const char *root, const char *wd, const char *a /* This will give incorrect results if the paths are relative and go outside * of the chroot. False negatives are possible. */ + if (!root) + root = "/"; + a = strjoina(path_is_absolute(a) ? root : wd, "/", a); b = strjoina(path_is_absolute(b) ? root : wd, "/", b); return path_equal_or_files_same(a, b); diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c index 430dda8e78..5b572bb0bf 100644 --- a/src/test/test-acl-util.c +++ b/src/test/test-acl-util.c @@ -35,7 +35,7 @@ static void test_add_acls_for_user(void) { uid_t uid; int r; - fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(fn); assert_se(fd >= 0); /* Use the mode that user journal files use */ diff --git a/src/test/test-async.c b/src/test/test-async.c index ada6d67c42..4ebc27f0bd 100644 --- a/src/test/test-async.c +++ b/src/test/test-async.c @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) { int fd; char name[] = "/tmp/test-asynchronous_close.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); asynchronous_close(fd); diff --git a/src/test/test-clock.c b/src/test/test-clock.c index 84f775e5bc..7d97328416 100644 --- a/src/test/test-clock.c +++ b/src/test/test-clock.c @@ -55,7 +55,7 @@ static void test_clock_is_localtime(void) { /* without an adjtime file we default to UTC */ assert_se(clock_is_localtime("/nonexisting/adjtime") == 0); - fd = mkostemp_safe(adjtime, O_WRONLY|O_CLOEXEC); + fd = mkostemp_safe(adjtime); assert_se(fd >= 0); log_info("adjtime test file: %s", adjtime); f = fdopen(fd, "w"); diff --git a/src/test/test-copy.c b/src/test/test-copy.c index 68154fc4e8..ed1ea51dbd 100644 --- a/src/test/test-copy.c +++ b/src/test/test-copy.c @@ -42,11 +42,11 @@ static void test_copy_file(void) { log_info("%s", __func__); - fd = mkostemp_safe(fn, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(fn); assert_se(fd >= 0); close(fd); - fd = mkostemp_safe(fn_copy, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(fn_copy); assert_se(fd >= 0); close(fd); @@ -71,9 +71,9 @@ static void test_copy_file_fd(void) { log_info("%s", __func__); - in_fd = mkostemp_safe(in_fn, O_RDWR); + in_fd = mkostemp_safe(in_fn); assert_se(in_fd >= 0); - out_fd = mkostemp_safe(out_fn, O_RDWR); + out_fd = mkostemp_safe(out_fn); assert_se(out_fd >= 0); assert_se(write_string_file(in_fn, text, WRITE_STRING_FILE_CREATE) == 0); @@ -207,10 +207,10 @@ static void test_copy_bytes_regular_file(const char *src, bool try_reflink, uint fd = open(src, O_RDONLY | O_CLOEXEC | O_NOCTTY); assert_se(fd >= 0); - fd2 = mkostemp_safe(fn2, O_RDWR); + fd2 = mkostemp_safe(fn2); assert_se(fd2 >= 0); - fd3 = mkostemp_safe(fn3, O_WRONLY); + fd3 = mkostemp_safe(fn3); assert_se(fd3 >= 0); r = copy_bytes(fd, fd2, max_bytes, try_reflink); diff --git a/src/test/test-engine.c b/src/test/test-engine.c index 23da10fa1a..a651f6b683 100644 --- a/src/test/test-engine.c +++ b/src/test/test-engine.c @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 05ec1d2eb1..25489cefbc 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -324,7 +324,7 @@ static int run_tests(UnitFileScope scope, test_function_t *tests) { r = manager_new(scope, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-fd-util.c b/src/test/test-fd-util.c index 421d3bdeb3..f555bb976c 100644 --- a/src/test/test-fd-util.c +++ b/src/test/test-fd-util.c @@ -31,9 +31,9 @@ static void test_close_many(void) { char name1[] = "/tmp/test-close-many.XXXXXX"; char name2[] = "/tmp/test-close-many.XXXXXX"; - fds[0] = mkostemp_safe(name0, O_RDWR|O_CLOEXEC); - fds[1] = mkostemp_safe(name1, O_RDWR|O_CLOEXEC); - fds[2] = mkostemp_safe(name2, O_RDWR|O_CLOEXEC); + fds[0] = mkostemp_safe(name0); + fds[1] = mkostemp_safe(name1); + fds[2] = mkostemp_safe(name2); close_many(fds, 2); @@ -52,7 +52,7 @@ static void test_close_nointr(void) { char name[] = "/tmp/test-test-close_nointr.XXXXXX"; int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); assert_se(close_nointr(fd) < 0); diff --git a/src/test/test-fdset.c b/src/test/test-fdset.c index 282aab1246..adbf99a7ec 100644 --- a/src/test/test-fdset.c +++ b/src/test/test-fdset.c @@ -31,7 +31,7 @@ static void test_fdset_new_fill(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_new_fill.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(fdset_new_fill(&fdset) >= 0); assert_se(fdset_contains(fdset, fd)); @@ -45,7 +45,7 @@ static void test_fdset_put_dup(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_put_dup.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -64,7 +64,7 @@ static void test_fdset_cloexec(void) { int flags = -1; char name[] = "/tmp/test-fdset_cloexec.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -91,7 +91,7 @@ static void test_fdset_close_others(void) { int flags = -1; char name[] = "/tmp/test-fdset_close_others.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -113,7 +113,7 @@ static void test_fdset_remove(void) { FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_remove.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -136,7 +136,7 @@ static void test_fdset_iterate(void) { int c = 0; int a; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -161,7 +161,7 @@ static void test_fdset_isempty(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_isempty.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); @@ -179,7 +179,7 @@ static void test_fdset_steal_first(void) { _cleanup_fdset_free_ FDSet *fdset = NULL; char name[] = "/tmp/test-fdset_steal_first.XXXXXX"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); fdset = fdset_new(); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index 79609765e0..92663ef66f 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -45,11 +45,11 @@ static void test_parse_env_file(void) { char **i; unsigned k; - fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(p); assert_se(fd >= 0); close(fd); - fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(t); assert_se(fd >= 0); f = fdopen(fd, "w"); @@ -158,11 +158,11 @@ static void test_parse_multiline_env_file(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; char **i; - fd = mkostemp_safe(p, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(p); assert_se(fd >= 0); close(fd); - fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(t); assert_se(fd >= 0); f = fdopen(fd, "w"); @@ -211,7 +211,7 @@ static void test_executable_is_script(void) { FILE *f; char *command; - fd = mkostemp_safe(t, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(t); assert_se(fd >= 0); f = fdopen(fd, "w"); @@ -300,7 +300,7 @@ static void test_write_string_stream(void) { int fd; char buf[64]; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); f = fdopen(fd, "r"); @@ -334,7 +334,7 @@ static void test_write_string_file(void) { char buf[64] = {}; _cleanup_close_ int fd; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); assert_se(write_string_file(fn, "boohoo", WRITE_STRING_FILE_CREATE) == 0); @@ -350,7 +350,7 @@ static void test_write_string_file_no_create(void) { _cleanup_close_ int fd; char buf[64] = {0}; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); assert_se(write_string_file("/a/file/which/does/not/exists/i/guess", "boohoo", 0) < 0); @@ -390,7 +390,7 @@ static void test_load_env_file_pairs(void) { _cleanup_strv_free_ char **l = NULL; char **k, **v; - fd = mkostemp_safe(fn, O_RDWR); + fd = mkostemp_safe(fn); assert_se(fd >= 0); r = write_string_file(fn, @@ -433,7 +433,7 @@ static void test_search_and_fopen(void) { int r; FILE *f; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); close(fd); @@ -469,7 +469,7 @@ static void test_search_and_fopen_nulstr(void) { int r; FILE *f; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); close(fd); @@ -504,7 +504,7 @@ static void test_writing_tmpfile(void) { IOVEC_SET_STRING(iov[1], ALPHANUMERICAL "\n"); IOVEC_SET_STRING(iov[2], ""); - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); printf("tmpfile: %s", name); r = writev(fd, iov, 3); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index b3c4a2a2eb..b35a2ea2c8 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -34,7 +34,7 @@ static void test_unlink_noerrno(void) { char name[] = "/tmp/test-close_nointr.XXXXXX"; int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(close_nointr(fd) >= 0); diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c index 227d4290f0..9eea3eb608 100644 --- a/src/test/test-glob-util.c +++ b/src/test/test-glob-util.c @@ -30,7 +30,7 @@ static void test_glob_exists(void) { int fd = -1; int r; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); close(fd); diff --git a/src/test/test-hostname-util.c b/src/test/test-hostname-util.c index 1c3d13ed1d..d2c3ea5e0d 100644 --- a/src/test/test-hostname-util.c +++ b/src/test/test-hostname-util.c @@ -104,7 +104,7 @@ static void test_read_hostname_config(void) { char *hostname; int fd; - fd = mkostemp_safe(path, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(path); assert(fd > 0); close(fd); diff --git a/src/test/test-path.c b/src/test/test-path.c index 62181e22a0..4d3f0e9948 100644 --- a/src/test/test-path.c +++ b/src/test/test-path.c @@ -47,7 +47,7 @@ static int setup_test(Manager **m) { r = manager_new(UNIT_FILE_USER, true, &tmp); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return -EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-sched-prio.c b/src/test/test-sched-prio.c index c068f5c39e..7b37910c33 100644 --- a/src/test/test-sched-prio.c +++ b/src/test/test-sched-prio.c @@ -40,7 +40,7 @@ int main(int argc, char *argv[]) { assert_se(set_unit_path(TEST_DIR) >= 0); r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return EXIT_TEST_SKIP; } assert_se(r >= 0); diff --git a/src/test/test-stat-util.c b/src/test/test-stat-util.c index a10227f823..6c34250a01 100644 --- a/src/test/test-stat-util.c +++ b/src/test/test-stat-util.c @@ -31,7 +31,7 @@ static void test_files_same(void) { char name[] = "/tmp/test-files_same.XXXXXX"; char name_alias[] = "/tmp/test-files_same.alias"; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(symlink(name, name_alias) >= 0); @@ -47,7 +47,7 @@ static void test_is_symlink(void) { char name_link[] = "/tmp/test-is_symlink.link"; _cleanup_close_ int fd = -1; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(symlink(name, name_link) >= 0); diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c index 84b448a095..373a1b70ba 100644 --- a/src/test/test-terminal-util.c +++ b/src/test/test-terminal-util.c @@ -50,7 +50,7 @@ static void test_read_one_char(void) { char name[] = "/tmp/test-read_one_char.XXXXXX"; int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); file = fdopen(fd, "r+"); assert_se(file); diff --git a/src/test/test-tmpfiles.c b/src/test/test-tmpfiles.c index b34ebeefb2..f35e6793b7 100644 --- a/src/test/test-tmpfiles.c +++ b/src/test/test-tmpfiles.c @@ -51,7 +51,7 @@ int main(int argc, char** argv) { log_debug("link1: %s", ans); assert_se(endswith(ans, " (deleted)")); - fd2 = mkostemp_safe(pattern, O_RDWR|O_CLOEXEC); + fd2 = mkostemp_safe(pattern); assert_se(fd >= 0); assert_se(unlink(pattern) == 0); diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c index ade0ff2a63..7ef087a2e3 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-unit-file.c @@ -56,12 +56,12 @@ static int test_unit_file_get_set(void) { r = unit_file_get_list(UNIT_FILE_SYSTEM, NULL, h, NULL, NULL); if (r == -EPERM || r == -EACCES) { - printf("Skipping test: unit_file_get_list: %s", strerror(-r)); + log_notice_errno(r, "Skipping test: unit_file_get_list: %m"); return EXIT_TEST_SKIP; } - log_full(r == 0 ? LOG_INFO : LOG_ERR, - "unit_file_get_list: %s", strerror(-r)); + log_full_errno(r == 0 ? LOG_INFO : LOG_ERR, r, + "unit_file_get_list: %m"); if (r < 0) return EXIT_FAILURE; @@ -117,7 +117,7 @@ static void test_config_parse_exec(void) { r = manager_new(UNIT_FILE_USER, true, &m); if (MANAGER_SKIP_TEST(r)) { - printf("Skipping test: manager_new: %s\n", strerror(-r)); + log_notice_errno(r, "Skipping test: manager_new: %m"); return; } @@ -485,7 +485,7 @@ static void test_load_env_file_1(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_1, sizeof(env_file_1)) == sizeof(env_file_1)); @@ -508,7 +508,7 @@ static void test_load_env_file_2(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_2, sizeof(env_file_2)) == sizeof(env_file_2)); @@ -526,7 +526,7 @@ static void test_load_env_file_3(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_3, sizeof(env_file_3)) == sizeof(env_file_3)); @@ -542,7 +542,7 @@ static void test_load_env_file_4(void) { _cleanup_close_ int fd; int r; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_4, sizeof(env_file_4)) == sizeof(env_file_4)); @@ -562,7 +562,7 @@ static void test_load_env_file_5(void) { char name[] = "/tmp/test-load-env-file.XXXXXX"; _cleanup_close_ int fd; - fd = mkostemp_safe(name, O_RDWR|O_CLOEXEC); + fd = mkostemp_safe(name); assert_se(fd >= 0); assert_se(write(fd, env_file_5, sizeof(env_file_5)) == sizeof(env_file_5)); diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index eedd94e777..ece9248c2a 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -191,20 +191,12 @@ static int load_link(link_config_ctx *ctx, const char *filename) { } static bool enable_name_policy(void) { - _cleanup_free_ char *line = NULL; - const char *word, *state; + _cleanup_free_ char *value = NULL; int r; - size_t l; - r = proc_cmdline(&line); - if (r < 0) { - log_warning_errno(r, "Failed to read /proc/cmdline, ignoring: %m"); - return true; - } - - FOREACH_WORD_QUOTED(word, l, line, state) - if (strneq(word, "net.ifnames=0", l)) - return false; + r = get_proc_cmdline_key("net.ifnames=", &value); + if (r > 0 && streq(value, "0")) + return false; return true; } diff --git a/src/update-done/update-done.c b/src/update-done/update-done.c index da306a4444..5cc5abfddf 100644 --- a/src/update-done/update-done.c +++ b/src/update-done/update-done.c @@ -23,67 +23,57 @@ #include "util.h" #define MESSAGE \ - "This file was created by systemd-update-done. Its only \n" \ - "purpose is to hold a timestamp of the time this directory\n" \ - "was updated. See systemd-update-done.service(8).\n" + "# This file was created by systemd-update-done. Its only \n" \ + "# purpose is to hold a timestamp of the time this directory\n" \ + "# was updated. See systemd-update-done.service(8).\n" static int apply_timestamp(const char *path, struct timespec *ts) { struct timespec twice[2] = { *ts, *ts }; - struct stat st; + int fd = -1; + _cleanup_fclose_ FILE *f = NULL; + int r; assert(path); assert(ts); - if (stat(path, &st) >= 0) { - /* Is the timestamp file already newer than the OS? If - * so, there's nothing to do. We ignore the nanosecond - * component of the timestamp, since some file systems - * do not support any better accuracy than 1s and we - * have no way to identify the accuracy - * available. Most notably ext4 on small disks (where - * 128 byte inodes are used) does not support better - * accuracy than 1s. */ - if (st.st_mtim.tv_sec > ts->tv_sec) - return 0; - - /* It is older? Then let's update it */ - if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) { - - if (errno == EROFS) - return log_debug("Can't update timestamp file %s, file system is read-only.", path); + /* + * We store the timestamp both as mtime of the file and in the file itself, + * to support filesystems which cannot store nanosecond-precision timestamps. + * Hence, don't bother updating the file, let's just rewrite it. + */ - return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); - } + r = mac_selinux_create_file_prepare(path, S_IFREG); + if (r < 0) + return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); - } else if (errno == ENOENT) { - _cleanup_close_ int fd = -1; - int r; + fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); + mac_selinux_create_file_clear(); - /* The timestamp file doesn't exist yet? Then let's create it. */ + if (fd < 0) { + if (errno == EROFS) + return log_debug("Can't create timestamp file %s, file system is read-only.", path); - r = mac_selinux_create_file_prepare(path, S_IFREG); - if (r < 0) - return log_error_errno(r, "Failed to set SELinux context for %s: %m", path); - - fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644); - mac_selinux_create_file_clear(); + return log_error_errno(errno, "Failed to create/open timestamp file %s: %m", path); + } - if (fd < 0) { - if (errno == EROFS) - return log_debug("Can't create timestamp file %s, file system is read-only.", path); + f = fdopen(fd, "w"); + if (!f) { + safe_close(fd); + return log_error_errno(errno, "Failed to fdopen() timestamp file %s: %m", path); + } - return log_error_errno(errno, "Failed to create timestamp file %s: %m", path); - } + (void) fprintf(f, + "%s" + "TimestampNSec=" NSEC_FMT "\n", + MESSAGE, timespec_load_nsec(ts)); - (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false); + fflush(f); - if (futimens(fd, twice) < 0) - return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); - } else - log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path); + if (futimens(fd, twice) < 0) + return log_error_errno(errno, "Failed to update timestamp on %s: %m", path); return 0; } |