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));
536 strcpy(attrname, "<NONE>");
538 printf(HDR VALS VALS,
539 "destroy", msg->ev_token, msg->ev_sequence,
541 "attrname", attrname);
542 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
543 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
545 printf("\t%-15s ", "attrcopy");
546 for (i = 0; i < clen; i++) {
547 printf("%.2x", copy[i]);
551 printf(VALS, "attrcopy", "<NONE>");
556 /***** MOUNT EVENT *****/
558 else if (msg->ev_type == DM_EVENT_MOUNT) {
559 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
561 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
562 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
563 hlen1 = DM_GET_LEN(msg_me, me_handle1);
565 print_one_mount_event(msg_me);
567 if (register_new_mnts) {
568 if (set_disposition(sid, hanp1, hlen1) == 0)
569 set_events(sid, hanp1, hlen1);
572 #else /* VERITAS_21 */
573 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
574 print_one_mount_event(msg_ne);
575 #endif /* VERITAS_21 */
579 /***** NAMESPACE EVENTS *****/
584 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
585 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
586 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
587 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
588 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
589 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
590 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
591 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
592 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
594 if (hanp1 && hlen1) {
595 hantoa(hanp1, hlen1, hans1);
597 if (hanp2 && hlen2) {
598 hantoa(hanp2, hlen2, hans2);
600 if (namp1 && nlen1) {
601 strncpy(nams1, namp1, nlen1);
602 if (nlen1 != sizeof(nams1))
605 if (namp2 && nlen2) {
606 strncpy(nams2, namp2, nlen2);
607 if (nlen2 != sizeof(nams2))
611 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
612 msg->ev_type == DM_EVENT_UNMOUNT) {
613 if (msg_ne->ne_mode == 0) {
616 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
618 } else if (msg_ne->ne_mode > 0) {
625 } else if (msg->ev_type == DM_EVENT_CREATE ||
626 msg->ev_type == DM_EVENT_POSTCREATE ||
627 msg->ev_type == DM_EVENT_REMOVE ||
628 msg->ev_type == DM_EVENT_POSTREMOVE) {
629 if (format_mode(msg_ne->ne_mode, &type)) {
634 switch(msg->ev_type) {
636 case DM_EVENT_PREUNMOUNT:
637 printf(HDR VALS VALS VALS,
638 "preunmount", msg->ev_token, msg->ev_sequence,
641 "unmount mode", type);
644 case DM_EVENT_UNMOUNT:
645 printf(HDR VALS VALS VALD,
646 "unmount", msg->ev_token, msg->ev_sequence,
648 "unmount mode", type,
649 "retcode", msg_ne->ne_retcode);
652 case DM_EVENT_NOSPACE:
654 "nospace", msg->ev_token, msg->ev_sequence,
656 response = DM_RESP_ABORT;
660 case DM_EVENT_DEBUT: /* not supported on SGI */
662 "debut", msg->ev_token, msg->ev_sequence,
666 case DM_EVENT_CREATE:
667 printf(HDR VALS VALS VALS,
668 "create", msg->ev_token, msg->ev_sequence,
674 case DM_EVENT_POSTCREATE:
675 printf(HDR VALS VALS VALS VALS VALD,
676 "postcreate", msg->ev_token, msg->ev_sequence,
681 "retcode", msg_ne->ne_retcode);
683 clear_region_event(sid, 0, hanp2, hlen2, hans2);
686 case DM_EVENT_REMOVE:
687 printf(HDR VALS VALS VALS,
688 "remove", msg->ev_token, msg->ev_sequence,
694 case DM_EVENT_POSTREMOVE:
695 printf(HDR VALS VALS VALS VALD,
696 "postremove", msg->ev_token, msg->ev_sequence,
700 "retcode", msg_ne->ne_retcode);
704 case DM_EVENT_RENAME:
705 printf(HDR VALS VALS VALS VALS,
706 "rename", msg->ev_token, msg->ev_sequence,
713 case DM_EVENT_POSTRENAME:
714 printf(HDR VALS VALS VALS VALS VALD,
715 "postrename", msg->ev_token, msg->ev_sequence,
720 "retcode", msg_ne->ne_retcode);
724 case DM_EVENT_SYMLINK:
725 printf(HDR VALS VALS VALS,
726 "symlink", msg->ev_token, msg->ev_sequence,
732 case DM_EVENT_POSTSYMLINK:
733 printf(HDR VALS VALS VALS VALS VALD,
734 "postsymlink", msg->ev_token, msg->ev_sequence,
739 "retcode", msg_ne->ne_retcode);
744 printf(HDR VALS VALS VALS,
745 "link", msg->ev_token, msg->ev_sequence,
751 case DM_EVENT_POSTLINK:
752 printf(HDR VALS VALS VALS VALD,
753 "postlink", msg->ev_token, msg->ev_sequence,
757 "retcode", msg_ne->ne_retcode);
761 case DM_EVENT_ATTRIBUTE:
763 "attribute", msg->ev_token, msg->ev_sequence,
768 case DM_EVENT_CLOSE: /* not supported on SGI */
770 "close", msg->ev_token, msg->ev_sequence,
778 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
779 "ev_type", msg->ev_type);
780 if (msg->ev_token == DM_INVALID_TOKEN)
787 * Now respond to those messages which require a response
790 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
792 errno_msg("Can't respond to event");
796 err_msg("Sleeping for %d seconds!\n", Sleep);
806 Convert a mode_t field into a printable string.
808 Returns non-zero if the mode_t is invalid. The string is
809 returned in *ptr, whether there is an error or not.
817 static char modestr[100];
821 if (S_ISFIFO(mode)) typestr = "FIFO";
822 else if(S_ISCHR (mode)) typestr = "Character Device";
823 else if(S_ISBLK (mode)) typestr = "Block Device";
824 else if(S_ISDIR (mode)) typestr = "Directory";
825 else if(S_ISREG (mode)) typestr = "Regular File";
826 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
827 else if(S_ISSOCK(mode)) typestr = "Socket";
829 typestr = "<unknown type>";
833 sprintf(modestr, "mode %06o: perm %c%c%c %c%c%c %c%c%c %c%c%c, type %s",
835 mode & S_ISUID ? 's':' ',
836 mode & S_ISGID ? 'g':' ',
837 mode & S_ISVTX ? 't':' ',
838 mode & S_IRUSR ? 'r':'-',
839 mode & S_IWUSR ? 'w':'-',
840 mode & S_IXUSR ? 'x':'-',
841 mode & S_IRGRP ? 'r':'-',
842 mode & S_IWGRP ? 'w':'-',
843 mode & S_IXGRP ? 'x':'-',
844 mode & S_IROTH ? 'r':'-',
845 mode & S_IWOTH ? 'w':'-',
846 mode & S_IXOTH ? 'x':'-',
859 char hans[HANDLE_STR];
861 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
862 errno_msg("Can't get filesystem handle");
866 hantoa(*fs_hanpp, *fs_hlenp, hans);
867 err_msg("File system handle for %s: %s\n", fsname, hans);
874 Set the event disposition for this filesystem to include all valid
875 DMAPI events so that we receive all events for this filesystem.
876 Also set DM_EVENT_MOUNT disposition for the global handle.
877 It does not make sense to specify DM_EVENT_USER in the disposition
878 mask since a session is always unconditionally registered for these
881 Returns non-zero on error.
888 dm_eventset_t eventlist;
891 err_msg("Setting event disposition to send all "
892 "mount events to this session\n");
895 /* DM_EVENT_MOUNT must be sent in a separate request using the global
896 handle. If we ever support more than one filesystem at a time, this
897 request should be moved out of this routine to a place where it is
901 DMEV_ZERO(eventlist);
902 DMEV_SET(DM_EVENT_MOUNT, eventlist);
904 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
905 &eventlist, DM_EVENT_MAX) == -1) {
906 errno_msg("Can't set event disposition for mount");
920 dm_eventset_t eventlist;
923 err_msg("Setting event disposition to send all "
924 "events to this session\n");
927 DMEV_ZERO(eventlist);
929 /* File system administration events. */
931 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
932 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
933 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
935 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
936 lets it be specified in a dm_set_disp call; its just that the
937 event will never be seen on some platforms.
940 DMEV_SET(DM_EVENT_DEBUT, eventlist);
943 /* Namespace events. */
945 DMEV_SET(DM_EVENT_CREATE, eventlist);
946 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
947 DMEV_SET(DM_EVENT_REMOVE, eventlist);
948 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
949 DMEV_SET(DM_EVENT_RENAME, eventlist);
950 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
951 DMEV_SET(DM_EVENT_LINK, eventlist);
952 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
953 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
954 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
956 /* Managed region data events. */
958 DMEV_SET(DM_EVENT_READ, eventlist);
959 DMEV_SET(DM_EVENT_WRITE, eventlist);
960 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
962 /* Metadata events. */
964 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
965 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && !defined(linux)
966 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
968 #if !defined( __sgi) && !defined(linux)
969 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
971 DMEV_SET(DM_EVENT_DESTROY, eventlist);
975 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
977 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
978 &eventlist, DM_EVENT_MAX) == -1) {
979 errno_msg("Can't set event disposition for filesystem");
987 Enable event generation on each valid filesystem-based DMAPI event
988 within the given file system.
990 Returns non-zero on errors.
999 dm_eventset_t eventlist;
1003 err_msg("Setting event list to enable all "
1004 "DMF-supported events "
1005 "for this file system\n");
1008 err_msg("Setting event list to enable all events "
1009 "for this file system\n");
1012 DMEV_ZERO(eventlist);
1014 /* File system administration events. */
1016 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
1017 EINVAL if specified.
1019 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1020 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1021 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1022 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
1024 /* Namespace events. */
1026 DMEV_SET(DM_EVENT_CREATE, eventlist);
1027 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1028 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1029 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1030 DMEV_SET(DM_EVENT_RENAME, eventlist);
1031 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1032 DMEV_SET(DM_EVENT_LINK, eventlist);
1033 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1034 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1035 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1037 /* Managed region data events. These are not settable by
1038 dm_set_eventlist on a filesystem basis. They are meant
1039 to be set using dm_set_region on regular files only.
1040 However, in the SGI implementation, they are filesystem-settable.
1041 Since this is useful for testing purposes, do it.
1045 /* DM_EVENT_WRITE */
1046 /* DM_EVENT_TRUNCATE */
1048 /* Metadata events. */
1050 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1051 #if ! defined ( __sgi ) && ! defined ( VERITAS_21 ) && ! defined(linux)
1052 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1054 #if !defined( __sgi) && !defined(linux)
1055 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1057 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1059 /* Did we want just the DMF events? */
1061 DMEV_ZERO(eventlist);
1062 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1063 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1066 /* Pseudo-events. */
1068 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1070 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1071 &eventlist, DM_EVENT_MAX) == -1) {
1072 errno_msg("Can't set event list");
1080 Disable monitoring for all events in the DMAPI for the given
1081 file system. This is done before exiting so that future
1082 operations won't hang waiting for their events to be handled.
1084 Returns non-zero on errors.
1093 dm_eventset_t eventlist;
1096 err_msg("Clearing event list to disable all events "
1097 "for this filesystem\n");
1099 DMEV_ZERO(eventlist);
1101 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1102 &eventlist, DM_EVENT_MAX) == -1) {
1103 errno_msg("Can't clear event list");
1119 dm_region_t region = { 0, 0, 0 };
1123 region.rg_flags = DM_REGION_READ|DM_REGION_WRITE|DM_REGION_TRUNCATE;
1124 region.rg_flags &= ~event;
1127 err_msg("Clearing region mask 0x%x for file %s\n",
1129 err_msg("Setting region mask 0x%x\n", region.rg_flags);
1132 if (dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, nelem, ®ion,
1134 errno_msg("Can't set region event");
1142 * Respond to any events which haven't been handled yet.
1143 * dm_getall_tokens provides a list of tokens for the outstanding events.
1144 * dm_find_eventmsg uses the token to lookup the corresponding message.
1145 * The message is passed to handle_message() for normal response processing.
1152 u_int nbytes, ntokens = 0, ret_ntokens, i;
1153 dm_token_t *tokenbuf = NULL;
1154 size_t buflen, ret_buflen;
1155 char *msgbuf = NULL;
1159 err_msg("Responding to any outstanding delivered event messages\n");
1162 * Initial sizes for the token and message buffers
1164 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1169 * The E2BIG dance...
1170 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1171 * If the routine returns E2BIG, use the returned size and try again.
1172 * If we're already using the returned size, double it and try again.
1175 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1176 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1177 tokenbuf = malloc(nbytes);
1178 if (tokenbuf == NULL) {
1179 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1183 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1184 } while (error && errno == E2BIG);
1187 errno_msg("Can't get all outstanding tokens");
1191 for (i = 0; i < ret_ntokens; i++) {
1193 err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
1196 * The E2BIG dance reprise...
1199 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1200 msgbuf = malloc(buflen);
1201 if (msgbuf == NULL) {
1202 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1206 error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
1207 } while (error && errno == E2BIG);
1209 errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
1213 msg = (dm_eventmsg_t *) msgbuf;
1214 while (msg != NULL) {
1215 error = handle_message(sid, msg);
1218 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1234 * Establish an exit handler since we run in an infinite loop
1237 establish_handler(void)
1239 struct sigaction act;
1242 * Set up signals so that we can wait for spawned children
1244 act.sa_handler = exit_handler;
1246 sigemptyset(&act.sa_mask);
1248 (void)sigaction(SIGHUP, &act, NULL);
1249 (void)sigaction(SIGINT, &act, NULL);
1250 (void)sigaction(SIGQUIT, &act, NULL);
1251 (void)sigaction(SIGTERM, &act, NULL);
1252 (void)sigaction(SIGUSR1, &act, NULL);
1253 (void)sigaction(SIGUSR1, &act, NULL);
1254 (void)sigaction(SIGUSR2, &act, NULL);
1263 * Stop events from being generated for the given file system
1264 * Respond to any events that were delivered but unanswered
1265 * (the event loop may have been in the middle of taking care of the event)
1266 * Try getting any undelivered events but don't block if none are there
1267 * (the file system may have generated an event after we killed dm_get_events)
1268 * Shutdown the session using the global "sid" variable.
1279 err_msg("Exiting...\n");
1281 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1284 error = clear_events(sid, fs_hanp, fs_hlen);
1286 /* just keep going */ ;
1289 error = finish_responding(sid);
1291 /* just keep going */ ;
1293 err_msg("Processing any undelivered event messages\n");
1294 event_loop(sid, 0 /*waitflag*/);
1296 err_msg("Shutting down the session\n");
1298 error = dm_destroy_session(sid);
1300 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");