]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/readdir.c
822818aecc644859635279f48e17176d4cd9b9fa
[thirdparty/xfsprogs-dev.git] / io / readdir.c
1 /*
2 * Copyright (c) 2013 Red Hat, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <xfs/xfs.h>
20 #include <xfs/command.h>
21 #include <xfs/input.h>
22 #include "init.h"
23 #include "io.h"
24
25 #include <sys/types.h>
26 #include <dirent.h>
27
28 static struct cmdinfo readdir_cmd;
29
30 const char *d_type_str(unsigned int type)
31 {
32 const char *str;
33
34 switch (type) {
35 case DT_UNKNOWN:
36 str = "DT_UNKNOWN";
37 break;
38 case DT_FIFO:
39 str = "DT_FIFO";
40 break;
41 case DT_CHR:
42 str = "DT_CHR";
43 break;
44 case DT_DIR:
45 str = "DT_DIR";
46 break;
47 case DT_BLK:
48 str = "DT_BLK";
49 break;
50 case DT_REG:
51 str = "DT_REG";
52 break;
53 case DT_LNK:
54 str = "DT_LNK";
55 break;
56 case DT_SOCK:
57 str = "DT_SOCK";
58 break;
59 case DT_WHT:
60 str = "DT_WHT";
61 break;
62 default:
63 str = "ERROR!";
64 break;
65 }
66
67 return str;
68 }
69
70 static void
71 dump_dirent(
72 long long offset,
73 struct dirent *dirent)
74 {
75 printf("%08llx: d_ino: 0x%08lx", offset, dirent->d_ino);
76 #ifdef _DIRENT_HAVE_D_OFF
77 printf(" d_off: 0x%08lx", dirent->d_off);
78 #endif
79 #ifdef _DIRENT_HAVE_D_RECLEN
80 printf(" d_reclen: 0x%x", dirent->d_reclen);
81 #endif
82 #ifdef _DIRENT_HAVE_D_TYPE
83 printf(" d_type: %s", d_type_str(dirent->d_type));
84 #endif
85 printf(" d_name: %s\n", dirent->d_name);
86 }
87
88 static int
89 read_directory(
90 DIR *dir,
91 long long offset,
92 unsigned long long length,
93 int dump,
94 unsigned long long *total)
95 {
96 struct dirent *dirent;
97 int count = 0;
98
99 seekdir(dir, offset);
100
101 *total = 0;
102 while (*total < length) {
103 dirent = readdir(dir);
104 if (!dirent)
105 break;
106
107 *total += dirent->d_reclen;
108 count++;
109
110 if (dump) {
111 dump_dirent(offset, dirent);
112 offset = dirent->d_off;
113 }
114 }
115
116 return count;
117 }
118
119 static int
120 readdir_f(
121 int argc,
122 char **argv)
123 {
124 int cnt;
125 unsigned long long total;
126 int c;
127 size_t fsblocksize, fssectsize;
128 struct timeval t1, t2;
129 char s1[64], s2[64], ts[64];
130 long long offset = -1;
131 unsigned long long length = -1; /* max length limit */
132 int verbose = 0;
133 DIR *dir;
134 int dfd;
135
136 init_cvtnum(&fsblocksize, &fssectsize);
137
138 while ((c = getopt(argc, argv, "l:o:v")) != EOF) {
139 switch (c) {
140 case 'l':
141 length = cvtnum(fsblocksize, fssectsize, optarg);
142 break;
143 case 'o':
144 offset = cvtnum(fsblocksize, fssectsize, optarg);
145 break;
146 case 'v':
147 verbose = 1;
148 break;
149 default:
150 return command_usage(&readdir_cmd);
151 }
152 }
153
154 dfd = dup(file->fd);
155 if (dfd < 0)
156 return -1;
157
158 dir = fdopendir(dfd);
159 if (!dir) {
160 close(dfd);
161 return -1;
162 }
163
164 if (offset == -1) {
165 rewinddir(dir);
166 offset = telldir(dir);
167 }
168
169 gettimeofday(&t1, NULL);
170 cnt = read_directory(dir, offset, length, verbose, &total);
171 gettimeofday(&t2, NULL);
172
173 closedir(dir);
174
175 t2 = tsub(t2, t1);
176 timestr(&t2, ts, sizeof(ts), 0);
177
178 cvtstr(total, s1, sizeof(s1));
179 cvtstr(tdiv(total, t2), s2, sizeof(s2));
180
181 printf(_("read %llu bytes from offset %lld\n"), total, offset);
182 printf(_("%s, %d ops, %s (%s/sec and %.4f ops/sec)\n"),
183 s1, cnt, ts, s2, tdiv(cnt, t2));
184
185 return 0;
186 }
187
188 void
189 readdir_init(void)
190 {
191 readdir_cmd.name = "readdir";
192 readdir_cmd.cfunc = readdir_f;
193 readdir_cmd.argmax = 5;
194 readdir_cmd.flags = CMD_NOMAP_OK|CMD_FOREIGN_OK;
195 readdir_cmd.args = _("[-v][-o offset][-l length]");
196 readdir_cmd.oneline = _("read directory entries");
197
198 add_command(&readdir_cmd);
199 }