src/idmapped-mounts: use renameat instead of renameat2
[xfstests-dev.git] / src / looptest.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2013 SGI.  All Rights Reserved.
4  */
5  
6 /* dxm - 28/2/2 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <malloc.h>
11 #include <fcntl.h>
12 #include <errno.h>
13 #include <string.h>
14 #include <sys/stat.h>
15 #include <sys/socket.h>
16
17 #include <unistd.h>
18 #include <sys/types.h>
19
20 FILE    *fp = NULL;
21
22 #define LL                  "ll"
23
24 #define PERROR(a,b)         perror(a)
25 #define GET_LAST_ERROR      errno
26
27 #define HANDLE              int
28 #define INVALID_HANDLE      -1
29 #define TRUNCATE_ERROR      -1
30 #define FLUSH_ERROR         EOF
31
32 #define FILE_BEGIN          SEEK_SET
33 #define FILE_CURRENT        SEEK_CUR
34
35 #define OPEN(N, F)          open(N, O_CREAT|O_RDWR|F, 0644); fp = fdopen(f, "r+")
36 #define SEEK(H, O, F)       (lseek(H, O, F))
37 #define READ(H, B, L)       (read(H, B, L))
38 #define WRITE(H, B, L)      (write(H, B, L))
39 #define CLOSE(H)            (close(H))
40 #define DELETE_FILE(F)      (unlink(F))
41 #define FLUSH(F)            (fflush(fp))
42 #define TRUNCATE(F)         (ftruncate(F, 0))
43
44 #define ALLOC_ALIGNED(S)    (memalign(65536, S))
45 #define FREE_ALIGNED(P)     (free(P))
46
47 #define DIRECT_IO_FLAG      O_DIRECT
48
49 enum {
50     FLAG_OPENCLOSE  = 1,
51     FLAG_READ       = 2,
52     FLAG_WRITE      = 4,
53     FLAG_VERBOSE    = 8,
54     FLAG_TRUNCATE   = 16,
55     FLAG_SEQUENTIAL = 32,
56     FLAG_FLUSH      = 64,
57     FLAG_DELETE     = 128,
58     FLAG_DIRECT     = 256,
59 };
60
61 void
62 usage(char *argv0)
63 {
64     printf(
65         "Usage: %s [switches] <filename>\n"
66         "              -i <count>   = repeat count (default forever)\n"
67         "              -o           = open/close\n"
68         "              -r           = read\n"
69         "              -w           = write\n"
70         "              -t           = truncate\n"
71         "              -d           = delete\n"
72         "              -b <size>    = buffer size\n"
73         "              -v           = verbose\n"
74         "              -s           = sequential\n"
75         "              -f           = flush\n"
76         "              -D           = direct-IO\n"
77         "              -h           = usage\n",
78             argv0);
79 }
80
81 extern int optind;
82 extern char *optarg;
83
84 int
85 main(int argc, char *argv[])
86 {
87     HANDLE              f               = INVALID_HANDLE;
88     char                *filename;
89     int                 i;
90     int                 c;
91     int                 count           = -1;
92     int                 bufsize         = 4096;
93     int                 flags           = 0;
94     char                *buf            = NULL;
95     int64_t             seek_to         = 0;
96         
97     while ((c = getopt(argc, argv, "i:orwb:svthfFDd?")) != EOF) {
98         switch (c) {
99             case 'i':
100                 count = atoi(optarg);
101                 break;
102             case 'o':
103                 flags |= FLAG_OPENCLOSE;
104                 break;
105             case 'r':
106                 flags |= FLAG_READ;
107                 break;
108             case 'w':
109                 flags |= FLAG_WRITE;
110                 break;
111             case 't':
112                 flags |= FLAG_TRUNCATE;
113                 break;
114             case 'v':
115                 flags |= FLAG_VERBOSE;
116                 break;
117             case 'b':
118                 bufsize = atoi(optarg);
119                 break;
120             case 's':
121                 flags |= FLAG_SEQUENTIAL;
122                 break;
123             case 'f':
124                 flags |= FLAG_FLUSH;
125                 break;
126             case 'D':
127                 flags |= FLAG_DIRECT;
128                 break;
129             case 'd':
130                 flags |= FLAG_DELETE;
131                 break;
132             case '?':
133             case 'h':
134             default:
135                 usage(argv[0]);
136                 return 1;
137         }
138     }
139     if (optind != argc - 1) {
140         usage(argv[0]);
141         return 1;
142     }
143
144     filename = argv[optind];
145     if (!flags) {
146         fprintf(stderr, "nothing to do!\n");
147         exit(1);
148     }
149
150     if (flags & FLAG_DIRECT)
151         buf = (char *)ALLOC_ALIGNED(bufsize);
152     else 
153         buf = (char *)malloc(bufsize);
154             
155     if (!buf)
156         PERROR("malloc", GET_LAST_ERROR);
157
158     for (i = 0; i < bufsize; i++) {
159         buf[i] = i & 127;
160     }
161
162     for (i = 0; count < 0 || i < count; i++) {
163         
164         if ((flags & FLAG_OPENCLOSE) || !i) {
165             int fileflags;
166             
167             if (flags & FLAG_VERBOSE)
168                 printf("open %s\n", filename);
169             
170             fileflags = 0;
171             if (flags & FLAG_DIRECT)
172                 fileflags |= DIRECT_IO_FLAG;
173             
174             f = OPEN(filename, fileflags);
175             if (f == INVALID_HANDLE)
176                 PERROR("OPEN", GET_LAST_ERROR);
177
178         }
179         
180         if ((flags & FLAG_OPENCLOSE) && (flags & FLAG_SEQUENTIAL)) {
181             if (flags & FLAG_VERBOSE)
182                 printf("seek %" LL "d\n", (long long)seek_to);
183             if (SEEK(f, seek_to, FILE_BEGIN) < 0)
184                 PERROR("SEEK", GET_LAST_ERROR);
185         }
186             
187         if (flags & FLAG_WRITE) {
188             int sizewritten;
189             
190             if (!(flags & FLAG_SEQUENTIAL)) {
191                 if (flags & FLAG_VERBOSE)
192                     printf("seek %" LL "d\n", (long long)seek_to);
193                 if (SEEK(f, seek_to, FILE_BEGIN) < 0)
194                     PERROR("SEEK", GET_LAST_ERROR);
195             }
196             
197             if (flags & FLAG_VERBOSE)
198                 printf("write %d\n", bufsize);
199             if ((sizewritten = WRITE(f, buf, bufsize)) != bufsize) {
200                 if (sizewritten < 0)
201                     PERROR("WRITE", GET_LAST_ERROR);
202                 else
203                     fprintf(stderr, "short write: %d of %d\n",
204                             sizewritten, bufsize);
205             }
206         }
207         
208         if (flags & FLAG_READ) {
209             int sizeread;
210             
211             if (!(flags & FLAG_SEQUENTIAL) || (flags & FLAG_WRITE)) {
212                 if (flags & FLAG_VERBOSE)
213                     printf("seek %" LL "d\n", (long long)seek_to);
214                 if (SEEK(f, seek_to, FILE_BEGIN) < 0)
215                     PERROR("SEEK", GET_LAST_ERROR);
216             }
217             
218             if (flags & FLAG_VERBOSE)
219                 printf("read %d\n", bufsize);
220             if ((sizeread = READ(f, buf, bufsize)) != bufsize) {
221                 if (sizeread < 0)
222                     PERROR("READ", GET_LAST_ERROR);
223                 else if (sizeread)
224                     fprintf(stderr, "short read: %d of %d\n",
225                         sizeread, bufsize);
226                 else {
227                     fprintf(stderr, "Read past EOF\n");
228                     exit(0);
229                 }
230             }
231         }
232         
233         if (flags & FLAG_TRUNCATE) {
234             if (flags & FLAG_VERBOSE)
235                 printf("seek 0\n");
236
237             if (SEEK(f, 0, FILE_BEGIN) < 0)
238                 PERROR("SEEK", GET_LAST_ERROR);
239             
240             if (flags & FLAG_VERBOSE)
241                 printf("truncate\n");
242             
243             if (TRUNCATE(f) == TRUNCATE_ERROR)
244                 PERROR("TRUNCATE", GET_LAST_ERROR);
245         }
246         
247         if (flags & FLAG_FLUSH) {
248             if (flags & FLAG_VERBOSE)
249                 printf("flush\n");
250             
251             if (FLUSH(f) == FLUSH_ERROR)
252                 PERROR("FLUSH", GET_LAST_ERROR);
253         }
254
255         if (flags & FLAG_SEQUENTIAL) {
256             seek_to += bufsize;
257             if (flags & FLAG_TRUNCATE) {
258                 if (flags & FLAG_VERBOSE)
259                     printf("seek %" LL "d\n", (long long)seek_to);
260                 if (SEEK(f, seek_to, FILE_BEGIN) < 0)
261                     PERROR("SEEK", GET_LAST_ERROR);
262             }
263         }
264         
265         if (flags & FLAG_OPENCLOSE) {
266             if (flags & FLAG_VERBOSE)
267                 printf("close %s\n", filename);
268             CLOSE(f);
269         }
270         
271         if (flags & FLAG_DELETE) {
272             if (flags & FLAG_VERBOSE)
273                 printf("delete %s\n", filename);
274             DELETE_FILE(filename);
275         }
276     }
277
278     if (buf) {
279         if (flags & FLAG_DIRECT)
280             FREE_ALIGNED(buf);
281         else
282             free(buf);
283     }
284     
285     return 0;
286 }