]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fileio: make get_status_field() more generic
authorAaro Koskinen <aaro.koskinen@nokia.com>
Wed, 30 Sep 2015 12:57:55 +0000 (15:57 +0300)
committerAaro Koskinen <aaro.koskinen@nokia.com>
Wed, 30 Sep 2015 12:57:55 +0000 (15:57 +0300)
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.

src/basic/fileio.c
src/basic/fileio.h
src/basic/process-util.c
src/basic/virt.c
src/shared/sleep-config.c
src/test/test-fileio.c

index 4a9105f421d3449ed120729d95621f55c6562cb4..13a85e11583e88b28f82cafb92d4745999d47f72 100644 (file)
@@ -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)
index 2e8148ff2424563bcfc60856a7591bde502601d8..4998d4d04232e31acaa7f4ef0a90fcd7a94df7c8 100644 (file)
@@ -48,4 +48,4 @@ int write_env_file(const char *fname, char **l);
 
 int executable_is_script(const char *path, char **interpreter);
 
-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);
index cff2d2a0348c091c0d33618f3c7a1561c71ea253..d8a94a457286c49cc0f0b6b02f4b875ae7726408 100644 (file)
@@ -215,7 +215,7 @@ int get_process_capeff(pid_t pid, char **capeff) {
 
         p = procfs_file_alloca(pid, "status");
 
-        r = get_status_field(p, "\nCapEff:", capeff);
+        r = get_proc_field(p, "CapEff", WHITESPACE, capeff);
         if (r == -ENOENT)
                 return -ESRCH;
 
index 1fc6c1babad643f2472bb9329a61d36d8576ba18..70543177b6fe1f9910635c2df312a879497676cd 100644 (file)
@@ -240,7 +240,7 @@ static int detect_vm_zvm(void) {
         _cleanup_free_ char *t = NULL;
         int r;
 
-        r = get_status_field("/proc/sysinfo", "VM00 Control Program:", &t);
+        r = get_proc_field("/proc/sysinfo", "VM00 Control Program", WHITESPACE, &t);
         if (r == -ENOENT)
                 return VIRTUALIZATION_NONE;
         if (r < 0)
index 1064fd5cbd3f73800bcd106df6fd4b82ac47cdf0..3dedbd1f6269db89a72569a466b9ce7a4296300d 100644 (file)
@@ -226,7 +226,7 @@ static bool enough_memory_for_hibernation(void) {
         if (r < 0)
                 return false;
 
-        r = get_status_field("/proc/meminfo", "\nActive(anon):", &active);
+        r = get_proc_field("/proc/meminfo", "Active(anon)", WHITESPACE, &active);
         if (r < 0) {
                 log_error_errno(r, "Failed to retrieve Active(anon) from /proc/meminfo: %m");
                 return false;
index be3a87958f9f426e5dcabc4d57750af527ee88c4..ad547822e7d83080d42d6d19d285ec282d6de46c 100644 (file)
@@ -241,18 +241,18 @@ static void test_status_field(void) {
         unsigned long long total = 0, buffers = 0;
         int r;
 
-        assert_se(get_status_field("/proc/self/status", "\nThreads:", &t) == 0);
+        assert_se(get_proc_field("/proc/self/status", "Threads", WHITESPACE, &t) == 0);
         puts(t);
         assert_se(streq(t, "1"));
 
-        r = get_status_field("/proc/meminfo", "MemTotal:", &p);
+        r = get_proc_field("/proc/meminfo", "MemTotal", WHITESPACE, &p);
         if (r != -ENOENT) {
                 assert_se(r == 0);
                 puts(p);
                 assert_se(safe_atollu(p, &total) == 0);
         }
 
-        r = get_status_field("/proc/meminfo", "\nBuffers:", &s);
+        r = get_proc_field("/proc/meminfo", "Buffers", WHITESPACE, &s);
         if (r != -ENOENT) {
                 assert_se(r == 0);
                 puts(s);
@@ -263,7 +263,7 @@ static void test_status_field(void) {
                 assert_se(buffers < total);
 
         /* Seccomp should be a good test for field full of zeros. */
-        r = get_status_field("/proc/meminfo", "\nSeccomp:", &z);
+        r = get_proc_field("/proc/meminfo", "Seccomp", WHITESPACE, &z);
         if (r != -ENOENT) {
                 assert_se(r == 0);
                 puts(z);