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
84 int dmf_events = 0; /* Use only those events that DMF uses */
90 fprintf(stderr, "Usage: %s ", prog);
91 fprintf(stderr, " <-S oldsid> <-v> <-s sleep> <-R> <-N> <-D> ");
92 fprintf(stderr, "filesystem \n");
108 /* Progname = argv[0];*/ Progname = "print_event";
111 while ((c = getopt(argc, argv, "vs:S:RND")) != EOF) {
114 Sleep = atoi(optarg);
117 register_new_mnts = 1;
126 oldsid = atoi(optarg);
137 if (optind >= argc) {
141 fsname = argv[optind];
142 if (fsname == NULL) {
148 * Establish an exit handler
150 error = establish_handler();
155 * Init the dmapi, and get a filesystem handle so
156 * we can set up our events
162 error = setup_dmapi(&sid);
167 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
172 * Set the event disposition so that our session will receive
173 * all the events for the given file system
175 error = set_disp_global(sid);
178 error = set_disposition(sid, fs_hanp, fs_hlen);
183 * Enable monitoring for all events in the given file system
185 error = set_events(sid, fs_hanp, fs_hlen);
190 * Now sit in an infinite loop, reporting on any events that occur.
191 * The program is exited after a signal through exit_handler().
194 event_loop(sid, 1 /*waitflag*/);
197 * If we get here, cleanup after the event_loop failure
206 * Main event loop processing
208 * The waitflag argument is set to 1 when we call this from main().
209 * In this case, continuously process incoming events,
210 * blocking if there are none available.
211 * In the exit_handler(), call this routine with waitflag=0.
212 * Just try to read the events once in this case with no blocking.
227 * We take a swag at a buffer size. If it's wrong, we can
231 bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
233 msgbuf = (void *)malloc(bufsize);
234 if (msgbuf == NULL) {
235 err_msg("Can't allocate memory for buffer");
240 error = dm_get_events(sid, ALL_AVAIL_MSGS,
241 waitflag ? DM_EV_WAIT:0, bufsize, msgbuf, &bufsize);
243 if (errno == EAGAIN) {
248 if (errno == E2BIG) {
250 msgbuf = (void *)malloc(bufsize);
251 if (msgbuf == NULL) {
252 err_msg("Can't resize msg buffer");
257 errno_msg("Error getting events from DMAPI (%d)", errno);
262 * Walk through the message buffer, pull out each individual
263 * message, and dispatch the messages to handle_message(),
264 * which will respond to the events.
268 msg = (dm_eventmsg_t *)msgbuf;
269 while (msg != NULL ) {
271 error = handle_message(sid, msg);
276 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
278 if (count != 1 && Verbose) {
279 err_msg("Found %d events in one call to "
280 "dm_get_events\n", count);
289 print_one_mount_event(
292 void *hanp1, *hanp2, *hanp3;
293 size_t hlen1, hlen2, hlen3;
294 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
297 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
301 dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
304 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
306 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
307 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
308 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
309 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
310 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
311 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
312 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
313 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
316 mode = msg_ne->ne_mode;
318 dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
320 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
321 hlen1 = DM_GET_LEN(msg_me, me_handle1);
322 hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
323 hlen2 = DM_GET_LEN(msg_me, me_handle2);
324 namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
325 nlen1 = DM_GET_LEN(msg_me, me_name1);
326 namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
327 nlen2 = DM_GET_LEN(msg_me, me_name2);
328 hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
329 hlen3 = DM_GET_LEN(msg_me, me_roothandle);
330 mode = msg_me->me_mode;
331 #endif /* VERITAS_21 */
333 if (hanp1 && hlen1) {
334 hantoa(hanp1, hlen1, hans1);
336 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
338 if (hanp2 && hlen2) {
339 hantoa(hanp2, hlen2, hans2);
341 sprintf(hans2, "<BAD HANDLE, hlen %d>", hlen2);
343 if (hanp3 && hlen3) {
344 hantoa(hanp3, hlen3, hans3);
346 sprintf(hans3, "<BAD HANDLE, hlen %d>", hlen3);
348 if (namp1 && nlen1) {
349 strncpy(nams1, namp1, nlen1);
350 if (nlen1 != sizeof(nams1))
353 sprintf(nams1, "<BAD STRING, nlen %d>", nlen1);
355 if (namp2 && nlen2) {
356 strncpy(nams2, namp2, nlen2);
357 if (nlen2 != sizeof(nams2))
360 sprintf(nams2, "<BAD STRING, nlen %d>", nlen2);
363 printf(VALS VALS VALS VALS VALS VALD,
365 "mtpt handle", hans2,
367 "media desig", nams2,
368 "root handle", hans3,
374 * First, weed out the events which return interesting structures.
375 * If it's not one of those, unpack the dm_namesp_event structure
376 * and display the contents.
385 dm_response_t response;
386 int respond, respcode;
387 dm_namesp_event_t *msg_ne;
389 dm_mount_event_t *msg_me;
391 void *hanp1, *hanp2, *namp1, *namp2;
392 u_int hlen1, hlen2, nlen1, nlen2;
393 char hans1[HANDLE_STR], hans2[HANDLE_STR];
394 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
397 * Set the defaults for responding to events
400 response = DM_RESP_CONTINUE;
403 /***** USER EVENTS *****/
405 if (msg->ev_type == DM_EVENT_USER) {
410 "user", msg->ev_token, msg->ev_sequence);
412 /* print private data as ascii or hex if it exists DM_CONFIG_MAX_MESSAGE_DATA */
414 privp = DM_GET_VALUE(msg, ev_data, char *);
415 plen = DM_GET_LEN (msg, ev_data);
417 for (i = 0; i < plen; i++) {
418 if (!isprint(privp[i]) && !isspace(privp[i]))
421 if (i == plen - 1 && privp[i] == '\0') {
425 printf("\t%-15s ", "privdata");
426 for (i = 0; i < plen; i++) {
427 printf("%.2x", privp[i]);
433 "privdata", "<NONE>");
436 if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
440 /***** CANCEL EVENT *****/
442 /* Not implemented on SGI or Veritas */
444 else if (msg->ev_type == DM_EVENT_CANCEL) {
445 dm_cancel_event_t *msg_ce;
447 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
448 printf(HDR VALD VALD,
449 "cancel", msg->ev_token, msg->ev_sequence,
450 "sequence", msg_ce->ce_sequence,
451 "token", msg_ce->ce_token);
455 /***** DATA EVENTS *****/
457 else if (msg->ev_type == DM_EVENT_READ ||
458 msg->ev_type == DM_EVENT_WRITE ||
459 msg->ev_type == DM_EVENT_TRUNCATE) {
460 dm_data_event_t *msg_de;
462 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
463 hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
464 hlen1 = DM_GET_LEN (msg_de, de_handle);
465 if (hanp1 && hlen1) {
466 hantoa(hanp1, hlen1, hans1);
469 switch(msg->ev_type) {
470 /* DM_EVENT_* and DM_REGION_* are different values, ug */
472 rgflag = DM_REGION_READ;
475 rgflag = DM_REGION_WRITE;
477 case DM_EVENT_TRUNCATE:
478 rgflag = DM_REGION_TRUNCATE;
481 clear_region_event(sid, rgflag, hanp1, hlen1, hans1);
484 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
487 switch(msg->ev_type) {
490 printf(HDR VALS VALLLD VALLLD,
491 "read", msg->ev_token, msg->ev_sequence,
492 "file handle", hans1,
493 "offset", msg_de->de_offset,
494 "length", msg_de->de_length);
498 printf(HDR VALS VALLLD VALLLD,
499 "write", msg->ev_token, msg->ev_sequence,
500 "file handle", hans1,
501 "offset", msg_de->de_offset,
502 "length", msg_de->de_length);
505 case DM_EVENT_TRUNCATE:
506 printf(HDR VALS VALLLD VALLLD,
507 "truncate", msg->ev_token, msg->ev_sequence,
508 "file handle", hans1,
509 "offset", msg_de->de_offset,
510 "length", msg_de->de_length);
516 /***** DESTROY EVENT *****/
518 else if (msg->ev_type == DM_EVENT_DESTROY) {
519 dm_destroy_event_t *msg_ds;
520 char attrname[DM_ATTR_NAME_SIZE + 1];
525 msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
526 hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
527 hlen1 = DM_GET_LEN (msg_ds, ds_handle);
528 if (hanp1 && hlen1) {
529 hantoa(hanp1, hlen1, hans1);
531 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
533 if (msg_ds->ds_attrname.an_chars[0] != '\0') {
534 strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
535 attrname[DM_ATTR_NAME_SIZE] = '\0'; /* terminate the string */
537 strcpy(attrname, "<NONE>");
539 printf(HDR VALS VALS,
540 "destroy", msg->ev_token, msg->ev_sequence,
542 "attrname", attrname);
543 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
544 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
546 printf("\t%-15s ", "attrcopy");
547 for (i = 0; i < clen; i++) {
548 printf("%.2x", copy[i]);
552 printf(VALS, "attrcopy", "<NONE>");
557 /***** MOUNT EVENT *****/
559 else if (msg->ev_type == DM_EVENT_MOUNT) {
560 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
562 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
563 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
564 hlen1 = DM_GET_LEN(msg_me, me_handle1);
566 print_one_mount_event(msg_me);
568 if (register_new_mnts) {
569 if (set_disposition(sid, hanp1, hlen1) == 0)
570 set_events(sid, hanp1, hlen1);
573 #else /* VERITAS_21 */
574 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
575 print_one_mount_event(msg_ne);
576 #endif /* VERITAS_21 */
580 /***** NAMESPACE EVENTS *****/
585 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
586 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
587 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
588 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
589 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
590 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
591 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
592 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
593 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
595 if (hanp1 && hlen1) {
596 hantoa(hanp1, hlen1, hans1);
598 if (hanp2 && hlen2) {
599 hantoa(hanp2, hlen2, hans2);
601 if (namp1 && nlen1) {
602 strncpy(nams1, namp1, nlen1);
603 if (nlen1 != sizeof(nams1))
606 if (namp2 && nlen2) {
607 strncpy(nams2, namp2, nlen2);
608 if (nlen2 != sizeof(nams2))
612 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
613 msg->ev_type == DM_EVENT_UNMOUNT) {
614 if (msg_ne->ne_mode == 0) {
617 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
619 } else if (msg_ne->ne_mode > 0) {
626 } else if (msg->ev_type == DM_EVENT_CREATE ||
627 msg->ev_type == DM_EVENT_POSTCREATE ||
628 msg->ev_type == DM_EVENT_REMOVE ||
629 msg->ev_type == DM_EVENT_POSTREMOVE) {
630 if (format_mode(msg_ne->ne_mode, &type)) {
635 switch(msg->ev_type) {
637 case DM_EVENT_PREUNMOUNT:
638 printf(HDR VALS VALS VALS,
639 "preunmount", msg->ev_token, msg->ev_sequence,
642 "unmount mode", type);
645 case DM_EVENT_UNMOUNT:
646 printf(HDR VALS VALS VALD,
647 "unmount", msg->ev_token, msg->ev_sequence,
649 "unmount mode", type,
650 "retcode", msg_ne->ne_retcode);
653 case DM_EVENT_NOSPACE:
655 "nospace", msg->ev_token, msg->ev_sequence,
657 response = DM_RESP_ABORT;
661 case DM_EVENT_DEBUT: /* not supported on SGI */
663 "debut", msg->ev_token, msg->ev_sequence,
667 case DM_EVENT_CREATE:
668 printf(HDR VALS VALS VALS,
669 "create", msg->ev_token, msg->ev_sequence,
675 case DM_EVENT_POSTCREATE:
676 printf(HDR VALS VALS VALS VALS VALD,
677 "postcreate", msg->ev_token, msg->ev_sequence,
682 "retcode", msg_ne->ne_retcode);
684 clear_region_event(sid, 0, hanp2, hlen2, hans2);
687 case DM_EVENT_REMOVE:
688 printf(HDR VALS VALS VALS,
689 "remove", msg->ev_token, msg->ev_sequence,
695 case DM_EVENT_POSTREMOVE:
696 printf(HDR VALS VALS VALS VALD,
697 "postremove", msg->ev_token, msg->ev_sequence,
701 "retcode", msg_ne->ne_retcode);
705 case DM_EVENT_RENAME:
706 printf(HDR VALS VALS VALS VALS,
707 "rename", msg->ev_token, msg->ev_sequence,
714 case DM_EVENT_POSTRENAME:
715 printf(HDR VALS VALS VALS VALS VALD,
716 "postrename", msg->ev_token, msg->ev_sequence,
721 "retcode", msg_ne->ne_retcode);
725 case DM_EVENT_SYMLINK:
726 printf(HDR VALS VALS VALS,
727 "symlink", msg->ev_token, msg->ev_sequence,
733 case DM_EVENT_POSTSYMLINK:
734 printf(HDR VALS VALS VALS VALS VALD,
735 "postsymlink", msg->ev_token, msg->ev_sequence,
740 "retcode", msg_ne->ne_retcode);
745 printf(HDR VALS VALS VALS,
746 "link", msg->ev_token, msg->ev_sequence,
752 case DM_EVENT_POSTLINK:
753 printf(HDR VALS VALS VALS VALD,
754 "postlink", msg->ev_token, msg->ev_sequence,
758 "retcode", msg_ne->ne_retcode);
762 case DM_EVENT_ATTRIBUTE:
764 "attribute", msg->ev_token, msg->ev_sequence,
769 case DM_EVENT_CLOSE: /* not supported on SGI */
771 "close", msg->ev_token, msg->ev_sequence,
779 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
780 "ev_type", msg->ev_type);
781 if (msg->ev_token == DM_INVALID_TOKEN)
788 * Now respond to those messages which require a response
791 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
793 errno_msg("Can't respond to event");
797 err_msg("Sleeping for %d seconds!\n", Sleep);
807 Convert a mode_t field into a printable string.
809 Returns non-zero if the mode_t is invalid. The string is
810 returned in *ptr, whether there is an error or not.
818 static char modestr[100];
822 if (S_ISFIFO(mode)) typestr = "FIFO";
823 else if(S_ISCHR (mode)) typestr = "Character Device";
824 else if(S_ISBLK (mode)) typestr = "Block Device";
825 else if(S_ISDIR (mode)) typestr = "Directory";
826 else if(S_ISREG (mode)) typestr = "Regular File";
827 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
828 else if(S_ISSOCK(mode)) typestr = "Socket";
830 typestr = "<unknown type>";
834 sprintf(modestr, "mode %06o: perm %c%c%c %c%c%c %c%c%c %c%c%c, type %s",
836 mode & S_ISUID ? 's':' ',
837 mode & S_ISGID ? 'g':' ',
838 mode & S_ISVTX ? 't':' ',
839 mode & S_IRUSR ? 'r':'-',
840 mode & S_IWUSR ? 'w':'-',
841 mode & S_IXUSR ? 'x':'-',
842 mode & S_IRGRP ? 'r':'-',
843 mode & S_IWGRP ? 'w':'-',
844 mode & S_IXGRP ? 'x':'-',
845 mode & S_IROTH ? 'r':'-',
846 mode & S_IWOTH ? 'w':'-',
847 mode & S_IXOTH ? 'x':'-',
860 char hans[HANDLE_STR];
862 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
863 errno_msg("Can't get filesystem handle");
867 hantoa(*fs_hanpp, *fs_hlenp, hans);
868 err_msg("File system handle for %s: %s\n", fsname, hans);
875 Set the event disposition for this filesystem to include all valid
876 DMAPI events so that we receive all events for this filesystem.
877 Also set DM_EVENT_MOUNT disposition for the global handle.
878 It does not make sense to specify DM_EVENT_USER in the disposition
879 mask since a session is always unconditionally registered for these
882 Returns non-zero on error.
889 dm_eventset_t eventlist;
892 err_msg("Setting event disposition to send all "
893 "mount events to this session\n");
896 /* DM_EVENT_MOUNT must be sent in a separate request using the global
897 handle. If we ever support more than one filesystem at a time, this
898 request should be moved out of this routine to a place where it is
902 DMEV_ZERO(eventlist);
903 DMEV_SET(DM_EVENT_MOUNT, eventlist);
905 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
906 &eventlist, DM_EVENT_MAX) == -1) {
907 errno_msg("Can't set event disposition for mount");
921 dm_eventset_t eventlist;
924 err_msg("Setting event disposition to send all "
925 "events to this session\n");
928 DMEV_ZERO(eventlist);
930 /* File system administration events. */
932 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
933 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
934 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
936 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
937 lets it be specified in a dm_set_disp call; its just that the
938 event will never be seen on some platforms.
941 DMEV_SET(DM_EVENT_DEBUT, eventlist);
944 /* Namespace events. */
946 DMEV_SET(DM_EVENT_CREATE, eventlist);
947 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
948 DMEV_SET(DM_EVENT_REMOVE, eventlist);
949 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
950 DMEV_SET(DM_EVENT_RENAME, eventlist);
951 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
952 DMEV_SET(DM_EVENT_LINK, eventlist);
953 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
954 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
955 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
957 /* Managed region data events. */
959 DMEV_SET(DM_EVENT_READ, eventlist);
960 DMEV_SET(DM_EVENT_WRITE, eventlist);
961 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
963 /* Metadata events. */
965 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
966 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && !defined(linux)
967 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
969 #if !defined( __sgi) && !defined(linux)
970 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
972 DMEV_SET(DM_EVENT_DESTROY, eventlist);
976 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
978 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
979 &eventlist, DM_EVENT_MAX) == -1) {
980 errno_msg("Can't set event disposition for filesystem");
988 Enable event generation on each valid filesystem-based DMAPI event
989 within the given file system.
991 Returns non-zero on errors.
1000 dm_eventset_t eventlist;
1004 err_msg("Setting event list to enable all "
1005 "DMF-supported events "
1006 "for this file system\n");
1009 err_msg("Setting event list to enable all events "
1010 "for this file system\n");
1013 DMEV_ZERO(eventlist);
1015 /* File system administration events. */
1017 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
1018 EINVAL if specified.
1020 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1021 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1022 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1023 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
1025 /* Namespace events. */
1027 DMEV_SET(DM_EVENT_CREATE, eventlist);
1028 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1029 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1030 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1031 DMEV_SET(DM_EVENT_RENAME, eventlist);
1032 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1033 DMEV_SET(DM_EVENT_LINK, eventlist);
1034 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1035 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1036 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1038 /* Managed region data events. These are not settable by
1039 dm_set_eventlist on a filesystem basis. They are meant
1040 to be set using dm_set_region on regular files only.
1041 However, in the SGI implementation, they are filesystem-settable.
1042 Since this is useful for testing purposes, do it.
1046 /* DM_EVENT_WRITE */
1047 /* DM_EVENT_TRUNCATE */
1049 /* Metadata events. */
1051 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1052 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && ! defined(linux)
1053 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1055 #if !defined( __sgi) && !defined(linux)
1056 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1058 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1060 /* Did we want just the DMF events? */
1062 DMEV_ZERO(eventlist);
1063 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1064 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1067 /* Pseudo-events. */
1069 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1071 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1072 &eventlist, DM_EVENT_MAX) == -1) {
1073 errno_msg("Can't set event list");
1081 Disable monitoring for all events in the DMAPI for the given
1082 file system. This is done before exiting so that future
1083 operations won't hang waiting for their events to be handled.
1085 Returns non-zero on errors.
1094 dm_eventset_t eventlist;
1097 err_msg("Clearing event list to disable all events "
1098 "for this filesystem\n");
1100 DMEV_ZERO(eventlist);
1102 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1103 &eventlist, DM_EVENT_MAX) == -1) {
1104 errno_msg("Can't clear event list");
1120 dm_region_t region = { 0, 0, 0 };
1124 region.rg_flags = DM_REGION_READ|DM_REGION_WRITE|DM_REGION_TRUNCATE;
1125 region.rg_flags &= ~event;
1128 err_msg("Clearing region mask 0x%x for file %s\n",
1130 err_msg("Setting region mask 0x%x\n", region.rg_flags);
1133 if (dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, nelem, ®ion,
1135 errno_msg("Can't set region event");
1143 * Respond to any events which haven't been handled yet.
1144 * dm_getall_tokens provides a list of tokens for the outstanding events.
1145 * dm_find_eventmsg uses the token to lookup the corresponding message.
1146 * The message is passed to handle_message() for normal response processing.
1153 u_int nbytes, ntokens = 0, ret_ntokens, i;
1154 dm_token_t *tokenbuf = NULL;
1155 size_t buflen, ret_buflen;
1156 char *msgbuf = NULL;
1160 err_msg("Responding to any outstanding delivered event messages\n");
1163 * Initial sizes for the token and message buffers
1165 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1170 * The E2BIG dance...
1171 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1172 * If the routine returns E2BIG, use the returned size and try again.
1173 * If we're already using the returned size, double it and try again.
1176 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1177 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1178 tokenbuf = malloc(nbytes);
1179 if (tokenbuf == NULL) {
1180 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1184 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1185 } while (error && errno == E2BIG);
1188 errno_msg("Can't get all outstanding tokens");
1192 for (i = 0; i < ret_ntokens; i++) {
1194 err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
1197 * The E2BIG dance reprise...
1200 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1201 msgbuf = malloc(buflen);
1202 if (msgbuf == NULL) {
1203 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1207 error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
1208 } while (error && errno == E2BIG);
1210 errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
1214 msg = (dm_eventmsg_t *) msgbuf;
1215 while (msg != NULL) {
1216 error = handle_message(sid, msg);
1219 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1235 * Establish an exit handler since we run in an infinite loop
1238 establish_handler(void)
1240 struct sigaction act;
1243 * Set up signals so that we can wait for spawned children
1245 act.sa_handler = exit_handler;
1247 sigemptyset(&act.sa_mask);
1249 (void)sigaction(SIGHUP, &act, NULL);
1250 (void)sigaction(SIGINT, &act, NULL);
1251 (void)sigaction(SIGQUIT, &act, NULL);
1252 (void)sigaction(SIGTERM, &act, NULL);
1253 (void)sigaction(SIGUSR1, &act, NULL);
1254 (void)sigaction(SIGUSR1, &act, NULL);
1255 (void)sigaction(SIGUSR2, &act, NULL);
1264 * Stop events from being generated for the given file system
1265 * Respond to any events that were delivered but unanswered
1266 * (the event loop may have been in the middle of taking care of the event)
1267 * Try getting any undelivered events but don't block if none are there
1268 * (the file system may have generated an event after we killed dm_get_events)
1269 * Shutdown the session using the global "sid" variable.
1280 err_msg("Exiting...\n");
1282 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1285 error = clear_events(sid, fs_hanp, fs_hlen);
1287 /* just keep going */ ;
1290 error = finish_responding(sid);
1292 /* just keep going */ ;
1294 err_msg("Processing any undelivered event messages\n");
1295 event_loop(sid, 0 /*waitflag*/);
1297 err_msg("Shutting down the session\n");
1299 error = dm_destroy_session(sid);
1301 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");