ab8e41ed16e4fd78e2218fdd147591aa9ab8ef7c
[xfstests-dev.git] / src / looptest.c
1 /*
2  * Copyright  2002 Silicon Graphics, Inc.  ALL RIGHTS RESERVED
3  * 
4  *  U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
5  * 
6  *  Use, duplication or disclosure by the Government is subject to restrictions
7  *  as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the 
8  *  Rights in Technical Data and Computer Software clause at DFARS 252.227-7013 
9  *  and/or in similar or successor clauses in the FAR, or the DOD or NASA FAR
10  *  Supplement. Unpublished -- rights reserved under the Copyright Laws 
11  *  of the United States. Contractor/manufacturer is Silicon Graphics, Inc.,
12  *  2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
13  * 
14  *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI
15  * 
16  *  The copyright notice above does not evidence any actual or intended 
17  *  publication or disclosure of this source code, which includes information 
18  *  that is the confidential and/or proprietary, and is a trade secret,
19  *  of Silicon Graphics, Inc. Any use, duplication or disclosure not 
20  *  specifically authorized in writing by Silicon Graphics is strictly 
21  *  prohibited. ANY DUPLICATION, MODIFICATION, DISTRIBUTION,PUBLIC PERFORMANCE,
22  *  OR PUBLIC DISPLAY OF THIS SOURCE CODE WITHOUT THE EXPRESS WRITTEN CONSENT 
23  *  OF SILICON GRAPHICS, INC. IS STRICTLY PROHIBITED.  THE RECEIPT OR POSSESSION
24  *  OF THIS SOURCE CODE AND/OR INFORMATION DOES NOT CONVEY ANY RIGHTS 
25  *  TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, OR TO MANUFACTURE, USE, 
26  *  OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
27  */
28  
29 /* dxm - 28/2/2 */
30
31 #define _GNU_SOURCE
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <malloc.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <sys/stat.h>
40 #include <sys/socket.h>
41
42 #include <unistd.h>
43 #include <sys/types.h>
44
45 FILE    *fp = NULL;
46
47 #define LL                  "ll"
48
49 #define PERROR(a,b)         perror(a)
50 #define GET_LAST_ERROR      errno
51
52 #define HANDLE              int
53 #define INVALID_HANDLE      -1
54 #define TRUNCATE_ERROR      -1
55 #define FLUSH_ERROR         EOF
56
57 #define FILE_BEGIN          SEEK_SET
58 #define FILE_CURRENT        SEEK_CUR
59
60 #define OPEN(N, F)          open(N, O_CREAT|O_RDWR|F, 0644); fp = fdopen(f, "r+")
61 #define SEEK(H, O, F)       (lseek(H, O, F))
62 #define READ(H, B, L)       (read(H, B, L))
63 #define WRITE(H, B, L)      (write(H, B, L))
64 #define CLOSE(H)            (close(H))
65 #define DELETE_FILE(F)      (unlink(F))
66 #define FLUSH(F)            (fflush(fp))
67 #define TRUNCATE(F)         (ftruncate(F, 0))
68
69 #define ALLOC_ALIGNED(S)    (memalign(65536, S))
70 #define FREE_ALIGNED(P)     (free(P))
71
72 #define DIRECT_IO_FLAG      O_DIRECT
73
74 enum {
75     FLAG_OPENCLOSE  = 1,
76     FLAG_READ       = 2,
77     FLAG_WRITE      = 4,
78     FLAG_VERBOSE    = 8,
79     FLAG_TRUNCATE   = 16,
80     FLAG_SEQUENTIAL = 32,
81     FLAG_FLUSH      = 64,
82     FLAG_DELETE     = 128,
83     FLAG_DIRECT     = 256,
84 };
85
86 void
87 usage(char *argv0)
88 {
89     printf(
90         "Usage: %s [switches] <filename>\n"
91         "              -i <count>   = repeat count (default forever)\n"
92         "              -o           = open/close\n"
93         "              -r           = read\n"
94         "              -w           = write\n"
95         "              -t           = truncate\n"
96         "              -d           = delete\n"
97         "              -b <size>    = buffer size\n"
98         "              -v           = verbose\n"
99         "              -s           = sequential\n"
100         "              -f           = flush\n"
101         "              -D           = direct-IO\n"
102         "              -h           = usage\n",
103             argv0);
104 }
105
106 extern int optind;
107 extern char *optarg;
108
109 int
110 main(int argc, char *argv[])
111 {
112     HANDLE              f               = INVALID_HANDLE;
113     char                *filename;
114     int                 i;
115     int                 c;
116     int                 count           = -1;
117     int                 bufsize         = 4096;
118     int                 flags           = 0;
119     char                *buf            = NULL;
120     int64_t             seek_to         = 0;
121         
122     while ((c = getopt(argc, argv, "i:orwb:svthfFDd?")) != EOF) {
123         switch (c) {
124             case 'i':
125                 count = atoi(optarg);
126                 break;
127             case 'o':
128                 flags |= FLAG_OPENCLOSE;
129                 break;
130             case 'r':
131                 flags |= FLAG_READ;
132                 break;
133             case 'w':
134                 flags |= FLAG_WRITE;
135                 break;
136             case 't':
137                 flags |= FLAG_TRUNCATE;
138                 break;
139             case 'v':
140                 flags |= FLAG_VERBOSE;
141                 break;
142             case 'b':
143                 bufsize = atoi(optarg);
144                 break;
145             case 's':
146                 flags |= FLAG_SEQUENTIAL;
147                 break;
148             case 'f':
149                 flags |= FLAG_FLUSH;
150                 break;
151             case 'D':
152                 flags |= FLAG_DIRECT;
153                 break;
154             case 'd':
155                 flags |= FLAG_DELETE;
156                 break;
157             case '?':
158             case 'h':
159             default:
160                 usage(argv[0]);
161                 return 1;
162         }
163     }
164     if (optind != argc - 1) {
165         usage(argv[0]);
166         return 1;
167     }
168
169     filename = argv[optind];
170     if (!flags) {
171         fprintf(stderr, "nothing to do!\n");
172         exit(1);
173     }
174
175     if (flags & FLAG_DIRECT)
176         buf = (char *)ALLOC_ALIGNED(bufsize);
177     else 
178         buf = (char *)malloc(bufsize);
179             
180     if (!buf)
181         PERROR("malloc", GET_LAST_ERROR);
182
183     for (i = 0; i < bufsize; i++) {
184         buf[i] = i & 127;
185     }
186
187     for (i = 0; count < 0 || i < count; i++) {
188         
189         if ((flags & FLAG_OPENCLOSE) || !i) {
190             int fileflags;
191             
192             if (flags & FLAG_VERBOSE)
193                 printf("open %s\n", filename);
194             
195             fileflags = 0;
196             if (flags & FLAG_DIRECT)
197                 fileflags |= DIRECT_IO_FLAG;
198             
199             f = OPEN(filename, fileflags);
200             if (f == INVALID_HANDLE)
201                 PERROR("OPEN", GET_LAST_ERROR);
202
203         }
204         
205         if ((flags & FLAG_OPENCLOSE) && (flags & FLAG_SEQUENTIAL)) {
206             if (flags & FLAG_VERBOSE)
207                 printf("seek %" LL "d\n", seek_to);
208             if (SEEK(f, seek_to, FILE_BEGIN) < 0)
209                 PERROR("SEEK", GET_LAST_ERROR);
210         }
211             
212         if (flags & FLAG_WRITE) {
213             int sizewritten;
214             
215             if (!(flags & FLAG_SEQUENTIAL)) {
216                 if (flags & FLAG_VERBOSE)
217                     printf("seek %" LL "d\n", seek_to);
218                 if (SEEK(f, seek_to, FILE_BEGIN) < 0)
219                     PERROR("SEEK", GET_LAST_ERROR);
220             }
221             
222             if (flags & FLAG_VERBOSE)
223                 printf("write %d\n", bufsize);
224             if ((sizewritten = WRITE(f, buf, bufsize)) != bufsize) {
225                 if (sizewritten < 0)
226                     PERROR("WRITE", GET_LAST_ERROR);
227                 else
228                     fprintf(stderr, "short write: %d of %d\n",
229                             sizewritten, bufsize);
230             }
231         }
232         
233         if (flags & FLAG_READ) {
234             int sizeread;
235             
236             if (!(flags & FLAG_SEQUENTIAL) || (flags & FLAG_WRITE)) {
237                 if (flags & FLAG_VERBOSE)
238                     printf("seek %" LL "d\n", seek_to);
239                 if (SEEK(f, seek_to, FILE_BEGIN) < 0)
240                     PERROR("SEEK", GET_LAST_ERROR);
241             }
242             
243             if (flags & FLAG_VERBOSE)
244                 printf("read %d\n", bufsize);
245             if ((sizeread = READ(f, buf, bufsize)) != bufsize) {
246                 if (sizeread < 0)
247                     PERROR("READ", GET_LAST_ERROR);
248                 else if (sizeread)
249                     fprintf(stderr, "short read: %d of %d\n",
250                         sizeread, bufsize);
251                 else {
252                     fprintf(stderr, "Read past EOF\n");
253                     exit(0);
254                 }
255             }
256         }
257         
258         if (flags & FLAG_TRUNCATE) {
259             if (flags & FLAG_VERBOSE)
260                 printf("seek 0\n");
261
262             if (SEEK(f, 0, FILE_BEGIN) < 0)
263                 PERROR("SEEK", GET_LAST_ERROR);
264             
265             if (flags & FLAG_VERBOSE)
266                 printf("truncate\n");
267             
268             if (TRUNCATE(f) == TRUNCATE_ERROR)
269                 PERROR("TRUNCATE", GET_LAST_ERROR);
270         }
271         
272         if (flags & FLAG_FLUSH) {
273             if (flags & FLAG_VERBOSE)
274                 printf("flush\n");
275             
276             if (FLUSH(f) == FLUSH_ERROR)
277                 PERROR("FLUSH", GET_LAST_ERROR);
278         }
279
280         if (flags & FLAG_SEQUENTIAL) {
281             seek_to += bufsize;
282             if (flags & FLAG_TRUNCATE) {
283                 if (flags & FLAG_VERBOSE)
284                     printf("seek %" LL "d\n", seek_to);
285                 if (SEEK(f, seek_to, FILE_BEGIN) < 0)
286                     PERROR("SEEK", GET_LAST_ERROR);
287             }
288         }
289         
290         if (flags & FLAG_OPENCLOSE) {
291             if (flags & FLAG_VERBOSE)
292                 printf("close %s\n", filename);
293             CLOSE(f);
294         }
295         
296         if (flags & FLAG_DELETE) {
297             if (flags & FLAG_VERBOSE)
298                 printf("delete %s\n", filename);
299             DELETE_FILE(filename);
300         }
301     }
302
303     if (buf) {
304         if (flags & FLAG_DIRECT)
305             FREE_ALIGNED(buf);
306         else
307             free(buf);
308     }
309     
310     return 0;
311 }