]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsns: Fix parser for /proc/<pid>/stat which is including space in comm
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Wed, 23 Nov 2016 05:13:34 +0000 (14:13 +0900)
committerKarel Zak <kzak@redhat.com>
Fri, 2 Dec 2016 12:20:41 +0000 (13:20 +0100)
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>
sys-utils/lsns.c

index e4fd2082703722f8e80cf7ba23fbd8dcbd4a1072..809737cfaeec792330e0ffb0b9fd21471213a7bf 100644 (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++) {