lsns: Fix parser for /proc/<pid>/stat which is including space in comm

For example, child process of spamd has

    32031 (spamd child) S 32026 32026 32026 0 -1 4210752 338 0 0 0 ...

fscanf("%d %*s %c %d*[^\n]") in read_process() can't parse above as we
expected, because %s only skips non-whitespace. I.e. it parses like
following,

    32031 (spamd child) S 32026 32026 32026 0 -1 4210752 338 0 0 0 ...
    +---+ +----+ +
      %d    %*s  %c

and returns 2 (pid=32031, state=c).

This fixes it by skipping task->comm part manually.

Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
This commit is contained in:
OGAWA Hirofumi 2016-11-23 14:13:34 +09:00 committed by Karel Zak
parent 12f17a23df
commit 3fcbd79789
1 changed files with 26 additions and 4 deletions

View File

@ -217,6 +217,30 @@ static int get_ns_ino(int dir, const char *nsname, ino_t *ino)
return 0;
}
static int parse_proc_stat(FILE *fp, pid_t *pid, char *state, pid_t *ppid)
{
char *line = NULL, *p;
size_t len = 0;
int rc;
if (getline(&line, &len, fp) < 0) {
rc = -errno;
goto error;
}
p = strrchr(line, ')');
if (p == NULL ||
sscanf(line, "%d (", pid) != 1 ||
sscanf(p, ") %c %d*[^\n]", state, ppid) != 2) {
rc = -EINVAL;
goto error;
}
rc = 0;
error:
free(line);
return rc;
}
static int read_process(struct lsns *ls, pid_t pid)
{
@ -255,11 +279,9 @@ static int read_process(struct lsns *ls, pid_t pid)
rc = -errno;
goto done;
}
rc = fscanf(f, "%d %*s %c %d*[^\n]", &p->pid, &p->state, &p->ppid);
if (rc != 3) {
rc = rc < 0 ? -errno : -EINVAL;
rc = parse_proc_stat(f, &p->pid, &p->state, &p->ppid);
if (rc < 0)
goto done;
}
rc = 0;
for (i = 0; i < ARRAY_SIZE(p->ns_ids); i++) {