summaryrefslogtreecommitdiff
path: root/src/basic/fileio.c
diff options
context:
space:
mode:
authorAaro Koskinen <aaro.koskinen@nokia.com>2015-09-30 15:57:55 +0300
committerAaro Koskinen <aaro.koskinen@nokia.com>2015-09-30 15:57:55 +0300
commitc4cd1d4d93e4a45a088edb6517555aa7e06e5f86 (patch)
tree4529a045943ee56bf1e96a6d2820318f36e5473d /src/basic/fileio.c
parent5e6ad75f259942c33bbb0b9bfc1e8dd5cc0d96e7 (diff)
fileio: make get_status_field() more generic
All users of get_status_field() expect the field pattern to occur in the beginning of a line, and the delimiter is ':'. Hardcode this into the function, and also skip any whitespace before ':' to support fields in files like /proc/cpuinfo. Add support for returning the full field value (currently stops on first whitespace). Rename the function so it's easier to ensure all callers switch to new semantics.
Diffstat (limited to 'src/basic/fileio.c')
-rw-r--r--src/basic/fileio.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 4a9105f421..13a85e1158 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -775,15 +775,19 @@ int executable_is_script(const char *path, char **interpreter) {
/**
* 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, *f;
size_t len;
int r;
+ assert(terminator);
assert(filename);
assert(pattern);
assert(field);
@@ -792,11 +796,31 @@ int get_status_field(const char *filename, const char *pattern, char **field) {
if (r < 0)
return r;
- t = strstr(status, pattern);
- if (!t)
- return -ENOENT;
+ 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++;
- t += strlen(pattern);
if (*t) {
t += strspn(t, " \t");
@@ -812,7 +836,7 @@ int get_status_field(const char *filename, const char *pattern, char **field) {
t --;
}
- len = strcspn(t, WHITESPACE);
+ len = strcspn(t, terminator);
f = strndup(t, len);
if (!f)