replay-log: add support for replaying ops in target device sector range
[xfstests-dev.git] / lib / databin.c
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include <stdio.h>
19 #include <sys/param.h>
20 #include <string.h> /* memset */
21 #include <stdlib.h> /* rand */
22 #include "databin.h"
23
24 #if UNIT_TEST
25 #include <malloc.h>
26 #endif
27
28 static char Errmsg[80];
29
30 void
31 databingen (mode, buffer, bsize, offset)
32 int mode;       /* either a, c, r, o, z or C */
33 unsigned char *buffer;  /* buffer pointer */
34 int bsize;      /* size of buffer */
35 int offset;     /* offset into the file where buffer starts */
36 {
37 int ind;
38
39         switch (mode)
40         {
41         default:
42         case 'a':       /* alternating bit pattern */
43                 memset(buffer,0x55,bsize);
44                 break;
45
46         case 'c':       /* checkerboard pattern */
47                 memset(buffer,0xf0,bsize);
48                 break;
49
50         case 'C':       /* */
51                 for (ind=0;ind< bsize;ind++) {
52                     buffer[ind] = ((offset+ind)%8 & 0177);
53                 }
54                 break;
55
56         case 'o':
57                 memset(buffer,0xff,bsize);
58                 break;
59
60         case 'z':
61                 memset(buffer,0x0,bsize);
62                 break;
63
64         case 'r':       /* random */
65                 for (ind=0;ind< bsize;ind++) {
66                     buffer[ind] = (rand () & 0177) | 0100;
67                 }
68         }
69 }
70
71 /***********************************************************************
72  *
73  * return values:
74  *      >= 0 : error at byte offset into the file, offset+buffer[0-(bsize-1)]
75  *      < 0  : no error
76  ***********************************************************************/
77 int
78 databinchk(mode, buffer, bsize, offset, errmsg)
79 int mode;       /* either a, c, r, z, o, or C */
80 unsigned char *buffer;  /* buffer pointer */
81 int bsize;      /* size of buffer */
82 int offset;     /* offset into the file where buffer starts */
83 char **errmsg;
84 {
85         int cnt;
86         unsigned char *chr;
87         long expbits;
88         long actbits;
89
90         chr=buffer;
91
92         if ( errmsg != NULL ) {
93             *errmsg = Errmsg;
94         }
95         
96         switch (mode)
97         {
98         default:
99         case 'a':       /* alternating bit pattern */
100                 expbits=0x55;
101                 break;
102
103         case 'c':       /* checkerboard pattern */
104                 expbits=0xf0;
105                 break;
106
107         case 'C':       /* counting pattern */
108                 for (cnt=0;cnt< bsize;cnt++) {
109                     expbits = ((offset+cnt)%8 & 0177);
110
111                     if ( buffer[cnt] != expbits ) {
112                         sprintf(Errmsg,
113                             "data mismatch at offset %d, exp:%#lo, act:%#o",
114                             offset+cnt, expbits, buffer[cnt]);
115                         return offset+cnt;
116                     }
117                 }
118                 sprintf(Errmsg, "all %d bytes match desired pattern", bsize);
119                 return -1;
120
121         case 'o':
122                 expbits=0xff;
123                 break;
124
125         case 'z':
126                 expbits=0;
127                 break;
128
129         case 'r':
130                 return -1;      /* no check can be done for random */
131         }
132
133         for (cnt=0; cnt<bsize; chr++, cnt++) {
134             actbits = (long)*chr;
135
136             if ( actbits != expbits ) {
137                 sprintf(Errmsg, "data mismatch at offset %d, exp:%#lo, act:%#lo",
138                     offset+cnt, expbits, actbits);
139                 return offset+cnt;
140             }
141         }
142
143         sprintf(Errmsg, "all %d bytes match desired pattern", bsize);
144         return -1; /* all ok */
145 }
146
147 #if UNIT_TEST
148
149 /***********************************************************************
150  * main for doing unit testing
151  ***********************************************************************/
152 int
153 main(ac, ag)
154 int ac;
155 char **ag;
156 {
157
158     int size=1023;
159     int offset;
160     int number;
161     unsigned char *buffer;
162     int ret;
163     char *errmsg;
164
165     if ((buffer=(unsigned char *)malloc(size)) == NULL ) {
166         perror("malloc");
167         exit(2);
168     }
169
170
171 printf("***** for a ****************************\n");
172     databingen('a', buffer, size, 0);
173     printf("databingen('a', buffer, %d, 0)\n", size);
174
175     ret=databinchk('a', buffer, size, 0, &errmsg);
176     printf("databinchk('a', buffer, %d, 0, &errmsg) returned %d: %s\n",
177         size, ret, errmsg);
178     if ( ret == -1 )
179         printf("\tPASS return value of -1 as expected\n");
180     else
181         printf("\tFAIL return value %d, expected -1\n", ret);
182
183     offset=232400;
184     ret=databinchk('a', &buffer[1], size-1, offset, &errmsg);
185     printf("databinchk('a', &buffer[1], %d, %d, &errmsg) returned %d: %s\n",
186         size, offset, ret, errmsg);
187     if ( ret == -1 )
188         printf("\tPASS return value of -1 as expected\n");
189     else
190         printf("\tFAIL return value %d, expected -1\n", ret);
191
192     buffer[15]= 0x0;
193     printf("changing char 15 (offset (%d+15) = %d) to 0x0\n", offset, offset+15);
194     number=offset+15;
195
196     ret=databinchk('a', &buffer[1], size-1, offset+1, &errmsg);
197     printf("databinchk('a', &buffer[1], %d, %d, &errmsg) returned %d: %s\n",
198         size-1, offset+1, ret, errmsg);
199     if ( ret == number )
200         printf("\tPASS return value of %d as expected\n", number);
201     else
202         printf("\tFAIL return value %d, expected %d\n", ret, number);
203
204
205
206 printf("***** for c ****************************\n");
207     databingen('c', buffer, size, 0);
208     printf("databingen('c', buffer, %d, 0)\n", size);
209
210     ret=databinchk('c', buffer, size, 0, &errmsg);
211     printf("databinchk('c', buffer, %d, 0, &errmsg) returned %d: %s\n",
212         size, ret, errmsg);
213     if ( ret == -1 )
214         printf("\tPASS return value of -1 as expected\n");
215     else
216         printf("\tFAIL return value %d, expected -1\n", ret);
217
218     offset=232400;
219     ret=databinchk('c', &buffer[1], size-1, offset, &errmsg);
220     printf("databinchk('c', &buffer[1], %d, %d, &errmsg) returned %d: %s\n",
221         size, offset, ret, errmsg);
222     if ( ret == -1 )
223         printf("\tPASS return value of -1 as expected\n");
224     else
225         printf("\tFAIL return value %d, expected -1\n", ret);
226
227     buffer[15]= 0x0;
228     printf("changing char 15 (offset (%d+15) = %d) to 0x0\n", offset, offset+15);
229     number=offset+15;
230
231     ret=databinchk('c', &buffer[1], size-1, offset+1, &errmsg);
232     printf("databinchk('c', &buffer[1], %d, %d, &errmsg) returned %d: %s\n",
233         size-1, offset+1, ret, errmsg);
234     if ( ret == number )
235         printf("\tPASS return value of %d as expected\n", number);
236     else
237         printf("\tFAIL return value %d, expected %d\n", ret, number);
238
239 printf("***** for C ****************************\n");
240
241     databingen('C', buffer, size, 0);
242     printf("databingen('C', buffer, %d, 0)\n", size);
243
244     ret=databinchk('C', buffer, size, 0, &errmsg);
245     printf("databinchk('C', buffer, %d, 0, &errmsg) returned %d: %s\n",
246         size, ret, errmsg);
247     if ( ret == -1 )
248         printf("\tPASS return value of -1 as expected\n");
249     else
250         printf("\tFAIL return value %d, expected -1\n", ret);
251
252     offset=18;
253     ret=databinchk('C', &buffer[18], size-18, 18, &errmsg);
254     printf("databinchk('C', &buffer[18], %d, 18, &errmsg) returned %d: %s\n",
255         size-18, ret, errmsg);
256     if ( ret == -1 )
257         printf("\tPASS return value of -1 as expected\n");
258     else
259         printf("\tFAIL return value %d, expected -1\n", ret);
260
261     buffer[20]= 0x0;
262     buffer[21]= 0x0;
263     printf("changing char 20 and 21 to 0x0 (offset %d and %d)\n", 20,
264         21);
265
266     ret=databinchk('C', &buffer[18], size-18, 18, &errmsg);
267     printf("databinchk('C', &buffer[18], %d, 18, &errmsg) returned %d: %s\n",
268         size-18, ret, errmsg);
269
270     if ( ret == 20 || ret == 21 )
271         printf("\tPASS return value of %d or %d as expected\n",
272             20, 21);
273     else
274         printf("\tFAIL return value %d, expected %d or %d\n", ret,
275             20, 21 );
276
277     exit(0);
278
279 }
280
281 #endif
282