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