diff --git a/src/basic/fileio.c b/src/basic/fileio.c index ef27c3f913..fe0c4f4707 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -136,16 +136,21 @@ static int write_string_file_atomic( assert(fn); assert(line); + /* Note that we'd really like to use O_TMPFILE here, but can't really, since we want replacement + * semantics here, and O_TMPFILE can't offer that. i.e. rename() replaces but linkat() doesn't. */ + r = fopen_temporary(fn, &f, &p); if (r < 0) return r; - (void) fchmod_umask(fileno(f), 0644); - r = write_string_stream_ts(f, line, flags, ts); if (r < 0) goto fail; + r = fchmod_umask(fileno(f), FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0644); + if (r < 0) + goto fail; + if (rename(p, fn) < 0) { r = -errno; goto fail; @@ -165,7 +170,7 @@ int write_string_file_ts( struct timespec *ts) { _cleanup_fclose_ FILE *f = NULL; - int q, r; + int q, r, fd; assert(fn); assert(line); @@ -190,26 +195,20 @@ int write_string_file_ts( } else assert(!ts); - if (flags & WRITE_STRING_FILE_CREATE) { - r = fopen_unlocked(fn, "we", &f); - if (r < 0) - goto fail; - } else { - int fd; + /* We manually build our own version of fopen(..., "we") that works without O_CREAT and with O_NOFOLLOW if needed. */ + fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY | + (FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) | + (FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0), + (FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0666)); + if (fd < 0) { + r = -errno; + goto fail; + } - /* We manually build our own version of fopen(..., "we") that - * works without O_CREAT */ - fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY | ((flags & WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0)); - if (fd < 0) { - r = -errno; - goto fail; - } - - r = fdopen_unlocked(fd, "w", &f); - if (r < 0) { - safe_close(fd); - goto fail; - } + r = fdopen_unlocked(fd, "w", &f); + if (r < 0) { + safe_close(fd); + goto fail; } if (flags & WRITE_STRING_FILE_DISABLE_BUFFER) diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 209a06f826..e6fea2afd4 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -23,6 +23,7 @@ typedef enum { WRITE_STRING_FILE_DISABLE_BUFFER = 1 << 5, WRITE_STRING_FILE_NOFOLLOW = 1 << 6, WRITE_STRING_FILE_MKDIR_0755 = 1 << 7, + WRITE_STRING_FILE_MODE_0600 = 1 << 8, /* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()