chiark / gitweb /
75f85b46e068543e335bbd16412e09170396a95b
[elogind.git] / src / readahead / readahead-analyze.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2012 Auke Kok <auke-jan.h.kok@intel.com>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdbool.h>
26 #include <unistd.h>
27 #include <inttypes.h>
28 #include <linux/limits.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <string.h>
32
33 #include "readahead-common.h"
34
35 int main_analyze(const char *pack_path)
36 {
37         char line[LINE_MAX];
38         char path[PATH_MAX];
39         FILE *pack;
40         int a;
41         int missing = 0;
42         off_t size;
43         off_t tsize = 0;
44         uint64_t inode;
45         uint32_t b;
46         uint32_t c;
47         struct stat st;
48
49         if (!pack_path)
50                 pack_path = "/.readahead";
51
52         pack = fopen(pack_path, "re");
53         if (!pack) {
54                 log_error("Pack file missing.");
55                 goto fail;
56         }
57
58         if (!fgets(line, sizeof(line), pack)) {
59                 log_error("Pack file corrupt.");
60                 goto fail;
61         }
62
63         char_array_0(line);
64
65         if (!endswith(line, READAHEAD_PACK_FILE_VERSION)) {
66                 log_error("Pack file version incompatible with this parser.");
67                 goto fail;
68         }
69
70         if ((a = getc(pack)) == EOF) {
71                 log_error("Pack file corrupt.");
72                 goto fail;
73         }
74
75         fprintf(stdout, "   pct  sections     size: path\n");
76         fprintf(stdout, "   ===  ========     ====: ====\n");
77
78         while(true) {
79                 int pages = 0;
80                 int sections = 0;
81
82                 if (!fgets(path, sizeof(path), pack))
83                         break; /* done */
84
85                 path[strlen(path)-1] = 0;
86
87                 if (fread(&inode, sizeof(inode), 1, pack) != 1) {
88                         log_error("Pack file corrupt.");
89                         goto fail;
90                 }
91
92                 while (true) {
93                         if (fread(&b, sizeof(b), 1, pack) != 1  ||
94                             fread(&c, sizeof(c), 1, pack) != 1) {
95                                 log_error("Pack file corrupt.");
96                                 goto fail;
97                         }
98                         if ((b == 0) && (c == 0))
99                                 break;
100
101                         /* Uncomment this to get all the chunks separately
102                         fprintf(stdout, " %d: %d %d\n", sections, b, c);
103                          */
104
105                         pages += (c - b);
106                         sections++;
107                 }
108
109                 if (stat(path, &st) == 0) {
110                         if (sections == 0)
111                                 size = st.st_size;
112                         else
113                                 size = pages * page_size();
114
115                         tsize += size;
116
117                         fprintf(stdout, "  %4d%% (%2d) %12ld: %s\n",
118                                 sections ? (int)(size / st.st_size * 100.0) : 100,
119                                 sections ? sections : 1,
120                                 (unsigned long)size,
121                                 path);
122                 } else {
123                         fprintf(stdout, "  %4dp (%2d) %12s: %s (MISSING)\n",
124                                 sections ? pages : -1,
125                                 sections ? sections : 1,
126                                 "???",
127                                 path);
128                         missing++;
129                 }
130
131         }
132
133         fclose(pack);
134
135         fprintf(stdout, "\nHOST:    %s", line);
136         fprintf(stdout, "TYPE:    %c\n", a);
137         fprintf(stdout, "MISSING: %d\n", missing);
138         fprintf(stdout, "TOTAL:   %ld\n", tsize);
139
140         return EXIT_SUCCESS;
141
142
143 fail:
144         fclose(pack);
145         return EXIT_FAILURE;
146 }