chiark / gitweb /
42bf9dbac97673d21c6703dec804ce4ad810cf4c
[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[1024];
38         char path[PATH_MAX];
39         FILE *pack;
40         int a;
41         int missing = 0;
42         off_t size;
43         long 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                 return EXIT_FAILURE;
56         }
57
58         if (!fgets(line, sizeof(line), pack)) {
59                 log_error("Pack file corrupt.");
60                 return EXIT_FAILURE;
61         }
62
63         if (!strstr(line, READAHEAD_PACK_FILE_VERSION)) {
64                 log_error("Pack file version incompatible with this parser.");
65                 return EXIT_FAILURE;
66         }
67
68         if ((a = getc(pack)) == EOF) {
69                 log_error("Pack file corrupt.");
70                 return EXIT_FAILURE;
71         }
72
73         fprintf(stdout, "   pct  sections     size: path\n");
74         fprintf(stdout, "   ===  ========     ====: ====\n");
75
76         while(true) {
77                 int pages = 0;
78                 int sections = 0;
79
80                 if (!fgets(path, sizeof(path), pack))
81                         break; /* done */
82
83                 path[strlen(path)-1] = 0;
84
85                 if (fread(&inode, sizeof(inode), 1, pack) != 1) {
86                         log_error("Pack file corrupt.");
87                         return EXIT_FAILURE;
88                 }
89
90                 while (true) {
91                         if (fread(&b, sizeof(b), 1, pack) != 1  ||
92                             fread(&c, sizeof(c), 1, pack) != 1) {
93                                 log_error("Pack file corrupt.");
94                                 return EXIT_FAILURE;
95                         }
96                         if ((b == 0) && (c == 0))
97                                 break;
98
99                         /* Uncomment this to get all the chunks separately
100                         fprintf(stdout, " %d: %d %d\n", sections, b, c);
101                          */
102
103                         pages += (c - b);
104                         sections++;
105                 }
106
107                 if (stat(path, &st) == 0) {
108                         if (sections == 0)
109                                 size = st.st_size;
110                         else
111                                 size = pages * page_size();
112
113                         tsize += size;
114
115                         fprintf(stdout, "  %4d%% (%2d) %12ld: %s\n",
116                                 sections ? (int)(size / st.st_size * 100.0) : 100,
117                                 sections ? sections : 1,
118                                 (unsigned long)size,
119                                 path);
120                 } else {
121                         fprintf(stdout, "  %4dp (%2d) %12s: %s (MISSING)\n",
122                                 sections ? pages : -1,
123                                 sections ? sections : 1,
124                                 "???",
125                                 path);
126                         missing++;
127                 }
128
129         }
130
131         fprintf(stdout, "\nHOST:    %s", line);
132         fprintf(stdout, "TYPE:    %c\n", a);
133         fprintf(stdout, "MISSING: %d\n", missing);
134         fprintf(stdout, "TOTAL:   %ld\n", tsize);
135
136         return EXIT_SUCCESS;
137 }