add smemcap tool

This commit is contained in:
Matt Mackall 2009-05-22 17:31:54 -05:00
commit 383d6480df

112
smemcap.c Normal file
View file

@ -0,0 +1,112 @@
/*
smem - a tool for meaningful memory reporting
Copyright 2008-2009 Matt Mackall <mpm@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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <memory.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
struct fileblock;
struct fileblock {
char data[512];
struct fileblock *next;
};
int writeheader(int destfd, const char *path, int mode, int uid, int gid,
int size, int mtime, int type)
{
char header[512];
int i, sum;
memset(header, 0, 512);
sprintf(header, "%s", path);
sprintf(header + 100, "%08o", mode);
sprintf(header + 108, "%08o", uid);
sprintf(header + 116, "%08o", gid);
sprintf(header + 124, "%012o", size);
sprintf(header + 136, "%08o", mtime);
sprintf(header + 148, " %1d", type);
/* fix checksum */
for (i = sum = 0; i < 512; i++)
sum += header[i];
sprintf(header + 148, "%06o\0 %1d", sum, type);
return write(destfd, header, 512);
}
int archivefile(const char *path, int destfd)
{
struct fileblock *start, *cur;
struct fileblock **prev = &start;
int fd, r, size = 0;
struct stat s;
/* buffer and stat the file */
fd = open(path, O_RDONLY);
fstat(fd, &s);
do {
cur = calloc(1, sizeof(struct fileblock));
*prev = cur;
prev = &cur->next;
r = read(fd, cur->data, 512);
if (r > 0)
size += r;
} while (r == 512);
close(fd);
/* write archive header */
writeheader(destfd, path, s.st_mode, s.st_uid, s.st_gid, size,
s.st_mtime, '0');
/* dump file contents */
for (cur = start; size > 0; size -= 512) {
write(destfd, cur->data, 512);
start = cur;
cur = cur->next;
free(start);
}
}
int archivejoin(const char *sub, const char *name, int destfd)
{
char path[256];
sprintf(path, "%s/%s", sub, name);
return archivefile(path, destfd);
}
int main(int argc, char *argv[])
{
int fd;
DIR *d;
struct dirent *de;
chdir("/proc");
archivefile("meminfo", 1);
archivefile("version", 1);
d = opendir(".");
while (de = readdir(d))
if (de->d_name[0] >= '0' && de->d_name[0] <= '9') {
writeheader(1, de->d_name, 040555, 0, 0, 0, 0, 5);
archivejoin(de->d_name, "smaps", 1);
archivejoin(de->d_name, "cmdline", 1);
archivejoin(de->d_name, "stat", 1);
}
return 0;
}