From c4cd1d4d93e4a45a088edb6517555aa7e06e5f86 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 30 Sep 2015 15:57:55 +0300 Subject: 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. --- src/basic/fileio.c | 40 ++++++++++++++++++++++++++++++++-------- src/basic/fileio.h | 2 +- src/basic/process-util.c | 2 +- src/basic/virt.c | 2 +- src/shared/sleep-config.c | 2 +- src/test/test-fileio.c | 8 ++++---- 6 files changed, 40 insertions(+), 16 deletions(-) (limited to 'src') 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) diff --git a/src/basic/fileio.h b/src/basic/fileio.h index 2e8148ff24..4998d4d042 100644 --- a/src/basic/fileio.h +++ b/src/basic/fileio.h @@ -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); diff --git a/src/basic/process-util.c b/src/basic/process-util.c index cff2d2a034..d8a94a4572 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -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; diff --git a/src/basic/virt.c b/src/basic/virt.c index 1fc6c1baba..70543177b6 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -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) diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index 1064fd5cbd..3dedbd1f62 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -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; diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index be3a87958f..ad547822e7 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -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); -- cgit v1.2.3-54-g00ecf From 8cf3a4a3c54c82e48b9b600fdb81b77f2c03a469 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 30 Sep 2015 15:57:55 +0300 Subject: architecture.h: define PROC_CPUINFO_MODEL Define PROC_CPUINFO_MODEL to indicate the CPU model field in /proc/cpuinfo. --- src/shared/architecture.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/shared/architecture.h b/src/shared/architecture.h index f5bbf65a90..61d067cad7 100644 --- a/src/shared/architecture.h +++ b/src/shared/architecture.h @@ -78,9 +78,11 @@ int uname_architecture(void); #if defined(__x86_64__) # define native_architecture() ARCHITECTURE_X86_64 # define LIB_ARCH_TUPLE "x86_64-linux-gnu" +# define PROC_CPUINFO_MODEL "model name" #elif defined(__i386__) # define native_architecture() ARCHITECTURE_X86 # define LIB_ARCH_TUPLE "i386-linux-gnu" +# define PROC_CPUINFO_MODEL "model name" #elif defined(__powerpc64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC64 @@ -89,6 +91,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_PPC64_LE # define LIB_ARCH_TUPLE "powerpc64le-linux-gnu" # endif +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__powerpc__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_PPC @@ -97,15 +100,18 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_PPC_LE # error "Missing LIB_ARCH_TUPLE for PPCLE" # endif +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__ia64__) # define native_architecture() ARCHITECTURE_IA64 # define LIB_ARCH_TUPLE "ia64-linux-gnu" #elif defined(__hppa64__) # define native_architecture() ARCHITECTURE_PARISC64 # error "Missing LIB_ARCH_TUPLE for HPPA64" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__hppa__) # define native_architecture() ARCHITECTURE_PARISC # define LIB_ARCH_TUPLE "hppa‑linux‑gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__s390x__) # define native_architecture() ARCHITECTURE_S390X # define LIB_ARCH_TUPLE "s390x-linux-gnu" @@ -115,9 +121,11 @@ int uname_architecture(void); #elif defined(__sparc64__) # define native_architecture() ARCHITECTURE_SPARC64 # define LIB_ARCH_TUPLE "sparc64-linux-gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__sparc__) # define native_architecture() ARCHITECTURE_SPARC # define LIB_ARCH_TUPLE "sparc-linux-gnu" +# define PROC_CPUINFO_MODEL "cpu" #elif defined(__mips64__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS64 @@ -126,6 +134,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_MIPS64_LE # error "Missing LIB_ARCH_TUPLE for MIPS64_LE" # endif +# define PROC_CPUINFO_MODEL "cpu model" #elif defined(__mips__) # if __BYTE_ORDER == __BIG_ENDIAN # define native_architecture() ARCHITECTURE_MIPS @@ -134,6 +143,7 @@ int uname_architecture(void); # define native_architecture() ARCHITECTURE_MIPS_LE # define LIB_ARCH_TUPLE "mipsel-linux-gnu" # endif +# define PROC_CPUINFO_MODEL "cpu model" #elif defined(__alpha__) # define native_architecture() ARCHITECTURE_ALPHA # define LIB_ARCH_TUPLE "alpha-linux-gnu" @@ -169,6 +179,7 @@ int uname_architecture(void); # define LIB_ARCH_TUPLE "arm-linux-gnu" # endif # endif +# define PROC_CPUINFO_MODEL "model name" #elif defined(__sh64__) # define native_architecture() ARCHITECTURE_SH64 # error "Missing LIB_ARCH_TUPLE for SH64" @@ -188,5 +199,10 @@ int uname_architecture(void); # error "Please register your architecture here!" #endif +#ifndef PROC_CPUINFO_MODEL +#warning "PROC_CPUINFO_MODEL not defined for your architecture" +#define PROC_CPUINFO_MODEL "model name" +#endif + const char *architecture_to_string(int a) _const_; int architecture_from_string(const char *s) _pure_; -- cgit v1.2.3-54-g00ecf From f2d28e80bc6260c90396e9fc798d559775dbde23 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 30 Sep 2015 15:57:55 +0300 Subject: bootchart: use get_proc_field and PROC_CPUINFO_MODEL Use get_proc_field and PROC_CPUINFO_MODEL to get the CPU type. Also don't fail if it missing, instead restore the old behaviour and print "Unknown". Fixes the following error seen with v225 on powerpc: Unable to read module name from cpuinfo. Error generating svg file: No such file or directory --- src/bootchart/svg.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/bootchart/svg.c b/src/bootchart/svg.c index c66f12e3a6..db5fc863b0 100644 --- a/src/bootchart/svg.c +++ b/src/bootchart/svg.c @@ -30,6 +30,7 @@ #include #include +#include "architecture.h" #include "util.h" #include "fileio.h" #include "macro.h" @@ -147,7 +148,7 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start, _cleanup_free_ char *model = NULL; _cleanup_free_ char *buf = NULL; char date[256] = "Unknown"; - char *cpu; + const char *cpu; char *c; time_t t; int r; @@ -188,20 +189,11 @@ static int svg_title(FILE *of, const char *build, int pscount, double log_start, assert_se(r > 0); /* CPU type */ - r = read_full_file("/proc/cpuinfo", &buf, NULL); + r = get_proc_field("/proc/cpuinfo", PROC_CPUINFO_MODEL, "\n", &buf); if (r < 0) - return log_error_errno(r, "Unable to read cpuinfo: %m"); - - cpu = strstr(buf, "model name"); - if (!cpu) { - log_error("Unable to read module name from cpuinfo.\n"); - return -ENOENT; - } - - cpu += 13; - c = strchr(cpu, '\n'); - if (c) - *c = '\0'; + cpu = "Unknown"; + else + cpu = buf; fprintf(of, "Bootchart for %s - %s\n", uts.nodename, date); -- cgit v1.2.3-54-g00ecf