+++ /dev/null
-
-
-/*
- * eventloop.c
- *
- * Joseph Jackson
- * 25-Jun-1996
- *
- * Monitor all events for a file system.
- * When one arrives, print a message with all the details.
- * If the message is synchronous, always reply with DM_RESP_CONTINUE
- * (This program doesn't perform any real file system or HSM work.)
- *
- * This is a simplification of the "migin.c" example program.
- * The original code was by Peter Lawthers:
- * This code was written by Peter Lawthers, and placed in the public
- * domain for use by DMAPI implementors and app writers.
- */
-
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <lib/hsm.h>
-
- /*
- * Define some standard formats for the printf statements below.
- */
-
-#define HDR "%s: token %d sequence %d\n"
-#define VALS "\t%-15s %s\n"
-#define VALD "\t%-15s %d\n"
-#define VALLLD "\t%-15s %lld\n"
-
-extern int optind;
-extern int errno;
-
-void usage (char *);
-int main (int, char **);
-static void event_loop (dm_sessid_t, int);
-int handle_message (dm_sessid_t, dm_eventmsg_t *);
-static int format_mode(mode_t mode, char **ptr);
-static int get_fs_handle (char *, void **, size_t *);
-static int set_disposition(dm_sessid_t, void *, size_t);
-static int set_disp_global(dm_sessid_t);
-static int set_events (dm_sessid_t, void *, size_t);
-static int clear_events (dm_sessid_t, void *, size_t);
-int finish_responding(dm_sessid_t);
-int establish_handler(void);
-void exit_handler (int);
-
-static int
-clear_region_event(
- dm_sessid_t sid,
- u_int event,
- void *hanp,
- size_t hlen,
- char *hans1);
-
-/*
- * Keep these global so the exit_handler and err_msg routines can get to them
- */
-char *Progname;
-int Sleep = 0;
-int Verbose;
-dm_sessid_t sid = 0;
-dm_sessid_t oldsid = 0;
-char *fsname;
-int register_new_mnts = 0;
-int rwt_bit_clear = 1; /* Clear read/write/trunc bit before
- * responding to event; reset all other
- * bits.
- */
-int dmf_events = 0; /* Use only those events that DMF uses */
-
-void
-usage(
- char *prog)
-{
- fprintf(stderr, "Usage: %s ", prog);
- fprintf(stderr, " <-S oldsid> <-v> <-s sleep> <-R> <-N> <-D> ");
- fprintf(stderr, "filesystem \n");
-}
-
-
-int
-main(
- int argc,
- char *argv[])
-{
-
- int c;
- int error;
- void *fs_hanp;
- size_t fs_hlen;
-
-
-/* Progname = argv[0];*/ Progname = "print_event";
- fsname = NULL;
-
- while ((c = getopt(argc, argv, "vs:S:RND")) != EOF) {
- switch (c) {
- case 's':
- Sleep = atoi(optarg);
- break;
- case 'R':
- register_new_mnts = 1;
- break;
- case 'D':
- dmf_events = 1;
- break;
- case 'N':
- rwt_bit_clear = 0;
- break;
- case 'S':
- oldsid = atoi(optarg);
- break;
- case 'v':
- Verbose = 1;
- break;
- case '?':
- default:
- usage(Progname);
- exit(1);
- }
- }
- if (optind >= argc) {
- usage(Progname);
- exit(1);
- }
- fsname = argv[optind];
- if (fsname == NULL) {
- usage(Progname);
- exit(1);
- }
-
- /*
- * Establish an exit handler
- */
- error = establish_handler();
- if (error)
- exit(1);
-
- /*
- * Init the dmapi, and get a filesystem handle so
- * we can set up our events
- */
-
- if (oldsid) {
- sid = oldsid;
- } else {
- error = setup_dmapi(&sid);
- if (error)
- exit(1);
- }
-
- error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
- if (error)
- goto cleanup;
-
- /*
- * Set the event disposition so that our session will receive
- * all the events for the given file system
- */
- error = set_disp_global(sid);
- if (error)
- goto cleanup;
- error = set_disposition(sid, fs_hanp, fs_hlen);
- if (error)
- goto cleanup;
-
- /*
- * Enable monitoring for all events in the given file system
- */
- error = set_events(sid, fs_hanp, fs_hlen);
- if (error)
- goto cleanup;
-
- /*
- * Now sit in an infinite loop, reporting on any events that occur.
- * The program is exited after a signal through exit_handler().
- */
- printf("\n");
- event_loop(sid, 1 /*waitflag*/);
-
- /*
- * If we get here, cleanup after the event_loop failure
- */
- cleanup:
- exit_handler(0);
- return(1);
-}
-
-
-/*
- * Main event loop processing
- *
- * The waitflag argument is set to 1 when we call this from main().
- * In this case, continuously process incoming events,
- * blocking if there are none available.
- * In the exit_handler(), call this routine with waitflag=0.
- * Just try to read the events once in this case with no blocking.
- */
-
-static void
-event_loop(
- dm_sessid_t sid,
- int waitflag)
-{
- void *msgbuf;
- size_t bufsize;
- int error;
- dm_eventmsg_t *msg;
- int count;
-
- /*
- * We take a swag at a buffer size. If it's wrong, we can
- * always resize it
- */
-
- bufsize = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
- bufsize *= 50;
- msgbuf = (void *)malloc(bufsize);
- if (msgbuf == NULL) {
- err_msg("Can't allocate memory for buffer");
- return;
- }
-
- for (;;) {
- error = dm_get_events(sid, ALL_AVAIL_MSGS,
- waitflag ? DM_EV_WAIT:0, bufsize, msgbuf, &bufsize);
- if (error) {
- if (errno == EAGAIN) {
- if (waitflag)
- continue;
- break;
- }
- if (errno == E2BIG) {
- free(msgbuf);
- msgbuf = (void *)malloc(bufsize);
- if (msgbuf == NULL) {
- err_msg("Can't resize msg buffer");
- return;
- }
- continue;
- }
- errno_msg("Error getting events from DMAPI (%d)", errno);
- break;
- }
-
- /*
- * Walk through the message buffer, pull out each individual
- * message, and dispatch the messages to handle_message(),
- * which will respond to the events.
- */
-
- count = 0;
- msg = (dm_eventmsg_t *)msgbuf;
- while (msg != NULL ) {
- count++;
- error = handle_message(sid, msg);
- if (error) {
- free(msgbuf);
- return;
- }
- msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
- }
- if (count != 1 && Verbose) {
- err_msg("Found %d events in one call to "
- "dm_get_events\n", count);
- }
- }
- if (msgbuf != NULL)
- free(msgbuf);
-}
-
-
-void
-print_one_mount_event(
- void *msg)
-{
- void *hanp1, *hanp2, *hanp3;
- size_t hlen1, hlen2, hlen3;
- char hans1[HANDLE_STR], hans2[HANDLE_STR], hans3[HANDLE_STR];
- void *namp1, *namp2;
- size_t nlen1, nlen2;
- char nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
- mode_t mode;
-
-#if VERITAS_21
- dm_namesp_event_t *msg_ne = (dm_namesp_event_t *)msg;
-
-/*
- msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
-*/
- hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
- hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
- hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
- hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
- namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
- nlen1 = DM_GET_LEN (msg_ne, ne_name1);
- namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
- nlen2 = DM_GET_LEN (msg_ne, ne_name2);
- hanp3 = NULL;
- hlen3 = 0;
- mode = msg_ne->ne_mode;
-#else
- dm_mount_event_t *msg_me = (dm_mount_event_t *)msg;
-
- hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
- hlen1 = DM_GET_LEN(msg_me, me_handle1);
- hanp2 = DM_GET_VALUE(msg_me, me_handle2, void *);
- hlen2 = DM_GET_LEN(msg_me, me_handle2);
- namp1 = DM_GET_VALUE(msg_me, me_name1, void *);
- nlen1 = DM_GET_LEN(msg_me, me_name1);
- namp2 = DM_GET_VALUE(msg_me, me_name2, void *);
- nlen2 = DM_GET_LEN(msg_me, me_name2);
- hanp3 = DM_GET_VALUE(msg_me, me_roothandle, void *);
- hlen3 = DM_GET_LEN(msg_me, me_roothandle);
- mode = msg_me->me_mode;
-#endif /* VERITAS_21 */
-
- if (hanp1 && hlen1) {
- hantoa(hanp1, hlen1, hans1);
- } else {
- sprintf(hans1, "<BAD HANDLE, hlen %zd>", hlen1);
- }
- if (hanp2 && hlen2) {
- hantoa(hanp2, hlen2, hans2);
- } else {
- sprintf(hans2, "<BAD HANDLE, hlen %zd>", hlen2);
- }
- if (hanp3 && hlen3) {
- hantoa(hanp3, hlen3, hans3);
- } else {
- sprintf(hans3, "<BAD HANDLE, hlen %zd>", hlen3);
- }
- if (namp1 && nlen1) {
- strncpy(nams1, namp1, nlen1);
- if (nlen1 != sizeof(nams1))
- nams1[nlen1] = '\0';
- } else {
- sprintf(nams1, "<BAD STRING, nlen %zd>", nlen1);
- }
- if (namp2 && nlen2) {
- strncpy(nams2, namp2, nlen2);
- if (nlen2 != sizeof(nams2))
- nams2[nlen2] = '\0';
- } else {
- sprintf(nams2, "<BAD STRING, nlen %zd>", nlen2);
- }
-
- printf(VALS VALS VALS VALS VALS VALD,
- "fs handle", hans1,
- "mtpt handle", hans2,
- "mtpt path", nams1,
- "media desig", nams2,
- "root handle", hans3,
- "mode", mode);
-}
-
-
-/*
- * First, weed out the events which return interesting structures.
- * If it's not one of those, unpack the dm_namesp_event structure
- * and display the contents.
- */
-int
-handle_message(
- dm_sessid_t sid,
- dm_eventmsg_t *msg)
-{
- int pkt_error = 0;
- int error;
- dm_response_t response;
- int respond, respcode;
- dm_namesp_event_t *msg_ne;
-#if !VERITAS_21
- dm_mount_event_t *msg_me;
-#endif
- void *hanp1, *hanp2, *namp1, *namp2;
- u_int hlen1, hlen2, nlen1, nlen2;
- char hans1[HANDLE_STR], hans2[HANDLE_STR];
- char nams1[NAME_MAX + 1], nams2[NAME_MAX + 1];
-
- /*
- * Set the defaults for responding to events
- */
- respond = 1;
- response = DM_RESP_CONTINUE;
- respcode = 0;
-
- /***** USER EVENTS *****/
-
- if (msg->ev_type == DM_EVENT_USER) {
- char *privp;
- u_int plen, i;
-
- printf(HDR,
- "user", msg->ev_token, msg->ev_sequence);
-
- /* print private data as ascii or hex if it exists DM_CONFIG_MAX_MESSAGE_DATA */
-
- privp = DM_GET_VALUE(msg, ev_data, char *);
- plen = DM_GET_LEN (msg, ev_data);
- if (plen) {
- for (i = 0; i < plen; i++) {
- if (!isprint(privp[i]) && !isspace(privp[i]))
- break;
- }
- if (i == plen - 1 && privp[i] == '\0') {
- printf(VALS,
- "privdata", privp);
- } else {
- printf("\t%-15s ", "privdata");
- for (i = 0; i < plen; i++) {
- printf("%.2x", privp[i]);
- }
- printf("\n");
- }
- } else {
- printf(VALS,
- "privdata", "<NONE>");
- }
-
- if (msg->ev_token == DM_INVALID_TOKEN) /* async dm_send_msg event */
- respond = 0;
- }
-
- /***** CANCEL EVENT *****/
-
-/* Not implemented on SGI or Veritas */
-
- else if (msg->ev_type == DM_EVENT_CANCEL) {
- dm_cancel_event_t *msg_ce;
-
- msg_ce = DM_GET_VALUE(msg, ev_data, dm_cancel_event_t *);
- printf(HDR VALD VALD,
- "cancel", msg->ev_token, msg->ev_sequence,
- "sequence", msg_ce->ce_sequence,
- "token", msg_ce->ce_token);
- respond = 0;
- }
-
- /***** DATA EVENTS *****/
-
- else if (msg->ev_type == DM_EVENT_READ ||
- msg->ev_type == DM_EVENT_WRITE ||
- msg->ev_type == DM_EVENT_TRUNCATE) {
- dm_data_event_t *msg_de;
-
- msg_de = DM_GET_VALUE(msg, ev_data, dm_data_event_t *);
- hanp1 = DM_GET_VALUE(msg_de, de_handle, void *);
- hlen1 = DM_GET_LEN (msg_de, de_handle);
- if (hanp1 && hlen1) {
- hantoa(hanp1, hlen1, hans1);
- if (rwt_bit_clear) {
- u_int rgflag;
- switch(msg->ev_type) {
- /* DM_EVENT_* and DM_REGION_* are different values, ug */
- case DM_EVENT_READ:
- rgflag = DM_REGION_READ;
- break;
- case DM_EVENT_WRITE:
- rgflag = DM_REGION_WRITE;
- break;
- case DM_EVENT_TRUNCATE:
- rgflag = DM_REGION_TRUNCATE;
- break;
- default:
- err_msg("unexpected event type (%d)\n", msg->ev_type);
- rgflag = DM_REGION_NOEVENT;
- break;
- }
- clear_region_event(sid, rgflag, hanp1, hlen1, hans1);
- }
- } else {
- sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
- }
-
- switch(msg->ev_type) {
-
- case DM_EVENT_READ:
- printf(HDR VALS VALLLD VALLLD,
- "read", msg->ev_token, msg->ev_sequence,
- "file handle", hans1,
- "offset", (long long) msg_de->de_offset,
- "length", (long long) msg_de->de_length);
- break;
-
- case DM_EVENT_WRITE:
- printf(HDR VALS VALLLD VALLLD,
- "write", msg->ev_token, msg->ev_sequence,
- "file handle", hans1,
- "offset", (long long) msg_de->de_offset,
- "length", (long long) msg_de->de_length);
- break;
-
- case DM_EVENT_TRUNCATE:
- printf(HDR VALS VALLLD VALLLD,
- "truncate", msg->ev_token, msg->ev_sequence,
- "file handle", hans1,
- "offset", (long long) msg_de->de_offset,
- "length", (long long) msg_de->de_length);
- break;
- default: break;
- }
- } /* RWT */
-
- /***** DESTROY EVENT *****/
-
- else if (msg->ev_type == DM_EVENT_DESTROY) {
- dm_destroy_event_t *msg_ds;
- char attrname[DM_ATTR_NAME_SIZE + 1];
- u_char *copy;
- u_int clen;
- u_int i;
-
- msg_ds= DM_GET_VALUE(msg, ev_data, dm_destroy_event_t *);
- hanp1 = DM_GET_VALUE(msg_ds, ds_handle, void *);
- hlen1 = DM_GET_LEN (msg_ds, ds_handle);
- if (hanp1 && hlen1) {
- hantoa(hanp1, hlen1, hans1);
- } else {
- sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen1);
- }
- if (msg_ds->ds_attrname.an_chars[0] != '\0') {
- strncpy(attrname, (char *)msg_ds->ds_attrname.an_chars, sizeof(attrname));
- attrname[DM_ATTR_NAME_SIZE] = '\0'; /* terminate the string */
- } else {
- strcpy(attrname, "<NONE>");
- }
- printf(HDR VALS VALS,
- "destroy", msg->ev_token, msg->ev_sequence,
- "handle", hans1,
- "attrname", attrname);
- copy = DM_GET_VALUE(msg_ds, ds_attrcopy, u_char *);
- clen = DM_GET_LEN (msg_ds, ds_attrcopy);
- if (copy && clen) {
- printf("\t%-15s ", "attrcopy");
- for (i = 0; i < clen; i++) {
- printf("%.2x", copy[i]);
- }
- printf("\n");
- } else {
- printf(VALS, "attrcopy", "<NONE>");
- }
- respond = 0;
- }
-
- /***** MOUNT EVENT *****/
-
- else if (msg->ev_type == DM_EVENT_MOUNT) {
- printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
-#if !VERITAS_21
- msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
- hanp1 = DM_GET_VALUE(msg_me, me_handle1, void *);
- hlen1 = DM_GET_LEN(msg_me, me_handle1);
-
- print_one_mount_event(msg_me);
-
- if (register_new_mnts) {
- if (set_disposition(sid, hanp1, hlen1) == 0)
- set_events(sid, hanp1, hlen1);
- }
-
-#else /* VERITAS_21 */
- msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
- print_one_mount_event(msg_ne);
-#endif /* VERITAS_21 */
-
- }
-
- /***** NAMESPACE EVENTS *****/
-
- else {
- char *type = NULL;
-
- msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
- hanp1 = DM_GET_VALUE(msg_ne, ne_handle1, void *);
- hlen1 = DM_GET_LEN (msg_ne, ne_handle1);
- hanp2 = DM_GET_VALUE(msg_ne, ne_handle2, void *);
- hlen2 = DM_GET_LEN (msg_ne, ne_handle2);
- namp1 = DM_GET_VALUE(msg_ne, ne_name1, void *);
- nlen1 = DM_GET_LEN (msg_ne, ne_name1);
- namp2 = DM_GET_VALUE(msg_ne, ne_name2, void *);
- nlen2 = DM_GET_LEN (msg_ne, ne_name2);
-
- if (hanp1 && hlen1) {
- hantoa(hanp1, hlen1, hans1);
- }
- if (hanp2 && hlen2) {
- hantoa(hanp2, hlen2, hans2);
- }
- if (namp1 && nlen1) {
- strncpy(nams1, namp1, nlen1);
- if (nlen1 != sizeof(nams1))
- nams1[nlen1] = '\0';
- }
- if (namp2 && nlen2) {
- strncpy(nams2, namp2, nlen2);
- if (nlen2 != sizeof(nams2))
- nams2[nlen2] = '\0';
- }
-
- if (msg->ev_type == DM_EVENT_PREUNMOUNT ||
- msg->ev_type == DM_EVENT_UNMOUNT) {
- if (msg_ne->ne_mode == 0) {
- type = "NOFORCE";
-#if !VERITAS_21
- } else if (msg_ne->ne_mode == DM_UNMOUNT_FORCE) {
-#else
- } else if (msg_ne->ne_mode > 0) {
-#endif
- type = "FORCE";
- } else {
- type = "UNKNOWN";
- pkt_error++;
- }
- } else if (msg->ev_type == DM_EVENT_CREATE ||
- msg->ev_type == DM_EVENT_POSTCREATE ||
- msg->ev_type == DM_EVENT_REMOVE ||
- msg->ev_type == DM_EVENT_POSTREMOVE) {
- if (format_mode(msg_ne->ne_mode, &type)) {
- pkt_error++;
- }
- }
-
- switch(msg->ev_type) {
-
- case DM_EVENT_PREUNMOUNT:
- printf(HDR VALS VALS VALS,
- "preunmount", msg->ev_token, msg->ev_sequence,
- "fs handle", hans1,
- "root dir", hans2,
- "unmount mode", type);
- break;
-
- case DM_EVENT_UNMOUNT:
- printf(HDR VALS VALS VALD,
- "unmount", msg->ev_token, msg->ev_sequence,
- "fs handle", hans1,
- "unmount mode", type,
- "retcode", msg_ne->ne_retcode);
- break;
-
- case DM_EVENT_NOSPACE:
- printf(HDR VALS,
- "nospace", msg->ev_token, msg->ev_sequence,
- "fs handle", hans1);
- response = DM_RESP_ABORT;
- respcode = ENOSPC;
- break;
-
- case DM_EVENT_DEBUT: /* not supported on SGI */
- printf(HDR VALS,
- "debut", msg->ev_token, msg->ev_sequence,
- "object", hans1);
- break;
-
- case DM_EVENT_CREATE:
- printf(HDR VALS VALS VALS,
- "create", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "name", nams1,
- "mode bits", type);
- break;
-
- case DM_EVENT_POSTCREATE:
- printf(HDR VALS VALS VALS VALS VALD,
- "postcreate", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "new object", hans2,
- "name", nams1,
- "mode bits", type,
- "retcode", msg_ne->ne_retcode);
- respond = 0;
- clear_region_event(sid, 0, hanp2, hlen2, hans2);
- break;
-
- case DM_EVENT_REMOVE:
- printf(HDR VALS VALS VALS,
- "remove", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "name", nams1,
- "mode bits", type);
- break;
-
- case DM_EVENT_POSTREMOVE:
- printf(HDR VALS VALS VALS VALD,
- "postremove", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "name", nams1,
- "mode bits", type,
- "retcode", msg_ne->ne_retcode);
- respond = 0;
- break;
-
- case DM_EVENT_RENAME:
- printf(HDR VALS VALS VALS VALS,
- "rename", msg->ev_token, msg->ev_sequence,
- "old parent", hans1,
- "new parent", hans2,
- "old name", nams1,
- "new name", nams2);
- break;
-
- case DM_EVENT_POSTRENAME:
- printf(HDR VALS VALS VALS VALS VALD,
- "postrename", msg->ev_token, msg->ev_sequence,
- "old parent", hans1,
- "new parent", hans2,
- "old name", nams1,
- "new name", nams2,
- "retcode", msg_ne->ne_retcode);
- respond = 0;
- break;
-
- case DM_EVENT_SYMLINK:
- printf(HDR VALS VALS VALS,
- "symlink", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "name", nams1,
- "contents", nams2);
- break;
-
- case DM_EVENT_POSTSYMLINK:
- printf(HDR VALS VALS VALS VALS VALD,
- "postsymlink", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "new object", hans2,
- "name", nams1,
- "contents", nams2,
- "retcode", msg_ne->ne_retcode);
- respond = 0;
- break;
-
- case DM_EVENT_LINK:
- printf(HDR VALS VALS VALS,
- "link", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "source", hans2,
- "name", nams1);
- break;
-
- case DM_EVENT_POSTLINK:
- printf(HDR VALS VALS VALS VALD,
- "postlink", msg->ev_token, msg->ev_sequence,
- "parent dir", hans1,
- "source", hans2,
- "name", nams1,
- "retcode", msg_ne->ne_retcode);
- respond = 0;
- break;
-
- case DM_EVENT_ATTRIBUTE:
- printf(HDR VALS,
- "attribute", msg->ev_token, msg->ev_sequence,
- "object", hans1);
- respond = 0;
- break;
-
- case DM_EVENT_CLOSE: /* not supported on SGI */
- printf(HDR VALS,
- "close", msg->ev_token, msg->ev_sequence,
- "object", hans1);
- respond = 0;
- break;
-
- default:
- pkt_error++;
- printf(HDR VALD,
- "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
- "ev_type", msg->ev_type);
- if (msg->ev_token == DM_INVALID_TOKEN)
- respond = 0;
- break;
- }
- }
-
- /*
- * Now respond to those messages which require a response
- */
- if (respond) {
- error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
- if (error) {
- errno_msg("Can't respond to event");
- return error;
- }
- if (Sleep) {
- err_msg("Sleeping for %d seconds!\n", Sleep);
- sleep(Sleep);
- }
- }
-
- return 0;
-}
-
-
-/*
- Convert a mode_t field into a printable string.
-
- Returns non-zero if the mode_t is invalid. The string is
- returned in *ptr, whether there is an error or not.
-*/
-
-static int
-format_mode(
- mode_t mode,
- char **ptr)
-{
-static char modestr[100];
- char *typestr;
- int error = 0;
-
- if (S_ISFIFO(mode)) typestr = "FIFO";
- else if(S_ISCHR (mode)) typestr = "Character Device";
- else if(S_ISBLK (mode)) typestr = "Block Device";
- else if(S_ISDIR (mode)) typestr = "Directory";
- else if(S_ISREG (mode)) typestr = "Regular File";
- else if(S_ISLNK (mode)) typestr = "Symbolic Link";
- else if(S_ISSOCK(mode)) typestr = "Socket";
- else {
- typestr = "<unknown type>";
- error++;
- }
-
- sprintf(modestr, "mode %06o: perm %c%c%c %c%c%c %c%c%c %c%c%c, type %s",
- mode,
- mode & S_ISUID ? 's':' ',
- mode & S_ISGID ? 'g':' ',
- mode & S_ISVTX ? 't':' ',
- mode & S_IRUSR ? 'r':'-',
- mode & S_IWUSR ? 'w':'-',
- mode & S_IXUSR ? 'x':'-',
- mode & S_IRGRP ? 'r':'-',
- mode & S_IWGRP ? 'w':'-',
- mode & S_IXGRP ? 'x':'-',
- mode & S_IROTH ? 'r':'-',
- mode & S_IWOTH ? 'w':'-',
- mode & S_IXOTH ? 'x':'-',
- typestr);
- *ptr = modestr;
- return(error);
-}
-
-
-static int
-get_fs_handle(
- char *fsname,
- void **fs_hanpp,
- size_t *fs_hlenp)
-{
- char hans[HANDLE_STR];
-
- if (dm_path_to_fshandle(fsname, fs_hanpp, fs_hlenp) == -1) {
- errno_msg("Can't get filesystem handle");
- return 1;
- }
- if (Verbose) {
- hantoa(*fs_hanpp, *fs_hlenp, hans);
- err_msg("File system handle for %s: %s\n", fsname, hans);
- }
- return 0;
-}
-
-
-/*
- Set the event disposition for this filesystem to include all valid
- DMAPI events so that we receive all events for this filesystem.
- Also set DM_EVENT_MOUNT disposition for the global handle.
- It does not make sense to specify DM_EVENT_USER in the disposition
- mask since a session is always unconditionally registered for these
- events.
-
- Returns non-zero on error.
-*/
-
-static int
-set_disp_global(
- dm_sessid_t sid)
-{
- dm_eventset_t eventlist;
-
- if (Verbose) {
- err_msg("Setting event disposition to send all "
- "mount events to this session\n");
- }
-
- /* DM_EVENT_MOUNT must be sent in a separate request using the global
- handle. If we ever support more than one filesystem at a time, this
- request should be moved out of this routine to a place where it is
- issued just once.
- */
-
- DMEV_ZERO(eventlist);
- DMEV_SET(DM_EVENT_MOUNT, eventlist);
-
- if (dm_set_disp(sid, DM_GLOBAL_HANP, DM_GLOBAL_HLEN, DM_NO_TOKEN,
- &eventlist, DM_EVENT_MAX) == -1) {
- errno_msg("Can't set event disposition for mount");
- return(1);
- }
-
- return(0);
-}
-
-
-static int
-set_disposition(
- dm_sessid_t sid,
- void *fs_hanp,
- size_t fs_hlen)
-{
- dm_eventset_t eventlist;
-
- if (Verbose) {
- err_msg("Setting event disposition to send all "
- "events to this session\n");
- }
-
- DMEV_ZERO(eventlist);
-
- /* File system administration events. */
-
- DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
- DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
- DMEV_SET(DM_EVENT_NOSPACE, eventlist);
-
- /* While DM_EVENT_DEBUT is optional, it appears that the spec always
- lets it be specified in a dm_set_disp call; its just that the
- event will never be seen on some platforms.
- */
-
- DMEV_SET(DM_EVENT_DEBUT, eventlist);
-
-
- /* Namespace events. */
-
- DMEV_SET(DM_EVENT_CREATE, eventlist);
- DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
- DMEV_SET(DM_EVENT_REMOVE, eventlist);
- DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
- DMEV_SET(DM_EVENT_RENAME, eventlist);
- DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
- DMEV_SET(DM_EVENT_LINK, eventlist);
- DMEV_SET(DM_EVENT_POSTLINK, eventlist);
- DMEV_SET(DM_EVENT_SYMLINK, eventlist);
- DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
-
- /* Managed region data events. */
-
- DMEV_SET(DM_EVENT_READ, eventlist);
- DMEV_SET(DM_EVENT_WRITE, eventlist);
- DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
-
- /* Metadata events. */
-
- DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
-#if !defined(VERITAS_21) && !defined(linux)
- DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
-#endif
-#if !defined(linux)
- DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
-#endif
- DMEV_SET(DM_EVENT_DESTROY, eventlist);
-
- /* Pseudo-events. */
-
- /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
-
- if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
- &eventlist, DM_EVENT_MAX) == -1) {
- errno_msg("Can't set event disposition for filesystem");
- return(1);
- }
- return(0);
-}
-
-
-/*
- Enable event generation on each valid filesystem-based DMAPI event
- within the given file system.
-
- Returns non-zero on errors.
-*/
-
-static int
-set_events(
- dm_sessid_t sid,
- void *fs_hanp,
- size_t fs_hlen)
-{
- dm_eventset_t eventlist;
-
- if (Verbose) {
- if (dmf_events) {
- err_msg("Setting event list to enable all "
- "DMF-supported events "
- "for this file system\n");
- }
- else {
- err_msg("Setting event list to enable all events "
- "for this file system\n");
- }
- }
- DMEV_ZERO(eventlist);
-
- /* File system administration events. */
-
- /* DM_EVENT_MOUNT - always enabled on the global handle - causes
- EINVAL if specified.
- */
- DMEV_SET(DM_EVENT_PREUNMOUNT, eventlist);
- DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
- DMEV_SET(DM_EVENT_NOSPACE, eventlist);
- /* DM_EVENT_DEBUT - always enabled - causes EINVAL if specified. */
-
- /* Namespace events. */
-
- DMEV_SET(DM_EVENT_CREATE, eventlist);
- DMEV_SET(DM_EVENT_POSTCREATE, eventlist);
- DMEV_SET(DM_EVENT_REMOVE, eventlist);
- DMEV_SET(DM_EVENT_POSTREMOVE, eventlist);
- DMEV_SET(DM_EVENT_RENAME, eventlist);
- DMEV_SET(DM_EVENT_POSTRENAME, eventlist);
- DMEV_SET(DM_EVENT_LINK, eventlist);
- DMEV_SET(DM_EVENT_POSTLINK, eventlist);
- DMEV_SET(DM_EVENT_SYMLINK, eventlist);
- DMEV_SET(DM_EVENT_POSTSYMLINK, eventlist);
-
- /* Managed region data events. These are not settable by
- dm_set_eventlist on a filesystem basis. They are meant
- to be set using dm_set_region on regular files only.
- However, in the SGI implementation, they are filesystem-settable.
- Since this is useful for testing purposes, do it.
- */
-
- /* DM_EVENT_READ */
- /* DM_EVENT_WRITE */
- /* DM_EVENT_TRUNCATE */
-
- /* Metadata events. */
-
- DMEV_SET(DM_EVENT_ATTRIBUTE, eventlist);
-#if !defined(VERITAS_21) && !defined(linux)
- DMEV_SET(DM_EVENT_CANCEL, eventlist); /* not supported on SGI */
-#endif
-#if !defined(linux)
- DMEV_SET(DM_EVENT_CLOSE, eventlist); /* not supported on SGI */
-#endif
- DMEV_SET(DM_EVENT_DESTROY, eventlist);
-
- /* Did we want just the DMF events? */
- if (dmf_events) {
- DMEV_ZERO(eventlist);
- DMEV_SET(DM_EVENT_UNMOUNT, eventlist);
- DMEV_SET(DM_EVENT_DESTROY, eventlist);
- }
-
- /* Pseudo-events. */
-
- /* DM_EVENT_USER - always enabled - causes EINVAL if specified */
-
- if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
- &eventlist, DM_EVENT_MAX) == -1) {
- errno_msg("Can't set event list");
- return(1);
- }
- return(0);
-}
-
-
-/*
- Disable monitoring for all events in the DMAPI for the given
- file system. This is done before exiting so that future
- operations won't hang waiting for their events to be handled.
-
- Returns non-zero on errors.
-*/
-
-static int
-clear_events(
- dm_sessid_t sid,
- void *fs_hanp,
- size_t fs_hlen)
-{
- dm_eventset_t eventlist;
-
- if (Verbose) {
- err_msg("Clearing event list to disable all events "
- "for this filesystem\n");
- }
- DMEV_ZERO(eventlist);
-
- if (dm_set_eventlist(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
- &eventlist, DM_EVENT_MAX) == -1) {
- errno_msg("Can't clear event list");
- return(1);
- }
- return(0);
-}
-
-
-
-static int
-clear_region_event(
- dm_sessid_t sid,
- u_int event,
- void *hanp,
- size_t hlen,
- char *hans1)
-{
- dm_region_t region = { 0, 0, 0 };
- u_int nelem = 1;
- u_int exactflag;
-
- region.rg_flags = DM_REGION_READ|DM_REGION_WRITE|DM_REGION_TRUNCATE;
- region.rg_flags &= ~event;
-
- if (Verbose) {
- err_msg("Clearing region mask 0x%x for file %s\n",
- (int)event, hans1);
- err_msg("Setting region mask 0x%x\n", region.rg_flags);
- }
-
- if (dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, nelem, ®ion,
- &exactflag)) {
- errno_msg("Can't set region event");
- return(1);
- }
- return(0);
-}
-
-
-/*
- * Respond to any events which haven't been handled yet.
- * dm_getall_tokens provides a list of tokens for the outstanding events.
- * dm_find_eventmsg uses the token to lookup the corresponding message.
- * The message is passed to handle_message() for normal response processing.
- */
-int
-finish_responding(
- dm_sessid_t sid)
-{
- int error = 0;
- u_int nbytes, ntokens = 0, ret_ntokens, i;
- dm_token_t *tokenbuf = NULL, *tokenptr;
- size_t buflen = 0, ret_buflen;
- char *msgbuf = NULL;
- dm_eventmsg_t *msg;
-
- if (Verbose)
- err_msg("Responding to any outstanding delivered event messages\n");
-
- /*
- * Initial sizes for the token and message buffers
- */
- ret_buflen = 16 * (sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t)
- + HANDLE_LEN);
- ret_ntokens = 16;
-
- /*
- * The E2BIG dance...
- * Take a guess at how large to make the buffer, starting with ret_ntokens.
- * If the routine returns E2BIG, use the returned size and try again.
- * If we're already using the returned size, double it and try again.
- */
- do {
- dm_token_t *tmpbuf;
- ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
- nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
- tmpbuf = realloc(tokenbuf, nbytes);
- if (tmpbuf == NULL) {
- err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
- error = 1;
- goto out;
- }
- tokenbuf = tmpbuf;
- error = dm_getall_tokens(sid, ntokens, tokenbuf, &ret_ntokens);
- } while (error && errno == E2BIG);
-
- if (error) {
- errno_msg("Can't get all outstanding tokens");
- goto out;
- }
-
- tokenptr = tokenbuf;
- for (i = 0; i < ret_ntokens; i++) {
- if (Verbose)
- err_msg("Responding to outstanding event for token %d\n",(int)*tokenptr);
-
- /*
- * The E2BIG dance reprise...
- */
- do {
- char *tmpbuf;
- buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
- tmpbuf = realloc(msgbuf, buflen);
- if (tmpbuf == NULL) {
- err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
- error = 1;
- goto out;
- }
- msgbuf = tmpbuf;
- error = dm_find_eventmsg(sid, *tokenptr, buflen, msgbuf, &ret_buflen);
- } while (error && errno == E2BIG);
- if (error) {
- errno_msg("Can't find the event message for token %d", (int)*tokenptr);
- goto out;
- }
-
- msg = (dm_eventmsg_t *) msgbuf;
- while (msg != NULL) {
- error = handle_message(sid, msg);
- if (error)
- goto out;
- msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
- }
-
- tokenptr++;
- }
-
- out:
- if (tokenbuf)
- free(tokenbuf);
- if (msgbuf)
- free(msgbuf);
- return error;
-}
-
-
-/*
- * Establish an exit handler since we run in an infinite loop
- */
-int
-establish_handler(void)
-{
- struct sigaction act;
-
- /*
- * Set up signals so that we can wait for spawned children
- */
- act.sa_handler = exit_handler;
- act.sa_flags = 0;
- sigemptyset(&act.sa_mask);
-
- (void)sigaction(SIGHUP, &act, NULL);
- (void)sigaction(SIGINT, &act, NULL);
- (void)sigaction(SIGQUIT, &act, NULL);
- (void)sigaction(SIGTERM, &act, NULL);
- (void)sigaction(SIGUSR1, &act, NULL);
- (void)sigaction(SIGUSR1, &act, NULL);
- (void)sigaction(SIGUSR2, &act, NULL);
-
- return(0);
-}
-
-
-/*
- * Exit gracefully
- *
- * Stop events from being generated for the given file system
- * Respond to any events that were delivered but unanswered
- * (the event loop may have been in the middle of taking care of the event)
- * Try getting any undelivered events but don't block if none are there
- * (the file system may have generated an event after we killed dm_get_events)
- * Shutdown the session using the global "sid" variable.
- */
-void
-exit_handler(int x)
-{
- int error;
- void *fs_hanp;
- size_t fs_hlen;
-
- if (Verbose)
- printf("\n"),
- err_msg("Exiting...\n");
-
- error = get_fs_handle(fsname, &fs_hanp, &fs_hlen);
-
- if (!error) {
- error = clear_events(sid, fs_hanp, fs_hlen);
- if (error)
- /* just keep going */ ;
- }
-
- error = finish_responding(sid);
- if (error)
- /* just keep going */ ;
-
- err_msg("Processing any undelivered event messages\n");
- event_loop(sid, 0 /*waitflag*/);
-
- err_msg("Shutting down the session\n");
- if (sid != 0) {
- error = dm_destroy_session(sid);
- if (error == -1) {
- errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");
- }
- }
-
- exit(0);
-}