mirror of
https://github.com/systemd/systemd.git
synced 2024-11-06 08:26:52 +03:00
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.
This commit is contained in:
parent
5e6ad75f25
commit
c4cd1d4d93
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user