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