small commit tweak in parse_datestr, no code changes
[oweals/busybox.git] / procps / nmeter.c
index 888b827eadeacfdc650c052aad10a65ae93b503d..5c3525dc70ee1e314ff355d6bd32a721aecb029b 100644 (file)
 //  totalram=2107416576, freeram=211525632, sharedram=0, bufferram=157204480}
 //  totalswap=134209536, freeswap=134209536, procs=157})
 
-#include <time.h>
 #include "libbb.h"
 
 typedef unsigned long long ullong;
 
-enum { PROC_FILE_SIZE = 4096 };
+enum {  /* Preferably use powers of 2 */
+       PROC_MIN_FILE_SIZE = 256,
+       PROC_MAX_FILE_SIZE = 16 * 1024,
+};
 
 typedef struct proc_file {
        char *file;
-       //const char *name;
+       int file_sz;
        smallint last_gen;
 } proc_file;
 
@@ -124,36 +126,47 @@ static void put_question_marks(int count)
                put_c('?');
 }
 
-static void readfile_z(char *buf, int sz, const char* fname)
+static void readfile_z(proc_file *pf, const char* fname)
 {
 // open_read_close() will do two reads in order to be sure we are at EOF,
 // and we don't need/want that.
-//     sz = open_read_close(fname, buf, sz-1);
-
-       int fd = xopen(fname, O_RDONLY);
+       int fd;
+       int sz, rdsz;
+       char *buf;
+
+       sz = pf->file_sz;
+       buf = pf->file;
+       if (!buf) {
+               buf = xmalloc(PROC_MIN_FILE_SIZE);
+               sz = PROC_MIN_FILE_SIZE;
+       }
+ again:
+       fd = xopen(fname, O_RDONLY);
        buf[0] = '\0';
-       if (fd >= 0) {
-               sz = read(fd, buf, sz-1);
-               if (sz > 0) buf[sz] = '\0';
-               close(fd);
+       rdsz = read(fd, buf, sz-1);
+       close(fd);
+       if (rdsz > 0) {
+               if (rdsz == sz-1 && sz < PROC_MAX_FILE_SIZE) {
+                       sz *= 2;
+                       buf = xrealloc(buf, sz);
+                       goto again;
+               }
+               buf[rdsz] = '\0';
        }
+       pf->file_sz = sz;
+       pf->file = buf;
 }
 
 static const char* get_file(proc_file *pf)
 {
        if (pf->last_gen != gen) {
                pf->last_gen = gen;
-               // We allocate PROC_FILE_SIZE bytes. This wastes memory,
-               // but allows us to allocate only once (at first sample)
-               // per proc file, and reuse buffer for each sample
-               if (!pf->file)
-                       pf->file = xmalloc(PROC_FILE_SIZE);
-               readfile_z(pf->file, PROC_FILE_SIZE, proc_name[pf - &first_proc_file]);
+               readfile_z(pf, proc_name[pf - &first_proc_file]);
        }
        return pf->file;
 }
 
-static inline ullong read_after_slash(const char *p)
+static ullong read_after_slash(const char *p)
 {
        p = strchr(p, '/');
        if (!p) return 0;
@@ -228,7 +241,7 @@ static int rdval_loadavg(const char* p, ullong *vec, ...)
 //   3  1 hda1 0 0 0 0 <- ignore if only 4 fields
 static int rdval_diskstats(const char* p, ullong *vec)
 {
-       ullong rd = 0; // to avoid "warning: 'rd' might be used uninitialized"
+       ullong rd = rd; // for compiler
        int indexline = 0;
        vec[0] = 0;
        vec[1] = 0;
@@ -268,20 +281,20 @@ static void scale(ullong ul)
 #define S_STAT(a) \
 typedef struct a { \
        struct s_stat *next; \
-       void (*collect)(struct a *s); \
+       void (*collect)(struct a *s) FAST_FUNC; \
        const char *label;
 #define S_STAT_END(a) } a;
 
 S_STAT(s_stat)
 S_STAT_END(s_stat)
 
-static void collect_literal(s_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_literal(s_stat *s UNUSED_PARAM)
 {
 }
 
 static s_stat* init_literal(void)
 {
-       s_stat *s = xzalloc(sizeof(s_stat));
+       s_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_literal;
        return (s_stat*)s;
 }
@@ -294,7 +307,7 @@ static s_stat* init_delay(const char *param)
        return NULL;
 }
 
-static s_stat* init_cr(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_cr(const char *param UNUSED_PARAM)
 {
        final_str = "\r";
        return (s_stat*)0;
@@ -312,7 +325,7 @@ S_STAT(cpu_stat)
 S_STAT_END(cpu_stat)
 
 
-static void collect_cpu(cpu_stat *s)
+static void FAST_FUNC collect_cpu(cpu_stat *s)
 {
        ullong data[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 };
        unsigned frac[CPU_FIELDCNT] = { 0, 0, 0, 0, 0, 0, 0 };
@@ -386,7 +399,7 @@ S_STAT(int_stat)
        int no;
 S_STAT_END(int_stat)
 
-static void collect_int(int_stat *s)
+static void FAST_FUNC collect_int(int_stat *s)
 {
        ullong data[1];
        ullong old;
@@ -420,7 +433,7 @@ S_STAT(ctx_stat)
        ullong old;
 S_STAT_END(ctx_stat)
 
-static void collect_ctx(ctx_stat *s)
+static void FAST_FUNC collect_ctx(ctx_stat *s)
 {
        ullong data[1];
        ullong old;
@@ -436,7 +449,7 @@ static void collect_ctx(ctx_stat *s)
        scale(data[0] - old);
 }
 
-static s_stat* init_ctx(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_ctx(const char *param UNUSED_PARAM)
 {
        ctx_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_ctx;
@@ -449,7 +462,7 @@ S_STAT(blk_stat)
        ullong old[2];
 S_STAT_END(blk_stat)
 
-static void collect_blk(blk_stat *s)
+static void FAST_FUNC collect_blk(blk_stat *s)
 {
        ullong data[2];
        int i;
@@ -478,7 +491,7 @@ static void collect_blk(blk_stat *s)
        scale(data[1]*512);
 }
 
-static s_stat* init_blk(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_blk(const char *param UNUSED_PARAM)
 {
        blk_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_blk;
@@ -491,7 +504,7 @@ S_STAT(fork_stat)
        ullong old;
 S_STAT_END(fork_stat)
 
-static void collect_thread_nr(fork_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_thread_nr(fork_stat *s UNUSED_PARAM)
 {
        ullong data[1];
 
@@ -502,7 +515,7 @@ static void collect_thread_nr(fork_stat *s ATTRIBUTE_UNUSED)
        scale(data[0]);
 }
 
-static void collect_fork(fork_stat *s)
+static void FAST_FUNC collect_fork(fork_stat *s)
 {
        ullong data[1];
        ullong old;
@@ -536,7 +549,7 @@ S_STAT(if_stat)
        char *device_colon;
 S_STAT_END(if_stat)
 
-static void collect_if(if_stat *s)
+static void FAST_FUNC collect_if(if_stat *s)
 {
        ullong data[4];
        int i;
@@ -611,7 +624,7 @@ S_STAT_END(mem_stat)
 //HugePages_Total:     0
 //HugePages_Free:      0
 //Hugepagesize:     4096 kB
-static void collect_mem(mem_stat *s)
+static void FAST_FUNC collect_mem(mem_stat *s)
 {
        ullong m_total = 0;
        ullong m_free = 0;
@@ -658,7 +671,7 @@ static s_stat* init_mem(const char *param)
 S_STAT(swp_stat)
 S_STAT_END(swp_stat)
 
-static void collect_swp(swp_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_swp(swp_stat *s UNUSED_PARAM)
 {
        ullong s_total[1];
        ullong s_free[1];
@@ -671,7 +684,7 @@ static void collect_swp(swp_stat *s ATTRIBUTE_UNUSED)
        scale((s_total[0]-s_free[0]) << 10);
 }
 
-static s_stat* init_swp(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_swp(const char *param UNUSED_PARAM)
 {
        swp_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_swp;
@@ -682,7 +695,7 @@ static s_stat* init_swp(const char *param ATTRIBUTE_UNUSED)
 S_STAT(fd_stat)
 S_STAT_END(fd_stat)
 
-static void collect_fd(fd_stat *s ATTRIBUTE_UNUSED)
+static void FAST_FUNC collect_fd(fd_stat *s UNUSED_PARAM)
 {
        ullong data[2];
 
@@ -694,7 +707,7 @@ static void collect_fd(fd_stat *s ATTRIBUTE_UNUSED)
        scale(data[0] - data[1]);
 }
 
-static s_stat* init_fd(const char *param ATTRIBUTE_UNUSED)
+static s_stat* init_fd(const char *param UNUSED_PARAM)
 {
        fd_stat *s = xzalloc(sizeof(*s));
        s->collect = collect_fd;
@@ -707,7 +720,7 @@ S_STAT(time_stat)
        int scale;
 S_STAT_END(time_stat)
 
-static void collect_time(time_stat *s)
+static void FAST_FUNC collect_time(time_stat *s)
 {
        char buf[sizeof("12:34:56.123456")];
        struct tm* tm;
@@ -742,7 +755,7 @@ static s_stat* init_time(const char *param)
        return (s_stat*)s;
 }
 
-static void collect_info(s_stat *s)
+static void FAST_FUNC collect_info(s_stat *s)
 {
        gen ^= 1;
        while (s) {
@@ -787,8 +800,10 @@ int nmeter_main(int argc, char **argv)
        if (argc != 2)
                bb_show_usage();
 
-       if (open_read_close("version", buf, sizeof(buf)) > 0)
-               is26 = (strstr(buf, " 2.4.")==NULL);
+       if (open_read_close("version", buf, sizeof(buf)-1) > 0) {
+               buf[sizeof(buf)-1] = '\0';
+               is26 = (strstr(buf, " 2.4.") == NULL);
+       }
 
        // Can use argv[1] directly, but this will mess up
        // parameters as seen by e.g. ps. Making a copy...
@@ -801,7 +816,7 @@ int nmeter_main(int argc, char **argv)
                if (!cur)
                        break;
                if (cur[1] == '%') {    // %%
-                       strcpy(cur, cur+1);
+                       overlapping_strcpy(cur, cur + 1);
                        cur++;
                        goto again;
                }