1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2013 SGI. All Rights Reserved.
15 #include <sys/socket.h>
18 #include <sys/types.h>
24 #define PERROR(a,b) perror(a)
25 #define GET_LAST_ERROR errno
28 #define INVALID_HANDLE -1
29 #define TRUNCATE_ERROR -1
30 #define FLUSH_ERROR EOF
32 #define FILE_BEGIN SEEK_SET
33 #define FILE_CURRENT SEEK_CUR
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))
44 #define ALLOC_ALIGNED(S) (memalign(65536, S))
45 #define FREE_ALIGNED(P) (free(P))
47 #define DIRECT_IO_FLAG O_DIRECT
65 "Usage: %s [switches] <filename>\n"
66 " -i <count> = repeat count (default forever)\n"
72 " -b <size> = buffer size\n"
85 main(int argc, char *argv[])
87 HANDLE f = INVALID_HANDLE;
97 while ((c = getopt(argc, argv, "i:orwb:svthfFDd?")) != EOF) {
100 count = atoi(optarg);
103 flags |= FLAG_OPENCLOSE;
112 flags |= FLAG_TRUNCATE;
115 flags |= FLAG_VERBOSE;
118 bufsize = atoi(optarg);
121 flags |= FLAG_SEQUENTIAL;
127 flags |= FLAG_DIRECT;
130 flags |= FLAG_DELETE;
139 if (optind != argc - 1) {
144 filename = argv[optind];
146 fprintf(stderr, "nothing to do!\n");
150 if (flags & FLAG_DIRECT)
151 buf = (char *)ALLOC_ALIGNED(bufsize);
153 buf = (char *)malloc(bufsize);
156 PERROR("malloc", GET_LAST_ERROR);
158 for (i = 0; i < bufsize; i++) {
162 for (i = 0; count < 0 || i < count; i++) {
164 if ((flags & FLAG_OPENCLOSE) || !i) {
167 if (flags & FLAG_VERBOSE)
168 printf("open %s\n", filename);
171 if (flags & FLAG_DIRECT)
172 fileflags |= DIRECT_IO_FLAG;
174 f = OPEN(filename, fileflags);
175 if (f == INVALID_HANDLE)
176 PERROR("OPEN", GET_LAST_ERROR);
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);
187 if (flags & FLAG_WRITE) {
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);
197 if (flags & FLAG_VERBOSE)
198 printf("write %d\n", bufsize);
199 if ((sizewritten = WRITE(f, buf, bufsize)) != bufsize) {
201 PERROR("WRITE", GET_LAST_ERROR);
203 fprintf(stderr, "short write: %d of %d\n",
204 sizewritten, bufsize);
208 if (flags & FLAG_READ) {
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);
218 if (flags & FLAG_VERBOSE)
219 printf("read %d\n", bufsize);
220 if ((sizeread = READ(f, buf, bufsize)) != bufsize) {
222 PERROR("READ", GET_LAST_ERROR);
224 fprintf(stderr, "short read: %d of %d\n",
227 fprintf(stderr, "Read past EOF\n");
233 if (flags & FLAG_TRUNCATE) {
234 if (flags & FLAG_VERBOSE)
237 if (SEEK(f, 0, FILE_BEGIN) < 0)
238 PERROR("SEEK", GET_LAST_ERROR);
240 if (flags & FLAG_VERBOSE)
241 printf("truncate\n");
243 if (TRUNCATE(f) == TRUNCATE_ERROR)
244 PERROR("TRUNCATE", GET_LAST_ERROR);
247 if (flags & FLAG_FLUSH) {
248 if (flags & FLAG_VERBOSE)
251 if (FLUSH(f) == FLUSH_ERROR)
252 PERROR("FLUSH", GET_LAST_ERROR);
255 if (flags & FLAG_SEQUENTIAL) {
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);
265 if (flags & FLAG_OPENCLOSE) {
266 if (flags & FLAG_VERBOSE)
267 printf("close %s\n", filename);
271 if (flags & FLAG_DELETE) {
272 if (flags & FLAG_VERBOSE)
273 printf("delete %s\n", filename);
274 DELETE_FILE(filename);
279 if (flags & FLAG_DIRECT)