replay-log: add support for replaying ops in target device sector range
[xfstests-dev.git] / src / t_dir_offset2.c
1 /*
2  * Copyright (c) 2011 GraÅžvydas Ignotas
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write the Free Software Foundation,
15  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16  */
17
18 /*
19  * This test checks if no duplicate d_off values are returned and
20  * that these offsets are seekable to entry with the right inode.
21  */
22
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <sys/stat.h>
29 #include <sys/syscall.h>
30
31 struct linux_dirent64 {
32         uint64_t        d_ino;
33         uint64_t        d_off;
34         unsigned short  d_reclen;
35         unsigned char   d_type;
36         char            d_name[0];
37 };
38
39 #define BUF_SIZE 4096
40 #define HISTORY_LEN 1024
41
42 static uint64_t d_off_history[HISTORY_LEN];
43 static uint64_t d_ino_history[HISTORY_LEN];
44
45 int
46 main(int argc, char *argv[])
47 {
48         int fd, nread;
49         char buf[BUF_SIZE];
50         struct linux_dirent64 *d;
51         int bpos, total, i;
52         off_t lret;
53         int retval = EXIT_SUCCESS;
54
55         fd = open(argv[1], O_RDONLY | O_DIRECTORY);
56         if (fd < 0) {
57                 perror("open");
58                 exit(EXIT_FAILURE);
59         }
60
61         total = 0;
62         for ( ; ; ) {
63                 nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
64                 if (nread == -1) {
65                         perror("getdents");
66                         exit(EXIT_FAILURE);
67                 }
68
69                 if (nread == 0)
70                         break;
71
72                 for (bpos = 0; bpos < nread; total++) {
73                         d = (struct linux_dirent64 *) (buf + bpos);
74
75                         if (total >= HISTORY_LEN) {
76                                 fprintf(stderr, "too many files\n");
77                                 break;
78                         }
79
80                         for (i = 0; i < total; i++)
81                         {
82                                 if (d_off_history[i] == d->d_off) {
83                                         fprintf(stderr, "entries %d and %d have duplicate d_off %lld\n",
84                                                 i, total, (long long int)d->d_off);
85                                         retval = EXIT_FAILURE;
86                                 }
87                         }
88                         d_off_history[total] = d->d_off;
89                         d_ino_history[total] = d->d_ino;
90                         bpos += d->d_reclen;
91                 }
92         }
93
94         /* check if seek works correctly */
95         d = (struct linux_dirent64 *)buf;
96         for (i = total - 1; i >= 0; i--)
97         {
98                 lret = lseek(fd, i > 0 ? d_off_history[i - 1] : 0, SEEK_SET);
99                 if (lret == -1) {
100                         perror("lseek");
101                         exit(EXIT_FAILURE);
102                 }
103
104                 nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
105                 if (nread == -1) {
106                         perror("getdents");
107                         exit(EXIT_FAILURE);
108                 }
109
110                 if (nread == 0) {
111                         fprintf(stderr, "getdents returned 0 on entry %d\n", i);
112                         retval = EXIT_FAILURE;
113                 }
114
115                 if (d->d_ino != d_ino_history[i]) {
116                         fprintf(stderr, "entry %d has inode %lld, expected %lld\n",
117                                 i, (long long int)d->d_ino, (long long int)d_ino_history[i]);
118                         retval = EXIT_FAILURE;
119                 }
120         }
121
122         close(fd);
123         exit(retval);
124 }