13 * Monitor all events for a file system.
14 * When one arrives, print a message with all the details.
15 * If the message is synchronous, always reply with DM_RESP_CONTINUE
16 * (This program doesn't perform any real file system or HSM work.)
18 * This is a simplification of the "migin.c" example program.
19 * The original code was by Peter Lawthers:
20 * This code was written by Peter Lawthers, and placed in the public
21 * domain for use by DMAPI implementors and app writers.
31 #include <sys/types.h>
33 #include <sys/resource.h>
34 #include <sys/errno.h>
36 #include <sys/param.h>
39 #include <lib/dmport.h>
43 * Define some standard formats for the printf statements below.
46 #define HDR "%s\ntoken :%d\nsequence :%d\n"
47 #define VALS "%-15s:%s\n"
48 #define VALD "%-15s:%d\n"
49 #define VALLLD "%-15s:%lld\n"
55 int main (int, char **);
56 static void event_loop (dm_sessid_t, int);
57 int handle_message (dm_sessid_t, dm_eventmsg_t *);
58 static int format_mode(mode_t mode, char **ptr);
59 static int get_fs_handle (char *, void **, size_t *);
60 static int set_disposition(dm_sessid_t, void *, size_t);
61 static int set_events (dm_sessid_t, void *, size_t);
62 static int clear_events (dm_sessid_t, void *, size_t);
63 int finish_responding(dm_sessid_t);
64 int establish_handler(void);
65 void exit_handler (int);
68 * Keep these global so the exit_handler and err_msg routines can get to them
74 dm_sessid_t oldsid = 0;
77 int unfriendly_errno=EBADMSG;
78 int unfriendly_count=0;
87 fprintf(stderr, "Usage: %s ", prog);
88 fprintf(stderr, "<-s sleeptime> <-S oldsid> <-v verbose> ");
89 fprintf(stderr, "filesystem \n");
103 char buf[BUFSIZ + 8];
108 while ((c = getopt(argc, argv, "vs:S:")) != EOF) {
111 Sleep = atoi(optarg);
114 oldsid = atoi(optarg);
125 if (optind >= argc) {
129 fsname = argv[optind];
130 if (fsname == NULL) {
136 * Establish an exit handler
138 error = establish_handler();
143 * Init the dmapi, and get a filesystem handle so
144 * we can set up our events
150 error = setup_dmapi(&sid);
155 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
160 * Set the event disposition so that our session will receive
161 * all the events for the given file system
163 error = set_disposition(sid, fs_hanp, fs_hlen);
168 * Enable monitoring for all events in the given file system
170 error = set_events(sid, fs_hanp, fs_hlen);
175 * Set line buffering!!
177 error = setvbuf(stdout, buf, _IOLBF, BUFSIZ);
182 * Now sit in an infinite loop, reporting on any events that occur.
183 * The program is exited after a signal through exit_handler().
186 event_loop(sid, 1 /*waitflag*/);
189 * If we get here, cleanup after the event_loop failure
198 * Main event loop processing
200 * The waitflag argument is set to 1 when we call this from main().
201 * In this case, continuously process incoming events,
202 * blocking if there are none available.
203 * In the exit_handler(), call this routine with waitflag=0.
204 * Just try to read the events once in this case with no blocking.
219 * We take a swag at a buffer size. If it's wrong, we can
223 bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
225 msgbuf = (void *)malloc(bufsize);
226 if (msgbuf == NULL) {
227 err_msg("Can't allocate memory for buffer");
232 error = dm_get_events(sid, ALL_AVAIL_MSGS,
233 waitflag ? DM_EV_WAIT:0, bufsize, msgbuf, &bufsize);
235 if (errno == EAGAIN) {
240 if (errno == E2BIG) {
242 msgbuf = (void *)malloc(bufsize);
243 if (msgbuf == NULL) {
244 err_msg("Can't resize msg buffer");
249 errno_msg("Error getting events from DMAPI");
254 * Walk through the message buffer, pull out each individual
255 * message, and dispatch the messages to handle_message(),
256 * which will respond to the events.
260 msg = (dm_eventmsg_t *)msgbuf;
261 while (msg != NULL ) {
263 error = handle_message(sid, msg);
268 printf("end_of_message\n");
269 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
271 if (count != 1 && Verbose) {
272 err_msg("Found %d events in one call to "
273 "dm_get_events\n", count);
282 print_one_mount_event(
285 void *hanp1, *hanp2, *hanp3;
286 size_t hlen1, hlen2, hlen3;
287 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
290 char nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
294 dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
296 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
297 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
298 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
299 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
300 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
301 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
302 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
303 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
304 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
307 mode = msg_ne->ne_mode;
309 dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
311 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
312 hlen1 = DM_GET_LEN(msg_me, me_handle1);
313 hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
314 hlen2 = DM_GET_LEN(msg_me, me_handle2);
315 namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
316 nlen1 = DM_GET_LEN(msg_me, me_name1);
317 namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
318 nlen2 = DM_GET_LEN(msg_me, me_name2);
319 hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
320 hlen3 = DM_GET_LEN(msg_me, me_roothandle);
321 mode = msg_me->me_mode;
324 if (hanp1 && hlen1) {
325 hantoa(hanp1, hlen1, hans1);
327 sprintf(hans1, "<BAD_HANDLE_hlen_%zd>", hlen1);
329 if (hanp2 && hlen2) {
330 hantoa(hanp2, hlen2, hans2);
332 sprintf(hans2, "<BAD_HANDLE_hlen_%zd>", hlen2);
334 if (hanp3 && hlen3) {
335 hantoa(hanp3, hlen3, hans3);
337 sprintf(hans3, "<BAD_HANDLE_hlen_%zd>", hlen3);
339 if (namp1 && nlen1) {
340 strncpy(nams1, namp1, nlen1);
341 if (nlen1 != sizeof(nams1))
344 sprintf(nams1, "<BAD STRING_nlen_%zd>", nlen1);
346 if (namp2 && nlen2) {
347 strncpy(nams2, namp2, nlen2);
348 if (nlen2 != sizeof(nams2))
351 sprintf(nams2, "<BAD_STRING_nlen_%zd>", nlen2);
354 printf(VALS VALS VALS VALS VALS VALD,
356 "mtpt handle", hans2,
358 "media desig", nams2,
359 "root handle", hans3,
365 * First, weed out the events which return interesting structures.
366 * If it's not one of those, unpack the dm_namesp_event structure
367 * and display the contents.
376 dm_response_t response = DM_RESP_INVALID;
377 int respond, respcode = 0;
378 dm_namesp_event_t *msg_ne;
380 dm_mount_event_t *msg_me;
382 void *hanp1, *hanp2, *namp1, *namp2;
383 u_int hlen1, hlen2, nlen1, nlen2;
384 char hans1[HANDLE_STR], hans2[HANDLE_STR];
385 char nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
388 dm_timestruct_t *pending_time;
391 * Set the defaults for responding to events
394 /*****************************************************
395 * If the daemon is feeling unfriendly, it will
396 * respond (when necessary) with DM_RESP_ABORT, rather
397 * than the standard DM_RESP_CONTINUE.
399 * While unfriendly, the daemon normally returns
400 * a respcode of "unfriendly_errno". This defaults to
401 * EBADMSG but can be set when unfriendly mode is
403 *****************************************************/
406 if (unfriendly_count==0) {
407 response = friendly ? DM_RESP_CONTINUE : DM_RESP_ABORT;
408 respcode = friendly ? 0 : unfriendly_errno;
410 else if (unfriendly_count > 0) {
411 if (unfriendly_count-- == 0) {
412 response = DM_RESP_CONTINUE;
416 response = DM_RESP_ABORT;
417 respcode = unfriendly_errno;
421 if (pending_count >= 0) {
422 if (msg->ev_type != DM_EVENT_USER) {
423 if (pending_count-- == 0) {
425 for (i=arr_top; i>=0; --i) {
426 dm_respond_event(sid, token_arr[i],
427 DM_RESP_CONTINUE, 0, 0, 0);
429 response = DM_RESP_CONTINUE;
433 if (pending_count<10) {
434 token_arr[pending_count]=msg->ev_token;
436 pending_time = malloc(sizeof(dm_timestruct_t));
437 pending_time->dm_tv_sec=0;
438 pending_time->dm_tv_nsec=0;
439 dm_pending(sid, msg->ev_token, pending_time);
440 printf("pending\ntries left\t:%d\n",pending_count);
446 /***** USER EVENTS *****/
448 if (msg->ev_type == DM_EVENT_USER) {
453 "user", msg->ev_token, msg->ev_sequence);
455 /* print private data as ascii or hex if it exists
456 DM_CONFIG_MAX_MESSAGE_DATA */
458 privp = DM_GET_VALUE(msg, ev_data, char *);
459 plen = DM_GET_LEN (msg, ev_data);
461 for (i = 0; i < plen; i++) {
462 if (!isprint(privp[i]) && !isspace(privp[i]))
465 if (i == plen - 1 && privp[i] == '\0') {
466 /*****************************************************
467 * Here, we check the messages from send_message.
468 * Some of them have special meanings.
469 *****************************************************/
470 if (strncmp(privp, "over", 4)==0) {
471 response = DM_RESP_CONTINUE;
474 else if (strncmp(privp, "pending", 7)==0){
475 if (strlen(privp)>8) {
476 sscanf(privp, "pending%*c%d", &pending_count);
481 arr_top=pending_count-1;
483 else if (strncmp(privp, "reset_fs", 8)==0){
484 if (get_fs_handle(fsname, &fs_hanp, &fs_hlen)){
485 strcpy(privp, "error");
487 else if (set_disposition(sid, fs_hanp, fs_hlen)){
488 strcpy(privp, "error");
490 else if (set_events(sid, fs_hanp, fs_hlen)){
491 strcpy(privp, "error");
494 else if (strncmp(privp, "friendly", 8)==0) {
496 response = DM_RESP_CONTINUE;
499 else if (strncmp(privp, "unfriendly", 10)==0) {
501 response = DM_RESP_CONTINUE;
503 if (strlen(privp)>11) {
504 sscanf(privp, "unfriendly%*c%d", &unfriendly_errno);
507 unfriendly_errno=EBADMSG;
510 else if (strncmp(privp, "countdown", 9)==0) {
511 response = DM_RESP_CONTINUE;
514 if (strlen(privp)>10) {
515 sscanf(privp, "countdown%*c%d%*c%d",
516 &unfriendly_count, &unfriendly_errno);
520 unfriendly_errno=EAGAIN;
529 printf("privdata :");
530 for (i = 0; i < plen; i++) {
531 printf("%.2x", privp[i]);
537 "privdata", "<NONE>");
540 if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
544 /***** CANCEL EVENT *****/
546 /* Not implemented on SGI or Veritas */
548 else if (msg->ev_type == DM_EVENT_CANCEL) {
549 dm_cancel_event_t *msg_ce;
551 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
552 printf(HDR VALD VALD,
553 "cancel", msg->ev_token, msg->ev_sequence,
554 "sequence", msg_ce->ce_sequence,
555 "token", msg_ce->ce_token);
559 /***** DATA EVENTS *****/
561 else if (msg->ev_type == DM_EVENT_READ ||
562 msg->ev_type == DM_EVENT_WRITE ||
563 msg->ev_type == DM_EVENT_TRUNCATE) {
564 dm_data_event_t *msg_de;
566 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
567 hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
568 hlen1 = DM_GET_LEN (msg_de, de_handle);
569 if (hanp1 && hlen1) {
570 hantoa(hanp1, hlen1, hans1);
572 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
575 switch(msg->ev_type) {
578 printf(HDR VALS VALLLD VALLLD,
579 "read", msg->ev_token, msg->ev_sequence,
580 "file handle", hans1,
581 "offset", (long long) msg_de->de_offset,
582 "length", (long long) msg_de->de_length);
586 printf(HDR VALS VALLLD VALLLD,
587 "write", msg->ev_token, msg->ev_sequence,
588 "file handle", hans1,
589 "offset", (long long) msg_de->de_offset,
590 "length", (long long) msg_de->de_length);
593 case DM_EVENT_TRUNCATE:
594 printf(HDR VALS VALLLD VALLLD,
595 "truncate", msg->ev_token, msg->ev_sequence,
596 "file handle", hans1,
597 "offset", (long long) msg_de->de_offset,
598 "length", (long long) msg_de->de_length);
604 /***** DESTROY EVENT *****/
606 else if (msg->ev_type == DM_EVENT_DESTROY) {
607 dm_destroy_event_t *msg_ds;
608 char attrname[DM_ATTR_NAME_SIZE + 1];
613 msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
614 hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
615 hlen1 = DM_GET_LEN (msg_ds, ds_handle);
616 if (hanp1 && hlen1) {
617 hantoa(hanp1, hlen1, hans1);
619 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
621 if (msg_ds->ds_attrname.an_chars[0] != '\0') {
622 strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
624 strcpy(attrname, "<NONE>");
626 printf(HDR VALS VALS,
627 "destroy", msg->ev_token, msg->ev_sequence,
629 "attrname", attrname);
630 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
631 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
633 printf("attrcopy :");
634 for (i = 0; i < clen; i++) {
635 /* Old version: printf("%.2x", copy[i]); */
636 printf("%c", copy[i]);
640 printf(VALS, "attrcopy", "<NONE>");
645 /***** MOUNT EVENT *****/
647 else if (msg->ev_type == DM_EVENT_MOUNT) {
648 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
650 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
651 print_one_mount_event(msg_me);
653 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
654 print_one_mount_event(msg_ne);
658 /***** NAMESPACE EVENTS *****/
663 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
664 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
665 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
666 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
667 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
668 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
669 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
670 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
671 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
673 if (hanp1 && hlen1) {
674 hantoa(hanp1, hlen1, hans1);
676 if (hanp2 && hlen2) {
677 hantoa(hanp2, hlen2, hans2);
679 if (namp1 && nlen1) {
680 strncpy(nams1, namp1, nlen1);
681 if (nlen1 != sizeof(nams1))
684 if (namp2 && nlen2) {
685 strncpy(nams2, namp2, nlen2);
686 if (nlen2 != sizeof(nams2))
690 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
691 msg->ev_type == DM_EVENT_UNMOUNT) {
692 if (msg_ne->ne_mode == 0) {
695 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
697 } else if (msg_ne->ne_mode > 0) {
704 } else if (msg->ev_type == DM_EVENT_CREATE ||
705 msg->ev_type == DM_EVENT_POSTCREATE ||
706 msg->ev_type == DM_EVENT_REMOVE ||
707 msg->ev_type == DM_EVENT_POSTREMOVE) {
708 if (format_mode(msg_ne->ne_mode, &type)) {
713 switch(msg->ev_type) {
715 case DM_EVENT_PREUNMOUNT:
716 printf(HDR VALS VALS VALS,
717 "preunmount", msg->ev_token, msg->ev_sequence,
720 "unmount mode", type);
723 case DM_EVENT_UNMOUNT:
724 printf(HDR VALS VALS VALD,
725 "unmount", msg->ev_token, msg->ev_sequence,
727 "unmount mode", type,
728 "retcode", msg_ne->ne_retcode);
731 case DM_EVENT_NOSPACE:
733 "nospace", msg->ev_token, msg->ev_sequence,
735 response = DM_RESP_ABORT;
741 "debut", msg->ev_token, msg->ev_sequence,
745 case DM_EVENT_CREATE:
746 printf(HDR VALS VALS VALS,
747 "create", msg->ev_token, msg->ev_sequence,
753 case DM_EVENT_POSTCREATE:
754 printf(HDR VALS VALS VALS VALS VALD,
755 "postcreate", msg->ev_token, msg->ev_sequence,
760 "retcode", msg_ne->ne_retcode);
764 case DM_EVENT_REMOVE:
765 printf(HDR VALS VALS VALS,
766 "remove", msg->ev_token, msg->ev_sequence,
772 case DM_EVENT_POSTREMOVE:
773 printf(HDR VALS VALS VALS VALD,
774 "postremove", msg->ev_token, msg->ev_sequence,
778 "retcode", msg_ne->ne_retcode);
782 case DM_EVENT_RENAME:
783 printf(HDR VALS VALS VALS VALS,
784 "rename", msg->ev_token, msg->ev_sequence,
791 case DM_EVENT_POSTRENAME:
792 printf(HDR VALS VALS VALS VALS VALD,
793 "postrename", msg->ev_token, msg->ev_sequence,
798 "retcode", msg_ne->ne_retcode);
802 case DM_EVENT_SYMLINK:
803 printf(HDR VALS VALS VALS,
804 "symlink", msg->ev_token, msg->ev_sequence,
810 case DM_EVENT_POSTSYMLINK:
811 printf(HDR VALS VALS VALS VALS VALD,
812 "postsymlink", msg->ev_token, msg->ev_sequence,
817 "retcode", msg_ne->ne_retcode);
822 printf(HDR VALS VALS VALS,
823 "link", msg->ev_token, msg->ev_sequence,
829 case DM_EVENT_POSTLINK:
830 printf(HDR VALS VALS VALS VALD,
831 "postlink", msg->ev_token, msg->ev_sequence,
835 "retcode", msg_ne->ne_retcode);
839 case DM_EVENT_ATTRIBUTE:
841 "attribute", msg->ev_token, msg->ev_sequence,
848 "close", msg->ev_token, msg->ev_sequence,
856 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
857 "ev_type", msg->ev_type);
858 if (msg->ev_token == DM_INVALID_TOKEN)
865 * Now respond to those messages which require a response
868 if (Sleep) sleep(Sleep); /* Slow things down here */
870 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
872 errno_msg("Can't respond to event");
882 Convert a mode_t field into a printable string.
884 Returns non-zero if the mode_t is invalid. The string is
885 returned in *ptr, whether there is an error or not.
893 static char modestr[100];
897 if (S_ISFIFO(mode)) typestr = "FIFO";
898 else if(S_ISCHR (mode)) typestr = "Character Device";
899 else if(S_ISBLK (mode)) typestr = "Block Device";
900 else if(S_ISDIR (mode)) typestr = "Directory";
901 else if(S_ISREG (mode)) typestr = "Regular File";
902 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
903 else if(S_ISSOCK(mode)) typestr = "Socket";
905 typestr = "<unknown type>";
909 sprintf(modestr, "mode %06o (perm %c%c%c %c%c%c %c%c%c %c%c%c) "
912 mode & S_ISUID ? 's':' ',
913 mode & S_ISGID ? 'g':' ',
914 mode & S_ISVTX ? 't':' ',
915 mode & S_IRUSR ? 'r':'-',
916 mode & S_IWUSR ? 'w':'-',
917 mode & S_IXUSR ? 'x':'-',
918 mode & S_IRGRP ? 'r':'-',
919 mode & S_IWGRP ? 'w':'-',
920 mode & S_IXGRP ? 'x':'-',
921 mode & S_IROTH ? 'r':'-',
922 mode & S_IWOTH ? 'w':'-',
923 mode & S_IXOTH ? 'x':'-',
936 char hans[HANDLE_STR];
938 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
939 errno_msg("Can't get filesystem handle");
943 hantoa(*fs_hanpp, *fs_hlenp, hans);
944 err_msg("File system handle for %s: %s\n", fsname, hans);
951 Set the event disposition for this filesystem to include all valid
952 DMAPI events so that we receive all events for this filesystem.
953 Also set DM_EVENT_MOUNT disposition for the global handle.
954 It does not make sense to specify DM_EVENT_USER in the disposition
955 mask since a session is always unconditionally registered for these
958 Returns non-zero on error.
967 dm_eventset_t eventlist;
970 err_msg("Setting event disposition to send all "
971 "events to this session\n");
974 /* DM_EVENT_MOUNT must be sent in a separate request using the global
975 handle. If we ever support more than one filesystem at a time, this
976 request should be moved out of this routine to a place where it is
980 DMEV_ZERO(eventlist);
981 DMEV_SET(DM_EVENT_MOUNT, eventlist);
983 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
984 &eventlist, DM_EVENT_MAX) == -1) {
985 errno_msg("Can't set event disposition for mount");
989 DMEV_ZERO(eventlist);
991 /* File system administration events. */
993 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
994 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
995 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
997 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
998 lets it be specified in a dm_set_disp call; its just that the
999 event will never be seen on some platforms.
1002 DMEV_SET(DM_EVENT_DEBUT, eventlist);
1005 /* Namespace events. */
1007 DMEV_SET(DM_EVENT_CREATE, eventlist);
1008 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1009 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1010 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1011 DMEV_SET(DM_EVENT_RENAME, eventlist);
1012 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1013 DMEV_SET(DM_EVENT_LINK, eventlist);
1014 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1015 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1016 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1018 /* Managed region data events. */
1020 DMEV_SET(DM_EVENT_READ, eventlist);
1021 DMEV_SET(DM_EVENT_WRITE, eventlist);
1022 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
1024 /* Metadata events. */
1026 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1027 #if !defined(VERITAS) && !defined(linux)
1028 DMEV_SET(DM_EVENT_CANCEL, eventlist);
1031 DMEV_SET(DM_EVENT_CLOSE, eventlist);
1033 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1035 /* Pseudo-events. */
1037 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1039 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1040 &eventlist, DM_EVENT_MAX) == -1) {
1041 errno_msg("Can't set event disposition for filesystem");
1049 Enable event generation on each valid filesystem-based DMAPI event
1050 within the given file system.
1052 Returns non-zero on errors.
1061 dm_eventset_t eventlist;
1064 err_msg("Setting event list to enable all events "
1065 "for this file system\n");
1067 DMEV_ZERO(eventlist);
1069 /* File system administration events. */
1071 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
1072 EINVAL if specified.
1074 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1075 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1076 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1077 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
1079 /* Namespace events. */
1081 DMEV_SET(DM_EVENT_CREATE, eventlist);
1082 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1083 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1084 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1085 DMEV_SET(DM_EVENT_RENAME, eventlist);
1086 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1087 DMEV_SET(DM_EVENT_LINK, eventlist);
1088 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1089 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1090 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1092 /* Managed region data events. These are not settable by
1093 dm_set_eventlist on a filesystem basis. They are meant
1094 to be set using dm_set_region on regular files only.
1095 However, in the SGI implementation, they are filesystem-settable.
1096 Since this is useful for testing purposes, do it.
1100 /* DM_EVENT_WRITE */
1101 /* DM_EVENT_TRUNCATE */
1103 /* Metadata events. */
1105 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1106 #if !defined(VERITAS) && !defined(linux)
1107 DMEV_SET(DM_EVENT_CANCEL, eventlist);
1110 DMEV_SET(DM_EVENT_CLOSE, eventlist);
1112 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1114 /* Pseudo-events. */
1116 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1118 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1119 &eventlist, DM_EVENT_MAX) == -1) {
1120 errno_msg("Can't set event list");
1128 Disable monitoring for all events in the DMAPI for the given
1129 file system. This is done before exiting so that future
1130 operations won't hang waiting for their events to be handled.
1132 Returns non-zero on errors.
1141 dm_eventset_t eventlist;
1144 err_msg("Clearing event list to disable all events "
1145 "for this filesystem\n");
1147 DMEV_ZERO(eventlist);
1149 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1150 &eventlist, DM_EVENT_MAX) == -1) {
1151 errno_msg("Can't clear event list");
1159 * Respond to any events which haven't been handled yet.
1160 * dm_getall_tokens provides a list of tokens for the outstanding events.
1161 * dm_find_eventmsg uses the token to lookup the corresponding message.
1162 * The message is passed to handle_message() for normal response processing.
1169 u_int nbytes, ntokens = 0, ret_ntokens, i;
1170 dm_token_t *tokenbuf = NULL, *tokenptr;
1171 size_t buflen = 0, ret_buflen;
1172 char *msgbuf = NULL;
1176 err_msg("Responding to any outstanding delivered event messages\n");
1179 * Initial sizes for the token and message buffers
1181 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1186 * The E2BIG dance...
1187 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1188 * If the routine returns E2BIG, use the returned size and try again.
1189 * If we're already using the returned size, double it and try again.
1193 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1194 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1195 tmpbuf = realloc(tokenbuf, nbytes);
1196 if (tmpbuf == NULL) {
1197 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1202 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1203 } while (error && errno == E2BIG);
1206 errno_msg("Can't get all outstanding tokens");
1210 tokenptr = tokenbuf;
1211 for (i = 0; i < ret_ntokens; i++) {
1213 err_msg("Responding to outstanding event for token %d\n",(int)*tokenptr);
1216 * The E2BIG dance reprise...
1220 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1221 tmpbuf = realloc(msgbuf, buflen);
1222 if (tmpbuf == NULL) {
1223 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1228 error = dm_find_eventmsg(sid, *tokenptr, buflen, msgbuf, &ret_buflen);
1229 } while (error && errno == E2BIG);
1231 errno_msg("Can't find the event message for token %d", (int)*tokenptr);
1235 msg = (dm_eventmsg_t *) msgbuf;
1236 while (msg != NULL) {
1237 error = handle_message(sid, msg);
1240 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1256 * Establish an exit handler since we run in an infinite loop
1259 establish_handler(void)
1261 struct sigaction act;
1264 * Set up signals so that we can wait for spawned children
1266 act.sa_handler = exit_handler;
1268 sigemptyset(&act.sa_mask);
1270 (void)sigaction(SIGHUP, &act, NULL);
1271 (void)sigaction(SIGINT, &act, NULL);
1272 (void)sigaction(SIGQUIT, &act, NULL);
1273 (void)sigaction(SIGTERM, &act, NULL);
1274 (void)sigaction(SIGUSR1, &act, NULL);
1275 (void)sigaction(SIGUSR1, &act, NULL);
1276 (void)sigaction(SIGUSR2, &act, NULL);
1285 * Stop events from being generated for the given file system
1286 * Respond to any events that were delivered but unanswered
1287 * (the event loop may have been in the middle of taking care of the event)
1288 * Try getting any undelivered events but don't block if none are there
1289 * (the file system may have generated an event after we killed dm_get_events)
1290 * Shutdown the session using the global "sid" variable.
1301 err_msg("Exiting...\n");
1303 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1306 error = clear_events(sid, fs_hanp, fs_hlen);
1308 /* just keep going */ ;
1311 error = finish_responding(sid);
1313 /* just keep going */ ;
1315 err_msg("Processing any undelivered event messages\n");
1316 event_loop(sid, 0 /*waitflag*/);
1318 err_msg("Shutting down the session\n");
1320 error = dm_destroy_session(sid);
1322 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");