mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
Merge pull request #6894 from poettering/read-full-file-optimize
fileio: various fixes
This commit is contained in:
commit
b6e386ca1c
@ -52,13 +52,17 @@
|
||||
|
||||
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
|
||||
|
||||
int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts) {
|
||||
int write_string_stream_ts(
|
||||
FILE *f,
|
||||
const char *line,
|
||||
WriteStringFileFlags flags,
|
||||
struct timespec *ts) {
|
||||
|
||||
assert(f);
|
||||
assert(line);
|
||||
|
||||
fputs(line, f);
|
||||
if (enforce_newline && !endswith(line, "\n"))
|
||||
if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"))
|
||||
fputc('\n', f);
|
||||
|
||||
if (ts) {
|
||||
@ -68,10 +72,18 @@ int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, stru
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return fflush_and_check(f);
|
||||
if (flags & WRITE_STRING_FILE_SYNC)
|
||||
return fflush_sync_and_check(f);
|
||||
else
|
||||
return fflush_and_check(f);
|
||||
}
|
||||
|
||||
static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline, bool do_fsync) {
|
||||
static int write_string_file_atomic(
|
||||
const char *fn,
|
||||
const char *line,
|
||||
WriteStringFileFlags flags,
|
||||
struct timespec *ts) {
|
||||
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
@ -85,22 +97,28 @@ static int write_string_file_atomic(const char *fn, const char *line, bool enfor
|
||||
|
||||
(void) fchmod_umask(fileno(f), 0644);
|
||||
|
||||
r = write_string_stream(f, line, enforce_newline);
|
||||
if (r >= 0 && do_fsync)
|
||||
r = fflush_sync_and_check(f);
|
||||
r = write_string_stream_ts(f, line, flags, ts);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (r >= 0) {
|
||||
if (rename(p, fn) < 0)
|
||||
r = -errno;
|
||||
if (rename(p, fn) < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
(void) unlink(p);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
(void) unlink(p);
|
||||
return r;
|
||||
}
|
||||
|
||||
int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts) {
|
||||
int write_string_file_ts(
|
||||
const char *fn,
|
||||
const char *line,
|
||||
WriteStringFileFlags flags,
|
||||
struct timespec *ts) {
|
||||
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int q, r;
|
||||
|
||||
@ -113,8 +131,7 @@ int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags
|
||||
if (flags & WRITE_STRING_FILE_ATOMIC) {
|
||||
assert(flags & WRITE_STRING_FILE_CREATE);
|
||||
|
||||
r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE),
|
||||
flags & WRITE_STRING_FILE_SYNC);
|
||||
r = write_string_file_atomic(fn, line, flags, ts);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@ -147,16 +164,10 @@ int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags
|
||||
}
|
||||
}
|
||||
|
||||
r = write_string_stream_ts(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE), ts);
|
||||
r = write_string_stream_ts(f, line, flags, ts);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (flags & WRITE_STRING_FILE_SYNC) {
|
||||
r = fflush_sync_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -259,11 +270,11 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
|
||||
if (st.st_size > READ_FULL_BYTES_MAX)
|
||||
return -E2BIG;
|
||||
|
||||
/* Start with the right file size, but be prepared for
|
||||
* files from /proc which generally report a file size
|
||||
* of 0 */
|
||||
/* Start with the right file size, but be prepared for files from /proc which generally report a file
|
||||
* size of 0. Note that we increase the size to read here by one, so that the first read attempt
|
||||
* already makes us notice the EOF. */
|
||||
if (st.st_size > 0)
|
||||
n = st.st_size;
|
||||
n = st.st_size + 1;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
@ -276,12 +287,13 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
|
||||
return -ENOMEM;
|
||||
|
||||
buf = t;
|
||||
errno = 0;
|
||||
k = fread(buf + l, 1, n - l, f);
|
||||
if (k > 0)
|
||||
l += k;
|
||||
|
||||
if (ferror(f))
|
||||
return -errno;
|
||||
return errno > 0 ? -errno : -EIO;
|
||||
|
||||
if (feof(f))
|
||||
break;
|
||||
|
@ -36,9 +36,9 @@ typedef enum {
|
||||
WRITE_STRING_FILE_SYNC = 1<<4,
|
||||
} WriteStringFileFlags;
|
||||
|
||||
int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts);
|
||||
static inline int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
|
||||
return write_string_stream_ts(f, line, enforce_newline, NULL);
|
||||
int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
|
||||
static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
|
||||
return write_string_stream_ts(f, line, flags, NULL);
|
||||
}
|
||||
int write_string_file_ts(const char *fn, const char *line, WriteStringFileFlags flags, struct timespec *ts);
|
||||
static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
|
||||
|
@ -66,7 +66,7 @@ static int write_state(FILE **f, char **states) {
|
||||
STRV_FOREACH(state, states) {
|
||||
int k;
|
||||
|
||||
k = write_string_stream(*f, *state, true);
|
||||
k = write_string_stream(*f, *state, 0);
|
||||
if (k == 0)
|
||||
return 0;
|
||||
log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
|
||||
|
@ -66,7 +66,7 @@ static void test_clock_is_localtime(void) {
|
||||
log_info("%s", scenarios[i].contents);
|
||||
rewind(f);
|
||||
ftruncate(fd, 0);
|
||||
assert_se(write_string_stream(f, scenarios[i].contents, false) == 0);
|
||||
assert_se(write_string_stream(f, scenarios[i].contents, WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
|
||||
assert_se(clock_is_localtime(adjtime) == scenarios[i].expected_result);
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ static void test_merge_env_file(void) {
|
||||
"zzz=${one:+replacement}\n"
|
||||
"zzzz=${foobar:-${nothing}}\n"
|
||||
"zzzzz=${nothing:+${nothing}}\n"
|
||||
, false);
|
||||
, WRITE_STRING_FILE_AVOID_NEWLINE);
|
||||
assert(r >= 0);
|
||||
|
||||
r = merge_env_file(&a, NULL, t);
|
||||
@ -302,7 +302,7 @@ static void test_merge_env_file_invalid(void) {
|
||||
";comment2=comment2\n"
|
||||
"#\n"
|
||||
"\n\n" /* empty line */
|
||||
, false);
|
||||
, WRITE_STRING_FILE_AVOID_NEWLINE);
|
||||
assert(r >= 0);
|
||||
|
||||
r = merge_env_file(&a, NULL, t);
|
||||
@ -414,12 +414,12 @@ static void test_write_string_stream(void) {
|
||||
|
||||
f = fdopen(fd, "r");
|
||||
assert_se(f);
|
||||
assert_se(write_string_stream(f, "boohoo", true) < 0);
|
||||
assert_se(write_string_stream(f, "boohoo", 0) < 0);
|
||||
|
||||
f = freopen(fn, "r+", f);
|
||||
assert_se(f);
|
||||
|
||||
assert_se(write_string_stream(f, "boohoo", true) == 0);
|
||||
assert_se(write_string_stream(f, "boohoo", 0) == 0);
|
||||
rewind(f);
|
||||
|
||||
assert_se(fgets(buf, sizeof(buf), f));
|
||||
@ -428,7 +428,7 @@ static void test_write_string_stream(void) {
|
||||
f = freopen(fn, "w+", f);
|
||||
assert_se(f);
|
||||
|
||||
assert_se(write_string_stream(f, "boohoo", false) == 0);
|
||||
assert_se(write_string_stream(f, "boohoo", WRITE_STRING_FILE_AVOID_NEWLINE) == 0);
|
||||
rewind(f);
|
||||
|
||||
assert_se(fgets(buf, sizeof(buf), f));
|
||||
|
Loading…
Reference in New Issue
Block a user