]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/readdir.c
xfs_io: refactor stat functions, add raw dump
[thirdparty/xfsprogs-dev.git] / io / readdir.c
CommitLineData
3bc05641
BF
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
6b803e5a
CH
19#include "command.h"
20#include "input.h"
3bc05641
BF
21#include "init.h"
22#include "io.h"
23
24#include <sys/types.h>
25#include <dirent.h>
26
2b86cff7
RS
27#ifndef _DIRENT_HAVE_D_RECLEN
28#include <string.h>
29#endif
30
3bc05641
BF
31static struct cmdinfo readdir_cmd;
32
33const char *d_type_str(unsigned int type)
34{
35 const char *str;
36
37 switch (type) {
38 case DT_UNKNOWN:
39 str = "DT_UNKNOWN";
40 break;
41 case DT_FIFO:
42 str = "DT_FIFO";
43 break;
44 case DT_CHR:
45 str = "DT_CHR";
46 break;
47 case DT_DIR:
48 str = "DT_DIR";
49 break;
50 case DT_BLK:
51 str = "DT_BLK";
52 break;
53 case DT_REG:
54 str = "DT_REG";
55 break;
56 case DT_LNK:
57 str = "DT_LNK";
58 break;
59 case DT_SOCK:
60 str = "DT_SOCK";
61 break;
62 case DT_WHT:
63 str = "DT_WHT";
64 break;
65 default:
66 str = "ERROR!";
67 break;
68 }
69
70 return str;
71}
72
73static void
74dump_dirent(
75 long long offset,
76 struct dirent *dirent)
77{
5e303e25
ES
78 printf("%08llx: d_ino: 0x%08llx", offset,
79 (unsigned long long)dirent->d_ino);
3bc05641 80#ifdef _DIRENT_HAVE_D_OFF
5e303e25 81 printf(" d_off: 0x%08llx", (unsigned long long)dirent->d_off);
3bc05641
BF
82#endif
83#ifdef _DIRENT_HAVE_D_RECLEN
84 printf(" d_reclen: 0x%x", dirent->d_reclen);
85#endif
86#ifdef _DIRENT_HAVE_D_TYPE
87 printf(" d_type: %s", d_type_str(dirent->d_type));
88#endif
89 printf(" d_name: %s\n", dirent->d_name);
90}
91
92static int
93read_directory(
94 DIR *dir,
95 long long offset,
96 unsigned long long length,
97 int dump,
98 unsigned long long *total)
99{
100 struct dirent *dirent;
101 int count = 0;
102
103 seekdir(dir, offset);
104
105 *total = 0;
106 while (*total < length) {
107 dirent = readdir(dir);
108 if (!dirent)
109 break;
110
19863f7b 111#ifdef _DIRENT_HAVE_D_RECLEN
3bc05641 112 *total += dirent->d_reclen;
19863f7b 113#else
2b86cff7 114 *total += strlen(dirent->d_name) + sizeof(*dirent);
19863f7b 115#endif
3bc05641
BF
116 count++;
117
118 if (dump) {
119 dump_dirent(offset, dirent);
19863f7b 120#ifdef _DIRENT_HAVE_D_OFF
3bc05641 121 offset = dirent->d_off;
19863f7b
JT
122#else
123 /* Some platforms don't have dirent->d_off, but because
124 * it is used only for dumping the value, it should be
125 * safe to only set it to zero in such case.
126 */
127 offset = 0;
128#endif
3bc05641
BF
129 }
130 }
131
132 return count;
133}
134
135static int
136readdir_f(
137 int argc,
138 char **argv)
139{
140 int cnt;
141 unsigned long long total;
142 int c;
143 size_t fsblocksize, fssectsize;
144 struct timeval t1, t2;
145 char s1[64], s2[64], ts[64];
146 long long offset = -1;
147 unsigned long long length = -1; /* max length limit */
148 int verbose = 0;
149 DIR *dir;
150 int dfd;
151
152 init_cvtnum(&fsblocksize, &fssectsize);
153
154 while ((c = getopt(argc, argv, "l:o:v")) != EOF) {
155 switch (c) {
156 case 'l':
157 length = cvtnum(fsblocksize, fssectsize, optarg);
158 break;
159 case 'o':
160 offset = cvtnum(fsblocksize, fssectsize, optarg);
161 break;
162 case 'v':
163 verbose = 1;
164 break;
165 default:
166 return command_usage(&readdir_cmd);
167 }
168 }
169
170 dfd = dup(file->fd);
171 if (dfd < 0)
172 return -1;
173
174 dir = fdopendir(dfd);
175 if (!dir) {
176 close(dfd);
177 return -1;
178 }
179
180 if (offset == -1) {
181 rewinddir(dir);
182 offset = telldir(dir);
183 }
184
185 gettimeofday(&t1, NULL);
186 cnt = read_directory(dir, offset, length, verbose, &total);
187 gettimeofday(&t2, NULL);
188
189 closedir(dir);
11e06961 190 close(dfd);
3bc05641
BF
191
192 t2 = tsub(t2, t1);
193 timestr(&t2, ts, sizeof(ts), 0);
194
195 cvtstr(total, s1, sizeof(s1));
196 cvtstr(tdiv(total, t2), s2, sizeof(s2));
197
198 printf(_("read %llu bytes from offset %lld\n"), total, offset);
199 printf(_("%s, %d ops, %s (%s/sec and %.4f ops/sec)\n"),
200 s1, cnt, ts, s2, tdiv(cnt, t2));
201
202 return 0;
203}
204
205void
206readdir_init(void)
207{
208 readdir_cmd.name = "readdir";
209 readdir_cmd.cfunc = readdir_f;
210 readdir_cmd.argmax = 5;
211 readdir_cmd.flags = CMD_NOMAP_OK|CMD_FOREIGN_OK;
212 readdir_cmd.args = _("[-v][-o offset][-l length]");
213 readdir_cmd.oneline = _("read directory entries");
214
215 add_command(&readdir_cmd);
216}