diff options
Diffstat (limited to 'procps')
-rw-r--r-- | procps/smemcap.c | 129 | ||||
-rw-r--r-- | procps/sysctl.c | 1 | ||||
-rw-r--r-- | procps/top.c | 8 |
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 | |||
25 | struct fileblock { | ||
26 | struct fileblock *next; | ||
27 | char data[TAR_BLOCK_SIZE]; | ||
28 | }; | ||
29 | |||
30 | static 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 | |||
60 | static 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 | |||
94 | static 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 | |||
105 | int smemcap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
106 | int 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); |