summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2017-09-24 14:27:21 +0200
committerSven Eden <yamakuzure@gmx.net>2017-11-22 08:22:23 +0100
commit68bb1246bf0dc56f61b6d655694ddd4df647167c (patch)
treed3ec4ecc37c903334f496981f12ead2973836c2f /src
parente0e02387f7dfc8ab4f415212264666476fc4a21f (diff)
fileio: return 0 from read_one_line_file on success
Fixup for f4b51a2d09. Suggested by Evgeny Vereshchagin.
Diffstat (limited to 'src')
-rw-r--r--src/basic/def.h2
-rw-r--r--src/basic/fileio.c160
-rw-r--r--src/basic/fileio.h4
-rw-r--r--src/basic/log.c2
-rw-r--r--src/libelogind/sd-event/test-event.c3
-rw-r--r--src/sleep/sleep.c2
-rw-r--r--src/test/meson.build20
-rw-r--r--src/test/test-cgroup.c3
-rw-r--r--src/test/test-log.c3
-rw-r--r--src/test/test-signal-util.c3
10 files changed, 130 insertions, 72 deletions
diff --git a/src/basic/def.h b/src/basic/def.h
index d30b4a106..1571f921b 100644
--- a/src/basic/def.h
+++ b/src/basic/def.h
@@ -96,3 +96,5 @@
"/usr/local/lib/" n "\0" \
"/usr/lib/" n "\0" \
_CONF_PATHS_SPLIT_USR(n)
+
+#define LONG_LINE_MAX (1U*1024U*1024U)
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 333effa5f..3990d4dce 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -30,6 +30,7 @@
#include "alloc-util.h"
#include "ctype.h"
+#include "def.h"
#include "env-util.h"
#include "escape.h"
#include "fd-util.h"
@@ -52,17 +53,13 @@
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
-int write_string_stream_ts(
- FILE *f,
- const char *line,
- WriteStringFileFlags flags,
- struct timespec *ts) {
+int write_string_stream_ts(FILE *f, const char *line, bool enforce_newline, struct timespec *ts) {
assert(f);
assert(line);
fputs(line, f);
- if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"))
+ if (enforce_newline && !endswith(line, "\n"))
fputc('\n', f);
if (ts) {
@@ -72,18 +69,10 @@ int write_string_stream_ts(
return -errno;
}
- if (flags & WRITE_STRING_FILE_SYNC)
- return fflush_sync_and_check(f);
- else
- return fflush_and_check(f);
+ return fflush_and_check(f);
}
-static int write_string_file_atomic(
- const char *fn,
- const char *line,
- WriteStringFileFlags flags,
- struct timespec *ts) {
-
+static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline, bool do_fsync) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
int r;
@@ -97,28 +86,22 @@ static int write_string_file_atomic(
(void) fchmod_umask(fileno(f), 0644);
- r = write_string_stream_ts(f, line, flags, ts);
- if (r < 0)
- goto fail;
+ r = write_string_stream(f, line, enforce_newline);
+ if (r >= 0 && do_fsync)
+ r = fflush_sync_and_check(f);
- if (rename(p, fn) < 0) {
- r = -errno;
- goto fail;
+ if (r >= 0) {
+ if (rename(p, fn) < 0)
+ r = -errno;
}
- return 0;
+ if (r < 0)
+ (void) unlink(p);
-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;
@@ -131,7 +114,8 @@ int write_string_file_ts(
if (flags & WRITE_STRING_FILE_ATOMIC) {
assert(flags & WRITE_STRING_FILE_CREATE);
- r = write_string_file_atomic(fn, line, flags, ts);
+ r = write_string_file_atomic(fn, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE),
+ flags & WRITE_STRING_FILE_SYNC);
if (r < 0)
goto fail;
@@ -164,10 +148,16 @@ int write_string_file_ts(
}
}
- r = write_string_stream_ts(f, line, flags, ts);
+ r = write_string_stream_ts(f, line, !(flags & WRITE_STRING_FILE_AVOID_NEWLINE), 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:
@@ -188,7 +178,7 @@ fail:
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
- char t[LINE_MAX], *c;
+ int r;
assert(fn);
assert(line);
@@ -197,21 +187,8 @@ int read_one_line_file(const char *fn, char **line) {
if (!f)
return -errno;
- if (!fgets(t, sizeof(t), f)) {
-
- if (ferror(f))
- return errno > 0 ? -errno : -EIO;
-
- t[0] = 0;
- }
-
- c = strdup(t);
- if (!c)
- return -ENOMEM;
- truncate_nl(c);
-
- *line = c;
- return 0;
+ r = read_line(f, LONG_LINE_MAX, line);
+ return r < 0 ? r : 0;
}
int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
@@ -270,11 +247,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. Note that we increase the size to read here by one, so that the first read attempt
- * already makes us notice the EOF. */
+ /* Start with the right file size, but be prepared for
+ * files from /proc which generally report a file size
+ * of 0 */
if (st.st_size > 0)
- n = st.st_size + 1;
+ n = st.st_size;
}
l = 0;
@@ -287,13 +264,12 @@ 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 > 0 ? -errno : -EIO;
+ return -errno;
if (feof(f))
break;
@@ -1550,3 +1526,77 @@ int mkdtemp_malloc(const char *template, char **ret) {
return 0;
}
#endif // 0
+
+static inline void funlockfilep(FILE **f) {
+ funlockfile(*f);
+}
+
+int read_line(FILE *f, size_t limit, char **ret) {
+ _cleanup_free_ char *buffer = NULL;
+ size_t n = 0, allocated = 0, count = 0;
+
+ assert(f);
+
+ /* Something like a bounded version of getline().
+ *
+ * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
+ * returned.
+ *
+ * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
+ * the number of characters in the returned string). When EOF is hit, 0 is returned.
+ *
+ * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
+ * delimiters. If the limit is hit we fail and return -ENOBUFS.
+ *
+ * If a line shall be skipped ret may be initialized as NULL. */
+
+ if (ret) {
+ if (!GREEDY_REALLOC(buffer, allocated, 1))
+ return -ENOMEM;
+ }
+
+ {
+ _cleanup_(funlockfilep) FILE *flocked = f;
+ flockfile(f);
+
+ for (;;) {
+ int c;
+
+ if (n >= limit)
+ return -ENOBUFS;
+
+ errno = 0;
+ c = fgetc_unlocked(f);
+ if (c == EOF) {
+ /* if we read an error, and have no data to return, then propagate the error */
+ if (ferror_unlocked(f) && n == 0)
+ return errno > 0 ? -errno : -EIO;
+
+ break;
+ }
+
+ count++;
+
+ if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
+ break;
+
+ if (ret) {
+ if (!GREEDY_REALLOC(buffer, allocated, n + 2))
+ return -ENOMEM;
+
+ buffer[n] = (char) c;
+ }
+
+ n++;
+ }
+ }
+
+ if (ret) {
+ buffer[n] = 0;
+
+ *ret = buffer;
+ buffer = NULL;
+ }
+
+ return (int) count;
+}
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index a56887555..1160c5849 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -36,7 +36,7 @@ typedef enum {
WRITE_STRING_FILE_SYNC = 1<<4,
} WriteStringFileFlags;
-int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts);
+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, WriteStringFileFlags flags) {
return write_string_stream_ts(f, line, flags, NULL);
}
@@ -113,3 +113,5 @@ int read_nul_string(FILE *f, char **ret);
int mkdtemp_malloc(const char *template, char **ret);
#endif // 0
+
+int read_line(FILE *f, size_t limit, char **ret);
diff --git a/src/basic/log.c b/src/basic/log.c
index c02a73a94..21f37c36e 100644
--- a/src/basic/log.c
+++ b/src/basic/log.c
@@ -494,7 +494,6 @@ static int write_to_kmsg(
return 1;
}
-#if 0 /// UNNEEDED by elogind
static int log_do_header(
char *header,
size_t size,
@@ -539,6 +538,7 @@ static int log_do_header(
return 0;
}
+#if 0 /// UNNEEDED by elogind
static int write_to_journal(
int level,
int error,
diff --git a/src/libelogind/sd-event/test-event.c b/src/libelogind/sd-event/test-event.c
index 656f08d56..d57f5fa8c 100644
--- a/src/libelogind/sd-event/test-event.c
+++ b/src/libelogind/sd-event/test-event.c
@@ -24,9 +24,10 @@
#include "fd-util.h"
#include "log.h"
#include "macro.h"
-#include "process-util.h"
#include "signal-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
static int prepare_handler(sd_event_source *s, void *userdata) {
log_info("preparing %c", PTR_TO_INT(userdata));
diff --git a/src/sleep/sleep.c b/src/sleep/sleep.c
index c6dd13197..01fa22349 100644
--- a/src/sleep/sleep.c
+++ b/src/sleep/sleep.c
@@ -69,7 +69,7 @@ static int write_state(FILE **f, char **states) {
STRV_FOREACH(state, states) {
int k;
- k = write_string_stream(*f, *state, 0);
+ k = write_string_stream(*f, *state, true);
if (k == 0)
return 0;
log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
diff --git a/src/test/meson.build b/src/test/meson.build
index 6059c2efd..c811dd675 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -365,16 +365,16 @@ tests += [
[libbasic],
[]],
- [['src/test/test-bpf.c',
- 'src/test/test-helper.c'],
- [libcore,
- libshared],
- [libmount,
- threads,
- librt,
- libseccomp,
- libselinux,
- libblkid]],
+# [['src/test/test-bpf.c',
+# 'src/test/test-helper.c'],
+# [libcore,
+# libshared],
+# [libmount,
+# threads,
+# librt,
+# libseccomp,
+# libselinux,
+# libblkid]],
[['src/test/test-hashmap.c',
'src/test/test-hashmap-plain.c',
diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c
index 2ed91c780..509946250 100644
--- a/src/test/test-cgroup.c
+++ b/src/test/test-cgroup.c
@@ -22,9 +22,10 @@
#include "cgroup-util.h"
#include "path-util.h"
-#include "process-util.h"
#include "string-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
int main(int argc, char*argv[]) {
char *path;
diff --git a/src/test/test-log.c b/src/test/test-log.c
index ec1bc2a63..2417b3aef 100644
--- a/src/test/test-log.c
+++ b/src/test/test-log.c
@@ -22,8 +22,9 @@
#include "format-util.h"
#include "log.h"
-#include "process-util.h"
#include "util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
assert_cc(LOG_REALM_REMOVE_LEVEL(LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, LOG_FTP | LOG_DEBUG))
== LOG_REALM_SYSTEMD);
diff --git a/src/test/test-signal-util.c b/src/test/test-signal-util.c
index 1830396ac..0db8a1e32 100644
--- a/src/test/test-signal-util.c
+++ b/src/test/test-signal-util.c
@@ -21,8 +21,9 @@
#include <unistd.h>
#include "macro.h"
-#include "process-util.h"
#include "signal-util.h"
+/// Additional includes needed by elogind
+#include "process-util.h"
static void test_block_signals(void) {
sigset_t ss;