generic/486: Get rid of the redundant error=%d printing
[xfstests-dev.git] / src / t_dir_type.c
1 /*
2  * Copyright (C) 2016 CTERA Networks. All Rights Reserved.
3  * Author: Amir Goldstein <amir73il@gmail.com>
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 /*
20  * t_dir_type
21  *
22  * print directory entries and their file type, optionally filtered by d_type
23  * or by inode number.
24  *
25  * ./t_dir_type <path> [u|f|d|c|b|l|p|s|w|<ino>]
26  */
27
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <dirent.h>
34 #include <sys/stat.h>
35 #include <sys/syscall.h>
36
37 struct linux_dirent64 {
38         uint64_t        d_ino;
39         int64_t         d_off;
40         unsigned short  d_reclen;
41         unsigned char   d_type;
42         char            d_name[0];
43 };
44
45 #define DT_MASK 15
46 #define DT_MAX 15
47 unsigned char type_to_char[DT_MAX] = {
48         [DT_UNKNOWN] = 'u',
49         [DT_DIR] = 'd',
50         [DT_REG] = 'f',
51         [DT_LNK] = 'l',
52         [DT_CHR] = 'c',
53         [DT_BLK] = 'b',
54         [DT_FIFO] = 'p',
55         [DT_SOCK] = 's',
56         [DT_WHT] = 'w',
57 };
58
59 #define DT_CHAR(t) type_to_char[(t)&DT_MASK]
60
61 #define BUF_SIZE 4096
62
63 int
64 main(int argc, char *argv[])
65 {
66         int fd, nread;
67         char buf[BUF_SIZE];
68         struct linux_dirent64 *d;
69         int bpos;
70         int type = -1; /* -1 means all types */
71         uint64_t ino = 0;
72         int ret = 1;
73
74         fd = open(argv[1], O_RDONLY | O_DIRECTORY);
75         if (fd < 0) {
76                 perror("open");
77                 exit(EXIT_FAILURE);
78         }
79
80         if (argc > 2 && argv[2][0]) {
81                 char t = argv[2][0];
82
83                 for (type = DT_MAX-1; type >= 0; type--)
84                         if (DT_CHAR(type) == t)
85                                 break;
86                 /* no match ends up with type = -1 */
87                 if (type < 0)
88                         ino = strtoul(argv[2], NULL, 10);
89         }
90
91         for ( ; ; ) {
92                 nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
93                 if (nread == -1) {
94                         perror("getdents");
95                         exit(EXIT_FAILURE);
96                 }
97
98                 if (nread == 0)
99                         break;
100
101                 for (bpos = 0; bpos < nread;) {
102                         d = (struct linux_dirent64 *) (buf + bpos);
103                         if ((type < 0 || type == (int)d->d_type) &&
104                             (!ino || ino == d->d_ino)) {
105                                 ret = 0;
106                                 printf("%s %c\n", d->d_name, DT_CHAR(d->d_type));
107                         }
108                         bpos += d->d_reclen;
109                 }
110         }
111
112         return ret;
113 }