X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Ffileio.c;h=82b40aa7daf93532dfb5d5d8f43b087d9ee66218;hb=ce5792dac67c5ae5656f1f9665b777d44af4cb35;hp=cbb40c237998438fac7ef27234bcb134866c44dc;hpb=0ce5a80601597fe4d1a715a8f70ce8d5ccaa2d86;p=elogind.git diff --git a/src/shared/fileio.c b/src/shared/fileio.c index cbb40c237..82b40aa7d 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -20,21 +20,21 @@ ***/ #include -#include -#include "fileio.h" + #include "util.h" #include "strv.h" #include "utf8.h" #include "ctype.h" +#include "fileio.h" -int write_string_stream(FILE *f, const char *line) { +int write_string_stream(FILE *f, const char *line, bool enforce_newline) { assert(f); assert(line); errno = 0; fputs(line, f); - if (!endswith(line, "\n")) + if (enforce_newline && !endswith(line, "\n")) fputc('\n', f); fflush(f); @@ -55,7 +55,29 @@ int write_string_file(const char *fn, const char *line) { if (!f) return -errno; - return write_string_stream(f, line); + return write_string_stream(f, line, true); +} + +int write_string_file_no_create(const char *fn, const char *line) { + _cleanup_fclose_ FILE *f = NULL; + int fd; + + assert(fn); + assert(line); + + /* We manually build our own version of fopen(..., "we") that + * works without O_CREAT */ + fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return -errno; + + f = fdopen(fd, "we"); + if (!f) { + safe_close(fd); + return -errno; + } + + return write_string_stream(f, line, true); } int write_string_file_atomic(const char *fn, const char *line) { @@ -72,20 +94,10 @@ int write_string_file_atomic(const char *fn, const char *line) { fchmod_umask(fileno(f), 0644); - errno = 0; - fputs(line, f); - if (!endswith(line, "\n")) - fputc('\n', f); - - fflush(f); - - if (ferror(f)) - r = errno ? -errno : -EIO; - else { + r = write_string_stream(f, line, true); + if (r >= 0) { if (rename(p, fn) < 0) r = -errno; - else - r = 0; } if (r < 0) @@ -122,75 +134,15 @@ int read_one_line_file(const char *fn, char **line) { return 0; } -ssize_t sendfile_full(int out_fd, const char *fn) { - _cleanup_fclose_ FILE *f; - struct stat st; +int verify_one_line_file(const char *fn, const char *line) { + _cleanup_free_ char *value = NULL; int r; - ssize_t s; - - size_t n, l; - _cleanup_free_ char *buf = NULL; - - assert(out_fd > 0); - assert(fn); - - f = fopen(fn, "re"); - if (!f) - return -errno; - - r = fstat(fileno(f), &st); - if (r < 0) - return -errno; - - s = sendfile(out_fd, fileno(f), NULL, st.st_size); - if (s < 0) - if (errno == EINVAL || errno == ENOSYS) { - /* continue below */ - } else - return -errno; - else - return s; - - /* sendfile() failed, fall back to read/write */ - - /* Safety check */ - if (st.st_size > 4*1024*1024) - return -E2BIG; - - n = st.st_size > 0 ? st.st_size : LINE_MAX; - l = 0; - while (true) { - char *t; - size_t k; - - t = realloc(buf, n); - if (!t) - return -ENOMEM; - - buf = t; - k = fread(buf + l, 1, n - l, f); - - if (k <= 0) { - if (ferror(f)) - return -errno; - - break; - } - - l += k; - n *= 2; - - /* Safety check */ - if (n > 4*1024*1024) - return -E2BIG; - } - - r = write(out_fd, buf, l); + r = read_one_line_file(fn, &value); if (r < 0) - return -errno; + return r; - return (ssize_t) l; + return streq(value, line); } int read_full_stream(FILE *f, char **contents, size_t *size) { @@ -274,8 +226,9 @@ static int parse_env_file_internal( const char *fname, const char *newline, int (*push) (const char *filename, unsigned line, - const char *key, char *value, void *userdata), - void *userdata) { + const char *key, char *value, void *userdata, int *n_pushed), + void *userdata, + int *n_pushed) { _cleanup_free_ char *contents = NULL, *key = NULL; size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1; @@ -364,7 +317,7 @@ static int parse_env_file_internal( if (last_key_whitespace != (size_t) -1) key[last_key_whitespace] = 0; - r = push(fname, line, key, value, userdata); + r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) goto fail; @@ -409,7 +362,7 @@ static int parse_env_file_internal( if (last_key_whitespace != (size_t) -1) key[last_key_whitespace] = 0; - r = push(fname, line, key, value, userdata); + r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) goto fail; @@ -544,7 +497,7 @@ static int parse_env_file_internal( if (last_key_whitespace != (size_t) -1) key[last_key_whitespace] = 0; - r = push(fname, line, key, value, userdata); + r = push(fname, line, key, value, userdata, n_pushed); if (r < 0) goto fail; } @@ -559,7 +512,8 @@ fail: static int parse_env_file_push( const char *filename, unsigned line, const char *key, char *value, - void *userdata) { + void *userdata, + int *n_pushed) { const char *k; va_list aq, *ap = userdata; @@ -591,6 +545,10 @@ static int parse_env_file_push( va_end(aq); free(*v); *v = value; + + if (n_pushed) + (*n_pushed)++; + return 1; } } @@ -606,22 +564,23 @@ int parse_env_file( const char *newline, ...) { va_list ap; - int r; + int r, n_pushed = 0; if (!newline) newline = NEWLINE; va_start(ap, newline); - r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap); + r = parse_env_file_internal(NULL, fname, newline, parse_env_file_push, &ap, &n_pushed); va_end(ap); - return r; + return r < 0 ? r : n_pushed; } static int load_env_file_push( const char *filename, unsigned line, const char *key, char *value, - void *userdata) { + void *userdata, + int *n_pushed) { char ***m = userdata; char *p; int r; @@ -648,6 +607,9 @@ static int load_env_file_push( if (r < 0) return r; + if (n_pushed) + (*n_pushed)++; + free(value); return 0; } @@ -659,7 +621,7 @@ int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) { if (!newline) newline = NEWLINE; - r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m); + r = parse_env_file_internal(f, fname, newline, load_env_file_push, &m, NULL); if (r < 0) { strv_free(m); return r; @@ -672,7 +634,8 @@ int load_env_file(FILE *f, const char *fname, const char *newline, char ***rl) { static int load_env_file_push_pairs( const char *filename, unsigned line, const char *key, char *value, - void *userdata) { + void *userdata, + int *n_pushed) { char ***m = userdata; int r; @@ -704,6 +667,9 @@ static int load_env_file_push_pairs( return r; } + if (n_pushed) + (*n_pushed)++; + return 0; } @@ -714,7 +680,7 @@ int load_env_file_pairs(FILE *f, const char *fname, const char *newline, char ** if (!newline) newline = NEWLINE; - r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m); + r = parse_env_file_internal(f, fname, newline, load_env_file_push_pairs, &m, NULL); if (r < 0) { strv_free(m); return r;