[git commit master 1/1] smemcap: new applet

Denys Vlasenko vda.linux at googlemail.com
Thu Jun 24 03:05:12 UTC 2010


commit: http://git.busybox.net/busybox/commit/?id=a091d45c3beb767ce9cb530ab0a81aee1238495d
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 procps/smemcap.c |  152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 152 insertions(+), 0 deletions(-)
 create mode 100644 procps/smemcap.c

diff --git a/procps/smemcap.c b/procps/smemcap.c
new file mode 100644
index 0000000..cdcc891
--- /dev/null
+++ b/procps/smemcap.c
@@ -0,0 +1,152 @@
+/*
+ smemcap - a tool for meaningful memory reporting
+
+ Copyright 2008-2009 Matt Mackall <mpm at selenic.com>
+
+ This software may be used and distributed according to the terms of
+ the GNU General Public License version 2 or later, incorporated
+ herein by reference.
+*/
+
+//applet:IF_SMEMCAP(APPLET(smemcap, _BB_DIR_USR_BIN, _BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_SMEMCAP) += smemcap.o
+
+//config:config SMEMCAP
+//config:	bool "smemcap"
+//config:	default y
+//config:	help
+//config:	  smemcap is a tool for capturing process data for smem,
+//config:	  a memory usage statistic tool.
+
+#include "libbb.h"
+
+struct tar_header {
+	char name[100];           /*   0-99 */
+	char mode[8];             /* 100-107 */
+	char uid[8];              /* 108-115 */
+	char gid[8];              /* 116-123 */
+	char size[12];            /* 124-135 */
+	char mtime[12];           /* 136-147 */
+	char chksum[8];           /* 148-155 */
+	char typeflag;            /* 156-156 */
+	char linkname[100];       /* 157-256 */
+	/* POSIX:   "ustar" NUL "00" */
+	/* GNU tar: "ustar  " NUL */
+	/* Normally it's defined as magic[6] followed by
+	 * version[2], but we put them together to save code.
+	 */
+	char magic[8];            /* 257-264 */
+	char uname[32];           /* 265-296 */
+	char gname[32];           /* 297-328 */
+	char devmajor[8];         /* 329-336 */
+	char devminor[8];         /* 337-344 */
+	char prefix[155];         /* 345-499 */
+	char padding[12];         /* 500-512 (pad to exactly TAR_512) */
+};
+
+struct fileblock {
+	struct fileblock *next;
+	char data[512];
+};
+
+static void writeheader(const char *path, struct stat *sb, int type)
+{
+	struct tar_header header;
+	int i, sum;
+
+	memset(&header, 0, 512);
+	strcpy(header.name, path);
+	sprintf(header.mode, "%o", sb->st_mode & 0777);
+	/* careful to not overflow fields! */
+	sprintf(header.uid, "%o", sb->st_uid & 07777777);
+	sprintf(header.gid, "%o", sb->st_gid & 07777777);
+	sprintf(header.size, "%o", (unsigned)sb->st_size);
+	sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
+	header.typeflag = type;
+	//strcpy(header.magic, "ustar  "); - do we want to be standard-compliant?
+
+	/* Calculate and store the checksum (the sum of all of the bytes of
+	 * the header). The checksum field must be filled with blanks for the
+	 * calculation. The checksum field is formatted differently from the
+	 * other fields: it has 6 digits, a NUL, then a space -- rather than
+	 * digits, followed by a NUL like the other fields... */
+	header.chksum[7] = ' ';
+	sum = ' ' * 7;
+	for (i = 0; i < 512; i++)
+		sum += ((unsigned char*)&header)[i];
+	sprintf(header.chksum, "%06o", sum);
+
+	xwrite(STDOUT_FILENO, &header, 512);
+}
+
+static void archivefile(const char *path)
+{
+	struct fileblock *start, *cur;
+	struct fileblock **prev = &start;
+	int fd, r;
+	unsigned size = 0;
+	struct stat s;
+
+	/* buffer the file */
+	fd = xopen(path, O_RDONLY);
+	do {
+		cur = xzalloc(sizeof(*cur));
+		*prev = cur;
+		prev = &cur->next;
+		r = full_read(fd, cur->data, 512);
+		if (r > 0)
+			size += r;
+	} while (r == 512);
+
+	/* write archive header */
+	fstat(fd, &s);
+	close(fd);
+	s.st_size = size;
+	writeheader(path, &s, '0');
+
+	/* dump file contents */
+	for (cur = start; (int)size > 0; size -= 512) {
+		xwrite(STDOUT_FILENO, cur->data, 512);
+		start = cur;
+		cur = cur->next;
+		free(start);
+	}
+}
+
+static void archivejoin(const char *sub, const char *name)
+{
+	char path[sizeof(long long)*3 + sizeof("/cmdline")];
+	sprintf(path, "%s/%s", sub, name);
+	archivefile(path);
+}
+
+//usage:#define smemcap_trivial_usage ">SMEMDATA.TAR"
+//usage:#define smemcap_full_usage "\n\n"
+//usage:       "Collect memory usage data in /proc and write it to stdout"
+
+int smemcap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int smemcap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+	DIR *d;
+	struct dirent *de;
+
+	xchdir("/proc");
+	d = xopendir(".");
+
+	archivefile("meminfo");
+	archivefile("version");
+	while ((de = readdir(d)) != NULL) {
+		if (isdigit(de->d_name[0])) {
+			struct stat s;
+			memset(&s, 0, sizeof(s));
+			s.st_mode = 0555;
+			writeheader(de->d_name, &s, '5');
+			archivejoin(de->d_name, "smaps");
+			archivejoin(de->d_name, "cmdline");
+			archivejoin(de->d_name, "stat");
+		}
+	}
+
+	return EXIT_SUCCESS;
+}
-- 
1.7.1



More information about the busybox-cvs mailing list