Fix build failure.
[xfstests-dev.git] / dmapi / src / suite2 / src / test_invis.c
1 /*
2  * Copyright (c) 2000-2001 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
19 #include <sys/types.h>
20 #include <sys/stat.h>
21
22 #include <limits.h>
23
24 #include <lib/hsm.h>
25 #include <lib/errtest.h>
26
27 #include <getopt.h>
28 #include <string.h>
29 #include <time.h>
30
31 /*---------------------------------------------------------------------------
32
33 Automated test of the DMAPI functions dm_write_invis() and dm_read_invis()
34
35 The command line is:
36
37         test_invis [-s sid] [-v] ls_path pathname
38
39 where:
40    sid
41       is the session ID whose events you you are interested in.
42    ls_path
43       is the path to a specific copy of ls, important only for its size
44    pathname
45       is the filesystem to use for the test.
46
47 DM_WRITE_SYNC is is not supported.
48 ----------------------------------------------------------------------------*/
49
50 #define OFF_MAX  50
51 #define OFF_STEP 5
52 #define LEN_MAX  50
53 #define LEN_STEP 5
54
55 #ifndef linux
56 extern  char    *sys_errlist[];
57 #endif
58 extern  int     optind;
59 extern  char    *optarg;
60
61
62 char    *Progname;
63
64
65 static void
66 usage(void)
67 {
68         fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path pathname\n", 
69                 Progname);
70         exit(1);
71 }
72
73
74 int
75 main(
76         int     argc, 
77         char    **argv)
78 {
79         dm_sessid_t     sid = DM_NO_SESSION;
80         char            *dir_name = NULL;
81         char            *ls_path = NULL;
82         dm_off_t        offset = 0;
83         dm_size_t       length = 1;
84         dm_size_t       curlength = 0;
85         u_char          ch;
86         void            *bufp = NULL;
87         void            *hanp;
88         size_t          hlen;
89         dm_ssize_t      rc;
90         char            *name;
91         char            test_file[128];
92         char            command[128];
93         int             opt;
94         int             i;
95         int             j;
96         int             k;
97         int             Vflag=0;
98         struct stat     statbuf;
99         struct stat     checkbuf;
100         dm_token_t      test_token;
101         void*           test_vp;
102         int             cont;
103         int             error_reported;
104
105         if (Progname = strrchr(argv[0], '/')) {
106                 Progname++;
107         } else {
108                 Progname = argv[0];
109         }
110
111         /* Crack and validate the command line options. */
112
113         while ((opt = getopt(argc, argv, "vs:")) != EOF) {
114                 switch (opt) {
115                 case 'v':
116                         Vflag++;
117                         break;
118                 case 's':
119                         sid = atol(optarg);
120                         break;
121                 case '?':
122                         usage();
123                 }
124         }
125         if (optind + 2 != argc)
126                 usage();
127         ls_path = argv[optind];
128         dir_name = argv[optind+1];
129
130         if (dm_init_service(&name) == -1)  {
131                 fprintf(stderr, "Can't initialize the DMAPI\n");
132                 exit(1);
133         }
134         if (sid == DM_NO_SESSION)
135                 find_test_session(&sid);
136         
137         /* Get a random character for read/write tests */
138         srand((unsigned int)time(NULL));
139         ch = (u_char)rand(); 
140
141         printf("Invisible read/write tests beginning...\n");
142         
143         /* File creation loop*/
144         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
145           for (j=0; j<OFF_MAX; j+=OFF_STEP) {
146             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
147                     dir_name, i, j);
148             sprintf(command, "cp %s %s\n", ls_path, test_file); 
149             system(command);
150           }
151         }
152         
153         /* Write to files, then read them to check for correct results. 
154            Do timestamp checking along the way. */
155
156         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
157           for (j=0; j<OFF_MAX; j+=OFF_STEP) {
158
159 #define max(a,b) ((a) > (b) ? (a) : (b))
160             length = max((dm_size_t)(i), length);
161             offset = (dm_off_t)(j);
162
163             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
164                     dir_name, i, j);
165             
166             if (stat(test_file, &statbuf)){
167               fprintf(stdout, 
168                       "Error: unable to stat test file; %s (before test)\n", 
169                       test_file);
170               continue;
171             }
172             
173             if (dm_path_to_handle(test_file, &hanp, &hlen)) {
174               fprintf(stderr, "can't get handle for %s; bypassing test\n",
175                       test_file);
176               continue;
177             }
178             
179             if (length > curlength) {
180               if(curlength>0)
181                 free(bufp);
182               if ((bufp = malloc(length)) == NULL) {
183                 fprintf(stderr, "malloc of %llu bytes failed\n", length);
184                 continue;
185               }
186               curlength = length;
187               memset(bufp, ch, length);
188             }
189
190             rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
191                                 0, offset, length, bufp);
192             cont = 0;
193             if (rc < 0) {
194               fprintf(stderr, "dm_write_invis failed, %s\n", ERR_NAME);
195               cont=1;
196             } else if (rc != length) {
197               fprintf(stderr, "expected to write %lld bytes, actually "
198                       "wrote %lld\n", length, rc);
199               cont=1;
200             }
201             if(cont)
202                 continue;
203             
204             /* Timestamp checking, part 1 */
205             if (stat(test_file, &checkbuf)){
206               fprintf(stdout, 
207                       "Error: unable to stat the test file; %s (after write)\n", 
208                       test_file);
209             }
210             else {
211 #ifdef __sgi
212               if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
213               (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
214               (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
215               (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
216               (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
217               (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
218 #else
219               if ((statbuf.st_atime == checkbuf.st_atime) &&
220               (statbuf.st_mtime == checkbuf.st_mtime) &&
221               (statbuf.st_ctime == checkbuf.st_ctime))
222 #endif
223                 {
224                 if (Vflag) {
225                   printf("Report: time stamp unchanged by write\n");
226                 }
227               }
228               else {
229                 printf("Error: time stamp changed by write\n");
230               }
231             }
232             
233             rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
234                                 offset, length, bufp);
235             if (rc < 0) {
236               fprintf(stderr, "dm_read_invis failed, %s\n", ERR_NAME);
237               continue;
238             } 
239             else if (rc != length) {
240               fprintf(stderr, "expected to read %lld bytes, actually "
241                       "wrote %lld\n", length, rc);
242               continue;
243             }
244             else {
245               /* Be sure the buffer is filled with the test char */
246               error_reported = 0;
247               for (k=0; k<i; k++){
248                 if (((u_char *)bufp)[k] == ch) {
249                   if (Vflag) printf(".");
250                 }
251                 else {
252                   if(!error_reported){
253                         printf("Error!(line=%d)\n", __LINE__);
254                         error_reported++;
255                   }
256                 }
257               }
258               if (Vflag) printf("\n");
259             }
260
261             /* Timestamp checking, part 2 */
262             if (stat(test_file, &statbuf)){
263               fprintf(stdout, 
264                       "Error: unable to stat the test file; %s (after write)\n", 
265                       test_file);
266             }
267             else {
268 #ifdef __sgi
269               if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
270               (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
271               (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
272               (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
273               (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
274               (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
275 #else
276               if ((statbuf.st_atime == checkbuf.st_atime) &&
277               (statbuf.st_mtime == checkbuf.st_mtime) &&
278               (statbuf.st_ctime == checkbuf.st_ctime))
279 #endif
280                 {
281                 if (Vflag) {
282                   printf("Report: time stamp unchanged by read\n");
283                 }
284               }
285               else {
286                 printf("Error: time stamp changed by read\n");
287               }
288             }
289           } /* for (j=0; j<OFF_MAX; j+=OFF_STEP) */
290         } /* for(i=0; i<LEN_MAX; i+=LEN_STEP) */
291         
292         /* File deletion loop*/
293         for(i=0; i<LEN_MAX; i+=LEN_STEP) {
294           for(j=0; j<OFF_MAX; j+=OFF_STEP) {
295             sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
296                     dir_name, i, j);
297             sprintf(command, "rm %s\n", test_file); 
298             system(command);
299           }
300         }
301         
302         /*************************************\
303         |* Correct-input testing complete.   *|
304         |* Beginning improper-input testing. *|
305         \*************************************/
306         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
307                 dir_name);
308         sprintf(command, "cp %s %s\n", ls_path, test_file); 
309         system(command);
310
311         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
312           fprintf(stderr, "can't get handle for %s; bypassing errno tests\n",
313                   test_file);
314         }
315         else {
316           dm_off_t offset;
317
318           /* Try writing a character waaaaaay up in the millions range */
319           sprintf(bufp, "%c", ch);
320           if (stat(test_file, &statbuf)){
321            fprintf(stdout, 
322                     "Error: unable to stat the test file; %s \n", 
323                     test_file);
324           }
325           offset = ((1000000*(dm_off_t)(ch)) > statbuf.st_size) ? 
326                             statbuf.st_size : (1000000*(dm_off_t)(ch));
327           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
328                              offset, 1, bufp)==-1){
329             printf("Error invis-writing 0x%x at byte 0x%x million: %s\n", 
330                    *(u_char *)bufp, (unsigned int)ch, ERR_NAME);
331           }
332           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
333                                  offset, 1, bufp)==-1){
334             printf("Error invis-reading at byte %u million: %s\n",
335                    (unsigned int)ch, ERR_NAME);
336           }
337           else if (((u_char *)bufp)[0]!=ch) {
338             printf("Error: wanted to read %c and instead got %s.\n",
339                    ch, (u_char *)bufp);
340           }
341           else if (Vflag) {
342             printf("Report: \"0x%x\" was written and \"0x%x\" was read "
343                    "at byte %d million.\n", ch, *(u_char *)bufp, ch);
344           }
345
346 #ifdef __sgi
347           /* Try writing a character in the 2 gigabyte (2^31) range */
348           sprintf(bufp, "%c", ch);
349           if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
350                              2147840000, 1, bufp)==-1){
351             printf("Error invis-writing %s at 2 gigabytes: %s\n", 
352                    (u_char *)bufp, ERR_NAME);
353           }
354           else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
355                                  2147840000, 1, bufp)==-1){
356             printf("Error invis-reading at 2 gigabytes: %s\n",
357                    ERR_NAME);
358           }
359           else if (((u_char *)bufp)[0]!=ch) {
360             printf("Error: wanted to read %c and instead got %s.\n",
361                    ch, (u_char *)bufp);
362           }
363           else if (Vflag) {
364             printf("Report: \"0x%x\" was written and \"0x%x\" was read "
365                    "at 2147840000 bytes\n\t(a bit over 2 gigabytes).\n", 
366                    ch, *(u_char *)bufp);
367           }
368 #endif
369
370           printf("\t(errno subtests beginning...)\n");
371           /**** WRITE tests ****/
372           /*---------------------------------------------------------*/
373           EXCLTEST("write", hanp, hlen, test_token, 
374                    dm_write_invis(sid, hanp, hlen, test_token,
375                                   0, 0, 13, "write test 1"))
376           /*---------------------------------------------------------*/
377             if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
378             fprintf(stderr, 
379                     "Cannot create a test handle (%s); skipping EBADF test\n",
380                     ERR_NAME);
381           }
382           else {
383             ((char *) test_vp)[hlen/2]++;
384             ERRTEST(EBADF,
385                     "write",
386                     dm_write_invis(sid, test_vp, hlen, DM_NO_TOKEN,
387                                    0, 0, 0, bufp))
388             ERRTEST(EBADF,
389                     "read",
390                     dm_read_invis(sid, test_vp, hlen, DM_NO_TOKEN,
391                                   0, 0, bufp))
392             dm_handle_free(test_vp, hlen);
393           }
394
395           /*---------------------------------------------------------*/
396           ERRTEST(EBADF,
397                   "write",
398                   dm_write_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
399                                  0, 0, 0, NULL))
400           /*---------------------------------------------------------*/
401           ERRTEST(EFAULT,
402                   "write",
403                   dm_write_invis(sid, NULL, hlen, DM_NO_TOKEN,
404                                  0, 0, 0, NULL))
405           /*---------------------------------------------------------*/
406 #if 0
407           PROBLEM: write_invis refuses to produce EINVAL for 
408           lengths that will not fit in a dm_size_t.
409
410           ERRTEST(EINVAL,
411                   "(bad length) write",
412                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
413                                  0, 4096, (long long)0xFFFFFFFFFFFFFFFFLL,
414                                  "write invalid length test"))
415 #endif
416           /*---------------------------------------------------------*/
417 #if 0
418           PROBLEM (somewhat fixed): A signal is sent, rather than EFBIG.
419           Presumably, this signal is needed to comply with...something.
420           If this is uncommented, the program will abort here, with the 
421           error message "exceeded file size limit". 
422
423           ERRTEST(EFBIG,
424                   "write",
425                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
426                                  0, (long long)0xFFFFFFFFFFLL, 
427                                  (long long)0xFFFFFFFFFFLL,
428                                  "foo foo foo"))
429 #endif
430           /*---------------------------------------------------------*/
431 #ifdef VERITAS_21
432           ERRTEST(EINVAL,
433                   "(bad offset) write",
434                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
435                                  0, (dm_size_t) ULONG_MAX, 5,
436                                  "write invalid offset test"))
437 #else
438 #ifndef linux
439           ERRTEST(EINVAL,
440                   "(bad offset) write",
441                   dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
442                                  0, (dm_size_t) ULONGLONG_MAX, 5,
443                                  "write invalid offset test"))
444 #endif
445 #endif
446
447           /*---------------------------------------------------------*/
448           ERRTEST(EINVAL,
449                   "(bad sid) write",
450                   dm_write_invis(-100, hanp, hlen, DM_NO_TOKEN,
451                                  0, 0, 26, "write invalid offset test"))
452
453
454           /**** READ tests ****/
455           /*---------------------------------------------------------*/
456           SHAREDTEST("read", hanp, hlen, test_token,
457                      dm_read_invis(sid, hanp, hlen, test_token, 
458                                    0, 13, bufp))
459           /*---------------------------------------------------------*/
460           ERRTEST(EBADF,
461                   "read",
462                   dm_read_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
463                                  0, 0, bufp))
464           /*---------------------------------------------------------*/
465           ERRTEST(EFAULT,
466                   "read",
467                   dm_read_invis(sid, NULL, hlen, DM_NO_TOKEN,
468                                  0, 0, bufp))
469           /*---------------------------------------------------------*/
470 #ifdef  VERITAS_21
471           ERRTEST(EINVAL,
472                   "(bad offset) read",
473                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
474                                 ULONG_MAX, 5, bufp));
475 #else
476 #ifndef linux
477           ERRTEST(EINVAL,
478                   "(bad offset) read",
479                   dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
480                                 ULONGLONG_MAX, 5, bufp));
481 #endif
482 #endif
483
484           /*---------------------------------------------------------*/
485           ERRTEST(EINVAL,
486                   "(bad sid) read",
487                   dm_read_invis(-100, hanp, hlen, DM_NO_TOKEN,
488                                 0, 5, bufp))
489           /*---------------------------------------------------------*/
490           printf("\t(errno subtests complete!)\n");
491         }
492         sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
493                 dir_name);
494         sprintf(command, "rm %s \n", test_file); 
495         system(command);
496
497         printf("Invisible read/write tests complete.\n");
498
499         dm_handle_free(hanp, hlen);
500         exit(0);
501 }