2 smemcap - a tool for meaningful memory reporting
4 Copyright 2008-2009 Matt Mackall <mpm@selenic.com>
6 This software may be used and distributed according to the terms of
7 the GNU General Public License version 2 or later, incorporated
10 //config:config SMEMCAP
11 //config: bool "smemcap (2.5 kb)"
14 //config: smemcap is a tool for capturing process data for smem,
15 //config: a memory usage statistic tool.
17 //applet:IF_SMEMCAP(APPLET(smemcap, BB_DIR_USR_BIN, BB_SUID_DROP))
19 //kbuild:lib-$(CONFIG_SMEMCAP) += smemcap.o
22 #include "bb_archive.h"
25 struct fileblock *next;
26 char data[TAR_BLOCK_SIZE];
29 static void writeheader(const char *path, struct stat *sb, int type)
31 struct tar_header_t header;
34 memset(&header, 0, TAR_BLOCK_SIZE);
35 strcpy(header.name, path);
36 sprintf(header.mode, "%o", sb->st_mode & 0777);
37 /* careful to not overflow fields! */
38 sprintf(header.uid, "%o", sb->st_uid & 07777777);
39 sprintf(header.gid, "%o", sb->st_gid & 07777777);
40 sprintf(header.size, "%o", (unsigned)sb->st_size);
41 sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
42 header.typeflag = type;
43 strcpy(header.magic, "ustar "); /* like GNU tar */
45 /* Calculate and store the checksum (the sum of all of the bytes of
46 * the header). The checksum field must be filled with blanks for the
47 * calculation. The checksum field is formatted differently from the
48 * other fields: it has 6 digits, a NUL, then a space -- rather than
49 * digits, followed by a NUL like the other fields... */
50 header.chksum[7] = ' ';
52 for (i = 0; i < TAR_BLOCK_SIZE; i++)
53 sum += ((unsigned char*)&header)[i];
54 sprintf(header.chksum, "%06o", sum);
56 xwrite(STDOUT_FILENO, &header, TAR_BLOCK_SIZE);
59 static void archivefile(const char *path)
61 struct fileblock *start, *cur;
62 struct fileblock **prev = &start;
68 fd = open(path, O_RDONLY);
70 /* skip vanished processes between dir listing and traversal */
74 cur = xzalloc(sizeof(*cur));
77 r = full_read(fd, cur->data, TAR_BLOCK_SIZE);
80 } while (r == TAR_BLOCK_SIZE);
82 /* write archive header */
86 writeheader(path, &s, '0');
88 /* dump file contents */
89 for (cur = start; (int)size > 0; size -= TAR_BLOCK_SIZE) {
90 xwrite(STDOUT_FILENO, cur->data, TAR_BLOCK_SIZE);
97 static void archivejoin(const char *sub, const char *name)
99 char path[sizeof(long long)*3 + sizeof("/cmdline")];
100 sprintf(path, "%s/%s", sub, name);
104 //usage:#define smemcap_trivial_usage ">SMEMDATA.TAR"
105 //usage:#define smemcap_full_usage "\n\n"
106 //usage: "Collect memory usage data in /proc and write it to stdout"
108 int smemcap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
109 int smemcap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
117 archivefile("meminfo");
118 archivefile("version");
119 while ((de = readdir(d)) != NULL) {
120 if (isdigit(de->d_name[0])) {
122 memset(&s, 0, sizeof(s));
124 writeheader(de->d_name, &s, '5');
125 archivejoin(de->d_name, "smaps");
126 archivejoin(de->d_name, "cmdline");
127 archivejoin(de->d_name, "stat");
131 if (ENABLE_FEATURE_CLEAN_UP)