summaryrefslogtreecommitdiff
path: root/procps/smemcap.c (plain)
blob: 7dc1601998b299b68dde6d120e49b3856a31bafc
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
11//applet:IF_SMEMCAP(APPLET(smemcap, BB_DIR_USR_BIN, BB_SUID_DROP))
12
13//kbuild:lib-$(CONFIG_SMEMCAP) += smemcap.o
14
15//config:config SMEMCAP
16//config: bool "smemcap"
17//config: default y
18//config: help
19//config: smemcap is a tool for capturing process data for smem,
20//config: a memory usage statistic tool.
21
22#include "libbb.h"
23#include "bb_archive.h"
24
25struct fileblock {
26 struct fileblock *next;
27 char data[TAR_BLOCK_SIZE];
28};
29
30static void writeheader(const char *path, struct stat *sb, int type)
31{
32 struct tar_header_t header;
33 int i, sum;
34
35 memset(&header, 0, TAR_BLOCK_SIZE);
36 strcpy(header.name, path);
37 sprintf(header.mode, "%o", sb->st_mode & 0777);
38 /* careful to not overflow fields! */
39#ifdef BIONIC_L
40 sprintf(header.uid, "%uo", sb->st_uid & 07777777);
41 sprintf(header.gid, "%uo", sb->st_gid & 07777777);
42#elif defined(__BIONIC__)
43 sprintf(header.uid, "%lo", sb->st_uid & 07777777);
44 sprintf(header.gid, "%lo", sb->st_gid & 07777777);
45#else
46 sprintf(header.uid, "%o", sb->st_uid & 07777777);
47 sprintf(header.gid, "%o", sb->st_gid & 07777777);
48#endif
49 sprintf(header.size, "%o", (unsigned)sb->st_size);
50 sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
51 header.typeflag = type;
52 strcpy(header.magic, "ustar "); /* like GNU tar */
53
54 /* Calculate and store the checksum (the sum of all of the bytes of
55 * the header). The checksum field must be filled with blanks for the
56 * calculation. The checksum field is formatted differently from the
57 * other fields: it has 6 digits, a NUL, then a space -- rather than
58 * digits, followed by a NUL like the other fields... */
59 header.chksum[7] = ' ';
60 sum = ' ' * 7;
61 for (i = 0; i < TAR_BLOCK_SIZE; i++)
62 sum += ((unsigned char*)&header)[i];
63 sprintf(header.chksum, "%06o", sum);
64
65 xwrite(STDOUT_FILENO, &header, TAR_BLOCK_SIZE);
66}
67
68static void archivefile(const char *path)
69{
70 struct fileblock *start, *cur;
71 struct fileblock **prev = &start;
72 int fd, r;
73 unsigned size = 0;
74 struct stat s;
75
76 /* buffer the file */
77 fd = xopen(path, O_RDONLY);
78 do {
79 cur = xzalloc(sizeof(*cur));
80 *prev = cur;
81 prev = &cur->next;
82 r = full_read(fd, cur->data, TAR_BLOCK_SIZE);
83 if (r > 0)
84 size += r;
85 } while (r == TAR_BLOCK_SIZE);
86
87 /* write archive header */
88 fstat(fd, &s);
89 close(fd);
90 s.st_size = size;
91 writeheader(path, &s, '0');
92
93 /* dump file contents */
94 for (cur = start; (int)size > 0; size -= TAR_BLOCK_SIZE) {
95 xwrite(STDOUT_FILENO, cur->data, TAR_BLOCK_SIZE);
96 start = cur;
97 cur = cur->next;
98 free(start);
99 }
100}
101
102static void archivejoin(const char *sub, const char *name)
103{
104 char path[sizeof(long long)*3 + sizeof("/cmdline")];
105 sprintf(path, "%s/%s", sub, name);
106 archivefile(path);
107}
108
109//usage:#define smemcap_trivial_usage ">SMEMDATA.TAR"
110//usage:#define smemcap_full_usage "\n\n"
111//usage: "Collect memory usage data in /proc and write it to stdout"
112
113int smemcap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
114int smemcap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
115{
116 DIR *d;
117 struct dirent *de;
118
119 xchdir("/proc");
120 d = xopendir(".");
121
122 archivefile("meminfo");
123 archivefile("version");
124 while ((de = readdir(d)) != NULL) {
125 if (isdigit(de->d_name[0])) {
126 struct stat s;
127 memset(&s, 0, sizeof(s));
128 s.st_mode = 0555;
129 writeheader(de->d_name, &s, '5');
130 archivejoin(de->d_name, "smaps");
131 archivejoin(de->d_name, "cmdline");
132 archivejoin(de->d_name, "stat");
133 }
134 }
135
136 if (ENABLE_FEATURE_CLEAN_UP)
137 closedir(d);
138
139 return EXIT_SUCCESS;
140}
141