]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - io/readdir.c
xfsprogs: don't install platform_defs.h
[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 "command.h"
20 #include "input.h"
21 #include "init.h"
22 #include "io.h"
23
24 #include <sys/types.h>
25 #include <dirent.h>
26
27 static struct cmdinfo readdir_cmd;
28
29 const char *d_type_str(unsigned int type)
30 {
31 const char *str;
32
33 switch (type) {
34 case DT_UNKNOWN:
35 str = "DT_UNKNOWN";
36 break;
37 case DT_FIFO:
38 str = "DT_FIFO";
39 break;
40 case DT_CHR:
41 str = "DT_CHR";
42 break;
43 case DT_DIR:
44 str = "DT_DIR";
45 break;
46 case DT_BLK:
47 str = "DT_BLK";
48 break;
49 case DT_REG:
50 str = "DT_REG";
51 break;
52 case DT_LNK:
53 str = "DT_LNK";
54 break;
55 case DT_SOCK:
56 str = "DT_SOCK";
57 break;
58 case DT_WHT:
59 str = "DT_WHT";
60 break;
61 default:
62 str = "ERROR!";
63 break;
64 }
65
66 return str;
67 }
68
69 static void
70 dump_dirent(
71 long long offset,
72 struct dirent *dirent)
73 {
74 printf("%08llx: d_ino: 0x%08lx", offset, dirent->d_ino);
75 #ifdef _DIRENT_HAVE_D_OFF
76 printf(" d_off: 0x%08lx", dirent->d_off);
77 #endif
78 #ifdef _DIRENT_HAVE_D_RECLEN
79 printf(" d_reclen: 0x%x", dirent->d_reclen);
80 #endif
81 #ifdef _DIRENT_HAVE_D_TYPE
82 printf(" d_type: %s", d_type_str(dirent->d_type));
83 #endif
84 printf(" d_name: %s\n", dirent->d_name);
85 }
86
87 static int
88 read_directory(
89 DIR *dir,
90 long long offset,
91 unsigned long long length,
92 int dump,
93 unsigned long long *total)
94 {
95 struct dirent *dirent;
96 int count = 0;
97
98 seekdir(dir, offset);
99
100 *total = 0;
101 while (*total < length) {
102 dirent = readdir(dir);
103 if (!dirent)
104 break;
105
106 *total += dirent->d_reclen;
107 count++;
108
109 if (dump) {
110 dump_dirent(offset, dirent);
111 offset = dirent->d_off;
112 }
113 }
114
115 return count;
116 }
117
118 static int
119 readdir_f(
120 int argc,
121 char **argv)
122 {
123 int cnt;
124 unsigned long long total;
125 int c;
126 size_t fsblocksize, fssectsize;
127 struct timeval t1, t2;
128 char s1[64], s2[64], ts[64];
129 long long offset = -1;
130 unsigned long long length = -1; /* max length limit */
131 int verbose = 0;
132 DIR *dir;
133 int dfd;
134
135 init_cvtnum(&fsblocksize, &fssectsize);
136
137 while ((c = getopt(argc, argv, "l:o:v")) != EOF) {
138 switch (c) {
139 case 'l':
140 length = cvtnum(fsblocksize, fssectsize, optarg);
141 break;
142 case 'o':
143 offset = cvtnum(fsblocksize, fssectsize, optarg);
144 break;
145 case 'v':
146 verbose = 1;
147 break;
148 default:
149 return command_usage(&readdir_cmd);
150 }
151 }
152
153 dfd = dup(file->fd);
154 if (dfd < 0)
155 return -1;
156
157 dir = fdopendir(dfd);
158 if (!dir) {
159 close(dfd);
160 return -1;
161 }
162
163 if (offset == -1) {
164 rewinddir(dir);
165 offset = telldir(dir);
166 }
167
168 gettimeofday(&t1, NULL);
169 cnt = read_directory(dir, offset, length, verbose, &total);
170 gettimeofday(&t2, NULL);
171
172 closedir(dir);
173 close(dfd);
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 }