source: branches/3.2/mindi-busybox/procps/smemcap.c @ 3232

Last change on this file since 3232 was 3232, checked in by bruno, 5 years ago
  • Update mindi-busybox to 1.21.1
  • Property svn:eol-style set to native
File size: 3.4 KB
Line 
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 "bb_archive.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  "); /* like GNU tar */
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    if (ENABLE_FEATURE_CLEAN_UP)
129        closedir(d);
130
131    return EXIT_SUCCESS;
132}
Note: See TracBrowser for help on using the repository browser.