Make get_events easier to use in a script
[xfstests-dev.git] / dmapi / src / common / lib / print.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 <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/stat.h>
36
37 #include <ctype.h>
38
39 #include <lib/hsm.h>
40
41 #include <string.h>
42 #ifdef linux
43 #define MAXNAMELEN 256
44 #endif
45
46   /*
47    * Define some standard formats for the printf statements below.
48    */
49
50 #define HDR  "type=%s token=%d sequence=%d\n"
51 #define VALS "\t%s=%s\n"
52 #define VALD "\t%s=%d\n"
53 #define VALLLD "\t%s=%lld\n"
54
55
56 /*
57         Convert a mode_t field into a printable string.
58
59         Returns non-zero if the mode_t is invalid.  The string is
60         returned in *ptr, whether there is an error or not.
61 */
62
63 int
64 format_mode(
65         mode_t  mode,
66         char    **ptr)
67 {
68 static  char    modestr[100];
69         char    *typestr;
70         int     error = 0;
71
72         if     (S_ISFIFO(mode)) typestr = "FIFO";
73         else if(S_ISCHR (mode)) typestr = "Character Device";
74         else if(S_ISBLK (mode)) typestr = "Block Device";
75         else if(S_ISDIR (mode)) typestr = "Directory";
76         else if(S_ISREG (mode)) typestr = "Regular File";
77         else if(S_ISLNK (mode)) typestr = "Symbolic Link";
78         else if(S_ISSOCK(mode)) typestr = "Socket";
79         else {
80                 typestr = "<unknown type>"; 
81                 error++;
82         }
83
84         sprintf(modestr, "mode %06o: perm %c%c%c %c%c%c %c%c%c %c%c%c, type %s",
85                 mode,
86                 mode & S_ISUID ? 's':' ',
87                 mode & S_ISGID ? 'g':' ',
88                 mode & S_ISVTX ? 't':' ',
89                 mode & S_IRUSR ? 'r':'-',
90                 mode & S_IWUSR ? 'w':'-',
91                 mode & S_IXUSR ? 'x':'-',
92                 mode & S_IRGRP ? 'r':'-',
93                 mode & S_IWGRP ? 'w':'-',
94                 mode & S_IXGRP ? 'x':'-',
95                 mode & S_IROTH ? 'r':'-',
96                 mode & S_IWOTH ? 'w':'-',
97                 mode & S_IXOTH ? 'x':'-',
98                 typestr);
99         *ptr = modestr;
100         return(error);
101 }
102
103
104 void
105 print_one_mount_event(
106         void            *msg)
107 {
108         void            *hanp1, *hanp2, *hanp3;
109         size_t          hlen1, hlen2, hlen3;
110         char            hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
111         void            *namp1, *namp2;
112         size_t          nlen1, nlen2;
113         char            nams1[MAXNAMELEN], nams2[MAXNAMELEN];
114         mode_t          mode;
115
116 #if     VERITAS_21
117         dm_namesp_event_t  *msg_ne = (dm_namesp_event_t *)msg;
118
119 /*
120         msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
121 */
122         hanp1  = DM_GET_VALUE(msg_ne, ne_handle1, void *);
123         hlen1  = DM_GET_LEN  (msg_ne, ne_handle1);
124         hanp2  = DM_GET_VALUE(msg_ne, ne_handle2, void *);
125         hlen2  = DM_GET_LEN  (msg_ne, ne_handle2);
126         namp1  = DM_GET_VALUE(msg_ne, ne_name1, void *);
127         nlen1  = DM_GET_LEN  (msg_ne, ne_name1);
128         namp2  = DM_GET_VALUE(msg_ne, ne_name2, void *);
129         nlen2  = DM_GET_LEN  (msg_ne, ne_name2);
130         hanp3  = NULL;
131         hlen3  = 0;
132         mode   = msg_ne->ne_mode;
133 #else
134         dm_mount_event_t  *msg_me = (dm_mount_event_t *)msg;
135
136         hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
137         hlen1 = DM_GET_LEN(msg_me, me_handle1);
138         hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
139         hlen2 = DM_GET_LEN(msg_me, me_handle2);
140         namp1  = DM_GET_VALUE(msg_me, me_name1, void *);
141         nlen1 = DM_GET_LEN(msg_me, me_name1);
142         namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
143         nlen2 = DM_GET_LEN(msg_me, me_name2);
144         hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
145         hlen3 = DM_GET_LEN(msg_me, me_roothandle);
146         mode  = msg_me->me_mode;
147 #endif  /* VERITAS_21 */
148
149         if (hanp1 && hlen1) {
150                 hantoa(hanp1, hlen1, hans1);
151         } else {
152                 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
153         }
154         if (hanp2 && hlen2) {
155                 hantoa(hanp2, hlen2, hans2);
156         } else {
157                 sprintf(hans2, "<BAD HANDLE, hlen %d>", hlen2);
158         }
159         if (hanp3 && hlen3) {
160                 hantoa(hanp3, hlen3, hans3);
161         } else {
162                 sprintf(hans3, "<BAD HANDLE, hlen %d>", hlen3);
163         }
164         if (namp1 && nlen1) {
165                 strncpy(nams1, namp1, nlen1);
166                 if (nlen1 != sizeof(nams1))
167                         nams1[nlen1] = '\0';
168         } else {
169                 sprintf(nams1, "<BAD STRING, nlen %d>", nlen1);
170         }
171         if (namp2 && nlen2) {
172                 strncpy(nams2, namp2, nlen2);
173                 if (nlen2 != sizeof(nams2))
174                         nams2[nlen2] = '\0';
175         } else {
176                 sprintf(nams2, "<BAD STRING, nlen %d>", nlen2);
177         }
178
179         printf(VALS VALS VALS VALS VALS VALD,
180              "fs handle",       hans1,
181              "mtpt handle",     hans2,
182              "mtpt path",       nams1,
183              "media desig",     nams2,
184              "root handle",     hans3,
185              "mode",            mode);
186 }
187
188
189 static int
190 print_one_data_event(
191         dm_data_event_t *msg_de)
192 {
193         char            handle[HANDLE_STR];
194         void            *hanp;
195         size_t          hlen;
196
197         hanp  = DM_GET_VALUE(msg_de, de_handle, void *);
198         hlen  = DM_GET_LEN  (msg_de, de_handle);
199
200         if (hanp && hlen) {
201                 hantoa(hanp, hlen, handle);
202         } else {
203                 sprintf(handle, "<BAD HANDLE, hlen %d>", hlen);
204         }
205
206         printf(VALS VALLLD VALLLD,
207                 "file_handle",  handle,
208                 "offset", msg_de->de_offset,
209                 "length", msg_de->de_length);
210
211         return(0);
212 }
213
214
215 int
216 print_one_message(
217         dm_eventmsg_t   *msg)
218 {
219         int             pkt_error = 0;
220         dm_namesp_event_t  *msg_ne;
221         void            *hanp1, *hanp2, *namp1, *namp2;
222         u_int           hlen1, hlen2, nlen1, nlen2;
223         char            hans1[HANDLE_STR], hans2[HANDLE_STR];
224         char            nams1[MAXNAMELEN], nams2[MAXNAMELEN];
225
226         /***** USER EVENTS *****/
227
228         if (msg->ev_type == DM_EVENT_USER) {
229     char        *privp;
230     u_int       plen, i;
231
232     printf(HDR,
233                 "user", msg->ev_token, msg->ev_sequence);
234
235     /* print private data as ascii or hex if it exists DM_CONFIG_MAX_MESSAGE_DATA */
236
237     privp = DM_GET_VALUE(msg, ev_data, char *);
238     plen  = DM_GET_LEN  (msg, ev_data);
239     if (plen) {
240         for (i = 0; i < plen; i++) {
241                 if (!isprint(privp[i]) && !isspace(privp[i]))
242                         break;
243         }
244         if (i == plen - 1 && privp[i] == '\0') {
245           printf(VALS,
246                         "privdata", privp);
247         } else {
248           printf("\t%-15s ", "privdata");
249           for (i = 0; i < plen; i++) {
250             printf("%.2x", privp[i]);
251           }
252           printf("\n");
253         }
254     } else {
255         printf(VALS,
256                 "privdata", "<NONE>");
257     }
258
259         /***** CANCEL EVENT *****/
260
261 /* Not implemented on SGI or Veritas */
262
263         } else if (msg->ev_type == DM_EVENT_CANCEL) {
264                 dm_cancel_event_t       *msg_ce;
265
266                 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
267                 printf(HDR VALD VALD,
268                         "cancel", msg->ev_token, msg->ev_sequence,
269                         "sequence", msg_ce->ce_sequence,
270                         "token", msg_ce->ce_token);
271
272         /***** DATA EVENTS *****/
273
274         } else if (msg->ev_type == DM_EVENT_READ ||
275                    msg->ev_type == DM_EVENT_WRITE ||
276                    msg->ev_type == DM_EVENT_TRUNCATE) {
277                 dm_data_event_t *msg_de;
278
279                 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
280
281                 switch (msg->ev_type) {
282                 case DM_EVENT_READ:
283                         printf(HDR, "read", msg->ev_token, msg->ev_sequence);
284                         break;
285
286                 case DM_EVENT_WRITE:
287                         printf(HDR, "write", msg->ev_token, msg->ev_sequence);
288                         break;
289
290                 case DM_EVENT_TRUNCATE:
291                         printf(HDR, "truncate", msg->ev_token,
292                                 msg->ev_sequence);
293                         break;
294                 default: break;
295                 }
296                 print_one_data_event(msg_de);
297
298   /***** DESTROY EVENT *****/
299
300         } else if (msg->ev_type == DM_EVENT_DESTROY) {
301     dm_destroy_event_t  *msg_ds;
302     char                attrname[DM_ATTR_NAME_SIZE + 1];
303     u_char              *copy;
304     u_int               clen;
305     u_int               i;
306
307     msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
308     hanp1  = DM_GET_VALUE(msg_ds, ds_handle, void *);
309     hlen1  = DM_GET_LEN  (msg_ds, ds_handle);
310     if (hanp1 && hlen1) {
311       hantoa(hanp1, hlen1, hans1);
312     } else {
313       sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
314     }
315     if (msg_ds->ds_attrname.an_chars[0] != '\0') {
316       strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
317     } else {
318       strcpy(attrname, "<NONE>");
319     }
320     printf(HDR VALS VALS,
321              "destroy", msg->ev_token, msg->ev_sequence,
322              "handle",          hans1,
323              "attrname",        attrname);
324     copy  = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
325     clen  = DM_GET_LEN  (msg_ds, ds_attrcopy);
326     if (copy && clen) {
327       printf("\t%-15s ", "attrcopy");
328       for (i = 0; i < clen; i++) {
329         printf("%.2x", copy[i]);
330       }
331       printf("\n");
332     } else {
333       printf(VALS, "attrcopy", "<NONE>");
334     }
335
336   /***** MOUNT EVENT *****/
337
338         } else if (msg->ev_type == DM_EVENT_MOUNT) {
339                 void    *msg_body;
340
341                 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
342 #if     !VERITAS_21
343                 msg_body = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
344 #else   /* VERITAS_21 */
345                 msg_body = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
346 #endif  /* VERITAS_21 */
347                 print_one_mount_event(msg_body);
348
349   /***** NAMESPACE EVENTS *****/
350
351         } else {
352     char        *type;
353
354     msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
355     hanp1  = DM_GET_VALUE(msg_ne, ne_handle1, void *);
356     hlen1  = DM_GET_LEN  (msg_ne, ne_handle1);
357     hanp2  = DM_GET_VALUE(msg_ne, ne_handle2, void *);
358     hlen2  = DM_GET_LEN  (msg_ne, ne_handle2);
359     namp1  = DM_GET_VALUE(msg_ne, ne_name1, void *);
360     nlen1  = DM_GET_LEN  (msg_ne, ne_name1);
361     namp2  = DM_GET_VALUE(msg_ne, ne_name2, void *);
362     nlen2  = DM_GET_LEN  (msg_ne, ne_name2);
363
364     if (hanp1 && hlen1) {
365       hantoa(hanp1, hlen1, hans1);
366     }
367     if (hanp2 && hlen2) {
368       hantoa(hanp2, hlen2, hans2);
369     }
370     if (namp1 && nlen1) {
371       strncpy(nams1, namp1, nlen1);
372       if (nlen1 != sizeof(nams1))
373         nams1[nlen1] = '\0';
374     }
375     if (namp2 && nlen2) {
376       strncpy(nams2, namp2, nlen2);
377       if (nlen2 != sizeof(nams2))
378         nams2[nlen2] = '\0';
379     }
380
381     if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
382         msg->ev_type == DM_EVENT_UNMOUNT) {
383       if (msg_ne->ne_mode == 0) {
384         type = "NOFORCE";
385 #if     !VERITAS_21
386       } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
387 #else
388       } else if (msg_ne->ne_mode > 0) {
389 #endif
390         type = "FORCE";
391       } else {
392         type = "UNKNOWN";
393         pkt_error++;
394       }
395     } else if (msg->ev_type == DM_EVENT_CREATE ||
396                msg->ev_type == DM_EVENT_POSTCREATE ||
397                msg->ev_type == DM_EVENT_REMOVE ||
398                msg->ev_type == DM_EVENT_POSTREMOVE) {
399         if (format_mode(msg_ne->ne_mode, &type)) {
400           pkt_error++;
401         }
402     }
403
404     switch(msg->ev_type) {
405
406     case DM_EVENT_PREUNMOUNT:
407       printf(HDR VALS VALS VALS,
408              "preunmount", msg->ev_token, msg->ev_sequence,
409              "fs handle",       hans1,
410              "root dir",        hans2,
411              "unmount mode",    type);
412       break;
413
414     case DM_EVENT_UNMOUNT:
415       printf(HDR VALS VALS VALD,
416              "unmount", msg->ev_token, msg->ev_sequence,
417              "fs handle",       hans1,
418              "unmount mode",    type,
419              "retcode",         msg_ne->ne_retcode);
420       break;
421
422     case DM_EVENT_NOSPACE:
423       printf(HDR VALS,
424              "nospace", msg->ev_token, msg->ev_sequence,
425              "fs handle",       hans1);
426       break;
427
428     case DM_EVENT_DEBUT:                /* not supported on SGI */
429       printf(HDR VALS,
430              "debut", msg->ev_token, msg->ev_sequence,
431              "object",          hans1);
432       break;
433
434     case DM_EVENT_CREATE:
435       printf(HDR VALS VALS VALS,
436              "create", msg->ev_token, msg->ev_sequence,
437              "parent dir",      hans1,
438              "name",            nams1,
439              "mode bits",       type);
440       break;
441
442     case DM_EVENT_POSTCREATE:
443       printf(HDR VALS VALS VALS VALS VALD,
444              "postcreate", msg->ev_token, msg->ev_sequence,
445              "parent dir",      hans1,
446              "new object",      hans2,
447              "name",            nams1,
448              "mode bits",       type,
449              "retcode",         msg_ne->ne_retcode);
450       break;
451
452     case DM_EVENT_REMOVE:
453       printf(HDR VALS VALS VALS,
454              "remove", msg->ev_token, msg->ev_sequence,
455              "parent dir",      hans1,
456              "name",            nams1,
457              "mode bits",       type);
458       break;
459
460     case DM_EVENT_POSTREMOVE:
461       printf(HDR VALS VALS VALS VALD,
462              "postremove", msg->ev_token, msg->ev_sequence,
463              "parent dir",      hans1,
464              "name",            nams1,
465              "mode bits",       type,
466              "retcode",         msg_ne->ne_retcode);
467       break;
468
469     case DM_EVENT_RENAME:
470       printf(HDR VALS VALS VALS VALS,
471              "rename", msg->ev_token, msg->ev_sequence,
472              "old parent",      hans1,
473              "new parent",      hans2,
474              "old name",        nams1,
475              "new name",        nams2);
476       break;
477
478     case DM_EVENT_POSTRENAME:
479       printf(HDR VALS VALS VALS VALS VALD,
480              "postrename", msg->ev_token, msg->ev_sequence,
481              "old parent",      hans1,
482              "new parent",      hans2,
483              "old name",        nams1,
484              "new name",        nams2,
485              "retcode",         msg_ne->ne_retcode);
486       break;
487
488     case DM_EVENT_SYMLINK:
489       printf(HDR VALS VALS VALS,
490              "symlink", msg->ev_token, msg->ev_sequence,
491              "parent dir",      hans1,
492              "name",            nams1,
493              "contents",        nams2);
494       break;
495
496     case DM_EVENT_POSTSYMLINK:
497       printf(HDR VALS VALS VALS VALS VALD,
498              "postsymlink", msg->ev_token, msg->ev_sequence,
499              "parent dir",      hans1,
500              "new object",      hans2,
501              "name",            nams1,
502              "contents",        nams2,
503              "retcode",         msg_ne->ne_retcode);
504       break;
505
506     case DM_EVENT_LINK:
507       printf(HDR VALS VALS VALS,
508              "link", msg->ev_token, msg->ev_sequence,
509              "parent dir",      hans1,
510              "source",          hans2,
511              "name",            nams1);
512       break;
513
514     case DM_EVENT_POSTLINK:
515       printf(HDR VALS VALS VALS VALD,
516              "postlink", msg->ev_token, msg->ev_sequence,
517              "parent dir",      hans1,
518              "source",          hans2,
519              "name",            nams1,
520              "retcode",         msg_ne->ne_retcode);
521       break;
522
523     case DM_EVENT_ATTRIBUTE:
524       printf(HDR VALS,
525              "attribute", msg->ev_token, msg->ev_sequence,
526              "object",          hans1);
527       break;
528
529     case DM_EVENT_CLOSE:        /* not supported on SGI */
530       printf(HDR VALS,
531              "close", msg->ev_token, msg->ev_sequence,
532              "object",          hans1);
533       break;
534
535     default:
536       pkt_error++;
537       printf(HDR VALD,
538              "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
539              "ev_type",         msg->ev_type);
540       break;
541     }
542         }
543         return(pkt_error);
544 }
545
546
547 int
548 handle_message(
549         dm_sessid_t     sid,
550         dm_eventmsg_t   *msg)
551 {
552         dm_response_t   response;
553         int             respond, respcode;
554         int             error = 0;
555
556         if (print_one_message(msg))
557                 error++;
558
559         /* Set the defaults for responding to events. */
560
561         respond = 1;
562         response = DM_RESP_CONTINUE;
563         respcode = 0;
564
565         /***** USER EVENTS *****/
566
567         switch (msg->ev_type) {
568         case DM_EVENT_USER:
569                 if (msg->ev_token == DM_INVALID_TOKEN)
570                         respond = 0;
571                 break;
572
573         case DM_EVENT_CANCEL:
574         case DM_EVENT_DESTROY:
575         case DM_EVENT_POSTCREATE:
576         case DM_EVENT_POSTREMOVE:
577         case DM_EVENT_POSTRENAME:
578         case DM_EVENT_POSTSYMLINK:
579         case DM_EVENT_POSTLINK:
580         case DM_EVENT_ATTRIBUTE:
581         case DM_EVENT_CLOSE:
582                 respond = 0;
583                 break;
584
585         case DM_EVENT_MOUNT:
586         case DM_EVENT_READ:
587         case DM_EVENT_WRITE:
588         case DM_EVENT_TRUNCATE:
589         case DM_EVENT_PREUNMOUNT:
590         case DM_EVENT_UNMOUNT:
591         case DM_EVENT_DEBUT:
592         case DM_EVENT_CREATE:
593         case DM_EVENT_REMOVE:
594         case DM_EVENT_RENAME:
595         case DM_EVENT_SYMLINK:
596         case DM_EVENT_LINK:
597                 break;
598
599         case DM_EVENT_NOSPACE:
600                 response = DM_RESP_ABORT;
601                 respcode = ENOSPC;
602                 break;
603
604         default:
605                 if (msg->ev_token == DM_INVALID_TOKEN)
606                         respond = 0;
607                 break;
608         }
609
610         /* Respond to those messages which require a response. */
611
612         if (respond) {
613                 if (dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0)) {
614                         errno_msg("Can't respond to event");
615                 }
616         }
617         return(error);
618 }