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"
41 #define VALLLD "\t%-15s %lld\n"
47 int main (int, char **);
48 static void event_loop (dm_sessid_t, int);
49 int handle_message (dm_sessid_t, dm_eventmsg_t *);
50 static int format_mode(mode_t mode, char **ptr);
51 static int get_fs_handle (char *, void **, size_t *);
52 static int set_disposition(dm_sessid_t, void *, size_t);
53 static int set_disp_global(dm_sessid_t);
54 static int set_events (dm_sessid_t, void *, size_t);
55 static int clear_events (dm_sessid_t, void *, size_t);
56 int finish_responding(dm_sessid_t);
57 int establish_handler(void);
58 void exit_handler (int);
68 #define MAXNAMELEN 256
71 * Keep these global so the exit_handler and err_msg routines can get to them
77 dm_sessid_t oldsid = 0;
79 int register_new_mnts = 0;
80 int rwt_bit_clear = 1; /* Clear read/write/trunc bit before
81 * responding to event; reset all other
89 fprintf(stderr, "Usage: %s ", prog);
90 fprintf(stderr, " <-S oldsid> <-v> <-s sleep> <-R> <-N> ");
91 fprintf(stderr, "filesystem \n");
107 /* Progname = argv[0];*/ Progname = "print_event";
110 while ((c = getopt(argc, argv, "vs:S:RN")) != EOF) {
113 Sleep = atoi(optarg);
116 register_new_mnts = 1;
122 oldsid = atoi(optarg);
133 if (optind >= argc) {
137 fsname = argv[optind];
138 if (fsname == NULL) {
144 * Establish an exit handler
146 error = establish_handler();
151 * Init the dmapi, and get a filesystem handle so
152 * we can set up our events
158 error = setup_dmapi(&sid);
163 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
168 * Set the event disposition so that our session will receive
169 * all the events for the given file system
171 error = set_disp_global(sid);
174 error = set_disposition(sid, fs_hanp, fs_hlen);
179 * Enable monitoring for all events in the given file system
181 error = set_events(sid, fs_hanp, fs_hlen);
186 * Now sit in an infinite loop, reporting on any events that occur.
187 * The program is exited after a signal through exit_handler().
190 event_loop(sid, 1 /*waitflag*/);
193 * If we get here, cleanup after the event_loop failure
202 * Main event loop processing
204 * The waitflag argument is set to 1 when we call this from main().
205 * In this case, continuously process incoming events,
206 * blocking if there are none available.
207 * In the exit_handler(), call this routine with waitflag=0.
208 * Just try to read the events once in this case with no blocking.
223 * We take a swag at a buffer size. If it's wrong, we can
227 bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
229 msgbuf = (void *)malloc(bufsize);
230 if (msgbuf == NULL) {
231 err_msg("Can't allocate memory for buffer");
236 error = dm_get_events(sid, ALL_AVAIL_MSGS,
237 waitflag ? DM_EV_WAIT:0, bufsize, msgbuf, &bufsize);
239 if (errno == EAGAIN) {
244 if (errno == E2BIG) {
246 msgbuf = (void *)malloc(bufsize);
247 if (msgbuf == NULL) {
248 err_msg("Can't resize msg buffer");
253 errno_msg("Error getting events from DMAPI (%d)", errno);
258 * Walk through the message buffer, pull out each individual
259 * message, and dispatch the messages to handle_message(),
260 * which will respond to the events.
264 msg = (dm_eventmsg_t *)msgbuf;
265 while (msg != NULL ) {
267 error = handle_message(sid, msg);
272 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
274 if (count != 1 && Verbose) {
275 err_msg("Found %d events in one call to "
276 "dm_get_events\n", count);
285 print_one_mount_event(
288 void *hanp1, *hanp2, *hanp3;
289 size_t hlen1, hlen2, hlen3;
290 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
293 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
297 dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
300 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
302 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
303 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
304 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
305 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
306 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
307 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
308 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
309 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
312 mode = msg_ne->ne_mode;
314 dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
316 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
317 hlen1 = DM_GET_LEN(msg_me, me_handle1);
318 hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
319 hlen2 = DM_GET_LEN(msg_me, me_handle2);
320 namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
321 nlen1 = DM_GET_LEN(msg_me, me_name1);
322 namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
323 nlen2 = DM_GET_LEN(msg_me, me_name2);
324 hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
325 hlen3 = DM_GET_LEN(msg_me, me_roothandle);
326 mode = msg_me->me_mode;
327 #endif /* VERITAS_21 */
329 if (hanp1 && hlen1) {
330 hantoa(hanp1, hlen1, hans1);
332 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
334 if (hanp2 && hlen2) {
335 hantoa(hanp2, hlen2, hans2);
337 sprintf(hans2, "<BAD HANDLE, hlen %d>", hlen2);
339 if (hanp3 && hlen3) {
340 hantoa(hanp3, hlen3, hans3);
342 sprintf(hans3, "<BAD HANDLE, hlen %d>", hlen3);
344 if (namp1 && nlen1) {
345 strncpy(nams1, namp1, nlen1);
346 if (nlen1 != sizeof(nams1))
349 sprintf(nams1, "<BAD STRING, nlen %d>", nlen1);
351 if (namp2 && nlen2) {
352 strncpy(nams2, namp2, nlen2);
353 if (nlen2 != sizeof(nams2))
356 sprintf(nams2, "<BAD STRING, nlen %d>", nlen2);
359 printf(VALS VALS VALS VALS VALS VALD,
361 "mtpt handle", hans2,
363 "media desig", nams2,
364 "root handle", hans3,
370 * First, weed out the events which return interesting structures.
371 * If it's not one of those, unpack the dm_namesp_event structure
372 * and display the contents.
381 dm_response_t response;
382 int respond, respcode;
383 dm_namesp_event_t *msg_ne;
385 dm_mount_event_t *msg_me;
387 void *hanp1, *hanp2, *namp1, *namp2;
388 u_int hlen1, hlen2, nlen1, nlen2;
389 char hans1[HANDLE_STR], hans2[HANDLE_STR];
390 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
393 * Set the defaults for responding to events
396 response = DM_RESP_CONTINUE;
399 /***** USER EVENTS *****/
401 if (msg->ev_type == DM_EVENT_USER) {
406 "user", msg->ev_token, msg->ev_sequence);
408 /* print private data as ascii or hex if it exists DM_CONFIG_MAX_MESSAGE_DATA */
410 privp = DM_GET_VALUE(msg, ev_data, char *);
411 plen = DM_GET_LEN (msg, ev_data);
413 for (i = 0; i < plen; i++) {
414 if (!isprint(privp[i]) && !isspace(privp[i]))
417 if (i == plen - 1 && privp[i] == '\0') {
421 printf("\t%-15s ", "privdata");
422 for (i = 0; i < plen; i++) {
423 printf("%.2x", privp[i]);
429 "privdata", "<NONE>");
432 if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
436 /***** CANCEL EVENT *****/
438 /* Not implemented on SGI or Veritas */
440 else if (msg->ev_type == DM_EVENT_CANCEL) {
441 dm_cancel_event_t *msg_ce;
443 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
444 printf(HDR VALD VALD,
445 "cancel", msg->ev_token, msg->ev_sequence,
446 "sequence", msg_ce->ce_sequence,
447 "token", msg_ce->ce_token);
451 /***** DATA EVENTS *****/
453 else if (msg->ev_type == DM_EVENT_READ ||
454 msg->ev_type == DM_EVENT_WRITE ||
455 msg->ev_type == DM_EVENT_TRUNCATE) {
456 dm_data_event_t *msg_de;
458 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
459 hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
460 hlen1 = DM_GET_LEN (msg_de, de_handle);
461 if (hanp1 && hlen1) {
462 hantoa(hanp1, hlen1, hans1);
465 switch(msg->ev_type) {
466 /* DM_EVENT_* and DM_REGION_* are different values, ug */
468 rgflag = DM_REGION_READ;
471 rgflag = DM_REGION_WRITE;
473 case DM_EVENT_TRUNCATE:
474 rgflag = DM_REGION_TRUNCATE;
477 clear_region_event(sid, rgflag, hanp1, hlen1, hans1);
480 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
483 switch(msg->ev_type) {
486 printf(HDR VALS VALLLD VALLLD,
487 "read", msg->ev_token, msg->ev_sequence,
488 "file handle", hans1,
489 "offset", msg_de->de_offset,
490 "length", msg_de->de_length);
494 printf(HDR VALS VALLLD VALLLD,
495 "write", msg->ev_token, msg->ev_sequence,
496 "file handle", hans1,
497 "offset", msg_de->de_offset,
498 "length", msg_de->de_length);
501 case DM_EVENT_TRUNCATE:
502 printf(HDR VALS VALLLD VALLLD,
503 "truncate", msg->ev_token, msg->ev_sequence,
504 "file handle", hans1,
505 "offset", msg_de->de_offset,
506 "length", msg_de->de_length);
512 /***** DESTROY EVENT *****/
514 else if (msg->ev_type == DM_EVENT_DESTROY) {
515 dm_destroy_event_t *msg_ds;
516 char attrname[DM_ATTR_NAME_SIZE + 1];
521 msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
522 hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
523 hlen1 = DM_GET_LEN (msg_ds, ds_handle);
524 if (hanp1 && hlen1) {
525 hantoa(hanp1, hlen1, hans1);
527 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
529 if (msg_ds->ds_attrname.an_chars[0] != '\0') {
530 strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
532 strcpy(attrname, "<NONE>");
534 printf(HDR VALS VALS,
535 "destroy", msg->ev_token, msg->ev_sequence,
537 "attrname", attrname);
538 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
539 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
541 printf("\t%-15s ", "attrcopy");
542 for (i = 0; i < clen; i++) {
543 printf("%.2x", copy[i]);
547 printf(VALS, "attrcopy", "<NONE>");
552 /***** MOUNT EVENT *****/
554 else if (msg->ev_type == DM_EVENT_MOUNT) {
555 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
557 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
558 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
559 hlen1 = DM_GET_LEN(msg_me, me_handle1);
561 print_one_mount_event(msg_me);
563 if (register_new_mnts) {
564 if (set_disposition(sid, hanp1, hlen1) == 0)
565 set_events(sid, hanp1, hlen1);
568 #else /* VERITAS_21 */
569 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
570 print_one_mount_event(msg_ne);
571 #endif /* VERITAS_21 */
575 /***** NAMESPACE EVENTS *****/
580 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
581 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
582 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
583 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
584 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
585 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
586 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
587 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
588 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
590 if (hanp1 && hlen1) {
591 hantoa(hanp1, hlen1, hans1);
593 if (hanp2 && hlen2) {
594 hantoa(hanp2, hlen2, hans2);
596 if (namp1 && nlen1) {
597 strncpy(nams1, namp1, nlen1);
598 if (nlen1 != sizeof(nams1))
601 if (namp2 && nlen2) {
602 strncpy(nams2, namp2, nlen2);
603 if (nlen2 != sizeof(nams2))
607 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
608 msg->ev_type == DM_EVENT_UNMOUNT) {
609 if (msg_ne->ne_mode == 0) {
612 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
614 } else if (msg_ne->ne_mode > 0) {
621 } else if (msg->ev_type == DM_EVENT_CREATE ||
622 msg->ev_type == DM_EVENT_POSTCREATE ||
623 msg->ev_type == DM_EVENT_REMOVE ||
624 msg->ev_type == DM_EVENT_POSTREMOVE) {
625 if (format_mode(msg_ne->ne_mode, &type)) {
630 switch(msg->ev_type) {
632 case DM_EVENT_PREUNMOUNT:
633 printf(HDR VALS VALS VALS,
634 "preunmount", msg->ev_token, msg->ev_sequence,
637 "unmount mode", type);
640 case DM_EVENT_UNMOUNT:
641 printf(HDR VALS VALS VALD,
642 "unmount", msg->ev_token, msg->ev_sequence,
644 "unmount mode", type,
645 "retcode", msg_ne->ne_retcode);
648 case DM_EVENT_NOSPACE:
650 "nospace", msg->ev_token, msg->ev_sequence,
652 response = DM_RESP_ABORT;
656 case DM_EVENT_DEBUT: /* not supported on SGI */
658 "debut", msg->ev_token, msg->ev_sequence,
662 case DM_EVENT_CREATE:
663 printf(HDR VALS VALS VALS,
664 "create", msg->ev_token, msg->ev_sequence,
670 case DM_EVENT_POSTCREATE:
671 printf(HDR VALS VALS VALS VALS VALD,
672 "postcreate", msg->ev_token, msg->ev_sequence,
677 "retcode", msg_ne->ne_retcode);
679 clear_region_event(sid, 0, hanp2, hlen2, hans2);
682 case DM_EVENT_REMOVE:
683 printf(HDR VALS VALS VALS,
684 "remove", msg->ev_token, msg->ev_sequence,
690 case DM_EVENT_POSTREMOVE:
691 printf(HDR VALS VALS VALS VALD,
692 "postremove", msg->ev_token, msg->ev_sequence,
696 "retcode", msg_ne->ne_retcode);
700 case DM_EVENT_RENAME:
701 printf(HDR VALS VALS VALS VALS,
702 "rename", msg->ev_token, msg->ev_sequence,
709 case DM_EVENT_POSTRENAME:
710 printf(HDR VALS VALS VALS VALS VALD,
711 "postrename", msg->ev_token, msg->ev_sequence,
716 "retcode", msg_ne->ne_retcode);
720 case DM_EVENT_SYMLINK:
721 printf(HDR VALS VALS VALS,
722 "symlink", msg->ev_token, msg->ev_sequence,
728 case DM_EVENT_POSTSYMLINK:
729 printf(HDR VALS VALS VALS VALS VALD,
730 "postsymlink", msg->ev_token, msg->ev_sequence,
735 "retcode", msg_ne->ne_retcode);
740 printf(HDR VALS VALS VALS,
741 "link", msg->ev_token, msg->ev_sequence,
747 case DM_EVENT_POSTLINK:
748 printf(HDR VALS VALS VALS VALD,
749 "postlink", msg->ev_token, msg->ev_sequence,
753 "retcode", msg_ne->ne_retcode);
757 case DM_EVENT_ATTRIBUTE:
759 "attribute", msg->ev_token, msg->ev_sequence,
764 case DM_EVENT_CLOSE: /* not supported on SGI */
766 "close", msg->ev_token, msg->ev_sequence,
774 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
775 "ev_type", msg->ev_type);
776 if (msg->ev_token == DM_INVALID_TOKEN)
783 * Now respond to those messages which require a response
786 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
788 errno_msg("Can't respond to event");
792 err_msg("Sleeping for %d seconds!\n", Sleep);
802 Convert a mode_t field into a printable string.
804 Returns non-zero if the mode_t is invalid. The string is
805 returned in *ptr, whether there is an error or not.
813 static char modestr[100];
817 if (S_ISFIFO(mode)) typestr = "FIFO";
818 else if(S_ISCHR (mode)) typestr = "Character Device";
819 else if(S_ISBLK (mode)) typestr = "Block Device";
820 else if(S_ISDIR (mode)) typestr = "Directory";
821 else if(S_ISREG (mode)) typestr = "Regular File";
822 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
823 else if(S_ISSOCK(mode)) typestr = "Socket";
825 typestr = "<unknown type>";
829 sprintf(modestr, "mode %06o: perm %c%c%c %c%c%c %c%c%c %c%c%c, type %s",
831 mode & S_ISUID ? 's':' ',
832 mode & S_ISGID ? 'g':' ',
833 mode & S_ISVTX ? 't':' ',
834 mode & S_IRUSR ? 'r':'-',
835 mode & S_IWUSR ? 'w':'-',
836 mode & S_IXUSR ? 'x':'-',
837 mode & S_IRGRP ? 'r':'-',
838 mode & S_IWGRP ? 'w':'-',
839 mode & S_IXGRP ? 'x':'-',
840 mode & S_IROTH ? 'r':'-',
841 mode & S_IWOTH ? 'w':'-',
842 mode & S_IXOTH ? 'x':'-',
855 char hans[HANDLE_STR];
857 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
858 errno_msg("Can't get filesystem handle");
862 hantoa(*fs_hanpp, *fs_hlenp, hans);
863 err_msg("File system handle for %s: %s\n", fsname, hans);
870 Set the event disposition for this filesystem to include all valid
871 DMAPI events so that we receive all events for this filesystem.
872 Also set DM_EVENT_MOUNT disposition for the global handle.
873 It does not make sense to specify DM_EVENT_USER in the disposition
874 mask since a session is always unconditionally registered for these
877 Returns non-zero on error.
884 dm_eventset_t eventlist;
887 err_msg("Setting event disposition to send all "
888 "mount events to this session\n");
891 /* DM_EVENT_MOUNT must be sent in a separate request using the global
892 handle. If we ever support more than one filesystem at a time, this
893 request should be moved out of this routine to a place where it is
897 DMEV_ZERO(eventlist);
898 DMEV_SET(DM_EVENT_MOUNT, eventlist);
900 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
901 &eventlist, DM_EVENT_MAX) == -1) {
902 errno_msg("Can't set event disposition for mount");
916 dm_eventset_t eventlist;
919 err_msg("Setting event disposition to send all "
920 "events to this session\n");
923 DMEV_ZERO(eventlist);
925 /* File system administration events. */
927 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
928 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
929 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
931 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
932 lets it be specified in a dm_set_disp call; its just that the
933 event will never be seen on some platforms.
936 DMEV_SET(DM_EVENT_DEBUT, eventlist);
939 /* Namespace events. */
941 DMEV_SET(DM_EVENT_CREATE, eventlist);
942 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
943 DMEV_SET(DM_EVENT_REMOVE, eventlist);
944 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
945 DMEV_SET(DM_EVENT_RENAME, eventlist);
946 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
947 DMEV_SET(DM_EVENT_LINK, eventlist);
948 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
949 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
950 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
952 /* Managed region data events. */
954 DMEV_SET(DM_EVENT_READ, eventlist);
955 DMEV_SET(DM_EVENT_WRITE, eventlist);
956 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
958 /* Metadata events. */
960 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
961 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && !defined(linux)
962 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
964 #if !defined( __sgi) && !defined(linux)
965 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
967 DMEV_SET(DM_EVENT_DESTROY, eventlist);
971 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
973 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
974 &eventlist, DM_EVENT_MAX) == -1) {
975 errno_msg("Can't set event disposition for filesystem");
983 Enable event generation on each valid filesystem-based DMAPI event
984 within the given file system.
986 Returns non-zero on errors.
995 dm_eventset_t eventlist;
998 err_msg("Setting event list to enable all events "
999 "for this file system\n");
1001 DMEV_ZERO(eventlist);
1003 /* File system administration events. */
1005 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
1006 EINVAL if specified.
1008 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1009 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1010 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1011 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
1013 /* Namespace events. */
1015 DMEV_SET(DM_EVENT_CREATE, eventlist);
1016 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1017 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1018 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1019 DMEV_SET(DM_EVENT_RENAME, eventlist);
1020 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1021 DMEV_SET(DM_EVENT_LINK, eventlist);
1022 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1023 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1024 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1026 /* Managed region data events. These are not settable by
1027 dm_set_eventlist on a filesystem basis. They are meant
1028 to be set using dm_set_region on regular files only.
1029 However, in the SGI implementation, they are filesystem-settable.
1030 Since this is useful for testing purposes, do it.
1034 /* DM_EVENT_WRITE */
1035 /* DM_EVENT_TRUNCATE */
1037 /* Metadata events. */
1039 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1040 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && ! defined(linux)
1041 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1043 #if !defined( __sgi) && !defined(linux)
1044 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1046 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1048 /* Pseudo-events. */
1050 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1052 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1053 &eventlist, DM_EVENT_MAX) == -1) {
1054 errno_msg("Can't set event list");
1062 Disable monitoring for all events in the DMAPI for the given
1063 file system. This is done before exiting so that future
1064 operations won't hang waiting for their events to be handled.
1066 Returns non-zero on errors.
1075 dm_eventset_t eventlist;
1078 err_msg("Clearing event list to disable all events "
1079 "for this filesystem\n");
1081 DMEV_ZERO(eventlist);
1083 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1084 &eventlist, DM_EVENT_MAX) == -1) {
1085 errno_msg("Can't clear event list");
1101 dm_region_t region = { 0, 0, 0 };
1105 region.rg_flags = DM_REGION_READ|DM_REGION_WRITE|DM_REGION_TRUNCATE;
1106 region.rg_flags &= ~event;
1109 err_msg("Clearing region mask 0x%x for file %s\n",
1111 err_msg("Setting region mask 0x%x\n", region.rg_flags);
1114 if (dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, nelem, ®ion,
1116 errno_msg("Can't set region event");
1124 * Respond to any events which haven't been handled yet.
1125 * dm_getall_tokens provides a list of tokens for the outstanding events.
1126 * dm_find_eventmsg uses the token to lookup the corresponding message.
1127 * The message is passed to handle_message() for normal response processing.
1134 u_int nbytes, ntokens = 0, ret_ntokens, i;
1135 dm_token_t *tokenbuf = NULL;
1136 size_t buflen, ret_buflen;
1137 char *msgbuf = NULL;
1141 err_msg("Responding to any outstanding delivered event messages\n");
1144 * Initial sizes for the token and message buffers
1146 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1151 * The E2BIG dance...
1152 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1153 * If the routine returns E2BIG, use the returned size and try again.
1154 * If we're already using the returned size, double it and try again.
1157 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1158 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1159 tokenbuf = malloc(nbytes);
1160 if (tokenbuf == NULL) {
1161 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1165 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1166 } while (error && errno == E2BIG);
1169 errno_msg("Can't get all outstanding tokens");
1173 for (i = 0; i < ret_ntokens; i++) {
1175 err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
1178 * The E2BIG dance reprise...
1181 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1182 msgbuf = malloc(buflen);
1183 if (msgbuf == NULL) {
1184 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1188 error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
1189 } while (error && errno == E2BIG);
1191 errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
1195 msg = (dm_eventmsg_t *) msgbuf;
1196 while (msg != NULL) {
1197 error = handle_message(sid, msg);
1200 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1216 * Establish an exit handler since we run in an infinite loop
1219 establish_handler(void)
1221 struct sigaction act;
1224 * Set up signals so that we can wait for spawned children
1226 act.sa_handler = exit_handler;
1228 sigemptyset(&act.sa_mask);
1230 (void)sigaction(SIGHUP, &act, NULL);
1231 (void)sigaction(SIGINT, &act, NULL);
1232 (void)sigaction(SIGQUIT, &act, NULL);
1233 (void)sigaction(SIGTERM, &act, NULL);
1234 (void)sigaction(SIGUSR1, &act, NULL);
1235 (void)sigaction(SIGUSR1, &act, NULL);
1236 (void)sigaction(SIGUSR2, &act, NULL);
1245 * Stop events from being generated for the given file system
1246 * Respond to any events that were delivered but unanswered
1247 * (the event loop may have been in the middle of taking care of the event)
1248 * Try getting any undelivered events but don't block if none are there
1249 * (the file system may have generated an event after we killed dm_get_events)
1250 * Shutdown the session using the global "sid" variable.
1261 err_msg("Exiting...\n");
1263 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1266 error = clear_events(sid, fs_hanp, fs_hlen);
1268 /* just keep going */ ;
1271 error = finish_responding(sid);
1273 /* just keep going */ ;
1275 err_msg("Processing any undelivered event messages\n");
1276 event_loop(sid, 0 /*waitflag*/);
1278 err_msg("Shutting down the session\n");
1280 error = dm_destroy_session(sid);
1282 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");