fstests: Add an auxiliary program to create an AF_UNIX socket
[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, optionally filtered by d_type
23  *
24  * ./t_dir_type <path> [u|f|d|c|b|l|p|s|w]
25  */
26
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <stdint.h>
31 #include <stdlib.h>
32 #include <dirent.h>
33 #include <sys/stat.h>
34 #include <sys/syscall.h>
35
36 struct linux_dirent64 {
37         uint64_t        d_ino;
38         int64_t         d_off;
39         unsigned short  d_reclen;
40         unsigned char   d_type;
41         char            d_name[0];
42 };
43
44 #define DT_MASK 15
45 #define DT_MAX 15
46 unsigned char type_to_char[DT_MAX] = {
47         [DT_UNKNOWN] = 'u',
48         [DT_DIR] = 'd',
49         [DT_REG] = 'f',
50         [DT_LNK] = 'l',
51         [DT_CHR] = 'c',
52         [DT_BLK] = 'b',
53         [DT_FIFO] = 'p',
54         [DT_SOCK] = 's',
55         [DT_WHT] = 'w',
56 };
57
58 #define DT_CHAR(t) type_to_char[(t)&DT_MASK]
59
60 #define BUF_SIZE 4096
61
62 int
63 main(int argc, char *argv[])
64 {
65         int fd, nread;
66         char buf[BUF_SIZE];
67         struct linux_dirent64 *d;
68         int bpos;
69         int type = -1; /* -1 means all types */
70         int ret = 1;
71
72         fd = open(argv[1], O_RDONLY | O_DIRECTORY);
73         if (fd < 0) {
74                 perror("open");
75                 exit(EXIT_FAILURE);
76         }
77
78         if (argc > 2 && argv[2][0]) {
79                 char t = argv[2][0];
80
81                 for (type = DT_MAX-1; type >= 0; type--)
82                         if (DT_CHAR(type) == t)
83                                 break;
84                 /* no match ends up with type = -1 */
85         }
86
87         for ( ; ; ) {
88                 nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
89                 if (nread == -1) {
90                         perror("getdents");
91                         exit(EXIT_FAILURE);
92                 }
93
94                 if (nread == 0)
95                         break;
96
97                 for (bpos = 0; bpos < nread;) {
98                         d = (struct linux_dirent64 *) (buf + bpos);
99                         if (type < 0 || type == (int)d->d_type) {
100                                 ret = 0;
101                                 printf("%s %c\n", d->d_name, DT_CHAR(d->d_type));
102                         }
103                         bpos += d->d_reclen;
104                 }
105         }
106
107         return ret;
108 }