9 * Monitor all events for a file system.
10 * When one arrives, print a message with all the details.
11 * If the message is synchronous, always reply with DM_RESP_CONTINUE
12 * (This program doesn't perform any real file system or HSM work.)
14 * This is a simplification of the "migin.c" example program.
15 * The original code was by Peter Lawthers:
16 * This code was written by Peter Lawthers, and placed in the public
17 * domain for use by DMAPI implementors and app writers.
25 #include <sys/types.h>
27 #include <sys/resource.h>
29 #include <sys/param.h>
35 * Define some standard formats for the printf statements below.
38 #define HDR "%s: token %d sequence %d\n"
39 #define VALS "\t%-15s %s\n"
40 #define VALD "\t%-15s %d\n"
42 #define VALLLD "\t%-15s %lld\n"
44 #define VALLLD "\t%-15s %ld\n"
51 int main (int, char **);
52 static void event_loop (dm_sessid_t, int);
53 int handle_message (dm_sessid_t, dm_eventmsg_t *);
54 static int format_mode(mode_t mode, char **ptr);
55 static int get_fs_handle (char *, void **, size_t *);
56 static int set_disposition(dm_sessid_t, void *, size_t);
57 static int set_events (dm_sessid_t, void *, size_t);
58 static int clear_events (dm_sessid_t, void *, size_t);
59 int finish_responding(dm_sessid_t);
60 int establish_handler(void);
61 void exit_handler (void);
63 #define MAXNAMELEN 256
66 * Keep these global so the exit_handler and err_msg routines can get to them
72 dm_sessid_t oldsid = 0;
80 fprintf(stderr, "Usage: %s ", prog);
81 fprintf(stderr, " <-S oldsid> <-v verbose> ");
82 fprintf(stderr, "filesystem \n");
98 /* Progname = argv[0];*/ Progname = "print_event";
101 while ((c = getopt(argc, argv, "vs:S:")) != EOF) {
104 Sleep = atoi(optarg);
107 oldsid = atoi(optarg);
118 if (optind >= argc) {
122 fsname = argv[optind];
123 if (fsname == NULL) {
129 * Establish an exit handler
131 error = establish_handler();
136 * Init the dmapi, and get a filesystem handle so
137 * we can set up our events
143 error = setup_dmapi(&sid);
148 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
153 * Set the event disposition so that our session will receive
154 * all the events for the given file system
156 error = set_disposition(sid, fs_hanp, fs_hlen);
161 * Enable monitoring for all events in the given file system
163 error = set_events(sid, fs_hanp, fs_hlen);
168 * Now sit in an infinite loop, reporting on any events that occur.
169 * The program is exited after a signal through exit_handler().
172 event_loop(sid, 1 /*waitflag*/);
175 * If we get here, cleanup after the event_loop failure
184 * Main event loop processing
186 * The waitflag argument is set to 1 when we call this from main().
187 * In this case, continuously process incoming events,
188 * blocking if there are none available.
189 * In the exit_handler(), call this routine with waitflag=0.
190 * Just try to read the events once in this case with no blocking.
205 * We take a swag at a buffer size. If it's wrong, we can
209 bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
211 msgbuf = (void *)malloc(bufsize);
212 if (msgbuf == NULL) {
213 err_msg("Can't allocate memory for buffer");
218 error = dm_get_events(sid, ALL_AVAIL_MSGS,
219 waitflag ? DM_EV_WAIT:0, bufsize, msgbuf, &bufsize);
221 if (errno == EAGAIN) {
226 if (errno == E2BIG) {
228 msgbuf = (void *)malloc(bufsize);
229 if (msgbuf == NULL) {
230 err_msg("Can't resize msg buffer");
235 errno_msg("Error getting events from DMAPI (%d)", errno);
240 * Walk through the message buffer, pull out each individual
241 * message, and dispatch the messages to handle_message(),
242 * which will respond to the events.
246 msg = (dm_eventmsg_t *)msgbuf;
247 while (msg != NULL ) {
249 error = handle_message(sid, msg);
254 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
256 if (count != 1 && Verbose) {
257 err_msg("Found %d events in one call to "
258 "dm_get_events\n", count);
267 print_one_mount_event(
270 void *hanp1, *hanp2, *hanp3;
271 size_t hlen1, hlen2, hlen3;
272 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
275 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
279 dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
282 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
284 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
285 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
286 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
287 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
288 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
289 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
290 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
291 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
294 mode = msg_ne->ne_mode;
296 dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
298 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
299 hlen1 = DM_GET_LEN(msg_me, me_handle1);
300 hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
301 hlen2 = DM_GET_LEN(msg_me, me_handle2);
302 namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
303 nlen1 = DM_GET_LEN(msg_me, me_name1);
304 namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
305 nlen2 = DM_GET_LEN(msg_me, me_name2);
306 hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
307 hlen3 = DM_GET_LEN(msg_me, me_roothandle);
308 mode = msg_me->me_mode;
309 #endif /* VERITAS_21 */
311 if (hanp1 && hlen1) {
312 hantoa(hanp1, hlen1, hans1);
314 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
316 if (hanp2 && hlen2) {
317 hantoa(hanp2, hlen2, hans2);
319 sprintf(hans2, "<BAD HANDLE, hlen %d>", hlen2);
321 if (hanp3 && hlen3) {
322 hantoa(hanp3, hlen3, hans3);
324 sprintf(hans3, "<BAD HANDLE, hlen %d>", hlen3);
326 if (namp1 && nlen1) {
327 strncpy(nams1, namp1, nlen1);
328 if (nlen1 != sizeof(nams1))
331 sprintf(nams1, "<BAD STRING, nlen %d>", nlen1);
333 if (namp2 && nlen2) {
334 strncpy(nams2, namp2, nlen2);
335 if (nlen2 != sizeof(nams2))
338 sprintf(nams2, "<BAD STRING, nlen %d>", nlen2);
341 printf(VALS VALS VALS VALS VALS VALD,
343 "mtpt handle", hans2,
345 "media desig", nams2,
346 "root handle", hans3,
352 * First, weed out the events which return interesting structures.
353 * If it's not one of those, unpack the dm_namesp_event structure
354 * and display the contents.
363 int respond, response, respcode;
364 dm_namesp_event_t *msg_ne;
366 dm_mount_event_t *msg_me;
368 void *hanp1, *hanp2, *namp1, *namp2;
369 u_int hlen1, hlen2, nlen1, nlen2;
370 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
371 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
374 * Set the defaults for responding to events
377 response = DM_RESP_CONTINUE;
380 /***** USER EVENTS *****/
382 if (msg->ev_type == DM_EVENT_USER) {
387 "user", msg->ev_token, msg->ev_sequence);
389 /* print private data as ascii or hex if it exists DM_CONFIG_MAX_MESSAGE_DATA */
391 privp = DM_GET_VALUE(msg, ev_data, char *);
392 plen = DM_GET_LEN (msg, ev_data);
394 for (i = 0; i < plen; i++) {
395 if (!isprint(privp[i]) && !isspace(privp[i]))
398 if (i == plen - 1 && privp[i] == '\0') {
402 printf("\t%-15s ", "privdata");
403 for (i = 0; i < plen; i++) {
404 printf("%.2x", privp[i]);
410 "privdata", "<NONE>");
413 if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
417 /***** CANCEL EVENT *****/
419 /* Not implemented on SGI or Veritas */
421 else if (msg->ev_type == DM_EVENT_CANCEL) {
422 dm_cancel_event_t *msg_ce;
424 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
425 printf(HDR VALD VALD,
426 "cancel", msg->ev_token, msg->ev_sequence,
427 "sequence", msg_ce->ce_sequence,
428 "token", msg_ce->ce_token);
432 /***** DATA EVENTS *****/
434 else if (msg->ev_type == DM_EVENT_READ ||
435 msg->ev_type == DM_EVENT_WRITE ||
436 msg->ev_type == DM_EVENT_TRUNCATE) {
437 dm_data_event_t *msg_de;
439 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
440 hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
441 hlen1 = DM_GET_LEN (msg_de, de_handle);
442 if (hanp1 && hlen1) {
443 hantoa(hanp1, hlen1, hans1);
445 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
448 switch(msg->ev_type) {
451 printf(HDR VALS VALLLD VALLLD,
452 "read", msg->ev_token, msg->ev_sequence,
453 "file handle", hans1,
454 "offset", msg_de->de_offset,
455 "length", msg_de->de_length);
459 printf(HDR VALS VALLLD VALLLD,
460 "write", msg->ev_token, msg->ev_sequence,
461 "file handle", hans1,
462 "offset", msg_de->de_offset,
463 "length", msg_de->de_length);
466 case DM_EVENT_TRUNCATE:
467 printf(HDR VALS VALLLD VALLLD,
468 "truncate", msg->ev_token, msg->ev_sequence,
469 "file handle", hans1,
470 "offset", msg_de->de_offset,
471 "length", msg_de->de_length);
476 /***** DESTROY EVENT *****/
478 else if (msg->ev_type == DM_EVENT_DESTROY) {
479 dm_destroy_event_t *msg_ds;
480 char attrname[DM_ATTR_NAME_SIZE + 1];
485 msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
486 hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
487 hlen1 = DM_GET_LEN (msg_ds, ds_handle);
488 if (hanp1 && hlen1) {
489 hantoa(hanp1, hlen1, hans1);
491 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
493 if (msg_ds->ds_attrname.an_chars[0] != '\0') {
494 strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
496 strcpy(attrname, "<NONE>");
498 printf(HDR VALS VALS,
499 "destroy", msg->ev_token, msg->ev_sequence,
501 "attrname", attrname);
502 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
503 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
505 printf("\t%-15s ", "attrcopy");
506 for (i = 0; i < clen; i++) {
507 printf("%.2x", copy[i]);
511 printf(VALS, "attrcopy", "<NONE>");
516 /***** MOUNT EVENT *****/
518 else if (msg->ev_type == DM_EVENT_MOUNT) {
519 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
521 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
522 print_one_mount_event(msg_me);
523 #else /* VERITAS_21 */
524 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
525 print_one_mount_event(msg_ne);
526 #endif /* VERITAS_21 */
529 /***** NAMESPACE EVENTS *****/
534 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
535 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
536 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
537 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
538 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
539 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
540 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
541 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
542 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
544 if (hanp1 && hlen1) {
545 hantoa(hanp1, hlen1, hans1);
547 if (hanp2 && hlen2) {
548 hantoa(hanp2, hlen2, hans2);
550 if (namp1 && nlen1) {
551 strncpy(nams1, namp1, nlen1);
552 if (nlen1 != sizeof(nams1))
555 if (namp2 && nlen2) {
556 strncpy(nams2, namp2, nlen2);
557 if (nlen2 != sizeof(nams2))
561 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
562 msg->ev_type == DM_EVENT_UNMOUNT) {
563 if (msg_ne->ne_mode == 0) {
566 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
568 } else if (msg_ne->ne_mode > 0) {
575 } else if (msg->ev_type == DM_EVENT_CREATE ||
576 msg->ev_type == DM_EVENT_POSTCREATE ||
577 msg->ev_type == DM_EVENT_REMOVE ||
578 msg->ev_type == DM_EVENT_POSTREMOVE) {
579 if (format_mode(msg_ne->ne_mode, &type)) {
584 switch(msg->ev_type) {
586 case DM_EVENT_PREUNMOUNT:
587 printf(HDR VALS VALS VALS,
588 "preunmount", msg->ev_token, msg->ev_sequence,
591 "unmount mode", type);
594 case DM_EVENT_UNMOUNT:
595 printf(HDR VALS VALS VALD,
596 "unmount", msg->ev_token, msg->ev_sequence,
598 "unmount mode", type,
599 "retcode", msg_ne->ne_retcode);
602 case DM_EVENT_NOSPACE:
604 "nospace", msg->ev_token, msg->ev_sequence,
606 response = DM_RESP_ABORT;
610 case DM_EVENT_DEBUT: /* not supported on SGI */
612 "debut", msg->ev_token, msg->ev_sequence,
616 case DM_EVENT_CREATE:
617 printf(HDR VALS VALS VALS,
618 "create", msg->ev_token, msg->ev_sequence,
624 case DM_EVENT_POSTCREATE:
625 printf(HDR VALS VALS VALS VALS VALD,
626 "postcreate", msg->ev_token, msg->ev_sequence,
631 "retcode", msg_ne->ne_retcode);
635 case DM_EVENT_REMOVE:
636 printf(HDR VALS VALS VALS,
637 "remove", msg->ev_token, msg->ev_sequence,
643 case DM_EVENT_POSTREMOVE:
644 printf(HDR VALS VALS VALS VALD,
645 "postremove", msg->ev_token, msg->ev_sequence,
649 "retcode", msg_ne->ne_retcode);
653 case DM_EVENT_RENAME:
654 printf(HDR VALS VALS VALS VALS,
655 "rename", msg->ev_token, msg->ev_sequence,
662 case DM_EVENT_POSTRENAME:
663 printf(HDR VALS VALS VALS VALS VALD,
664 "postrename", msg->ev_token, msg->ev_sequence,
669 "retcode", msg_ne->ne_retcode);
673 case DM_EVENT_SYMLINK:
674 printf(HDR VALS VALS VALS,
675 "symlink", msg->ev_token, msg->ev_sequence,
681 case DM_EVENT_POSTSYMLINK:
682 printf(HDR VALS VALS VALS VALS VALD,
683 "postsymlink", msg->ev_token, msg->ev_sequence,
688 "retcode", msg_ne->ne_retcode);
693 printf(HDR VALS VALS VALS,
694 "link", msg->ev_token, msg->ev_sequence,
700 case DM_EVENT_POSTLINK:
701 printf(HDR VALS VALS VALS VALD,
702 "postlink", msg->ev_token, msg->ev_sequence,
706 "retcode", msg_ne->ne_retcode);
710 case DM_EVENT_ATTRIBUTE:
712 "attribute", msg->ev_token, msg->ev_sequence,
717 case DM_EVENT_CLOSE: /* not supported on SGI */
719 "close", msg->ev_token, msg->ev_sequence,
727 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
728 "ev_type", msg->ev_type);
729 if (msg->ev_token == DM_INVALID_TOKEN)
736 * Now respond to those messages which require a response
739 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
741 errno_msg("Can't respond to event");
745 err_msg("Sleeping for %d seconds!\n", Sleep);
755 Convert a mode_t field into a printable string.
757 Returns non-zero if the mode_t is invalid. The string is
758 returned in *ptr, whether there is an error or not.
766 static char modestr[100];
770 if (S_ISFIFO(mode)) typestr = "FIFO";
771 else if(S_ISCHR (mode)) typestr = "Character Device";
772 else if(S_ISBLK (mode)) typestr = "Block Device";
773 else if(S_ISDIR (mode)) typestr = "Directory";
774 else if(S_ISREG (mode)) typestr = "Regular File";
775 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
776 else if(S_ISSOCK(mode)) typestr = "Socket";
778 typestr = "<unknown type>";
782 sprintf(modestr, "mode %06o: perm %c%c%c %c%c%c %c%c%c %c%c%c, type %s",
784 mode & S_ISUID ? 's':' ',
785 mode & S_ISGID ? 'g':' ',
786 mode & S_ISVTX ? 't':' ',
787 mode & S_IRUSR ? 'r':'-',
788 mode & S_IWUSR ? 'w':'-',
789 mode & S_IXUSR ? 'x':'-',
790 mode & S_IRGRP ? 'r':'-',
791 mode & S_IWGRP ? 'w':'-',
792 mode & S_IXGRP ? 'x':'-',
793 mode & S_IROTH ? 'r':'-',
794 mode & S_IWOTH ? 'w':'-',
795 mode & S_IXOTH ? 'x':'-',
808 char hans[HANDLE_STR];
810 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
811 errno_msg("Can't get filesystem handle");
815 hantoa(*fs_hanpp, *fs_hlenp, hans);
816 err_msg("File system handle for %s: %s\n", fsname, hans);
823 Set the event disposition for this filesystem to include all valid
824 DMAPI events so that we receive all events for this filesystem.
825 Also set DM_EVENT_MOUNT disposition for the global handle.
826 It does not make sense to specify DM_EVENT_USER in the disposition
827 mask since a session is always unconditionally registered for these
830 Returns non-zero on error.
839 dm_eventset_t eventlist;
842 err_msg("Setting event disposition to send all "
843 "events to this session\n");
846 /* DM_EVENT_MOUNT must be sent in a separate request using the global
847 handle. If we ever support more than one filesystem at a time, this
848 request should be moved out of this routine to a place where it is
852 DMEV_ZERO(eventlist);
853 DMEV_SET(DM_EVENT_MOUNT, eventlist);
855 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
856 &eventlist, DM_EVENT_MAX) == -1) {
857 errno_msg("Can't set event disposition for mount");
861 DMEV_ZERO(eventlist);
863 /* File system administration events. */
865 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
866 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
867 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
869 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
870 lets it be specified in a dm_set_disp call; its just that the
871 event will never be seen on some platforms.
874 DMEV_SET(DM_EVENT_DEBUT, eventlist);
877 /* Namespace events. */
879 DMEV_SET(DM_EVENT_CREATE, eventlist);
880 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
881 DMEV_SET(DM_EVENT_REMOVE, eventlist);
882 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
883 DMEV_SET(DM_EVENT_RENAME, eventlist);
884 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
885 DMEV_SET(DM_EVENT_LINK, eventlist);
886 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
887 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
888 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
890 /* Managed region data events. */
892 DMEV_SET(DM_EVENT_READ, eventlist);
893 DMEV_SET(DM_EVENT_WRITE, eventlist);
894 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
896 /* Metadata events. */
898 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
900 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 )
901 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
904 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
907 DMEV_SET(DM_EVENT_DESTROY, eventlist);
911 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
913 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
914 &eventlist, DM_EVENT_MAX) == -1) {
915 errno_msg("Can't set event disposition for filesystem");
923 Enable event generation on each valid filesystem-based DMAPI event
924 within the given file system.
926 Returns non-zero on errors.
935 dm_eventset_t eventlist;
938 err_msg("Setting event list to enable all events "
939 "for this file system\n");
941 DMEV_ZERO(eventlist);
943 /* File system administration events. */
945 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
948 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
949 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
950 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
951 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
953 /* Namespace events. */
955 DMEV_SET(DM_EVENT_CREATE, eventlist);
956 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
957 DMEV_SET(DM_EVENT_REMOVE, eventlist);
958 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
959 DMEV_SET(DM_EVENT_RENAME, eventlist);
960 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
961 DMEV_SET(DM_EVENT_LINK, eventlist);
962 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
963 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
964 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
966 /* Managed region data events. These are not settable by
967 dm_set_eventlist on a filesystem basis. They are meant
968 to be set using dm_set_region on regular files only.
969 However, in the SGI implementation, they are filesystem-settable.
970 Since this is useful for testing purposes, do it.
975 /* DM_EVENT_TRUNCATE */
977 /* Metadata events. */
979 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
981 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 )
982 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
985 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
988 DMEV_SET(DM_EVENT_DESTROY, eventlist);
992 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
994 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
995 &eventlist, DM_EVENT_MAX) == -1) {
996 errno_msg("Can't set event list");
1004 Disable monitoring for all events in the DMAPI for the given
1005 file system. This is done before exiting so that future
1006 operations won't hang waiting for their events to be handled.
1008 Returns non-zero on errors.
1017 dm_eventset_t eventlist;
1020 err_msg("Clearing event list to disable all events "
1021 "for this filesystem\n");
1023 DMEV_ZERO(eventlist);
1025 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1026 &eventlist, DM_EVENT_MAX) == -1) {
1027 errno_msg("Can't clear event list");
1035 * Respond to any events which haven't been handled yet.
1036 * dm_getall_tokens provides a list of tokens for the outstanding events.
1037 * dm_find_eventmsg uses the token to lookup the corresponding message.
1038 * The message is passed to handle_message() for normal response processing.
1045 u_int nbytes, ntokens = 0, ret_ntokens, i;
1046 dm_token_t *tokenbuf = NULL;
1047 size_t buflen, ret_buflen;
1048 char *msgbuf = NULL;
1052 err_msg("Responding to any outstanding delivered event messages\n");
1055 * Initial sizes for the token and message buffers
1057 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1062 * The E2BIG dance...
1063 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1064 * If the routine returns E2BIG, use the returned size and try again.
1065 * If we're already using the returned size, double it and try again.
1068 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1069 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1070 tokenbuf = malloc(nbytes);
1071 if (tokenbuf == NULL) {
1072 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1076 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1077 } while (error && errno == E2BIG);
1080 errno_msg("Can't get all outstanding tokens");
1084 for (i = 0; i < ret_ntokens; i++) {
1086 err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
1089 * The E2BIG dance reprise...
1092 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1093 msgbuf = malloc(buflen);
1094 if (msgbuf == NULL) {
1095 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1099 error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
1100 } while (error && errno == E2BIG);
1102 errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
1106 msg = (dm_eventmsg_t *) msgbuf;
1107 while (msg != NULL) {
1108 error = handle_message(sid, msg);
1111 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1127 * Establish an exit handler since we run in an infinite loop
1130 establish_handler(void)
1132 struct sigaction act;
1135 * Set up signals so that we can wait for spawned children
1137 act.sa_handler = exit_handler;
1139 sigemptyset(&act.sa_mask);
1141 (void)sigaction(SIGHUP, &act, NULL);
1142 (void)sigaction(SIGINT, &act, NULL);
1143 (void)sigaction(SIGQUIT, &act, NULL);
1144 (void)sigaction(SIGTERM, &act, NULL);
1145 (void)sigaction(SIGUSR1, &act, NULL);
1146 (void)sigaction(SIGUSR1, &act, NULL);
1147 (void)sigaction(SIGUSR2, &act, NULL);
1156 * Stop events from being generated for the given file system
1157 * Respond to any events that were delivered but unanswered
1158 * (the event loop may have been in the middle of taking care of the event)
1159 * Try getting any undelivered events but don't block if none are there
1160 * (the file system may have generated an event after we killed dm_get_events)
1161 * Shutdown the session using the global "sid" variable.
1172 err_msg("Exiting...\n");
1174 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1177 error = clear_events(sid, fs_hanp, fs_hlen);
1179 /* just keep going */ ;
1182 error = finish_responding(sid);
1184 /* just keep going */ ;
1186 err_msg("Processing any undelivered event messages\n");
1187 event_loop(sid, 0 /*waitflag*/);
1189 err_msg("Shutting down the session\n");
1191 error = dm_destroy_session(sid);
1193 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");