Update copyright dates
[xfstests-dev.git] / dmapi / src / suite2 / src / test_eventlist.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 <lib/hsm.h>
34 #include <lib/errtest.h>
35
36 #include <getopt.h>
37 #include <string.h>
38
39
40 /*---------------------------------------------------------------------------
41
42 Test program used to test the DMAPI function dm_set_eventlist().  The
43 command line is:
44
45         test_eventlist [-v] [-s sid] [-t token] directory
46
47 where:
48 ls_path
49         is the path to a specific copy of ls, important only for its size
50 directory
51         is the pathname to a DMAPI filesystem.
52 sid
53         is the dm_sessid_t value to use.
54 token
55         is the dm_token_t value to use (DM_NO_TOKEN is the default).
56 ----------------------------------------------------------------------------*/
57
58 #ifndef linux
59 extern  char    *sys_errlist[];
60 #endif
61 extern  int     optind;
62 extern  char    *optarg;
63
64
65 char    *Progname;
66
67 int check_one_event (dm_sessid_t, void*, size_t, dm_token_t, 
68                      dm_eventtype_t, int);
69
70 static void
71 usage(void)
72 {
73         fprintf(stderr, "usage:\t%s [-v] [-s sid] [-t token]"
74                 "ls_path directory \n", Progname);
75         /* fprintf(stderr, "possible events are:\n");
76            for (i = 0; i < ev_namecnt; i++) {
77                 fprintf(stderr, "%s (%d)\n", ev_names[i].name,
78                         ev_names[i].value);
79         }
80         */
81         exit(1);
82 }
83
84
85 int
86 main(
87         int     argc, 
88         char    **argv)
89 {
90         dm_sessid_t     sid = DM_NO_SESSION;
91         dm_token_t      token = DM_NO_TOKEN;
92         char            object[128];
93         void            *hanp;
94         size_t          hlen;
95         int             Vflag = 0;
96         char            *name;
97         int             opt;
98         int             error;
99         void           *fshanp;
100         size_t          fshlen;
101         int             i;
102         char            command[128];
103         char           *ls_path;
104         char           *dir_name;
105         dm_token_t      test_token = DM_NO_TOKEN;
106         dm_eventset_t   eventset;
107         void           *test_vp;
108         u_int           nelemp;
109
110         if (Progname = strrchr(argv[0], '/')) {
111                 Progname++;
112         } else {
113                 Progname = argv[0];
114         }
115
116         /* Crack and validate the command line options. */
117
118         while ((opt = getopt(argc, argv, "s:t:uv")) != EOF) {
119                 switch (opt) {
120                 case 's':
121                         sid = atol(optarg);
122                         break;
123                 case 't':
124                         token = atol(optarg);
125                         break;
126                 case 'u':
127                         Vflag=2;
128                         break;
129                 case 'v':
130                         if (Vflag==0) Vflag=1;
131                         break;
132                 case '?':
133                         usage();
134                 }
135         }
136
137         if (optind + 2 != argc)
138                 usage();
139         ls_path = argv[optind];
140         dir_name = argv[optind+1];
141
142         if (dm_init_service(&name) == -1)  {
143                 fprintf(stderr, "Can't initialize the DMAPI\n");
144                 exit(1);
145         }
146
147         if (sid == DM_NO_SESSION)
148                 find_test_session(&sid);
149         
150         /* Get the directory handle */
151         if (dm_path_to_handle(dir_name, &hanp, &hlen)) {
152                 fprintf(stderr, "can't get handle for %s\n", dir_name);
153                 exit(1);
154         }
155
156         /***********************************************\
157         |* Test to run on a FILE...                    *|
158         \***********************************************/
159         
160         printf("File test beginning...\n");
161         sprintf(object, "%s/VeryLongUnlikelyFilename.DMAPIFOO", dir_name);
162         sprintf(command, "cp %s %s \n", ls_path, object); 
163         system(command);
164
165         if (dm_path_to_handle(object, &hanp, &hlen)) {
166                 fprintf(stderr, "can't get handle for %s\n; aborting test",
167                         object);
168         }
169         else {
170           for (i = 0; i < ev_namecnt; i++) {
171             error = check_one_event(sid, hanp, hlen, token,
172                                     ev_names[i].value, Vflag);  
173             switch (ev_names[i].value){
174             case DM_EVENT_ATTRIBUTE: case DM_EVENT_DESTROY:
175               if (error) {
176                 fprintf(stderr, "ERROR: %s failed on a file!\n",
177                         ev_names[i].name);  
178               }
179               break;
180             default: 
181               if (!error) {
182                 fprintf(stderr, "ERROR: %s succeeded on a file!\n",
183                         ev_names[i].name);  
184               }
185             }
186           }
187           /*------------------------*\
188           |*  ## Errno subtests ##  *|
189           \*------------------------*/
190           printf("\t(errno subtests beginning...)\n");
191           DMEV_ZERO(eventset);
192           DMEV_SET(DM_EVENT_ATTRIBUTE, eventset);
193           /*---------------------------------------------------------*/
194           EXCLTEST("set", hanp, hlen, test_token, 
195                    dm_set_eventlist(sid, hanp, hlen, test_token, 
196                                     &eventset, DM_EVENT_MAX))
197           /*---------------------------------------------------------*/
198           if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
199             fprintf(stderr, 
200                     "Cannot create a test handle (%s); skipping EBADF test\n",
201                     ERR_NAME);
202           }
203           else {
204             /* Alter the handle copy to make it (presumably) invalid */
205             ((char *) test_vp)[hlen/2]++;
206             ERRTEST(EBADF,
207                     "set",
208                     dm_set_eventlist(sid, test_vp, hlen, token,
209                                      &eventset, DM_EVENT_MAX))
210             dm_handle_free(test_vp, hlen);
211           }
212           /*---------------------------------------------------------*/
213 #ifdef  VERITAS_21
214         /* Veritas gets a segmentation fault if hanp is NULL or if the
215            &eventset is out of range.
216         */
217         fprintf(stderr, "\tERROR testing for EFAULT in set (bad hanp): "
218                 "Veritas gets a segmentation fault.\n");
219         fprintf(stderr, "\tERROR testing for EFAULT in set (bad eventset): "
220                 "Veritas gets a segmentation fault.\n");
221 #else
222           ERRTEST(EFAULT, 
223                   "set",
224                   dm_set_eventlist(sid, NULL, hlen, token, 
225                                 &eventset, DM_EVENT_MAX))
226           ERRTEST(EFAULT, 
227                   "set",
228                   dm_set_eventlist(sid, hanp, hlen, token, 
229                                 (dm_eventset_t*)(-1000), DM_EVENT_MAX))
230 #endif
231           /*---------------------------------------------------------*/
232           ERRTEST(EINVAL,
233                   "set (bad session)",
234                   dm_set_eventlist(-100, hanp, hlen, token,
235                                    &eventset, DM_EVENT_MAX))
236           /*---------------------------------------------------------*/
237           ERRTEST(EINVAL, 
238                   "set (bad token)",
239                   dm_set_eventlist(sid, hanp, hlen, 0, 
240                                 &eventset, DM_EVENT_MAX))
241           /*---------------------------------------------------------*/
242 #if 0
243           PROBLEM: too-small buffer does not produce E2BIG 
244           { 
245             dm_eventset_t  *small_evsp = malloc(0);
246             if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
247               fprintf(stderr, 
248                       "can't get filesystem handle from %s; aborting test\n",
249                       dir_name);
250             } 
251             else {
252               check_one_event(sid, fshanp, fshlen, token, 
253                               DM_EVENT_CREATE, Vflag);
254               ERRTEST(E2BIG,
255                       "(broken) get",
256                       dm_get_eventlist(sid, fshanp, fshlen, token, 
257                                        DM_EVENT_MAX, small_evsp, &nelemp))
258               check_one_event(sid, fshanp, fshlen, token, 
259                               DM_EVENT_INVALID, Vflag);
260             }
261           }
262 #endif
263           /*---------------------------------------------------------*/
264           SHAREDTEST("get", hanp, hlen, test_token, 
265                      dm_get_eventlist(sid, hanp, hlen, test_token,
266                                       DM_EVENT_MAX, &eventset, &nelemp))
267           /*---------------------------------------------------------*/
268           ERRTEST(EBADF,
269                   "get",
270                   dm_get_eventlist(sid, test_vp, hlen, token, DM_EVENT_MAX,
271                                    &eventset, &nelemp))
272           /*---------------------------------------------------------*/
273 #ifdef  VERITAS_21
274         /* Veritas gets a segmentation fault if hanp is NULL. */
275
276         fprintf(stderr, "\tERROR testing for EFAULT in get (bad hanp): "
277                 "Veritas gets a segmentation fault.\n");
278 #else
279           ERRTEST(EFAULT, 
280                   "get",
281                   dm_get_eventlist(sid, NULL, hlen, token, DM_EVENT_MAX,
282                                    &eventset, &nelemp ))
283 #endif
284           /*---------------------------------------------------------*/
285           ERRTEST(EINVAL,
286                   "get (bad session)",
287                   dm_get_eventlist(-100, hanp, hlen, token, DM_EVENT_MAX,
288                                    &eventset, &nelemp))
289           /*---------------------------------------------------------*/
290           ERRTEST(EINVAL, 
291                   "get (bad token)",
292                   dm_get_eventlist(sid, hanp, hlen, 0, DM_EVENT_MAX,
293                                 &eventset, &nelemp))
294           /*---------------------------------------------------------*/
295           printf("\t(errno subtests complete)\n");
296           /*---------------------*\
297           |* End of errno tests  *|
298           \*---------------------*/
299
300         /* Finally, use DM_EVENT_INVALID to delete events... */
301         check_one_event(sid, hanp, hlen, token, DM_EVENT_INVALID, Vflag);
302         }
303         sprintf(command, "rm %s \n", object); 
304         system(command);
305         printf("\tFile test complete.\n");
306         if (Vflag) printf("\n");
307         
308         /***********************************************\
309         |* Test to run on a DIRECTORY...               *|
310         \***********************************************/
311         
312         printf("Directory test beginning...\n");
313         sprintf(object, "%s/VeryLongUnlikelyDirectoryName.DMAPIFOO",
314                 dir_name);
315         sprintf(command, "mkdir %s \n", object); 
316         system(command);        
317         
318         if (opaque_to_handle(object, &hanp, &hlen)) {
319                 fprintf(stderr, "can't get handle for %s\n; aborting test",
320                         object);
321         }
322         else {
323           for (i = 0; i < ev_namecnt; i++) {
324             error = check_one_event(sid, hanp, hlen, token,
325                                     ev_names[i].value, Vflag);
326             switch (ev_names[i].value){
327             case DM_EVENT_CREATE:    case DM_EVENT_POSTCREATE:
328             case DM_EVENT_REMOVE:    case DM_EVENT_POSTREMOVE:
329             case DM_EVENT_RENAME:    case DM_EVENT_POSTRENAME:
330             case DM_EVENT_LINK:      case DM_EVENT_POSTLINK:
331             case DM_EVENT_SYMLINK:   case DM_EVENT_POSTSYMLINK:
332             case DM_EVENT_ATTRIBUTE: case DM_EVENT_DESTROY:
333               if (error) {
334                 fprintf(stderr, "ERROR: %s failed on a directory!\n",
335                         ev_names[i].name);  
336               }
337               break;
338             default: 
339               if (!error) {
340                 fprintf(stderr, "ERROR: %s succeeded on a directory!\n",
341                         ev_names[i].name);  
342               }
343             }
344           }
345         /* Use DM_EVENT_INVALID to delete events... */
346         check_one_event(sid, hanp, hlen, token, DM_EVENT_INVALID, Vflag);
347         }
348         sprintf(object, "%s/VeryLongUnlikelyDirectoryName.DMAPIFOO", dir_name);
349         sprintf(command, "rmdir %s\n", object); 
350         system(command);
351         printf("\tDirectory test complete.\n");
352         if (Vflag) printf("\n");
353
354         /***********************************************\
355         |* Test to run on a FILESYSTEM...              *|
356         \***********************************************/
357         
358         printf("Filesystem test beginning...\n");
359         
360         if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
361           fprintf(stderr, 
362                   "can't get filesystem handle from %s; aborting test\n",
363                   dir_name);
364         }
365         else {
366           for (i = 0; i < ev_namecnt; i++) {
367             error = check_one_event(sid, fshanp, fshlen, token, 
368                                     ev_names[i].value, Vflag);
369             switch (ev_names[i].value){
370             case DM_EVENT_PREUNMOUNT: case DM_EVENT_UNMOUNT:
371             case DM_EVENT_NOSPACE:    case DM_EVENT_DEBUT:
372             case DM_EVENT_CREATE:     case DM_EVENT_POSTCREATE:
373             case DM_EVENT_REMOVE:     case DM_EVENT_POSTREMOVE:
374             case DM_EVENT_RENAME:     case DM_EVENT_POSTRENAME:
375             case DM_EVENT_LINK:       case DM_EVENT_POSTLINK:
376             case DM_EVENT_SYMLINK:    case DM_EVENT_POSTSYMLINK:
377             case DM_EVENT_ATTRIBUTE:  case DM_EVENT_DESTROY:
378               if (error) {
379                 fprintf(stderr, "ERROR: %s failed on a filesystem!\n",
380                         ev_names[i].name);  
381               }
382               break;
383             default: 
384               if (!error) {
385                 fprintf(stderr, "ERROR: %s succeeded on a filesystem!\n",
386                         ev_names[i].name);  
387               }
388             }
389           }
390         /* Use DM_EVENT_INVALID to delete events... */
391         check_one_event(sid, fshanp, fshlen, token, DM_EVENT_INVALID, Vflag);
392         }
393         printf("\tFilesystem test complete.\n");
394
395         /***********************************************\
396         |* End of tests!                               *|
397         \***********************************************/
398
399         dm_handle_free(fshanp, fshlen);
400         dm_handle_free(hanp, hlen);
401         exit(0);
402 }
403
404 /*-------------------------------------------------------------------
405   check_one_event: 
406    
407   Using dm_set_eventlist, set a single event on the object
408   indicated by the handle.
409
410   Using dm_get_eventlist, check to see that the single event
411   was set correctly.
412   -------------------------------------------------------------------*/
413
414 int 
415 check_one_event (
416                  dm_sessid_t       sid,
417                  void              *hanp,
418                  size_t            hlen,
419                  dm_token_t        token,
420                  dm_eventtype_t    event,
421                  int               Vflag )
422 {
423         dm_eventset_t   eventset;
424         dm_eventset_t   check_eventset;
425         u_int           nelemp;
426         int             set_count = 0;
427         int             i;
428
429         DMEV_ZERO(eventset);
430         DMEV_ZERO(check_eventset);
431                 
432         if (event != DM_EVENT_INVALID) {
433           DMEV_SET(event, eventset);
434         }
435
436         if (dm_set_eventlist(sid, hanp, hlen, token, 
437                                       &eventset, DM_EVENT_MAX)) {
438                 if (Vflag){
439                   fprintf(stdout, " note: %s could not be set (%s)\n",
440                           ev_value_to_name(event), errno_names[errno]);
441                 }
442                 return (-1);
443         }
444
445         if (dm_get_eventlist(sid, hanp, hlen, token,
446                              DM_EVENT_MAX, &check_eventset, &nelemp)) {
447                 if (Vflag){
448                 fprintf(stdout, "dm_get_eventlist failed, %s\n",
449                         errno_names[errno]);
450                 }
451                 return (-2);
452         }
453         
454         /*  For each element, see that get_eventlist agrees 
455          *  with set_eventlist; if not, make noise.
456          */  
457         for (i = 0; i < ev_namecnt; i++) {
458           int set = DMEV_ISSET(ev_names[i].value, eventset);
459           int found = DMEV_ISSET(ev_names[i].value, check_eventset);
460           if (set && !found) {
461             fprintf(stderr, "ERROR: event %s was set but not found.\n",
462                     ev_names[i].name);
463             return (-3);
464           } 
465           else if (!set && found) {
466             fprintf(stderr, "ERROR: Found unexpected event %s \n",
467                     ev_names[i].name);
468             return (-4);
469           }
470           else if ((Vflag == 2) && !set && !found) {
471             fprintf(stderr, "clear: %s\n",
472                    ev_names[i].name);
473           }
474           else if (Vflag && set && found) {
475             fprintf(stderr, "  SET: %s\n", ev_names[i].name);
476             set_count++;
477           }
478         }
479         if (Vflag && set_count == 0) {
480           fprintf(stderr, "\t(All events cleared)\n");
481         }
482         return 0;
483 }