aboutsummaryrefslogtreecommitdiff
path: root/procps
diff options
context:
space:
mode:
Diffstat (limited to 'procps')
-rw-r--r--procps/smemcap.c129
-rw-r--r--procps/sysctl.c1
-rw-r--r--procps/top.c8
3 files changed, 134 insertions, 4 deletions
diff --git a/procps/smemcap.c b/procps/smemcap.c
new file mode 100644
index 000000000..06cf93c85
--- /dev/null
+++ b/procps/smemcap.c
@@ -0,0 +1,129 @@
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 "unarchive.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 sprintf(header.uid, "%o", sb->st_uid & 07777777);
40 sprintf(header.gid, "%o", sb->st_gid & 07777777);
41 sprintf(header.size, "%o", (unsigned)sb->st_size);
42 sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
43 header.typeflag = type;
44 //strcpy(header.magic, "ustar "); - do we want to be standard-compliant?
45
46 /* Calculate and store the checksum (the sum of all of the bytes of
47 * the header). The checksum field must be filled with blanks for the
48 * calculation. The checksum field is formatted differently from the
49 * other fields: it has 6 digits, a NUL, then a space -- rather than
50 * digits, followed by a NUL like the other fields... */
51 header.chksum[7] = ' ';
52 sum = ' ' * 7;
53 for (i = 0; i < TAR_BLOCK_SIZE; i++)
54 sum += ((unsigned char*)&header)[i];
55 sprintf(header.chksum, "%06o", sum);
56
57 xwrite(STDOUT_FILENO, &header, TAR_BLOCK_SIZE);
58}
59
60static void archivefile(const char *path)
61{
62 struct fileblock *start, *cur;
63 struct fileblock **prev = &start;
64 int fd, r;
65 unsigned size = 0;
66 struct stat s;
67
68 /* buffer the file */
69 fd = xopen(path, O_RDONLY);
70 do {
71 cur = xzalloc(sizeof(*cur));
72 *prev = cur;
73 prev = &cur->next;
74 r = full_read(fd, cur->data, TAR_BLOCK_SIZE);
75 if (r > 0)
76 size += r;
77 } while (r == TAR_BLOCK_SIZE);
78
79 /* write archive header */
80 fstat(fd, &s);
81 close(fd);
82 s.st_size = size;
83 writeheader(path, &s, '0');
84
85 /* dump file contents */
86 for (cur = start; (int)size > 0; size -= TAR_BLOCK_SIZE) {
87 xwrite(STDOUT_FILENO, cur->data, TAR_BLOCK_SIZE);
88 start = cur;
89 cur = cur->next;
90 free(start);
91 }
92}
93
94static void archivejoin(const char *sub, const char *name)
95{
96 char path[sizeof(long long)*3 + sizeof("/cmdline")];
97 sprintf(path, "%s/%s", sub, name);
98 archivefile(path);
99}
100
101//usage:#define smemcap_trivial_usage ">SMEMDATA.TAR"
102//usage:#define smemcap_full_usage "\n\n"
103//usage: "Collect memory usage data in /proc and write it to stdout"
104
105int smemcap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
106int smemcap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
107{
108 DIR *d;
109 struct dirent *de;
110
111 xchdir("/proc");
112 d = xopendir(".");
113
114 archivefile("meminfo");
115 archivefile("version");
116 while ((de = readdir(d)) != NULL) {
117 if (isdigit(de->d_name[0])) {
118 struct stat s;
119 memset(&s, 0, sizeof(s));
120 s.st_mode = 0555;
121 writeheader(de->d_name, &s, '5');
122 archivejoin(de->d_name, "smaps");
123 archivejoin(de->d_name, "cmdline");
124 archivejoin(de->d_name, "stat");
125 }
126 }
127
128 return EXIT_SUCCESS;
129}
diff --git a/procps/sysctl.c b/procps/sysctl.c
index 7a5bf1435..fc601d637 100644
--- a/procps/sysctl.c
+++ b/procps/sysctl.c
@@ -212,6 +212,7 @@ static int sysctl_handle_preload_file(const char *filename)
212//TODO: comment may be only at line start. "var=1 #abc" - "1 #abc" is the value 212//TODO: comment may be only at line start. "var=1 #abc" - "1 #abc" is the value
213// (but _whitespace_ from ends should be trimmed first (and we do it right)) 213// (but _whitespace_ from ends should be trimmed first (and we do it right))
214//TODO: "var==1" is mishandled (must use "=1" as a value, but uses "1") 214//TODO: "var==1" is mishandled (must use "=1" as a value, but uses "1")
215// can it be fixed by removing PARSE_COLLAPSE bit?
215 while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) { 216 while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) {
216 char *tp; 217 char *tp;
217 sysctl_dots_to_slashes(token[0]); 218 sysctl_dots_to_slashes(token[0]);
diff --git a/procps/top.c b/procps/top.c
index 04dd82633..ec8437442 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -686,10 +686,10 @@ static int topmem_sort(char *a, char *b)
686 n = offsetof(topmem_status_t, vsz) + (sort_field * sizeof(mem_t)); 686 n = offsetof(topmem_status_t, vsz) + (sort_field * sizeof(mem_t));
687 l = *(mem_t*)(a + n); 687 l = *(mem_t*)(a + n);
688 r = *(mem_t*)(b + n); 688 r = *(mem_t*)(b + n);
689// if (l == r) { 689 if (l == r) {
690// l = a->mapped_rw; 690 l = ((topmem_status_t*)a)->dirty;
691// r = b->mapped_rw; 691 r = ((topmem_status_t*)b)->dirty;
692// } 692 }
693 /* We want to avoid unsigned->signed and truncation errors */ 693 /* We want to avoid unsigned->signed and truncation errors */
694 /* l>r: -1, l=r: 0, l<r: 1 */ 694 /* l>r: -1, l=r: 0, l<r: 1 */
695 n = (l > r) ? -1 : (l != r); 695 n = (l > r) ? -1 : (l != r);