diff --git a/smemcap.c b/smemcap.c new file mode 100644 index 0000000..bcdfc29 --- /dev/null +++ b/smemcap.c @@ -0,0 +1,112 @@ +/* + smem - a tool for meaningful memory reporting + + Copyright 2008-2009 Matt Mackall + + 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 +#include +#include +#include +#include +#include +#include +#include + +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; +}