busybox/procps/smemcap.c
<<
>>
Prefs
   1/*
   2 smemcap - a tool for meaningful memory reporting
   3
   4 Copyright 2008-2009 Matt Mackall <mpm@selenic.com>
   5
   6 This software may be used and distributed according to the terms of
   7 the GNU General Public License version 2 or later, incorporated
   8 herein by reference.
   9*/
  10//config:config SMEMCAP
  11//config:       bool "smemcap (2.5 kb)"
  12//config:       default y
  13//config:       help
  14//config:       smemcap is a tool for capturing process data for smem,
  15//config:       a memory usage statistic tool.
  16
  17//applet:IF_SMEMCAP(APPLET(smemcap, BB_DIR_USR_BIN, BB_SUID_DROP))
  18
  19//kbuild:lib-$(CONFIG_SMEMCAP) += smemcap.o
  20
  21#include "libbb.h"
  22#include "bb_archive.h"
  23
  24struct fileblock {
  25        struct fileblock *next;
  26        char data[TAR_BLOCK_SIZE];
  27};
  28
  29static void writeheader(const char *path, struct stat *sb, int type)
  30{
  31        struct tar_header_t header;
  32
  33        memset(&header, 0, TAR_BLOCK_SIZE);
  34        strcpy(header.name, path);
  35        sprintf(header.mode, "%o", sb->st_mode & 0777);
  36        /* careful to not overflow fields! */
  37        sprintf(header.uid, "%o", sb->st_uid & 07777777);
  38        sprintf(header.gid, "%o", sb->st_gid & 07777777);
  39        sprintf(header.size, "%o", (unsigned)sb->st_size);
  40        sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
  41        header.typeflag = type;
  42        chksum_and_xwrite_tar_header(STDOUT_FILENO, &header);
  43}
  44
  45static void archivefile(const char *path)
  46{
  47        struct fileblock *start, *cur;
  48        struct fileblock **prev = &start;
  49        int fd, r;
  50        unsigned size = 0;
  51        struct stat s;
  52
  53        /* buffer the file */
  54        fd = open(path, O_RDONLY);
  55        if (fd == -1) {
  56                /* skip vanished processes between dir listing and traversal */
  57                return;
  58        }
  59        do {
  60                cur = xzalloc(sizeof(*cur));
  61                *prev = cur;
  62                prev = &cur->next;
  63                r = full_read(fd, cur->data, TAR_BLOCK_SIZE);
  64                if (r > 0)
  65                        size += r;
  66        } while (r == TAR_BLOCK_SIZE);
  67
  68        /* write archive header */
  69        fstat(fd, &s);
  70        close(fd);
  71        s.st_size = size;
  72        writeheader(path, &s, '0');
  73
  74        /* dump file contents */
  75        for (cur = start; (int)size > 0; size -= TAR_BLOCK_SIZE) {
  76                xwrite(STDOUT_FILENO, cur->data, TAR_BLOCK_SIZE);
  77                start = cur;
  78                cur = cur->next;
  79                free(start);
  80        }
  81}
  82
  83static void archivejoin(const char *sub, const char *name)
  84{
  85        char path[sizeof(long long)*3 + sizeof("/cmdline")];
  86        sprintf(path, "%s/%s", sub, name);
  87        archivefile(path);
  88}
  89
  90//usage:#define smemcap_trivial_usage ">SMEMDATA.TAR"
  91//usage:#define smemcap_full_usage "\n\n"
  92//usage:       "Collect memory usage data in /proc and write it to stdout"
  93
  94int smemcap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  95int smemcap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  96{
  97        DIR *d;
  98        struct dirent *de;
  99
 100        xchdir("/proc");
 101        d = xopendir(".");
 102
 103        archivefile("meminfo");
 104        archivefile("version");
 105        while ((de = readdir(d)) != NULL) {
 106                if (isdigit(de->d_name[0])) {
 107                        struct stat s;
 108                        memset(&s, 0, sizeof(s));
 109                        s.st_mode = 0555;
 110                        writeheader(de->d_name, &s, '5');
 111                        archivejoin(de->d_name, "smaps");
 112                        archivejoin(de->d_name, "cmdline");
 113                        archivejoin(de->d_name, "stat");
 114                }
 115        }
 116
 117        if (ENABLE_FEATURE_CLEAN_UP)
 118                closedir(d);
 119
 120        return EXIT_SUCCESS;
 121}
 122