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"
53 #define VALLLD "%-15s:%lld\n"
59 int main (int, char **);
60 static void event_loop (dm_sessid_t, int);
61 int handle_message (dm_sessid_t, dm_eventmsg_t *);
62 static int format_mode(mode_t mode, char **ptr);
63 static int get_fs_handle (char *, void **, size_t *);
64 static int set_disposition(dm_sessid_t, void *, size_t);
65 static int set_events (dm_sessid_t, void *, size_t);
66 static int clear_events (dm_sessid_t, void *, size_t);
67 int finish_responding(dm_sessid_t);
68 int establish_handler(void);
69 void exit_handler (int);
72 * Keep these global so the exit_handler and err_msg routines can get to them
78 dm_sessid_t oldsid = 0;
81 int unfriendly_errno=EBADMSG;
82 int unfriendly_count=0;
91 fprintf(stderr, "Usage: %s ", prog);
92 fprintf(stderr, "<-s sleeptime> <-S oldsid> <-v verbose> ");
93 fprintf(stderr, "filesystem \n");
107 char buf[BUFSIZ + 8];
112 while ((c = getopt(argc, argv, "vs:S:")) != EOF) {
115 Sleep = atoi(optarg);
118 oldsid = atoi(optarg);
129 if (optind >= argc) {
133 fsname = argv[optind];
134 if (fsname == NULL) {
140 * Establish an exit handler
142 error = establish_handler();
147 * Init the dmapi, and get a filesystem handle so
148 * we can set up our events
154 error = setup_dmapi(&sid);
159 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
164 * Set the event disposition so that our session will receive
165 * all the events for the given file system
167 error = set_disposition(sid, fs_hanp, fs_hlen);
172 * Enable monitoring for all events in the given file system
174 error = set_events(sid, fs_hanp, fs_hlen);
179 * Set line buffering!!
181 error = setvbuf(stdout, buf, _IOLBF, BUFSIZ);
186 * Now sit in an infinite loop, reporting on any events that occur.
187 * The program is exited after a signal through exit_handler().
190 event_loop(sid, 1 /*waitflag*/);
193 * If we get here, cleanup after the event_loop failure
202 * Main event loop processing
204 * The waitflag argument is set to 1 when we call this from main().
205 * In this case, continuously process incoming events,
206 * blocking if there are none available.
207 * In the exit_handler(), call this routine with waitflag=0.
208 * Just try to read the events once in this case with no blocking.
223 * We take a swag at a buffer size. If it's wrong, we can
227 bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
229 msgbuf = (void *)malloc(bufsize);
230 if (msgbuf == NULL) {
231 err_msg("Can't allocate memory for buffer");
236 error = dm_get_events(sid, ALL_AVAIL_MSGS,
237 waitflag ? DM_EV_WAIT:0, bufsize, msgbuf, &bufsize);
239 if (errno == EAGAIN) {
244 if (errno == E2BIG) {
246 msgbuf = (void *)malloc(bufsize);
247 if (msgbuf == NULL) {
248 err_msg("Can't resize msg buffer");
253 errno_msg("Error getting events from DMAPI");
258 * Walk through the message buffer, pull out each individual
259 * message, and dispatch the messages to handle_message(),
260 * which will respond to the events.
264 msg = (dm_eventmsg_t *)msgbuf;
265 while (msg != NULL ) {
267 error = handle_message(sid, msg);
272 printf("end_of_message\n");
273 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
275 if (count != 1 && Verbose) {
276 err_msg("Found %d events in one call to "
277 "dm_get_events\n", count);
286 print_one_mount_event(
289 void *hanp1, *hanp2, *hanp3;
290 size_t hlen1, hlen2, hlen3;
291 char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
294 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
298 dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
300 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
301 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
302 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
303 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
304 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
305 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
306 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
307 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
308 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
311 mode = msg_ne->ne_mode;
313 dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
315 hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
316 hlen1 = DM_GET_LEN(msg_me, me_handle1);
317 hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
318 hlen2 = DM_GET_LEN(msg_me, me_handle2);
319 namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
320 nlen1 = DM_GET_LEN(msg_me, me_name1);
321 namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
322 nlen2 = DM_GET_LEN(msg_me, me_name2);
323 hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
324 hlen3 = DM_GET_LEN(msg_me, me_roothandle);
325 mode = msg_me->me_mode;
328 if (hanp1 && hlen1) {
329 hantoa(hanp1, hlen1, hans1);
331 sprintf(hans1, "<BAD_HANDLE_hlen_%d>", hlen1);
333 if (hanp2 && hlen2) {
334 hantoa(hanp2, hlen2, hans2);
336 sprintf(hans2, "<BAD_HANDLE_hlen_%d>", hlen2);
338 if (hanp3 && hlen3) {
339 hantoa(hanp3, hlen3, hans3);
341 sprintf(hans3, "<BAD_HANDLE_hlen_%d>", hlen3);
343 if (namp1 && nlen1) {
344 strncpy(nams1, namp1, nlen1);
345 if (nlen1 != sizeof(nams1))
348 sprintf(nams1, "<BAD STRING_nlen_%d>", nlen1);
350 if (namp2 && nlen2) {
351 strncpy(nams2, namp2, nlen2);
352 if (nlen2 != sizeof(nams2))
355 sprintf(nams2, "<BAD_STRING_nlen_%d>", nlen2);
358 printf(VALS VALS VALS VALS VALS VALD,
360 "mtpt handle", hans2,
362 "media desig", nams2,
363 "root handle", hans3,
369 * First, weed out the events which return interesting structures.
370 * If it's not one of those, unpack the dm_namesp_event structure
371 * and display the contents.
380 dm_response_t response;
381 int respond, respcode;
382 dm_namesp_event_t *msg_ne;
384 dm_mount_event_t *msg_me;
386 void *hanp1, *hanp2, *namp1, *namp2;
387 u_int hlen1, hlen2, nlen1, nlen2;
388 char hans1[HANDLE_STR], hans2[HANDLE_STR];
389 char nams1[MAXNAMELEN], nams2[MAXNAMELEN];
392 dm_timestruct_t *pending_time;
395 * Set the defaults for responding to events
398 /*****************************************************
399 * If the daemon is feeling unfriendly, it will
400 * respond (when necessary) with DM_RESP_ABORT, rather
401 * than the standard DM_RESP_CONTINUE.
403 * While unfriendly, the daemon normally returns
404 * a respcode of "unfriendly_errno". This defaults to
405 * EBADMSG but can be set when unfriendly mode is
407 *****************************************************/
410 if (unfriendly_count==0) {
411 response = friendly ? DM_RESP_CONTINUE : DM_RESP_ABORT;
412 respcode = friendly ? 0 : unfriendly_errno;
414 else if (unfriendly_count > 0) {
415 if (unfriendly_count-- == 0) {
416 response = DM_RESP_CONTINUE;
420 response = DM_RESP_ABORT;
421 respcode = unfriendly_errno;
425 if (pending_count >= 0) {
426 if (msg->ev_type != DM_EVENT_USER) {
427 if (pending_count-- == 0) {
429 for (i=arr_top; i>=0; --i) {
430 dm_respond_event(sid, token_arr[i],
431 DM_RESP_CONTINUE, 0, 0, 0);
433 response = DM_RESP_CONTINUE;
437 if (pending_count<10) {
438 token_arr[pending_count]=msg->ev_token;
440 pending_time = malloc(sizeof(dm_timestruct_t));
441 pending_time->dm_tv_sec=0;
442 pending_time->dm_tv_nsec=0;
443 dm_pending(sid, msg->ev_token, pending_time);
444 printf("pending\ntries left\t:%d\n",pending_count);
450 /***** USER EVENTS *****/
452 if (msg->ev_type == DM_EVENT_USER) {
457 "user", msg->ev_token, msg->ev_sequence);
459 /* print private data as ascii or hex if it exists
460 DM_CONFIG_MAX_MESSAGE_DATA */
462 privp = DM_GET_VALUE(msg, ev_data, char *);
463 plen = DM_GET_LEN (msg, ev_data);
465 for (i = 0; i < plen; i++) {
466 if (!isprint(privp[i]) && !isspace(privp[i]))
469 if (i == plen - 1 && privp[i] == '\0') {
470 /*****************************************************
471 * Here, we check the messages from send_message.
472 * Some of them have special meanings.
473 *****************************************************/
474 if (strncmp(privp, "over", 4)==0) {
475 response = DM_RESP_CONTINUE;
478 else if (strncmp(privp, "pending", 7)==0){
479 if (strlen(privp)>8) {
480 sscanf(privp, "pending%*c%d", &pending_count);
485 arr_top=pending_count-1;
487 else if (strncmp(privp, "reset_fs", 8)==0){
488 if (get_fs_handle(fsname, &fs_hanp, &fs_hlen)){
489 strcpy(privp, "error");
491 else if (set_disposition(sid, fs_hanp, fs_hlen)){
492 strcpy(privp, "error");
494 else if (set_events(sid, fs_hanp, fs_hlen)){
495 strcpy(privp, "error");
498 else if (strncmp(privp, "friendly", 8)==0) {
500 response = DM_RESP_CONTINUE;
503 else if (strncmp(privp, "unfriendly", 10)==0) {
505 response = DM_RESP_CONTINUE;
507 if (strlen(privp)>11) {
508 sscanf(privp, "unfriendly%*c%d", &unfriendly_errno);
511 unfriendly_errno=EBADMSG;
514 else if (strncmp(privp, "countdown", 9)==0) {
515 response = DM_RESP_CONTINUE;
518 if (strlen(privp)>10) {
519 sscanf(privp, "countdown%*c%d%*c%d",
520 &unfriendly_count, &unfriendly_errno);
524 unfriendly_errno=EAGAIN;
533 printf("privdata :");
534 for (i = 0; i < plen; i++) {
535 printf("%.2x", privp[i]);
541 "privdata", "<NONE>");
544 if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
548 /***** CANCEL EVENT *****/
550 /* Not implemented on SGI or Veritas */
552 else if (msg->ev_type == DM_EVENT_CANCEL) {
553 dm_cancel_event_t *msg_ce;
555 msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
556 printf(HDR VALD VALD,
557 "cancel", msg->ev_token, msg->ev_sequence,
558 "sequence", msg_ce->ce_sequence,
559 "token", msg_ce->ce_token);
563 /***** DATA EVENTS *****/
565 else if (msg->ev_type == DM_EVENT_READ ||
566 msg->ev_type == DM_EVENT_WRITE ||
567 msg->ev_type == DM_EVENT_TRUNCATE) {
568 dm_data_event_t *msg_de;
570 msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
571 hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
572 hlen1 = DM_GET_LEN (msg_de, de_handle);
573 if (hanp1 && hlen1) {
574 hantoa(hanp1, hlen1, hans1);
576 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
579 switch(msg->ev_type) {
582 printf(HDR VALS VALLLD VALLLD,
583 "read", msg->ev_token, msg->ev_sequence,
584 "file handle", hans1,
585 "offset", msg_de->de_offset,
586 "length", msg_de->de_length);
590 printf(HDR VALS VALLLD VALLLD,
591 "write", msg->ev_token, msg->ev_sequence,
592 "file handle", hans1,
593 "offset", msg_de->de_offset,
594 "length", msg_de->de_length);
597 case DM_EVENT_TRUNCATE:
598 printf(HDR VALS VALLLD VALLLD,
599 "truncate", msg->ev_token, msg->ev_sequence,
600 "file handle", hans1,
601 "offset", msg_de->de_offset,
602 "length", msg_de->de_length);
608 /***** DESTROY EVENT *****/
610 else if (msg->ev_type == DM_EVENT_DESTROY) {
611 dm_destroy_event_t *msg_ds;
612 char attrname[DM_ATTR_NAME_SIZE + 1];
617 msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
618 hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
619 hlen1 = DM_GET_LEN (msg_ds, ds_handle);
620 if (hanp1 && hlen1) {
621 hantoa(hanp1, hlen1, hans1);
623 sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
625 if (msg_ds->ds_attrname.an_chars[0] != '\0') {
626 strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
628 strcpy(attrname, "<NONE>");
630 printf(HDR VALS VALS,
631 "destroy", msg->ev_token, msg->ev_sequence,
633 "attrname", attrname);
634 copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
635 clen = DM_GET_LEN (msg_ds, ds_attrcopy);
637 printf("attrcopy :");
638 for (i = 0; i < clen; i++) {
639 /* Old version: printf("%.2x", copy[i]); */
640 printf("%c", copy[i]);
644 printf(VALS, "attrcopy", "<NONE>");
649 /***** MOUNT EVENT *****/
651 else if (msg->ev_type == DM_EVENT_MOUNT) {
652 printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
654 msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
655 print_one_mount_event(msg_me);
657 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
658 print_one_mount_event(msg_ne);
662 /***** NAMESPACE EVENTS *****/
667 msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
668 hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
669 hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
670 hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
671 hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
672 namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
673 nlen1 = DM_GET_LEN (msg_ne, ne_name1);
674 namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
675 nlen2 = DM_GET_LEN (msg_ne, ne_name2);
677 if (hanp1 && hlen1) {
678 hantoa(hanp1, hlen1, hans1);
680 if (hanp2 && hlen2) {
681 hantoa(hanp2, hlen2, hans2);
683 if (namp1 && nlen1) {
684 strncpy(nams1, namp1, nlen1);
685 if (nlen1 != sizeof(nams1))
688 if (namp2 && nlen2) {
689 strncpy(nams2, namp2, nlen2);
690 if (nlen2 != sizeof(nams2))
694 if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
695 msg->ev_type == DM_EVENT_UNMOUNT) {
696 if (msg_ne->ne_mode == 0) {
699 } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
701 } else if (msg_ne->ne_mode > 0) {
708 } else if (msg->ev_type == DM_EVENT_CREATE ||
709 msg->ev_type == DM_EVENT_POSTCREATE ||
710 msg->ev_type == DM_EVENT_REMOVE ||
711 msg->ev_type == DM_EVENT_POSTREMOVE) {
712 if (format_mode(msg_ne->ne_mode, &type)) {
717 switch(msg->ev_type) {
719 case DM_EVENT_PREUNMOUNT:
720 printf(HDR VALS VALS VALS,
721 "preunmount", msg->ev_token, msg->ev_sequence,
724 "unmount mode", type);
727 case DM_EVENT_UNMOUNT:
728 printf(HDR VALS VALS VALD,
729 "unmount", msg->ev_token, msg->ev_sequence,
731 "unmount mode", type,
732 "retcode", msg_ne->ne_retcode);
735 case DM_EVENT_NOSPACE:
737 "nospace", msg->ev_token, msg->ev_sequence,
739 response = DM_RESP_ABORT;
743 case DM_EVENT_DEBUT: /* not supported on SGI */
745 "debut", msg->ev_token, msg->ev_sequence,
749 case DM_EVENT_CREATE:
750 printf(HDR VALS VALS VALS,
751 "create", msg->ev_token, msg->ev_sequence,
757 case DM_EVENT_POSTCREATE:
758 printf(HDR VALS VALS VALS VALS VALD,
759 "postcreate", msg->ev_token, msg->ev_sequence,
764 "retcode", msg_ne->ne_retcode);
768 case DM_EVENT_REMOVE:
769 printf(HDR VALS VALS VALS,
770 "remove", msg->ev_token, msg->ev_sequence,
776 case DM_EVENT_POSTREMOVE:
777 printf(HDR VALS VALS VALS VALD,
778 "postremove", msg->ev_token, msg->ev_sequence,
782 "retcode", msg_ne->ne_retcode);
786 case DM_EVENT_RENAME:
787 printf(HDR VALS VALS VALS VALS,
788 "rename", msg->ev_token, msg->ev_sequence,
795 case DM_EVENT_POSTRENAME:
796 printf(HDR VALS VALS VALS VALS VALD,
797 "postrename", msg->ev_token, msg->ev_sequence,
802 "retcode", msg_ne->ne_retcode);
806 case DM_EVENT_SYMLINK:
807 printf(HDR VALS VALS VALS,
808 "symlink", msg->ev_token, msg->ev_sequence,
814 case DM_EVENT_POSTSYMLINK:
815 printf(HDR VALS VALS VALS VALS VALD,
816 "postsymlink", msg->ev_token, msg->ev_sequence,
821 "retcode", msg_ne->ne_retcode);
826 printf(HDR VALS VALS VALS,
827 "link", msg->ev_token, msg->ev_sequence,
833 case DM_EVENT_POSTLINK:
834 printf(HDR VALS VALS VALS VALD,
835 "postlink", msg->ev_token, msg->ev_sequence,
839 "retcode", msg_ne->ne_retcode);
843 case DM_EVENT_ATTRIBUTE:
845 "attribute", msg->ev_token, msg->ev_sequence,
850 case DM_EVENT_CLOSE: /* not supported on SGI */
852 "close", msg->ev_token, msg->ev_sequence,
860 "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
861 "ev_type", msg->ev_type);
862 if (msg->ev_token == DM_INVALID_TOKEN)
869 * Now respond to those messages which require a response
872 if (Sleep) sleep(Sleep); /* Slow things down here */
874 error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
876 errno_msg("Can't respond to event");
886 Convert a mode_t field into a printable string.
888 Returns non-zero if the mode_t is invalid. The string is
889 returned in *ptr, whether there is an error or not.
897 static char modestr[100];
901 if (S_ISFIFO(mode)) typestr = "FIFO";
902 else if(S_ISCHR (mode)) typestr = "Character Device";
903 else if(S_ISBLK (mode)) typestr = "Block Device";
904 else if(S_ISDIR (mode)) typestr = "Directory";
905 else if(S_ISREG (mode)) typestr = "Regular File";
906 else if(S_ISLNK (mode)) typestr = "Symbolic Link";
907 else if(S_ISSOCK(mode)) typestr = "Socket";
909 typestr = "<unknown type>";
913 sprintf(modestr, "mode %06o (perm %c%c%c %c%c%c %c%c%c %c%c%c) "
916 mode & S_ISUID ? 's':' ',
917 mode & S_ISGID ? 'g':' ',
918 mode & S_ISVTX ? 't':' ',
919 mode & S_IRUSR ? 'r':'-',
920 mode & S_IWUSR ? 'w':'-',
921 mode & S_IXUSR ? 'x':'-',
922 mode & S_IRGRP ? 'r':'-',
923 mode & S_IWGRP ? 'w':'-',
924 mode & S_IXGRP ? 'x':'-',
925 mode & S_IROTH ? 'r':'-',
926 mode & S_IWOTH ? 'w':'-',
927 mode & S_IXOTH ? 'x':'-',
940 char hans[HANDLE_STR];
942 if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
943 errno_msg("Can't get filesystem handle");
947 hantoa(*fs_hanpp, *fs_hlenp, hans);
948 err_msg("File system handle for %s: %s\n", fsname, hans);
955 Set the event disposition for this filesystem to include all valid
956 DMAPI events so that we receive all events for this filesystem.
957 Also set DM_EVENT_MOUNT disposition for the global handle.
958 It does not make sense to specify DM_EVENT_USER in the disposition
959 mask since a session is always unconditionally registered for these
962 Returns non-zero on error.
971 dm_eventset_t eventlist;
974 err_msg("Setting event disposition to send all "
975 "events to this session\n");
978 /* DM_EVENT_MOUNT must be sent in a separate request using the global
979 handle. If we ever support more than one filesystem at a time, this
980 request should be moved out of this routine to a place where it is
984 DMEV_ZERO(eventlist);
985 DMEV_SET(DM_EVENT_MOUNT, eventlist);
987 if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
988 &eventlist, DM_EVENT_MAX) == -1) {
989 errno_msg("Can't set event disposition for mount");
993 DMEV_ZERO(eventlist);
995 /* File system administration events. */
997 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
998 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
999 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1001 /* While DM_EVENT_DEBUT is optional, it appears that the spec always
1002 lets it be specified in a dm_set_disp call; its just that the
1003 event will never be seen on some platforms.
1006 DMEV_SET(DM_EVENT_DEBUT, eventlist);
1009 /* Namespace events. */
1011 DMEV_SET(DM_EVENT_CREATE, eventlist);
1012 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1013 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1014 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1015 DMEV_SET(DM_EVENT_RENAME, eventlist);
1016 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1017 DMEV_SET(DM_EVENT_LINK, eventlist);
1018 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1019 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1020 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1022 /* Managed region data events. */
1024 DMEV_SET(DM_EVENT_READ, eventlist);
1025 DMEV_SET(DM_EVENT_WRITE, eventlist);
1026 DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
1028 /* Metadata events. */
1030 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1031 #if ! defined ( __sgi ) && ! defined ( VERITAS ) && ! defined(linux)
1032 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1034 #if !defined(__sgi) && !defined(linux)
1035 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1037 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1039 /* Pseudo-events. */
1041 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1043 if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1044 &eventlist, DM_EVENT_MAX) == -1) {
1045 errno_msg("Can't set event disposition for filesystem");
1053 Enable event generation on each valid filesystem-based DMAPI event
1054 within the given file system.
1056 Returns non-zero on errors.
1065 dm_eventset_t eventlist;
1068 err_msg("Setting event list to enable all events "
1069 "for this file system\n");
1071 DMEV_ZERO(eventlist);
1073 /* File system administration events. */
1075 /* DM_EVENT_MOUNT - always enabled on the global handle - causes
1076 EINVAL if specified.
1078 DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
1079 DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
1080 DMEV_SET(DM_EVENT_NOSPACE, eventlist);
1081 /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
1083 /* Namespace events. */
1085 DMEV_SET(DM_EVENT_CREATE, eventlist);
1086 DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
1087 DMEV_SET(DM_EVENT_REMOVE, eventlist);
1088 DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
1089 DMEV_SET(DM_EVENT_RENAME, eventlist);
1090 DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
1091 DMEV_SET(DM_EVENT_LINK, eventlist);
1092 DMEV_SET(DM_EVENT_POSTLINK, eventlist);
1093 DMEV_SET(DM_EVENT_SYMLINK, eventlist);
1094 DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
1096 /* Managed region data events. These are not settable by
1097 dm_set_eventlist on a filesystem basis. They are meant
1098 to be set using dm_set_region on regular files only.
1099 However, in the SGI implementation, they are filesystem-settable.
1100 Since this is useful for testing purposes, do it.
1104 /* DM_EVENT_WRITE */
1105 /* DM_EVENT_TRUNCATE */
1107 /* Metadata events. */
1109 DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
1110 #if ! defined ( __sgi ) && ! defined ( VERITAS ) && !defined(linux)
1111 DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
1113 #if !defined(__sgi) && !defined(linux)
1114 DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
1116 DMEV_SET(DM_EVENT_DESTROY, eventlist);
1118 /* Pseudo-events. */
1120 /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
1122 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1123 &eventlist, DM_EVENT_MAX) == -1) {
1124 errno_msg("Can't set event list");
1132 Disable monitoring for all events in the DMAPI for the given
1133 file system. This is done before exiting so that future
1134 operations won't hang waiting for their events to be handled.
1136 Returns non-zero on errors.
1145 dm_eventset_t eventlist;
1148 err_msg("Clearing event list to disable all events "
1149 "for this filesystem\n");
1151 DMEV_ZERO(eventlist);
1153 if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
1154 &eventlist, DM_EVENT_MAX) == -1) {
1155 errno_msg("Can't clear event list");
1163 * Respond to any events which haven't been handled yet.
1164 * dm_getall_tokens provides a list of tokens for the outstanding events.
1165 * dm_find_eventmsg uses the token to lookup the corresponding message.
1166 * The message is passed to handle_message() for normal response processing.
1173 u_int nbytes, ntokens = 0, ret_ntokens, i;
1174 dm_token_t *tokenbuf = NULL;
1175 size_t buflen, ret_buflen;
1176 char *msgbuf = NULL;
1180 err_msg("Responding to any outstanding delivered event messages\n");
1183 * Initial sizes for the token and message buffers
1185 ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
1190 * The E2BIG dance...
1191 * Take a guess at how large to make the buffer, starting with ret_ntokens.
1192 * If the routine returns E2BIG, use the returned size and try again.
1193 * If we're already using the returned size, double it and try again.
1196 ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
1197 nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
1198 tokenbuf = malloc(nbytes);
1199 if (tokenbuf == NULL) {
1200 err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
1204 error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
1205 } while (error && errno == E2BIG);
1208 errno_msg("Can't get all outstanding tokens");
1212 for (i = 0; i < ret_ntokens; i++) {
1214 err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
1217 * The E2BIG dance reprise...
1220 buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
1221 msgbuf = malloc(buflen);
1222 if (msgbuf == NULL) {
1223 err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
1227 error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
1228 } while (error && errno == E2BIG);
1230 errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
1234 msg = (dm_eventmsg_t *) msgbuf;
1235 while (msg != NULL) {
1236 error = handle_message(sid, msg);
1239 msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
1255 * Establish an exit handler since we run in an infinite loop
1258 establish_handler(void)
1260 struct sigaction act;
1263 * Set up signals so that we can wait for spawned children
1265 act.sa_handler = exit_handler;
1267 sigemptyset(&act.sa_mask);
1269 (void)sigaction(SIGHUP, &act, NULL);
1270 (void)sigaction(SIGINT, &act, NULL);
1271 (void)sigaction(SIGQUIT, &act, NULL);
1272 (void)sigaction(SIGTERM, &act, NULL);
1273 (void)sigaction(SIGUSR1, &act, NULL);
1274 (void)sigaction(SIGUSR1, &act, NULL);
1275 (void)sigaction(SIGUSR2, &act, NULL);
1284 * Stop events from being generated for the given file system
1285 * Respond to any events that were delivered but unanswered
1286 * (the event loop may have been in the middle of taking care of the event)
1287 * Try getting any undelivered events but don't block if none are there
1288 * (the file system may have generated an event after we killed dm_get_events)
1289 * Shutdown the session using the global "sid" variable.
1300 err_msg("Exiting...\n");
1302 error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
1305 error = clear_events(sid, fs_hanp, fs_hlen);
1307 /* just keep going */ ;
1310 error = finish_responding(sid);
1312 /* just keep going */ ;
1314 err_msg("Processing any undelivered event messages\n");
1315 event_loop(sid, 0 /*waitflag*/);
1317 err_msg("Shutting down the session\n");
1319 error = dm_destroy_session(sid);
1321 errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");