fd0912bbebae65f90913e5b0947bebc49d03f49c
[xfstests-dev.git] / src / holes.c
1 /*
2  * Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 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, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * 
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  * 
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  * 
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  * 
26  * http://www.sgi.com 
27  * 
28  * For further information regarding this notice, see: 
29  * 
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32  
33 #include "global.h"
34
35 int verbose;            /* print lots of debugging info */
36
37 void usage(char *progname);
38 void writeblks(int fd, long filesize, int blocksize,
39                    int interleave, int base, int rev);
40 int readblks(int fd, long filesize, int blocksize,
41                   int interleave, int count);
42
43 void
44 usage(char *progname)
45 {
46         fprintf(stderr, "usage: %s [-l filesize] [-b blocksize] [-i interleave]\n"
47                         "\t\t[-c count] [-r(everse)] [-v(erbose)] filename\n",
48                         progname);
49         exit(1);
50 }
51
52 int
53 main(int argc, char *argv[])
54 {
55         int interleave, blocksize, count, rev, i, ch, fd;
56         long filesize;
57         char *filename = NULL;
58         int errs;
59
60         filesize = 1024*1024;
61         blocksize = 4096;
62         count = interleave = 4;
63         rev = verbose = 0;
64         while ((ch = getopt(argc, argv, "b:l:i:c:rv")) != EOF) {
65                 switch(ch) {
66                 case 'b':       blocksize  = atoi(optarg);      break;
67                 case 'c':       count      = atoi(optarg);      break;
68                 case 'i':       interleave = atoi(optarg);      break;
69                 case 'l':       filesize   = atol(optarg);      break;
70                 case 'v':       verbose++;                      break;
71                 case 'r':       rev++;                          break;
72                 default:        usage(argv[0]);                 break;
73                 }
74         }
75         if (optind == argc-1)
76                 filename = argv[optind];
77         else
78                 usage(argv[0]);
79         if ((filesize % (blocksize*interleave)) != 0) {
80                 filesize -= filesize % (blocksize * interleave);
81                 printf("filesize not a multiple of blocksize*interleave,\n");
82                 printf("reducing filesize to %ld\n", filesize);
83         }
84         if (count > interleave) {
85                 count = interleave;
86                 printf("count of passes is too large, setting to %d\n", count);
87         } else if (count < 1) {
88                 count = 1;
89                 printf("count of passes is too small, setting to %d\n", count);
90         }
91
92         if ((fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
93                 perror("open");
94                 return 1;
95         }
96         for (i = 0; i < count; i++) {
97                 writeblks(fd, filesize, blocksize, interleave, i, rev);
98         }
99         errs=readblks(fd, filesize, blocksize, interleave, count);
100         if (close(fd) < 0) {
101                 perror("close");
102                 return 1;
103         }
104         if (errs) {
105             printf("%d errors detected during readback\n", errs);
106             return 1;
107         }
108         return 0;
109 }
110
111 void
112 writeblks(int fd, long filesize, int blocksize, int interleave, int base, int rev)
113 {
114         long offset;
115         char *buffer;
116
117         if ((buffer = calloc(1, blocksize)) == NULL) {
118                 perror("malloc");
119                 exit(1);
120         }
121
122         if (rev) {
123                 offset = (filesize-blocksize) - (base * blocksize);
124         } else {
125                 offset = base * blocksize;
126         }
127         for (;;) {
128                 if (lseek(fd, offset, SEEK_SET) < 0) {
129                         perror("lseek");
130                         exit(1);
131                 }
132                 *(long *)buffer = *(long *)(buffer+256) = offset;
133                 if (write(fd, buffer, blocksize) < blocksize) {
134                         perror("write");
135                         exit(1);
136                 }
137                 if (verbose) {
138                         printf("writing data at offset=%ld, delta=%d, value 0x%lx and 0x%lx\n",
139                                         offset-base*blocksize, base,
140                                         *(long *)buffer,
141                                         *(long *)(buffer+256));
142                 }
143
144                 if (rev) {
145                         offset -= interleave*blocksize;
146                         if (offset < 0)
147                                 break;
148                 } else {
149                         offset += interleave*blocksize;
150                         if (offset >= filesize)
151                                 break;
152                 }
153         }
154         
155         {
156             /* pad file out to full length */
157             char *zero="";
158             if (lseek(fd, filesize-1, SEEK_SET)<0) {
159                 perror("lseek");
160                 exit(1);
161             }
162             if (write(fd, zero, 1)!=1) {
163                 perror("write");
164                 exit(1);
165             }
166         }
167
168         free(buffer);
169 }
170
171 int
172 readblks(int fd, long filesize, int blocksize, int interleave, int count)
173 {
174         long offset;
175         char *buffer, *tmp;
176         int xfer, i;
177         int errs=0;
178
179         if ((buffer = calloc(interleave, blocksize)) == NULL) {
180                 perror("malloc");
181                 exit(1);
182         }
183         xfer = interleave * blocksize;
184
185         if (lseek(fd, (long)0, SEEK_SET) < 0) {
186                 perror("lseek");
187                 exit(1);
188         }
189         for (offset = 0; offset < filesize; offset += xfer) {
190                 if ((i = read(fd, buffer, xfer) < xfer)) {
191                         if (i == 0)
192                                 break;
193                         if (i < 0)
194                                 perror("read");
195                         printf("short read: %d of %d bytes read\n", i, xfer);
196                         
197                         exit(1);
198                 }
199                 for (tmp = buffer, i = 0; i < count; i++, tmp += blocksize) {
200                         if ( (*(long *)tmp != (offset+i*blocksize)) ||
201                              (*(long *)(tmp+256) != (offset+i*blocksize)) ) {
202                                 printf("mismatched data at offset=%ld, delta=%d, expected 0x%lx, got 0x%lx and 0x%lx\n",
203                                                    offset, i,
204                                                    offset+i*blocksize,
205                                                    *(long *)tmp,
206                                                    *(long *)(tmp+256));
207                                 errs++;
208                         }
209                 }
210         }
211
212         free(buffer);
213         return errs;
214 }