#include "fileio.h"
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
+
assert(f);
assert(line);
- errno = 0;
-
fputs(line, f);
if (enforce_newline && !endswith(line, "\n"))
fputc('\n', f);
- fflush(f);
-
- if (ferror(f))
- return errno ? -errno : -EIO;
-
- return 0;
+ return fflush_and_check(f);
}
static int write_string_file_atomic(const char *fn, const char *line, bool enforce_newline) {
/**
* Retrieve one field from a file like /proc/self/status. pattern
- * should start with '\n' and end with a ':'. Whitespace and zeros
- * after the ':' will be skipped. field must be freed afterwards.
+ * should not include whitespace or the delimiter (':'). pattern matches only
+ * the beginning of a line. Whitespace before ':' is skipped. Whitespace and
+ * zeros after the ':' will be skipped. field must be freed afterwards.
+ * terminator specifies the terminating characters of the field value (not
+ * included in the value).
*/
-int get_status_field(const char *filename, const char *pattern, char **field) {
+int get_proc_field(const char *filename, const char *pattern, const char *terminator, char **field) {
_cleanup_free_ char *status = NULL;
- char *t;
+ char *t, *f;
size_t len;
int r;
+ assert(terminator);
assert(filename);
assert(pattern);
assert(field);
if (r < 0)
return r;
- t = strstr(status, pattern);
+ t = status;
+
+ do {
+ bool pattern_ok;
+
+ do {
+ t = strstr(t, pattern);
if (!t)
return -ENOENT;
+ /* Check that pattern occurs in beginning of line. */
+ pattern_ok = (t == status || t[-1] == '\n');
+
t += strlen(pattern);
+
+ } while (!pattern_ok);
+
+ t += strspn(t, " \t");
+ if (!*t)
+ return -ENOENT;
+
+ } while (*t != ':');
+
+ t++;
+
if (*t) {
t += strspn(t, " \t");
t --;
}
- len = strcspn(t, WHITESPACE);
+ len = strcspn(t, terminator);
- *field = strndup(t, len);
- if (!*field)
+ f = strndup(t, len);
+ if (!f)
return -ENOMEM;
+ *field = f;
return 0;
}