1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "libbb.h"
22#include "bb_archive.h"
23
24struct fileblock {
25 struct fileblock *next;
26 char data[TAR_BLOCK_SIZE];
27};
28
29static void writeheader(const char *path, struct stat *sb, int type)
30{
31 struct tar_header_t header;
32 int i, sum;
33
34 memset(&header, 0, TAR_BLOCK_SIZE);
35 strcpy(header.name, path);
36 sprintf(header.mode, "%o", sb->st_mode & 0777);
37
38 sprintf(header.uid, "%o", sb->st_uid & 07777777);
39 sprintf(header.gid, "%o", sb->st_gid & 07777777);
40 sprintf(header.size, "%o", (unsigned)sb->st_size);
41 sprintf(header.mtime, "%llo", sb->st_mtime & 077777777777LL);
42 header.typeflag = type;
43 strcpy(header.magic, "ustar ");
44
45
46
47
48
49
50 header.chksum[7] = ' ';
51 sum = ' ' * 7;
52 for (i = 0; i < TAR_BLOCK_SIZE; i++)
53 sum += ((unsigned char*)&header)[i];
54 sprintf(header.chksum, "%06o", sum);
55
56 xwrite(STDOUT_FILENO, &header, TAR_BLOCK_SIZE);
57}
58
59static void archivefile(const char *path)
60{
61 struct fileblock *start, *cur;
62 struct fileblock **prev = &start;
63 int fd, r;
64 unsigned size = 0;
65 struct stat s;
66
67
68 fd = open(path, O_RDONLY);
69 if (fd == -1) {
70
71 return;
72 }
73 do {
74 cur = xzalloc(sizeof(*cur));
75 *prev = cur;
76 prev = &cur->next;
77 r = full_read(fd, cur->data, TAR_BLOCK_SIZE);
78 if (r > 0)
79 size += r;
80 } while (r == TAR_BLOCK_SIZE);
81
82
83 fstat(fd, &s);
84 close(fd);
85 s.st_size = size;
86 writeheader(path, &s, '0');
87
88
89 for (cur = start; (int)size > 0; size -= TAR_BLOCK_SIZE) {
90 xwrite(STDOUT_FILENO, cur->data, TAR_BLOCK_SIZE);
91 start = cur;
92 cur = cur->next;
93 free(start);
94 }
95}
96
97static void archivejoin(const char *sub, const char *name)
98{
99 char path[sizeof(long long)*3 + sizeof("/cmdline")];
100 sprintf(path, "%s/%s", sub, name);
101 archivefile(path);
102}
103
104
105
106
107
108int smemcap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
109int smemcap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
110{
111 DIR *d;
112 struct dirent *de;
113
114 xchdir("/proc");
115 d = xopendir(".");
116
117 archivefile("meminfo");
118 archivefile("version");
119 while ((de = readdir(d)) != NULL) {
120 if (isdigit(de->d_name[0])) {
121 struct stat s;
122 memset(&s, 0, sizeof(s));
123 s.st_mode = 0555;
124 writeheader(de->d_name, &s, '5');
125 archivejoin(de->d_name, "smaps");
126 archivejoin(de->d_name, "cmdline");
127 archivejoin(de->d_name, "stat");
128 }
129 }
130
131 if (ENABLE_FEATURE_CLEAN_UP)
132 closedir(d);
133
134 return EXIT_SUCCESS;
135}
136