diff options
author | Ulrich Drepper <drepper@redhat.com> | 2009-04-15 15:57:47 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2009-04-15 15:57:47 +0000 |
commit | 6a3d03ff58742430a252beac4a1917506512e319 (patch) | |
tree | 0ec8e3e51b4f6be9ee19ee37e4908731518474fc /sysdeps/unix/sysv/linux/getsysstats.c | |
parent | ae650a41ef732a40c7897f4ae99d967b859c05d6 (diff) | |
download | glibc-6a3d03ff58742430a252beac4a1917506512e319.tar.gz glibc-6a3d03ff58742430a252beac4a1917506512e319.tar.xz glibc-6a3d03ff58742430a252beac4a1917506512e319.zip |
* sysdeps/unix/sysv/linux/getsysstats.c (next_line): Make sure there cvs/fedora-glibc-20090415T1619
are always at least 4 bytes in the returned line. 2009-04-15 Jakub Jelinek <jakub@redhat.com> * sysdeps/unix/sysv/linux/getsysstats.c (__get_nprocs): Check __libc_use_alloca (8192), if the stack is too small use 512 bytes instead of 8K. Stop searching in /proc/stat after hitting first line not starting with cpu. (next_line): Truncate too long lines at buffer size * 3/4 instead of pretending there were line breaks inside of large lines.
Diffstat (limited to 'sysdeps/unix/sysv/linux/getsysstats.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/getsysstats.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c index 28f52c0463..97e20d249b 100644 --- a/sysdeps/unix/sysv/linux/getsysstats.c +++ b/sysdeps/unix/sysv/linux/getsysstats.c @@ -93,15 +93,42 @@ next_line (int fd, char *const buffer, char **cp, char **re, return NULL; *re += n; + + nl = memchr (*cp, '\n', *re - *cp); + while (nl == NULL && *re == buffer_end) + { + /* Truncate too long lines. */ + *re = buffer + 3 * (buffer_end - buffer) / 4; + n = read_not_cancel (fd, *re, buffer_end - *re); + if (n < 0) + return NULL; + + nl = memchr (*re, '\n', n); + **re = '\n'; + *re += n; + } } + else + nl = memchr (*cp, '\n', *re - *cp); res = *cp; - nl = memchr (*cp, '\n', *re - *cp); } if (nl == NULL) nl = *re - 1; } + else if (nl + 5 >= *re) + { + memmove (buffer, nl, *re - nl); + *re = buffer + (*re - nl); + nl = *cp = buffer; + + ssize_t n = read_not_cancel (fd, *re, buffer_end - *re); + if (n < 0) + return NULL; + + *re += n; + } *cp = nl + 1; assert (*cp <= *re); @@ -115,8 +142,9 @@ __get_nprocs () { /* XXX Here will come a test for the new system call. */ - char buffer[8192]; - char *const buffer_end = buffer + sizeof (buffer); + const size_t buffer_size = __libc_use_alloca (8192) ? 8192 : 512; + char *buffer = alloca (buffer_size); + char *buffer_end = buffer + buffer_size; char *cp = buffer_end; char *re = buffer_end; int result = 1; @@ -134,7 +162,11 @@ __get_nprocs () char *l; while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) - if (strncmp (l, "cpu", 3) == 0 && isdigit (l[3])) + /* The current format of /proc/stat has all the cpu* entries + at the front. We assume here that stays this way. */ + if (strncmp (l, "cpu", 3) != 0) + break; + else if (isdigit (l[3])) ++result; close_not_cancel_no_status (fd); |