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 MAXNAMELEN 256
47 * Define some standard formats for the printf statements below.
50 #define HDR "%s\ntoken :%d\nsequence :%d\n"
51 #define VALS "%-15s:%s\n"
52 #define VALD "%-15s:%d\n"
54 #define VALLLD "%-15s:%lld\n"
56 #define VALLLD "%-15s:%ld\n"
63 int main (int, char **);
64 static void event_loop (dm_sessid_t, int);
65 int handle_message (dm_sessid_t, dm_eventmsg_t *);
66 static int format_mode(mode_t mode, char **ptr);
67 static int get_fs_handle (char *, void **, size_t *);
68 static int set_disposition(dm_sessid_t, void *, size_t);
69 static int set_events (dm_sessid_t, void *, size_t);
70 static int clear_events (dm_sessid_t, void *, size_t);
71 int finish_responding(dm_sessid_t);
72 int establish_handler(void);
73 void exit_handler (int);
76 * Keep these global so the exit_handler and err_msg routines can get to them
82 dm_sessid_t oldsid = 0;
85 int unfriendly_errno=EBADMSG;
86 int unfriendly_count=0;
95 fprintf(stderr, "Usage: %s ", prog);
96 fprintf(stderr, "<-s sleeptime> <-S oldsid> <-v verbose> ");
97 fprintf(stderr, "filesystem \n");
111 char buf[BUFSIZ + 8];
116 while ((c = getopt(argc, argv, "vs:S:")) != EOF) {
119 Sleep = atoi(optarg);
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_disposition(sid, fs_hanp, fs_hlen);
176 * Enable monitoring for all events in the given file system
178 error = set_events(sid, fs_hanp, fs_hlen);
183 * Set line buffering!!
185 error = setvbuf(stdout, buf, _IOLBF, BUFSIZ);
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");
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 printf("end_of_message\n");
277 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
279 if (count != 1 && Verbose) {
280 err_msg("Found %d events in one call to "
281 "dm_get_events\n", count);
290 print_one_mount_event(
293 void *hanp1, *hanp2, *hanp3;
294 size_t hlen1, hlen2, hlen3;
295 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
298 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
302 dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
304 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
305 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
306 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
307 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
308 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
309 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
310 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
311 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
312 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
315 mode = msg_ne->ne_mode;
317 dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
319 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
320 hlen1 = DM_GET_LEN(msg_me, me_handle1);
321 hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
322 hlen2 = DM_GET_LEN(msg_me, me_handle2);
323 namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
324 nlen1 = DM_GET_LEN(msg_me, me_name1);
325 namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
326 nlen2 = DM_GET_LEN(msg_me, me_name2);
327 hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
328 hlen3 = DM_GET_LEN(msg_me, me_roothandle);
329 mode = msg_me->me_mode;
332 if (hanp1 && hlen1) {
333 hantoa(hanp1, hlen1, hans1);
335 sprintf(hans1, "<BAD_HANDLE_hlen_%d>", hlen1);
337 if (hanp2 && hlen2) {
338 hantoa(hanp2, hlen2, hans2);
340 sprintf(hans2, "<BAD_HANDLE_hlen_%d>", hlen2);
342 if (hanp3 && hlen3) {
343 hantoa(hanp3, hlen3, hans3);
345 sprintf(hans3, "<BAD_HANDLE_hlen_%d>", hlen3);
347 if (namp1 && nlen1) {
348 strncpy(nams1, namp1, nlen1);
349 if (nlen1 != sizeof(nams1))
352 sprintf(nams1, "<BAD STRING_nlen_%d>", nlen1);
354 if (namp2 && nlen2) {
355 strncpy(nams2, namp2, nlen2);
356 if (nlen2 != sizeof(nams2))
359 sprintf(nams2, "<BAD_STRING_nlen_%d>", nlen2);
362 printf(VALS VALS VALS VALS VALS VALD,
364 "mtpt handle", hans2,
366 "media desig", nams2,
367 "root handle", hans3,
373 * First, weed out the events which return interesting structures.
374 * If it's not one of those, unpack the dm_namesp_event structure
375 * and display the contents.
384 dm_response_t response;
385 int respond, respcode;
386 dm_namesp_event_t *msg_ne;
388 dm_mount_event_t *msg_me;
390 void *hanp1, *hanp2, *namp1, *namp2;
391 u_int hlen1, hlen2, nlen1, nlen2;
392 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
393 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
396 dm_timestruct_t *pending_time;
399 * Set the defaults for responding to events
402 /*****************************************************
403 * If the daemon is feeling unfriendly, it will
404 * respond (when necessary) with DM_RESP_ABORT, rather
405 * than the standard DM_RESP_CONTINUE.
407 * While unfriendly, the daemon normally returns
408 * a respcode of "unfriendly_errno". This defaults to
409 * EBADMSG but can be set when unfriendly mode is
411 *****************************************************/
414 if (unfriendly_count==0) {
415 response = friendly ? DM_RESP_CONTINUE : DM_RESP_ABORT;
416 respcode = friendly ? 0 : unfriendly_errno;
418 else if (unfriendly_count > 0) {
419 if (unfriendly_count-- == 0) {
420 response = DM_RESP_CONTINUE;
424 response = DM_RESP_ABORT;
425 respcode = unfriendly_errno;
429 if (pending_count >= 0) {
430 if (msg->ev_type != DM_EVENT_USER) {
431 if (pending_count-- == 0) {
433 for (i=arr_top; i>=0; --i) {
434 dm_respond_event(sid, token_arr[i],
435 DM_RESP_CONTINUE, 0, 0, 0);
437 response = DM_RESP_CONTINUE;
441 if (pending_count<10) {
442 token_arr[pending_count]=msg->ev_token;
444 pending_time = malloc(sizeof(dm_timestruct_t));
445 pending_time->dm_tv_sec=0;
446 pending_time->dm_tv_nsec=0;
447 dm_pending(sid, msg->ev_token, pending_time);
448 printf("pending\ntries left\t:%d\n",pending_count);
454 /***** USER EVENTS *****/
456 if (msg->ev_type == DM_EVENT_USER) {
461 "user", msg->ev_token, msg->ev_sequence);
463 /* print private data as ascii or hex if it exists
464 DM_CONFIG_MAX_MESSAGE_DATA */
466 privp = DM_GET_VALUE(msg, ev_data, char *);
467 plen = DM_GET_LEN (msg, ev_data);
469 for (i = 0; i < plen; i++) {
470 if (!isprint(privp[i]) && !isspace(privp[i]))
473 if (i == plen - 1 && privp[i] == '\0') {
474 /*****************************************************
475 * Here, we check the messages from send_message.
476 * Some of them have special meanings.
477 *****************************************************/
478 if (strncmp(privp, "over", 4)==0) {
479 response = DM_RESP_CONTINUE;
482 else if (strncmp(privp, "pending", 7)==0){
483 if (strlen(privp)>8) {
484 sscanf(privp, "pending%*c%d", &pending_count);
489 arr_top=pending_count-1;
491 else if (strncmp(privp, "reset_fs", 8)==0){
492 if (get_fs_handle(fsname, &fs_hanp, &fs_hlen)){
493 strcpy(privp, "error");
495 else if (set_disposition(sid, fs_hanp, fs_hlen)){
496 strcpy(privp, "error");
498 else if (set_events(sid, fs_hanp, fs_hlen)){
499 strcpy(privp, "error");
502 else if (strncmp(privp, "friendly", 8)==0) {
504 response = DM_RESP_CONTINUE;
507 else if (strncmp(privp, "unfriendly", 10)==0) {
509 response = DM_RESP_CONTINUE;
511 if (strlen(privp)>11) {
512 sscanf(privp, "unfriendly%*c%d", &unfriendly_errno);
515 unfriendly_errno=EBADMSG;
518 else if (strncmp(privp, "countdown", 9)==0) {
519 response = DM_RESP_CONTINUE;
522 if (strlen(privp)>10) {
523 sscanf(privp, "countdown%*c%d%*c%d",
524 &unfriendly_count, &unfriendly_errno);
528 unfriendly_errno=EAGAIN;
537 printf("privdata :");
538 for (i = 0; i < plen; i++) {
539 printf("%.2x", privp[i]);
545 "privdata", "<NONE>");
548 if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
552 /***** CANCEL EVENT *****/
554 /* Not implemented on SGI or Veritas */
556 else if (msg->ev_type == DM_EVENT_CANCEL) {
557 dm_cancel_event_t *msg_ce;
559 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
560 printf(HDR VALD VALD,
561 "cancel", msg->ev_token, msg->ev_sequence,
562 "sequence", msg_ce->ce_sequence,
563 "token", msg_ce->ce_token);
567 /***** DATA EVENTS *****/
569 else if (msg->ev_type == DM_EVENT_READ ||
570 msg->ev_type == DM_EVENT_WRITE ||
571 msg->ev_type == DM_EVENT_TRUNCATE) {
572 dm_data_event_t *msg_de;
574 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
575 hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
576 hlen1 = DM_GET_LEN (msg_de, de_handle);
577 if (hanp1 && hlen1) {
578 hantoa(hanp1, hlen1, hans1);
580 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
583 switch(msg->ev_type) {
586 printf(HDR VALS VALLLD VALLLD,
587 "read", msg->ev_token, msg->ev_sequence,
588 "file handle", hans1,
589 "offset", msg_de->de_offset,
590 "length", msg_de->de_length);
594 printf(HDR VALS VALLLD VALLLD,
595 "write", msg->ev_token, msg->ev_sequence,
596 "file handle", hans1,
597 "offset", msg_de->de_offset,
598 "length", msg_de->de_length);
601 case DM_EVENT_TRUNCATE:
602 printf(HDR VALS VALLLD VALLLD,
603 "truncate", msg->ev_token, msg->ev_sequence,
604 "file handle", hans1,
605 "offset", msg_de->de_offset,
606 "length", msg_de->de_length);
611 /***** DESTROY EVENT *****/
613 else if (msg->ev_type == DM_EVENT_DESTROY) {
614 dm_destroy_event_t *msg_ds;
615 char attrname[DM_ATTR_NAME_SIZE + 1];
620 msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
621 hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
622 hlen1 = DM_GET_LEN (msg_ds, ds_handle);
623 if (hanp1 && hlen1) {
624 hantoa(hanp1, hlen1, hans1);
626 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
628 if (msg_ds->ds_attrname.an_chars[0] != '\0') {
629 strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
631 strcpy(attrname, "<NONE>");
633 printf(HDR VALS VALS,
634 "destroy", msg->ev_token, msg->ev_sequence,
636 "attrname", attrname);
637 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
638 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
640 printf("attrcopy :");
641 for (i = 0; i < clen; i++) {
642 /* Old version: printf("%.2x", copy[i]); */
643 printf("%c", copy[i]);
647 printf(VALS, "attrcopy", "<NONE>");
652 /***** MOUNT EVENT *****/
654 else if (msg->ev_type == DM_EVENT_MOUNT) {
655 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
657 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
658 print_one_mount_event(msg_me);
660 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
661 print_one_mount_event(msg_ne);
665 /***** NAMESPACE EVENTS *****/
670 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
671 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
672 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
673 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
674 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
675 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
676 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
677 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
678 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
680 if (hanp1 && hlen1) {
681 hantoa(hanp1, hlen1, hans1);
683 if (hanp2 && hlen2) {
684 hantoa(hanp2, hlen2, hans2);
686 if (namp1 && nlen1) {
687 strncpy(nams1, namp1, nlen1);
688 if (nlen1 != sizeof(nams1))
691 if (namp2 && nlen2) {
692 strncpy(nams2, namp2, nlen2);
693 if (nlen2 != sizeof(nams2))
697 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
698 msg->ev_type == DM_EVENT_UNMOUNT) {
699 if (msg_ne->ne_mode == 0) {
702 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
704 } else if (msg_ne->ne_mode > 0) {
711 } else if (msg->ev_type == DM_EVENT_CREATE ||
712 msg->ev_type == DM_EVENT_POSTCREATE ||
713 msg->ev_type == DM_EVENT_REMOVE ||
714 msg->ev_type == DM_EVENT_POSTREMOVE) {
715 if (format_mode(msg_ne->ne_mode, &type)) {
720 switch(msg->ev_type) {
722 case DM_EVENT_PREUNMOUNT:
723 printf(HDR VALS VALS VALS,
724 "preunmount", msg->ev_token, msg->ev_sequence,
727 "unmount mode", type);
730 case DM_EVENT_UNMOUNT:
731 printf(HDR VALS VALS VALD,
732 "unmount", msg->ev_token, msg->ev_sequence,
734 "unmount mode", type,
735 "retcode", msg_ne->ne_retcode);
738 case DM_EVENT_NOSPACE:
740 "nospace", msg->ev_token, msg->ev_sequence,
742 response = DM_RESP_ABORT;
746 case DM_EVENT_DEBUT: /* not supported on SGI */
748 "debut", msg->ev_token, msg->ev_sequence,
752 case DM_EVENT_CREATE:
753 printf(HDR VALS VALS VALS,
754 "create", msg->ev_token, msg->ev_sequence,
760 case DM_EVENT_POSTCREATE:
761 printf(HDR VALS VALS VALS VALS VALD,
762 "postcreate", msg->ev_token, msg->ev_sequence,
767 "retcode", msg_ne->ne_retcode);
771 case DM_EVENT_REMOVE:
772 printf(HDR VALS VALS VALS,
773 "remove", msg->ev_token, msg->ev_sequence,
779 case DM_EVENT_POSTREMOVE:
780 printf(HDR VALS VALS VALS VALD,
781 "postremove", msg->ev_token, msg->ev_sequence,
785 "retcode", msg_ne->ne_retcode);
789 case DM_EVENT_RENAME:
790 printf(HDR VALS VALS VALS VALS,
791 "rename", msg->ev_token, msg->ev_sequence,
798 case DM_EVENT_POSTRENAME:
799 printf(HDR VALS VALS VALS VALS VALD,
800 "postrename", msg->ev_token, msg->ev_sequence,
805 "retcode", msg_ne->ne_retcode);
809 case DM_EVENT_SYMLINK:
810 printf(HDR VALS VALS VALS,
811 "symlink", msg->ev_token, msg->ev_sequence,
817 case DM_EVENT_POSTSYMLINK:
818 printf(HDR VALS VALS VALS VALS VALD,
819 "postsymlink", msg->ev_token, msg->ev_sequence,
824 "retcode", msg_ne->ne_retcode);
829 printf(HDR VALS VALS VALS,
830 "link", msg->ev_token, msg->ev_sequence,
836 case DM_EVENT_POSTLINK:
837 printf(HDR VALS VALS VALS VALD,
838 "postlink", msg->ev_token, msg->ev_sequence,
842 "retcode", msg_ne->ne_retcode);
846 case DM_EVENT_ATTRIBUTE:
848 "attribute", msg->ev_token, msg->ev_sequence,
853 case DM_EVENT_CLOSE: /* not supported on SGI */
855 "close", msg->ev_token, msg->ev_sequence,
863 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
864 "ev_type", msg->ev_type);
865 if (msg->ev_token == DM_INVALID_TOKEN)
872 * Now respond to those messages which require a response
875 if (Sleep) sleep(Sleep); /* Slow things down here */
877 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
879 errno_msg("Can't respond to event");
889 Convert a mode_t field into a printable string.
891 Returns non-zero if the mode_t is invalid. The string is
892 returned in *ptr, whether there is an error or not.
900 static char modestr[100];
904 if (S_ISFIFO(mode)) typestr = "FIFO";
905 else if(S_ISCHR (mode)) typestr = "Character Device";
906 else if(S_ISBLK (mode)) typestr = "Block Device";
907 else if(S_ISDIR (mode)) typestr = "Directory";
908 else if(S_ISREG (mode)) typestr = "Regular File";
909 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
910 else if(S_ISSOCK(mode)) typestr = "Socket";
912 typestr = "<unknown type>";
916 sprintf(modestr, "mode %06o (perm %c%c%c %c%c%c %c%c%c %c%c%c) "
919 mode & S_ISUID ? 's':' ',
920 mode & S_ISGID ? 'g':' ',
921 mode & S_ISVTX ? 't':' ',
922 mode & S_IRUSR ? 'r':'-',
923 mode & S_IWUSR ? 'w':'-',
924 mode & S_IXUSR ? 'x':'-',
925 mode & S_IRGRP ? 'r':'-',
926 mode & S_IWGRP ? 'w':'-',
927 mode & S_IXGRP ? 'x':'-',
928 mode & S_IROTH ? 'r':'-',
929 mode & S_IWOTH ? 'w':'-',
930 mode & S_IXOTH ? 'x':'-',
943 char hans[HANDLE_STR];
945 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
946 errno_msg("Can't get filesystem handle");
950 hantoa(*fs_hanpp, *fs_hlenp, hans);
951 err_msg("File system handle for %s: %s\n", fsname, hans);
958 Set the event disposition for this filesystem to include all valid
959 DMAPI events so that we receive all events for this filesystem.
960 Also set DM_EVENT_MOUNT disposition for the global handle.
961 It does not make sense to specify DM_EVENT_USER in the disposition
962 mask since a session is always unconditionally registered for these
965 Returns non-zero on error.
974 dm_eventset_t eventlist;
977 err_msg("Setting event disposition to send all "
978 "events to this session\n");
981 /* DM_EVENT_MOUNT must be sent in a separate request using the global
982 handle. If we ever support more than one filesystem at a time, this
983 request should be moved out of this routine to a place where it is
987 DMEV_ZERO(eventlist);
988 DMEV_SET(DM_EVENT_MOUNT, eventlist);
990 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
991 &eventlist, DM_EVENT_MAX) == -1) {
992 errno_msg("Can't set event disposition for mount");
996 DMEV_ZERO(eventlist);
998 /* File system administration events. */
1000 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1001 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1002 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1004 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
1005 lets it be specified in a dm_set_disp call; its just that the
1006 event will never be seen on some platforms.
1009 DMEV_SET(DM_EVENT_DEBUT, eventlist);
1012 /* Namespace events. */
1014 DMEV_SET(DM_EVENT_CREATE, eventlist);
1015 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1016 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1017 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1018 DMEV_SET(DM_EVENT_RENAME, eventlist);
1019 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1020 DMEV_SET(DM_EVENT_LINK, eventlist);
1021 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1022 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1023 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1025 /* Managed region data events. */
1027 DMEV_SET(DM_EVENT_READ, eventlist);
1028 DMEV_SET(DM_EVENT_WRITE, eventlist);
1029 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
1031 /* Metadata events. */
1033 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1034 #if ! defined ( __sgi ) && ! defined ( VERITAS ) && ! defined(linux)
1035 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1037 #if !defined(__sgi) && !defined(linux)
1038 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1040 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1042 /* Pseudo-events. */
1044 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1046 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1047 &eventlist, DM_EVENT_MAX) == -1) {
1048 errno_msg("Can't set event disposition for filesystem");
1056 Enable event generation on each valid filesystem-based DMAPI event
1057 within the given file system.
1059 Returns non-zero on errors.
1068 dm_eventset_t eventlist;
1071 err_msg("Setting event list to enable all events "
1072 "for this file system\n");
1074 DMEV_ZERO(eventlist);
1076 /* File system administration events. */
1078 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
1079 EINVAL if specified.
1081 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1082 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1083 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1084 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
1086 /* Namespace events. */
1088 DMEV_SET(DM_EVENT_CREATE, eventlist);
1089 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1090 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1091 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1092 DMEV_SET(DM_EVENT_RENAME, eventlist);
1093 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1094 DMEV_SET(DM_EVENT_LINK, eventlist);
1095 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1096 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1097 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1099 /* Managed region data events. These are not settable by
1100 dm_set_eventlist on a filesystem basis. They are meant
1101 to be set using dm_set_region on regular files only.
1102 However, in the SGI implementation, they are filesystem-settable.
1103 Since this is useful for testing purposes, do it.
1107 /* DM_EVENT_WRITE */
1108 /* DM_EVENT_TRUNCATE */
1110 /* Metadata events. */
1112 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1113 #if ! defined ( __sgi ) && ! defined ( VERITAS ) && !defined(linux)
1114 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1116 #if !defined(__sgi) && !defined(linux)
1117 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1119 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1121 /* Pseudo-events. */
1123 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1125 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1126 &eventlist, DM_EVENT_MAX) == -1) {
1127 errno_msg("Can't set event list");
1135 Disable monitoring for all events in the DMAPI for the given
1136 file system. This is done before exiting so that future
1137 operations won't hang waiting for their events to be handled.
1139 Returns non-zero on errors.
1148 dm_eventset_t eventlist;
1151 err_msg("Clearing event list to disable all events "
1152 "for this filesystem\n");
1154 DMEV_ZERO(eventlist);
1156 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1157 &eventlist, DM_EVENT_MAX) == -1) {
1158 errno_msg("Can't clear event list");
1166 * Respond to any events which haven't been handled yet.
1167 * dm_getall_tokens provides a list of tokens for the outstanding events.
1168 * dm_find_eventmsg uses the token to lookup the corresponding message.
1169 * The message is passed to handle_message() for normal response processing.
1176 u_int nbytes, ntokens = 0, ret_ntokens, i;
1177 dm_token_t *tokenbuf = NULL;
1178 size_t buflen, ret_buflen;
1179 char *msgbuf = NULL;
1183 err_msg("Responding to any outstanding delivered event messages\n");
1186 * Initial sizes for the token and message buffers
1188 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1193 * The E2BIG dance...
1194 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1195 * If the routine returns E2BIG, use the returned size and try again.
1196 * If we're already using the returned size, double it and try again.
1199 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1200 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1201 tokenbuf = malloc(nbytes);
1202 if (tokenbuf == NULL) {
1203 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1207 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1208 } while (error && errno == E2BIG);
1211 errno_msg("Can't get all outstanding tokens");
1215 for (i = 0; i < ret_ntokens; i++) {
1217 err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
1220 * The E2BIG dance reprise...
1223 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1224 msgbuf = malloc(buflen);
1225 if (msgbuf == NULL) {
1226 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1230 error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
1231 } while (error && errno == E2BIG);
1233 errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
1237 msg = (dm_eventmsg_t *) msgbuf;
1238 while (msg != NULL) {
1239 error = handle_message(sid, msg);
1242 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1258 * Establish an exit handler since we run in an infinite loop
1261 establish_handler(void)
1263 struct sigaction act;
1266 * Set up signals so that we can wait for spawned children
1268 act.sa_handler = exit_handler;
1270 sigemptyset(&act.sa_mask);
1272 (void)sigaction(SIGHUP, &act, NULL);
1273 (void)sigaction(SIGINT, &act, NULL);
1274 (void)sigaction(SIGQUIT, &act, NULL);
1275 (void)sigaction(SIGTERM, &act, NULL);
1276 (void)sigaction(SIGUSR1, &act, NULL);
1277 (void)sigaction(SIGUSR1, &act, NULL);
1278 (void)sigaction(SIGUSR2, &act, NULL);
1287 * Stop events from being generated for the given file system
1288 * Respond to any events that were delivered but unanswered
1289 * (the event loop may have been in the middle of taking care of the event)
1290 * Try getting any undelivered events but don't block if none are there
1291 * (the file system may have generated an event after we killed dm_get_events)
1292 * Shutdown the session using the global "sid" variable.
1303 err_msg("Exiting...\n");
1305 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1308 error = clear_events(sid, fs_hanp, fs_hlen);
1310 /* just keep going */ ;
1313 error = finish_responding(sid);
1315 /* just keep going */ ;
1317 err_msg("Processing any undelivered event messages\n");
1318 event_loop(sid, 0 /*waitflag*/);
1320 err_msg("Shutting down the session\n");
1322 error = dm_destroy_session(sid);
1324 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");