]> www.infradead.org Git - users/hch/xfstests-dev.git/commitdiff
cmd/xfsprogs/libdm/dmapi_tests/README 1.1 Renamed to cmd/xfstests/dmapi/README
authorNathan Scott <nathans@sgi.com>
Wed, 17 Jan 2001 01:24:14 +0000 (01:24 +0000)
committerNathan Scott <nathans@sgi.com>
Wed, 17 Jan 2001 01:24:14 +0000 (01:24 +0000)
113 files changed:
dmapi/README [new file with mode: 0644]
dmapi/src/common/cmd/read_invis.c [new file with mode: 0644]
dmapi/src/common/cmd/set_region.c [new file with mode: 0644]
dmapi/src/common/cmd/set_return_on_destroy.c [new file with mode: 0644]
dmapi/src/common/cmd/write_invis.c [new file with mode: 0644]
dmapi/src/common/lib/dmport.h [new file with mode: 0644]
dmapi/src/common/lib/find_session.c [new file with mode: 0644]
dmapi/src/common/lib/hsm.h [new file with mode: 0644]
dmapi/src/common/lib/print.c [new file with mode: 0644]
dmapi/src/common/lib/stubs.c [new file with mode: 0644]
dmapi/src/common/lib/util.c [new file with mode: 0644]
dmapi/src/sample_hsm/README [new file with mode: 0644]
dmapi/src/sample_hsm/migfind.c [new file with mode: 0644]
dmapi/src/sample_hsm/migin.c [new file with mode: 0644]
dmapi/src/sample_hsm/migout.c [new file with mode: 0644]
dmapi/src/sample_hsm/mls.c [new file with mode: 0644]
dmapi/src/sample_hsm/mrmean.c [new file with mode: 0644]
dmapi/src/sample_hsm/wbee.c [new file with mode: 0644]
dmapi/src/simple/dm_create_session.c [new file with mode: 0644]
dmapi/src/simple/dm_destroy_session.c [new file with mode: 0644]
dmapi/src/simple/dm_find_eventmsg.c [new file with mode: 0644]
dmapi/src/simple/dm_getall_sessions.c [new file with mode: 0644]
dmapi/src/simple/dm_getall_tokens.c [new file with mode: 0644]
dmapi/src/simple/dm_query_session.c [new file with mode: 0644]
dmapi/src/suite1/cmd/create_userevent.c [new file with mode: 0644]
dmapi/src/suite1/cmd/dm_handle.c [new file with mode: 0644]
dmapi/src/suite1/cmd/downgrade_right.c [new file with mode: 0644]
dmapi/src/suite1/cmd/fd_to_handle.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_allocinfo.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_config_events.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_dirattrs.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_dmattr.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_eventlist.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_events.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_fileattr.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_mountinfo.c [new file with mode: 0644]
dmapi/src/suite1/cmd/get_region.c [new file with mode: 0644]
dmapi/src/suite1/cmd/getall_disp.c [new file with mode: 0644]
dmapi/src/suite1/cmd/getall_dmattr.c [new file with mode: 0644]
dmapi/src/suite1/cmd/handle_to_fshandle.c [new file with mode: 0644]
dmapi/src/suite1/cmd/handle_to_path.c [new file with mode: 0644]
dmapi/src/suite1/cmd/init_service.c [new file with mode: 0644]
dmapi/src/suite1/cmd/link_test.c [new file with mode: 0644]
dmapi/src/suite1/cmd/make_rt_sparse.c [new file with mode: 0644]
dmapi/src/suite1/cmd/make_sparse.c [new file with mode: 0644]
dmapi/src/suite1/cmd/obj_ref_hold.c [new file with mode: 0644]
dmapi/src/suite1/cmd/obj_ref_query.c [new file with mode: 0644]
dmapi/src/suite1/cmd/obj_ref_rele.c [new file with mode: 0644]
dmapi/src/suite1/cmd/path_to_fshandle.c [new file with mode: 0644]
dmapi/src/suite1/cmd/path_to_handle.c [new file with mode: 0644]
dmapi/src/suite1/cmd/pending.c [new file with mode: 0644]
dmapi/src/suite1/cmd/print_event.c [new file with mode: 0644]
dmapi/src/suite1/cmd/print_fshandle.c [new file with mode: 0644]
dmapi/src/suite1/cmd/probe_hole.c [new file with mode: 0644]
dmapi/src/suite1/cmd/punch_hole.c [new file with mode: 0644]
dmapi/src/suite1/cmd/query_right.c [new file with mode: 0644]
dmapi/src/suite1/cmd/randomize_file.c [new file with mode: 0644]
dmapi/src/suite1/cmd/release_right.c [new file with mode: 0644]
dmapi/src/suite1/cmd/remove_dmattr.c [new file with mode: 0644]
dmapi/src/suite1/cmd/request_right.c [new file with mode: 0644]
dmapi/src/suite1/cmd/respond_event.c [new file with mode: 0644]
dmapi/src/suite1/cmd/rwt.c [new file with mode: 0644]
dmapi/src/suite1/cmd/security_hole.c [new file with mode: 0644]
dmapi/src/suite1/cmd/security_hole2.c [new file with mode: 0644]
dmapi/src/suite1/cmd/set_disp.c [new file with mode: 0644]
dmapi/src/suite1/cmd/set_dmattr.c [new file with mode: 0644]
dmapi/src/suite1/cmd/set_eventlist.c [new file with mode: 0644]
dmapi/src/suite1/cmd/set_fileattr.c [new file with mode: 0644]
dmapi/src/suite1/cmd/struct_test.c [new file with mode: 0644]
dmapi/src/suite1/cmd/sync_by_handle.c [new file with mode: 0644]
dmapi/src/suite1/cmd/test_assumption.c [new file with mode: 0644]
dmapi/src/suite1/cmd/upgrade_right.c [new file with mode: 0644]
dmapi/src/suite1/function_coverage [new file with mode: 0644]
dmapi/src/suite2/DMAPI_aliases [new file with mode: 0644]
dmapi/src/suite2/README [new file with mode: 0644]
dmapi/src/suite2/README_for_check_dmapi [new file with mode: 0644]
dmapi/src/suite2/bindir/crttf [new file with mode: 0755]
dmapi/src/suite2/bindir/ctf [new file with mode: 0755]
dmapi/src/suite2/bindir/make_holey [new file with mode: 0755]
dmapi/src/suite2/bindir/run_test [new file with mode: 0755]
dmapi/src/suite2/bindir/stf [new file with mode: 0755]
dmapi/src/suite2/bindir/test_allocinfo_1 [new file with mode: 0755]
dmapi/src/suite2/bindir/test_allocinfo_2 [new file with mode: 0755]
dmapi/src/suite2/create_cpio [new file with mode: 0644]
dmapi/src/suite2/data/fail.dat [new file with mode: 0644]
dmapi/src/suite2/data/main.dat [new file with mode: 0644]
dmapi/src/suite2/data/nfs.dat [new file with mode: 0644]
dmapi/src/suite2/data/pending.dat [new file with mode: 0644]
dmapi/src/suite2/data/pending_nfs.dat [new file with mode: 0644]
dmapi/src/suite2/data/realtime.dat [new file with mode: 0644]
dmapi/src/suite2/data/smallq.dat [new file with mode: 0644]
dmapi/src/suite2/data/standard.dat [new file with mode: 0644]
dmapi/src/suite2/data/standard_nfs.dat [new file with mode: 0644]
dmapi/src/suite2/dist/README [new file with mode: 0644]
dmapi/src/suite2/lib/errtest.h [new file with mode: 0644]
dmapi/src/suite2/menu_test [new file with mode: 0755]
dmapi/src/suite2/src/check_dmapi.c [new file with mode: 0644]
dmapi/src/suite2/src/dm_test_daemon.c [new file with mode: 0644]
dmapi/src/suite2/src/dump_allocinfo.c [new file with mode: 0644]
dmapi/src/suite2/src/invis_test.c [new file with mode: 0644]
dmapi/src/suite2/src/mm_fill.c [new file with mode: 0644]
dmapi/src/suite2/src/mmap.c [new file with mode: 0644]
dmapi/src/suite2/src/mmap_cp.c [new file with mode: 0644]
dmapi/src/suite2/src/region_test.c [new file with mode: 0644]
dmapi/src/suite2/src/send_msg.c [new file with mode: 0644]
dmapi/src/suite2/src/test_dmattr.c [new file with mode: 0644]
dmapi/src/suite2/src/test_efault.c [new file with mode: 0644]
dmapi/src/suite2/src/test_eventlist.c [new file with mode: 0644]
dmapi/src/suite2/src/test_fileattr.c [new file with mode: 0644]
dmapi/src/suite2/src/test_hole.c [new file with mode: 0644]
dmapi/src/suite2/src/test_invis.c [new file with mode: 0644]
dmapi/src/suite2/src/test_region.c [new file with mode: 0644]
dmapi/src/suite2/src/test_rights.c [new file with mode: 0644]

diff --git a/dmapi/README b/dmapi/README
new file mode 100644 (file)
index 0000000..af77060
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+
+The tests in this directory are a collection of suites that were developed
+over the time the DMAPI spec was being created and when DMAPI was being
+implemented on Irix.  In many cases, each suite was built on an earlier suite.
+Many of these tests have been ported to work with XFS/DMAPI on linux 2.4; many
+are untouched from their Irix versions.
diff --git a/dmapi/src/common/cmd/read_invis.c b/dmapi/src/common/cmd/read_invis.c
new file mode 100644 (file)
index 0000000..ea01855
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <ctype.h>
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#include <malloc.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_read_invis().  The
+command line is:
+
+       read_invis [-o offset] [-l length] [-s sid] pathname
+
+where:
+'offset' is the offset of the start of the write (0 is the default),
+'length' is the length of the write in bytes (1 is the default),
+'sid' is the session ID whose events you you are interested in.
+'pathname' is the name of the file to be written.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-o offset] [-l length] "
+               "[-s sid] pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname = NULL;
+       dm_off_t        offset = 0;
+       dm_size_t       length = 1;
+       char            *bufp = NULL;
+       void            *hanp;
+       size_t          hlen;
+       dm_ssize_t      rc;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "o:l:s:")) != EOF) {
+               switch (opt) {
+               case 'o':
+                       offset = atol(optarg);
+                       break;
+               case 'l':
+                       length = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       if (length > 0) {
+               /* In case it is a realtime file, align the buffer on a
+                  sufficiently big boundary.
+               */
+               if ((bufp = memalign(4096, length)) == NULL) {
+                       fprintf(stderr, "malloc of %d bytes failed\n", length);
+                       exit(1);
+               }
+               memset(bufp, '\0', length);
+       }
+
+       rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, offset, length, bufp);
+
+       if (rc < 0) {
+               fprintf(stderr, "dm_read_invis failed, %s\n", strerror(errno));
+               exit(1);
+       } else if (rc != length) {
+               fprintf(stderr, "expected to read %lld bytes, actually "
+                       "read %lld\n", length, rc);
+               exit(1);
+       }
+       for (i = 0; i < rc; i++) {
+               if (isprint(bufp[i])) {
+                       fprintf(stdout, "%c", bufp[i]);
+               } else {
+                       fprintf(stdout, "\\%03d", bufp[i]);
+               }
+       }
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/common/cmd/set_region.c b/dmapi/src/common/cmd/set_region.c
new file mode 100644 (file)
index 0000000..c4ed4ae
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_set_region().  The
+command line is:
+
+       set_region [-n nelem] [-o offset] [-l length] [-s sid] pathname [event...]
+
+where pathname is the name of a file, nelem is the number of regions to pass
+in the call, offset is the offset of the start of
+the managed region, and length is the length.  sid is the session ID whose
+events you you are interested in, and event is zero or more managed region
+events to set.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static struct  {
+       char    *name;
+       int     value;
+} rg_events[3] = {
+       { "DM_REGION_READ", DM_REGION_READ },
+       { "DM_REGION_WRITE", DM_REGION_WRITE },
+       { "DM_REGION_TRUNCATE", DM_REGION_TRUNCATE }
+};
+static int     nevents = sizeof(rg_events)/sizeof(rg_events[0]);
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-n nelem] [-o offset] [-l length] "
+               "[-s sid] pathname [event...]\n", Progname);
+       fprintf(stderr, "possible events are:\n");
+       for (i = 0; i < nevents; i++)
+               fprintf(stderr, "%s (0x%x)\n", rg_events[i].name, rg_events[i].value);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_region_t     region = { 0, 0, 0 };
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname = NULL;
+       u_int           exactflag;
+       u_int           nelem = 1;
+       void            *hanp;
+       size_t           hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "n:o:l:s:")) != EOF) {
+               switch (opt) {
+               case 'n':
+                       nelem = atol(optarg);
+                       break;
+               case 'o':
+                       region.rg_offset = atol(optarg);
+                       break;
+               case 'l':
+                       region.rg_size = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 > argc)
+               usage();
+       pathname = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       for (; optind < argc; optind++) {
+               if (strspn(argv[optind], "0123456789") == strlen(argv[optind])){
+                       region.rg_flags |= atol(argv[optind]);
+                       continue;
+               }
+               for (i = 0; i < nevents; i++) {
+                       if (!strcmp(argv[optind], rg_events[i].name))
+                               break;
+               }
+               if (i == nevents) {
+                       fprintf(stderr, "invalid event %s\n", argv[optind]);
+                       exit(1);
+               }
+               region.rg_flags |= rg_events[i].value;
+       }
+
+       if (dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, nelem, &region,
+           &exactflag)) {
+               fprintf(stderr, "dm_set_region failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       fprintf(stdout, "exactflag is %s\n",
+               exactflag == DM_TRUE ? "True" : "False");
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/common/cmd/set_return_on_destroy.c b/dmapi/src/common/cmd/set_return_on_destroy.c
new file mode 100644 (file)
index 0000000..b670d9b
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_set_return_on_destroy().  The
+command line is:
+
+       set_return_on_destroy [-s sid] pathname [attr]
+
+where pathname is the name of a file which resides in the filesystem of
+interest.  attr is the name of the DMAPI attribute; if none is specified,
+then set-return-on-destroy will be disabled for the filesystem.
+sid is the session ID whose attribute you are interested in setting.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-s sid] pathname [attr]\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname;
+       dm_attrname_t   *attrnamep = NULL;
+       dm_boolean_t    enable = DM_FALSE;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "s:")) != EOF) {
+               switch (opt) {
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind == argc || optind + 2 < argc)
+               usage();
+       pathname = argv[optind++];
+       if (optind < argc) {
+               enable = DM_TRUE;
+               attrnamep = (dm_attrname_t *)argv[optind++];
+       }
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_fshandle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get filesystem handle for file %s, %s\n",
+                       pathname, strerror(errno));
+               exit(1);
+       }
+
+       if (dm_set_return_on_destroy(sid, hanp, hlen, DM_NO_TOKEN,
+           attrnamep, enable)) {
+               fprintf(stderr, "dm_set_return_on_destroy failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/common/cmd/write_invis.c b/dmapi/src/common/cmd/write_invis.c
new file mode 100644 (file)
index 0000000..0dcbd30
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#include <malloc.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_write_invis().  The
+command line is:
+
+       write_invis [-c char] [-o offset] [-l length] [-s sid] pathname
+
+where:
+'char' is the character to use as a repeated pattern ('X' is the default),
+'offset' is the offset of the start of the write (0 is the default),
+'length' is the length of the write in bytes (1 is the default),
+'sid' is the session ID whose events you you are interested in.
+'pathname' is the name of the file to be written.
+
+DM_WRITE_SYNC is is not supported.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-c char] [-o offset] [-l length] "
+               "[-s sid] pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname = NULL;
+       dm_off_t        offset = 0;
+       dm_size_t       length = 1;
+       u_char          ch = 'X';
+       void            *bufp = NULL;
+       void            *hanp;
+       size_t          hlen;
+       dm_ssize_t      rc;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "c:o:l:s:")) != EOF) {
+               switch (opt) {
+               case 'c':
+                       ch = *optarg;
+                       break;
+               case 'o':
+                       offset = atol(optarg);
+                       break;
+               case 'l':
+                       length = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       if (length > 0) {
+               /* In case it is a realtime file, align the buffer on a
+                  sufficiently big boundary.
+               */
+               if ((bufp = memalign(4096, length)) == NULL) {
+                       fprintf(stderr, "malloc of %d bytes failed\n", length);
+                       exit(1);
+               }
+               memset(bufp, ch, length);
+       }
+
+       rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, offset, length, bufp);
+
+       if (rc < 0) {
+               fprintf(stderr, "dm_write_invis failed, %s\n", strerror(errno));
+               exit(1);
+       } else if (rc != length) {
+               fprintf(stderr, "expected to write %lld bytes, actually "
+                       "wrote %lld\n", length, rc);
+               exit(1);
+       }
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/common/lib/dmport.h b/dmapi/src/common/lib/dmport.h
new file mode 100644 (file)
index 0000000..b7722f6
--- /dev/null
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#ifndef        _DMFSAPI_DMPORT_H
+#define        _DMFSAPI_DMPORT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************
+ *                                                                        *
+ * DMF's use of DMAPI is based upon the X/Open document                  *
+ *      Systems Management: Data Storage Managment (XDSM) API             *
+ * dated February 1997.  However, no implementation of DMAPI perfectly   *
+ * matches the spec.  Each implementation has some functions that it     *
+ * didn't implement, non-standard functions that it added, differences   *
+ * in function parameter types, return value types, number and order of          *
+ * parameters, etc.  There are also differences in the formats of some   *
+ * of the DMAPI structures used by those functions.  Finally, there are          *
+ * many scalar values for which DMAPI assigned no particular size.  For          *
+ * example, a dm_fsid_t is 32 bits under Veritas and 64 bits under SGI.   *
+ *                                                                       *
+ * To hide the differences as much as possible, this include file tries          *
+ * to shoehorn each DMAPI implementation into the XDSM mold as much as   *
+ * possible.  Functions which are not compatible with the XDSM spec are   *
+ * redefined using wrapper routines to make them conform to the spec.    *
+ * Functions which were not implemented have stubs defined which return   *
+ * ENOSYS (see file stubs.c for all wrappers and stubs).  In dmport.h,   *
+ * missing structures and scalers are defined, incompatible typedefs are  *
+ * redefined, etc.                                                       *
+ *                                                                       *
+ * The goal is to reduce as much as possible the number of #ifdefs that   *
+ * have to be added to DMF to handle specific DMAPI implementations.      *
+ * Some #ifdefs may still be required because of semantic differences     *
+ * between the XDSM spec definition and the actual implementation.       *
+ *                                                                       *
+ * Following all the implementation-specific definitions, dmport.h       *
+ * includes a complete set of prototypes for all functions that are part  *
+ * of  the XDSM specification.  This is done as a double-check.  Should   *
+ * any of the actual implementations change, the compiler should tip us   *
+ * off by complaining about imcompatible function redefinitions.         *
+ *                                                                        *
+ **************************************************************************/
+
+
+/* ---------------- Veritas-specific hack documentation -----------------
+
+The following functions have no prototypes in the Veritas include file
+<sys/dmapi/dmapi.h>.  They do not link either.
+
+extern int dm_handle_is_valid(void *, size_t);
+
+
+The following functions have prototypes in <sys/dmapi/dmapi.h>, but
+they do not link.
+
+extern int dm_getall_disp(dm_sessid_t, size_t, void *, size_t *);
+extern int dm_getall_dmattr(dm_sessid_t, void *, size_t, 
+               dm_token_t, size_t, void *, size_t *);
+
+
+The following functions have no prototypes in <sys/dmapi/dmapi.h> but do link.
+
+extern int dm_obj_ref_hold(dm_sessid_t, dm_token_t, void *, size_t);
+extern int dm_obj_ref_rele(dm_sessid_t, dm_token_t, void *, size_t);
+extern int dm_obj_ref_query(dm_sessid_t, dm_token_t, void *, size_t);
+
+
+The following Veritas prototypes are different in some way from the
+spec prototypes, either in parameter types, return value types, or in
+some semantic way.  Look below to see the spec versions of the prototypes.
+
+extern int dm_downgrade_right(dm_sessid_t, void *, size_t, 
+               dm_token_t, int, dm_right_t);
+extern int dm_get_config_events(void *, size_t, u_int,
+               dm_eventset_t *, u_int *);
+extern int dm_get_events(dm_sessid_t, u_int, int, size_t, void *, size_t *);
+extern int dm_get_mountinfo(dm_sessid_t, dm_token_t, void *, size_t, 
+               size_t, void *, size_t *);
+extern int dm_init_service(void);
+extern int dm_make_handle(dev_t , long, long, void **, size_t *);
+extern int dm_make_fshandle(dev_t , void **, size_t *);
+extern dev_t dm_handle_to_dev(void *, size_t);
+extern long dm_handle_to_fgen(void *, size_t);
+extern long dm_handle_to_ino(void *, size_t);
+extern int dm_pending(dm_sessid_t, void *, size_t, dm_token_t, int);
+extern dm_ssize_t dm_read_invis(dm_sessid_t, void *, size_t,
+               dm_token_t, dm_off_t, dm_ssize_t, void *);
+extern dm_ssize_t dm_write_invis(dm_sessid_t, void *, size_t,
+               dm_token_t, dm_off_t, dm_ssize_t, void *, int);
+extern int dm_request_right(dm_sessid_t, void *, size_t, 
+               dm_token_t, int, dm_right_t);
+extern int dm_set_inherit(dm_sessid_t, void *, size_t,
+               dm_token_t, dm_attrname_t *, u_int);
+extern int dm_set_return_ondestroy(dm_sessid_t, void *, size_t,
+               dm_token_t,  dm_attrname_t *, int);
+extern int dm_upgrade_right(dm_sessid_t, void *, size_t, 
+               dm_token_t, int, dm_right_t);
+extern int dm_set_region(dm_sessid_t, void *, size_t,
+               dm_token_t, u_int, dm_region_t *, u_int *);
+extern dm_ssize_t dm_sync_by_handle(dm_sessid_t, void *, size_t, dm_token_t);
+
+
+The following Veritas prototype exists in <sys/dmapi/dmapi.h> but
+does not appear in the spec.
+
+extern void dm_attach_event(dm_sessid_t, dm_token_t);
+
+The following functions exist in the Veritas library libdmi.a, but have no
+prototypes within <sys/dmapi/dmapi.h>.  Their function is unknown.
+
+dm_attach_event_nofork
+dm_event_query
+dm_event_valid
+dm_get_disp
+dm_set_resident
+dmregion_compare
+kdm_get_eventinfo
+kdm_get_sessioninfo
+
+-------------- end of Veritas-specific hack documentation --------------- */
+
+#ifdef VERITAS_21
+
+#include <sys/types.h>
+
+#include <sys/dmapi/dmapi.h>
+
+/* Rename functions whose prototypes clash with the XDSM standard.  (Library
+   routines map from XDSM functions back to Veritas functions.)
+*/
+
+#define        dm_downgrade_right      xvfs_dm_downgrade_right
+#define dm_fd_to_handle                xvfs_dm_fd_to_handle
+#define        dm_get_events           xvfs_dm_get_events
+#define        dm_get_mountinfo        xvfs_dm_get_mountinfo
+#define        dm_handle_to_ino        xvfs_dm_handle_to_ino
+#define        dm_init_service         xvfs_dm_init_service
+#define        dm_make_fshandle        xvfs_dm_make_fshandle
+#define        dm_make_handle          xvfs_dm_make_handle
+#define dm_path_to_fshandle    xvfs_dm_path_to_fshandle
+#define dm_path_to_handle      xvfs_dm_path_to_handle
+#define        dm_pending              xvfs_dm_pending
+#define        dm_read_invis           xvfs_dm_read_invis
+#define        dm_write_invis          xvfs_dm_write_invis
+#define        dm_request_right        xvfs_dm_request_right
+#define        dm_set_inherit          xvfs_dm_set_inherit
+#define        dm_set_region           xvfs_dm_set_region
+#define        dm_sync_by_handle       xvfs_dm_sync_by_handle
+#define        dm_upgrade_right        xvfs_dm_upgrade_right
+
+
+#define        DM_ATTR_NAME_SIZE       8
+#undef DM_ATTRNAME_SIZE
+#define        DM_VER_STR_CONTENTS     "Veritas DMAPI V1.0"
+
+#define        DM_EV_WAIT      0x1
+#define        DM_RR_WAIT      0x1
+#undef DM_WAIT
+#undef DM_NOWAIT
+#undef DM_EVENT_NOWAIT
+
+#define        DM_CONFIG_INHERIT_ATTRIBS       (DM_CONFIG_LOCK_UPGRADE + 1)
+#undef DM_CONFIG_INHERIT
+#define        DM_CONFIG_MAX_HANDLE_SIZE       (DM_CONFIG_INHERIT_ATTRIBS + 1)
+#undef DM_CONFIG_MAX_FILE_HANDLE_SIZE
+#define        DM_CONFIG_MAX_ATTR_ON_DESTROY   (DM_CONFIG_MAX_HANDLE_SIZE + 1)
+#undef DM_CONFIG_MAX_ATTR_BYTES_ON_DESTROY
+#define        DM_CONFIG_OBJ_REF               (DM_CONFIG_MAX_ATTR_ON_DESTROY + 1)
+#define        DM_CONFIG_DTIME_OVERLOAD        (DM_CONFIG_OBJ_REF + 1)
+#undef DM_CONFIG_MAX
+
+#define        DM_AT_DTIME     DM_AT_DTIMES
+
+/* In the dm_fileattr_t structure, Veritas used 'timeval' structures for all
+   the time fields while XDSM uses 'time_t' structures.  Define some symbols
+   that can be used for the time fields with all implementation types.
+*/
+
+#define FA_ATIME       fa_atime.tv_sec
+#define FA_MTIME       fa_atime.tv_sec
+#define FA_CTIME       fa_ctime.tv_sec
+#define FA_DTIME       fa_dtime.tv_sec
+
+#define        DM_WRITE_SYNC   0x1     /* used in dm_write_invis() */
+
+#define        DM_UNMOUNT_FORCE 0x1    /* ne_mode field in dm_namesp_event_t */
+
+/* Rename one event to match the XDSM standard. */
+
+#define        DM_EVENT_CLOSE          (DM_EVENT_DESTROY + 1)
+#undef DM_EVENT_CLOSED
+
+/* DM_EVENT_CANCEL is defined above DM_EVENT_MAX, and is unsupported. */
+
+#undef DM_REGION_VALIDFLAG
+
+/* Add missing typedefs */
+
+typedef        u_int   dm_boolean_t;
+typedef        dev_t   dm_fsid_t;      /* This could be made a uint64_t with work! */
+typedef        long    dm_igen_t;
+typedef        long    dm_ino_t;
+typedef        u_int   dm_sequence_t;
+
+
+/* Define missing fields within the various event structures. */
+
+#define ev_sequence     ev_token       /* for compilation only!  Won't work! */
+
+#define        ds_handle       te_handle       /* fix fields in dm_destroy_event_t */
+#define        ds_attrname     te_attrname
+#define        ds_attrcopy     te_attrdata
+
+
+struct dm_cancel_event {               /* define missing dm_cancel_event_t */
+       dm_sequence_t   ce_sequence;
+       dm_token_t      ce_token;
+};
+typedef        struct dm_cancel_event  dm_cancel_event_t;
+
+
+struct dm_mount_event {                /* define missing dm_mount_event_t */
+       mode_t          me_mode;
+       dm_vardata_t    me_handle1;
+       dm_vardata_t    me_handle2;
+       dm_vardata_t    me_name1;
+       dm_vardata_t    me_name2;
+       dm_vardata_t    me_roothandle;
+};
+typedef        struct dm_mount_event   dm_mount_event_t;
+
+
+/* Add the missing dm_timestruct_t structure used by dm_pending. */
+
+struct dm_timestruct {
+       time_t          dm_tv_sec;
+       int             dm_tv_nsec;
+};
+typedef        struct dm_timestruct dm_timestruct_t;
+
+#endif
+
+
+
+/* -------------------- SGI-specific hack documentation -------------------
+
+   There are various fields within DMAPI structures that are not supported.
+   Fill in this information someday.
+
+   The following functions have prototypes defined in <sys/dmi.h> and have
+   entry points defined in libdm.so, but they are not actually implemented
+   within the kernel.  They all return ENOSYS if called.
+
+       dm_clear_inherit
+       dm_create_by_handle
+       dm_get_bulkall
+       dm_getall_inherit
+       dm_mkdir_by_handle
+       dm_set_inherit
+       dm_symlink_by_handle
+
+   The DMAPI functions which deal with rights do not work as described in
+   the specification.  While the functions exist and are callable, they
+   always return successfully without actually obtaining any locks within
+   the filesystem.                        
+
+       dm_downgrade_right
+       dm_query_right
+       dm_release_right
+       dm_request_right
+       dm_upgrade_right
+
+   The following non-standard SGI prototype is added to the DMAPI interface
+   so that real-time files may be migrated and recalled.
+
+       dm_get_dioinfo
+
+-------------- end of SGI-specific hack documentation --------------- */
+
+#ifdef __sgi
+
+#include <sys/dmi.h>
+
+/* In the dm_fileattr_t structure, Veritas used 'timeval' structures for all
+   the time fields while XDSM uses 'time_t' structures.  Define some symbols
+   that can be used for the time fields with all implementation types.
+*/
+
+#define FA_ATIME       fa_atime
+#define FA_MTIME       fa_mtime
+#define FA_CTIME       fa_ctime
+#define FA_DTIME       fa_dtime
+
+#endif /* __sgi */
+
+#ifdef linux
+
+#include <linux/dmapi.h>
+
+/* In the dm_fileattr_t structure, Veritas used 'timeval' structures for all
+   the time fields while XDSM uses 'time_t' structures.  Define some symbols
+   that can be used for the time fields with all implementation types.
+*/
+
+#define FA_ATIME       fa_atime
+#define FA_MTIME       fa_mtime
+#define FA_CTIME       fa_ctime
+#define FA_DTIME       fa_dtime
+
+#endif /* linux */
+
+/* ----------------------- XDSM standard prototypes ----------------------- */
+
+/* The following list provides the prototypes for all functions defined in
+   the DMAPI interface spec from X/Open (XDSM) dated February 1997.  They
+   are here to force compiler errors in case the Veritas or SGI DMAPI
+   prototypes should ever change without our knowing about it.
+*/
+
+extern int
+dm_clear_inherit(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrname_t   *attrnamep);
+
+extern int
+dm_create_by_handle(
+       dm_sessid_t     sid,
+       void            *dirhanp,
+       size_t          dirhlen,
+       dm_token_t      token,
+       void            *hanp,
+       size_t          hlen,
+       char            *cname);
+
+extern int
+dm_create_session(
+       dm_sessid_t     oldsid,
+       char            *sessinfop,
+       dm_sessid_t     *newsidp);
+
+extern int
+dm_create_userevent(
+       dm_sessid_t     sid,
+       size_t          msglen,
+       void            *msgdatap,
+       dm_token_t      *tokenp);
+
+extern int
+dm_destroy_session(
+       dm_sessid_t     sid);
+
+extern int
+dm_downgrade_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token);
+
+extern int
+dm_fd_to_handle(
+       int             fd,
+       void            **hanpp,
+       size_t          *hlenp);
+
+extern int
+dm_find_eventmsg(
+       dm_sessid_t     sid,
+       dm_token_t      token,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_get_allocinfo(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_off_t        *offp,
+       u_int           nelem,
+       dm_extent_t     *extentp,
+       u_int           *nelemp);
+
+extern int
+dm_get_bulkall(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           mask,
+       dm_attrname_t   *attrnamep,
+       dm_attrloc_t    *locp,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_get_bulkattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           mask,
+       dm_attrloc_t    *locp,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_get_config(
+       void            *hanp,
+       size_t          hlen,
+       dm_config_t     flagname,
+       dm_size_t       *retvalp);
+
+extern int
+dm_get_config_events(
+       void            *hanp,
+       size_t          hlen,
+       u_int           nelem,
+       dm_eventset_t   *eventsetp,
+       u_int           *nelemp);
+
+extern int
+dm_get_dirattrs(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           mask,
+       dm_attrloc_t    *locp,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_get_dmattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrname_t   *attrnamep,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_get_eventlist(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           nelem,
+       dm_eventset_t   *eventsetp,
+       u_int           *nelemp);
+
+extern int
+dm_get_events(
+       dm_sessid_t     sid,
+       u_int           maxmsgs,
+       u_int           flags,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_get_fileattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           mask,
+       dm_stat_t       *statp);
+
+extern int
+dm_get_mountinfo(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_get_region(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           nelem,
+       dm_region_t     *regbufp,
+       u_int           *nelemp);
+
+extern int
+dm_getall_disp(
+       dm_sessid_t     sid,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_getall_dmattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern int
+dm_getall_inherit(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           nelem,
+       dm_inherit_t    *inheritbufp,
+       u_int           *nelemp);
+
+extern int
+dm_getall_sessions(
+       u_int           nelem,
+       dm_sessid_t     *sidbufp,
+       u_int           *nelemp);
+
+extern int
+dm_getall_tokens(
+       dm_sessid_t     sid,
+       u_int           nelem,
+       dm_token_t      *tokenbufp,
+       u_int           *nelemp);
+
+extern int
+dm_handle_cmp(
+       void            *hanp1,
+       size_t          hlen1,
+       void            *hanp2,
+       size_t          hlen2);
+
+extern void
+dm_handle_free(
+       void            *hanp,
+       size_t          hlen);
+
+extern u_int
+dm_handle_hash(
+       void            *hanp,
+       size_t          hlen);
+
+extern dm_boolean_t
+dm_handle_is_valid(
+       void            *hanp,
+       size_t          hlen);
+
+extern int
+dm_handle_to_fshandle(
+       void            *hanp,
+       size_t          hlen,
+       void            **fshanpp,
+       size_t          *fshlenp);
+
+extern int
+dm_handle_to_fsid(
+       void            *hanp,
+       size_t          hlen,
+       dm_fsid_t       *fsidp);
+
+extern int
+dm_handle_to_igen(
+       void            *hanp,
+       size_t          hlen,
+       dm_igen_t       *igenp);
+
+extern int
+dm_handle_to_ino(
+       void            *hanp,
+       size_t          hlen,
+       dm_ino_t        *inop);
+
+extern int
+dm_handle_to_path(
+       void            *dirhanp,
+       size_t          dirhlen,
+       void            *targhanp,
+       size_t          targhlen,
+       size_t          buflen,
+       char            *pathbufp,
+       size_t          *rlenp);
+
+extern int
+dm_init_attrloc(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrloc_t    *locp);
+
+extern int
+dm_init_service(
+       char            **versionstrpp);
+
+extern int
+dm_make_fshandle(
+       dm_fsid_t       *fsidp,
+       void            **hanpp,
+       size_t          *hlenp);
+
+extern int
+dm_make_handle(
+       dm_fsid_t       *fsidp,
+       dm_ino_t        *inop,
+       dm_igen_t       *igenp,
+       void            **hanpp,
+       size_t          *hlenp);
+
+extern int
+dm_mkdir_by_handle(
+       dm_sessid_t     sid,
+       void            *dirhanp,
+       size_t          dirhlen,
+       dm_token_t      token,
+       void            *hanp,
+       size_t          hlen,
+       char            *cname);
+
+extern int
+dm_move_event(
+       dm_sessid_t     srcsid,
+       dm_token_t      token,
+       dm_sessid_t     targetsid,
+       dm_token_t      *rtokenp);
+
+extern int
+dm_obj_ref_hold(
+       dm_sessid_t     sid,
+       dm_token_t      token,
+       void            *hanp,
+       size_t          hlen);
+
+extern int
+dm_obj_ref_query(
+       dm_sessid_t     sid,
+       dm_token_t      token,
+       void            *hanp,
+       size_t          hlen);
+
+extern int
+dm_obj_ref_rele(
+       dm_sessid_t     sid,
+       dm_token_t      token,
+       void            *hanp,
+       size_t          hlen);
+
+extern int
+dm_path_to_fshandle(
+       char            *path,
+       void            **hanpp,
+       size_t          *hlenp);
+
+extern int
+dm_path_to_handle(
+       char            *path,
+       void            **hanpp,
+       size_t          *hlenp);
+
+extern int
+dm_pending(
+       dm_sessid_t     sid,
+       dm_token_t      token,
+       dm_timestruct_t *delay);
+
+extern int
+dm_probe_hole(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_off_t        off,
+       dm_size_t       len,
+       dm_off_t        *roffp,
+       dm_size_t       *rlenp);
+
+extern int
+dm_punch_hole(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_off_t        off,
+       dm_size_t       len);
+
+extern int
+dm_query_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_right_t      *rightp);
+
+extern int
+dm_query_session(
+       dm_sessid_t     sid,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp);
+
+extern dm_ssize_t
+dm_read_invis(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_off_t        off,
+       dm_size_t       len,
+       void            *bufp);
+
+extern int
+dm_release_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token);
+
+extern int
+dm_remove_dmattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       int             setdtime,
+       dm_attrname_t   *attrnamep);
+
+extern int
+dm_request_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           flags,
+       dm_right_t      right);
+
+extern int
+dm_respond_event(
+       dm_sessid_t     sid,
+       dm_token_t      token,
+       dm_response_t   response,
+       int             reterror,
+       size_t          buflen,
+       void            *respbufp);
+
+extern int
+dm_send_msg(
+       dm_sessid_t     targetsid,
+       dm_msgtype_t    msgtype,
+       size_t          buflen,
+       void            *bufp);
+
+extern int
+dm_set_disp(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_eventset_t   *eventsetp,
+       u_int           maxevent);
+
+extern int
+dm_set_dmattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrname_t   *attrnamep,
+       int             setdtime,
+       size_t          buflen,
+       void            *bufp);
+
+extern int
+dm_set_eventlist(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_eventset_t   *eventsetp,
+       u_int           maxevent);
+
+extern int
+dm_set_fileattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           mask,
+       dm_fileattr_t   *attrp);
+
+extern int
+dm_set_inherit(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrname_t   *attrnamep,
+       mode_t          mode);
+
+extern int
+dm_set_region(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           nelem,
+       dm_region_t     *regbufp,
+       dm_boolean_t    *exactflagp);
+
+extern int
+dm_set_return_on_destroy(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrname_t   *attrnamep,
+       dm_boolean_t    enable);
+
+extern int
+dm_symlink_by_handle(
+       dm_sessid_t     sid,
+       void            *dirhanp,
+       size_t          dirhlen,
+       dm_token_t      token,
+       void            *hanp,
+       size_t          hlen,
+       char            *cname,
+       char            *path);
+
+extern int
+dm_sync_by_handle(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token);
+
+extern int
+dm_upgrade_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token);
+
+extern dm_ssize_t
+dm_write_invis(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       int             flags,
+       dm_off_t        off,
+       dm_size_t       len,
+       void            *bufp);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DMFSAPI_DMPORT_H */
diff --git a/dmapi/src/common/lib/find_session.c b/dmapi/src/common/lib/find_session.c
new file mode 100644 (file)
index 0000000..2e3d6e1
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+
+/*******************************************************************************
+*
+* NAME
+*      find_test_session - find or create a test DMAPI session.
+*
+* DESCRIPTION
+*      find_test_session() is used to find a test DMAPI session to
+*      use.  There is only one test session per host; all test processes
+*      share the same session.  If the session does not already exist,
+*      then the first process to call find_test_session() causes
+*      the session to be created.
+*
+*      Note: It is possible for N different programs to call this routine
+*      at the same time.  Each would find that a test session does not
+*      exist, and each one would then create a new test session.  Since
+*      excess test sessions are not automatically released on death of
+*      process, we need to make sure that we don't leave such excess
+*      sessions around.  So, after creating a session we go back and find
+*      the test session with the lowest session number.  If it is ours,
+*      great; we are done.  If not, then we must destroy our session
+*      and use the one with the lower session ID.  There is still a risk
+*      here of creating a session and crashing before it can be removed
+*      again.  To deal with this, the daemon will periodically remove all
+*      test sessions except for the one with the lowest ID value.
+*
+* RETURN VALUE
+*      None.
+*
+*******************************************************************************/
+
+#define        TEST_MSG        "DMAPI test session"
+
+static int
+session_compare(
+const  void    *a,
+const  void    *b)
+{
+       return(*((dm_sessid_t *)a) - *((dm_sessid_t *)b));
+}
+
+extern void
+find_test_session(
+       dm_sessid_t     *session)
+{
+       char            buffer[DM_SESSION_INFO_LEN];
+       dm_sessid_t     *sidbuf = NULL;
+       dm_sessid_t     new_session;
+       u_int           allocelem = 0;
+       u_int           nelem;
+       size_t          rlen;
+       int             error;
+       int             rc;
+       u_int           i;
+
+       /* Retrieve the list of all active sessions on the host. */
+
+       nelem = 100;            /* a reasonable first guess */
+       do {
+               if (allocelem < nelem) {
+                       allocelem = nelem;
+                       sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
+                       if (sidbuf == NULL) {
+                               fprintf(stderr, "realloc of %d bytes failed\n",
+                                       nelem * sizeof(*sidbuf));
+                               exit(1);
+                       }
+               }
+               error = dm_getall_sessions(allocelem, sidbuf, &nelem);
+       } while (error < 0 && errno == E2BIG);
+
+       /* If an error occurred, translate it into something meaningful. */
+
+       if (error < 0) {
+               fprintf(stderr, "unexpected dm_getall_sessions failure, %s\n",
+                       strerror(errno));
+               free(sidbuf);
+               exit(1);
+       }
+
+       /* We have the list of all active sessions.  Scan the list looking
+          for an existing "test" session that we can use.  The list must
+          first be sorted in case other processes happen to be creating test
+          sessions at the same time; we need to make sure that we pick the one
+          with the lowest session ID.
+       */
+
+       qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
+
+       for (i = 0; i < nelem; i++) {
+               error = dm_query_session(sidbuf[i], sizeof(buffer),
+                               buffer, &rlen);
+               if (error < 0) {
+                       fprintf(stderr, "unexpected dm_query_session "
+                               "failure, %s\n", strerror(errno));
+                       free(sidbuf);
+                       exit(1);
+               }
+
+               if (!strncmp(buffer, TEST_MSG, strlen(TEST_MSG)))
+                       break;
+       }
+       if (i < nelem) {
+               *session = (dm_sessid_t)sidbuf[i];
+               free(sidbuf);
+               return;
+       }
+
+       /* No test session exists, so we have to create one ourselves. */
+
+       if (dm_create_session(DM_NO_SESSION, TEST_MSG, &new_session) != 0) {
+               fprintf(stderr, "dm_create_session failed, %s\n",
+                       strerror(errno));
+               free(sidbuf);
+               exit(1);
+       }
+
+       /* Now re-retrieve the list of active sessions. */
+
+       do {
+               if (allocelem < nelem) {
+                       allocelem = nelem;
+                       sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
+                       if (sidbuf == NULL) {
+                               fprintf(stderr, "realloc of %d bytes failed\n",
+                                       nelem * sizeof(*sidbuf));
+                               exit(1);
+                       }
+               }
+               error = dm_getall_sessions(allocelem, sidbuf, &nelem);
+       } while (error < 0 && errno == E2BIG);
+
+       if (error < 0) {
+               fprintf(stderr, "dm_getall_sessions failed, %s\n",
+                       strerror(errno));
+               free(sidbuf);
+               exit(1);
+       }
+
+       /* Sort the session ID list into ascending ID order, then find the
+          test session with the lowest session ID.  We better find at
+          least one since we created one!
+       */
+
+       qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
+
+       for (i = 0; i < nelem; i++) {
+               error = dm_query_session(sidbuf[i], sizeof(buffer),
+                               buffer, &rlen);
+               if (error < 0) {
+                       fprintf(stderr, "dm_query_session failed, %s\n",
+                               strerror(errno));
+                       free(sidbuf);
+                       exit(1);
+               }
+               if (!strncmp(buffer, TEST_MSG, strlen(TEST_MSG)))
+                       break;
+       }
+       if (i == nelem) {
+               fprintf(stderr, "can't find the session we created\n");
+               free(sidbuf);
+               exit(1);
+       }
+       *session = (dm_sessid_t)sidbuf[i];
+       free(sidbuf);
+
+       /* If the session we are going to use is not the one we created,
+          then we need to get rid of the created one.
+       */
+
+       if (*session != new_session) {
+               if ((new_session) != 0) {
+                       fprintf(stderr, "dm_destroy_session failed, %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+       }
+}
diff --git a/dmapi/src/common/lib/hsm.h b/dmapi/src/common/lib/hsm.h
new file mode 100644 (file)
index 0000000..e09c1f9
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Defines and structures for our pseudo HSM example
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef        _LIB_HSM_H
+#define        _LIB_HSM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <lib/dmport.h>
+
+#define HANDLE_LEN      64                      /* Swag for this example */
+#define HANDLE_STR      ((HANDLE_LEN * 2) + 1)  /* handle as ascii, plus null */
+#define IBUFSIZE         1024                  /* input buffer size */
+#define CHUNKSIZE      (1024*1024*4)           /* write size */
+#define FENCEPOST_SIZE  ((dm_size_t)(1024*8))
+#define ALL_AVAIL_MSGS 0
+
+/*
+ * Actions to be performed by the worker bees
+ */
+#define RESTORE_FILE   "-r"
+#define INVAL_FILE     "-i"
+
+#define WORKER_BEE     "wbee"
+
+
+/*
+ * Names of DM attribute used for storing location of a file's data.
+ * DM attributes are 8 bytes, including NULL.
+ */
+
+#define DLOC_HAN       "dhanloc"               /* staging file handle */
+#define DLOC_HANLEN    "dhanlen"               /* staging handle length */
+
+/*
+ * Default log file
+ */
+#define LOG_DEFAULT    "/tmp/dmig_log"
+
+struct ev_name_to_value {
+        char            *name;         /* name of event */
+        dm_eventtype_t  value;         /* value of event */
+};
+
+extern struct  ev_name_to_value        ev_names[];
+extern int     ev_namecnt;
+
+
+struct rt_name_to_value {
+        char            *name;         /* name of right */
+        dm_right_t     value;          /* value of right */
+};
+
+extern struct  rt_name_to_value        rt_names[];
+extern int     rt_namecnt;
+
+
+extern void hantoa(void *hanp, size_t hlen, char *handle_str);
+extern int atohan(char *handle_str, void **hanpp, size_t *hlenp);
+extern void print_handle(void *hanp, size_t hlen);
+extern void print_victim(void *hanp, size_t hlen, dm_off_t fsize);
+extern void errno_msg(char *fmt, ...);
+extern void err_msg(char *fmt, ...);
+extern int setup_dmapi(dm_sessid_t *sid);
+extern int get_dmchange(dm_sessid_t sid, void *hanp, size_t hlen,
+        dm_token_t token, u_int *change_start);
+extern int save_filedata(dm_sessid_t sid, void *hanp, size_t hlen,
+        int stg_fd, dm_size_t fsize);
+extern int restore_filedata(dm_sessid_t sid, void *hanp, size_t hlen,
+        dm_token_t token, void *stg_hanp, size_t stg_hlen, dm_off_t off);
+
+extern void find_test_session(dm_sessid_t *session);
+
+void
+print_one_mount_event(
+       void            *msg);
+
+int
+print_one_message(
+       dm_eventmsg_t   *msg);
+
+int
+handle_message(
+       dm_sessid_t     sid,
+       dm_eventmsg_t   *msg);
+
+extern char *date_to_string(
+       time_t          timeval);
+
+extern char *mode_to_string(
+       mode_t          mode);
+
+extern mode_t field_to_mode(
+       mode_t          mode);
+
+extern int validate_state(
+       dm_stat_t       *dmstat,
+       char            *pathname,
+       int             report_errors);
+
+extern char *emask_to_string(
+       dm_eventset_t   emask);
+
+extern char *xflags_to_string(
+       u_int           xflags);
+
+extern void print_state(
+       dm_stat_t       *dmstat);
+
+extern void print_line(
+       dm_stat_t       *dmstat);
+
+extern dm_eventtype_t
+ev_name_to_value(
+       char            *name);
+
+extern char *
+ev_value_to_name(
+       dm_eventtype_t  event);
+
+extern int
+rt_name_to_value(
+       char            *name,
+       dm_right_t      *rightp);
+
+extern char *
+rt_value_to_name(
+       dm_right_t      right);
+
+extern int
+opaque_to_handle(
+       char            *name,
+       void            **hanpp,
+       size_t          *hlenp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIB_HSM_H */
diff --git a/dmapi/src/common/lib/print.c b/dmapi/src/common/lib/print.c
new file mode 100644 (file)
index 0000000..daec180
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#define MAXNAMELEN 256
+#endif
+
+  /*
+   * 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"
+#ifdef __sgi
+#define VALLLD "\t%-15s %lld\n"
+#else
+#define VALLLD "\t%-15s %ld\n"
+#endif
+
+
+/*
+       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.
+*/
+
+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);
+}
+
+
+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[MAXNAMELEN], nams2[MAXNAMELEN];
+       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 %d>", hlen1);
+       }
+       if (hanp2 && hlen2) {
+               hantoa(hanp2, hlen2, hans2);
+       } else {
+               sprintf(hans2, "<BAD HANDLE, hlen %d>", hlen2);
+       }
+       if (hanp3 && hlen3) {
+               hantoa(hanp3, hlen3, hans3);
+       } else {
+               sprintf(hans3, "<BAD HANDLE, hlen %d>", hlen3);
+       }
+       if (namp1 && nlen1) {
+               strncpy(nams1, namp1, nlen1);
+               if (nlen1 != sizeof(nams1))
+                       nams1[nlen1] = '\0';
+       } else {
+               sprintf(nams1, "<BAD STRING, nlen %d>", nlen1);
+       }
+       if (namp2 && nlen2) {
+               strncpy(nams2, namp2, nlen2);
+               if (nlen2 != sizeof(nams2))
+                       nams2[nlen2] = '\0';
+       } else {
+               sprintf(nams2, "<BAD STRING, nlen %d>", 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);
+}
+
+
+static int
+print_one_data_event(
+       dm_data_event_t *msg_de)
+{
+       char            handle[HANDLE_STR];
+       void            *hanp;
+       size_t          hlen;
+
+       hanp  = DM_GET_VALUE(msg_de, de_handle, void *);
+       hlen  = DM_GET_LEN  (msg_de, de_handle);
+
+       if (hanp && hlen) {
+               hantoa(hanp, hlen, handle);
+       } else {
+               sprintf(handle, "<BAD HANDLE, hlen %d>", hlen);
+       }
+
+       printf(VALS VALLLD VALLLD,
+               "file handle",  handle,
+               "offset", msg_de->de_offset,
+               "length", msg_de->de_length);
+
+       return(0);
+}
+
+
+int
+print_one_message(
+       dm_eventmsg_t   *msg)
+{
+       int             pkt_error = 0;
+       int             error;
+       dm_namesp_event_t  *msg_ne;
+       void            *hanp1, *hanp2, *namp1, *namp2;
+       u_int           hlen1, hlen2, nlen1, nlen2;
+       char            hans1[HANDLE_STR], hans2[HANDLE_STR];
+       char            nams1[MAXNAMELEN], nams2[MAXNAMELEN];
+
+       /***** 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>");
+    }
+
+       /***** 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);
+
+       /***** 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 *);
+
+               switch (msg->ev_type) {
+               case DM_EVENT_READ:
+                       printf(HDR, "read", msg->ev_token, msg->ev_sequence);
+                       break;
+
+               case DM_EVENT_WRITE:
+                       printf(HDR, "write", msg->ev_token, msg->ev_sequence);
+                       break;
+
+               case DM_EVENT_TRUNCATE:
+                       printf(HDR, "truncate", msg->ev_token,
+                               msg->ev_sequence);
+                       break;
+               }
+               print_one_data_event(msg_de);
+
+  /***** 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));
+    } 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>");
+    }
+
+  /***** MOUNT EVENT *****/
+
+       } else if (msg->ev_type == DM_EVENT_MOUNT) {
+               void    *msg_body;
+
+               printf(HDR, "mount", msg->ev_token, msg->ev_sequence);
+#if    !VERITAS_21
+               msg_body = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
+#else  /* VERITAS_21 */
+               msg_body = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
+#endif /* VERITAS_21 */
+               print_one_mount_event(msg_body);
+
+  /***** NAMESPACE EVENTS *****/
+
+       } else {
+    char       *type;
+
+    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);
+      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);
+      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);
+      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);
+      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);
+      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);
+      break;
+
+    case DM_EVENT_ATTRIBUTE:
+      printf(HDR VALS,
+            "attribute", msg->ev_token, msg->ev_sequence,
+            "object",          hans1);
+      break;
+
+    case DM_EVENT_CLOSE:       /* not supported on SGI */
+      printf(HDR VALS,
+            "close", msg->ev_token, msg->ev_sequence,
+            "object",          hans1);
+      break;
+
+    default:
+      pkt_error++;
+      printf(HDR VALD,
+            "<UNKNOWN>", msg->ev_token, msg->ev_sequence,
+            "ev_type",         msg->ev_type);
+      break;
+    }
+       }
+       return(pkt_error);
+}
+
+
+int
+handle_message(
+       dm_sessid_t     sid,
+       dm_eventmsg_t   *msg)
+{
+       int             respond, response, respcode;
+       int             error = 0;
+
+       if (print_one_message(msg))
+               error++;
+
+       /* Set the defaults for responding to events. */
+
+       respond = 1;
+       response = DM_RESP_CONTINUE;
+       respcode = 0;
+
+       /***** USER EVENTS *****/
+
+       switch (msg->ev_type) {
+       case DM_EVENT_USER:
+               if (msg->ev_token == DM_INVALID_TOKEN)
+                       respond = 0;
+               break;
+
+       case DM_EVENT_CANCEL:
+       case DM_EVENT_DESTROY:
+       case DM_EVENT_POSTCREATE:
+       case DM_EVENT_POSTREMOVE:
+       case DM_EVENT_POSTRENAME:
+       case DM_EVENT_POSTSYMLINK:
+       case DM_EVENT_POSTLINK:
+       case DM_EVENT_ATTRIBUTE:
+       case DM_EVENT_CLOSE:
+               respond = 0;
+               break;
+
+       case DM_EVENT_MOUNT:
+       case DM_EVENT_READ:
+       case DM_EVENT_WRITE:
+       case DM_EVENT_TRUNCATE:
+       case DM_EVENT_PREUNMOUNT:
+       case DM_EVENT_UNMOUNT:
+       case DM_EVENT_DEBUT:
+       case DM_EVENT_CREATE:
+       case DM_EVENT_REMOVE:
+       case DM_EVENT_RENAME:
+       case DM_EVENT_SYMLINK:
+       case DM_EVENT_LINK:
+               break;
+
+       case DM_EVENT_NOSPACE:
+               response = DM_RESP_ABORT;
+               respcode = ENOSPC;
+               break;
+
+       default:
+               if (msg->ev_token == DM_INVALID_TOKEN)
+                       respond = 0;
+               break;
+       }
+
+       /* Respond to those messages which require a response. */
+
+       if (respond) {
+               if (dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0)) {
+                       errno_msg("Can't respond to event");
+               }
+       }
+       return(error);
+}
diff --git a/dmapi/src/common/lib/stubs.c b/dmapi/src/common/lib/stubs.c
new file mode 100644 (file)
index 0000000..3cfe27c
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <errno.h>
+
+#include <stdlib.h>
+#include <lib/dmport.h>
+
+
+/* See dmport.h for a description of why all these wrapper routines are
+   necessary.  Because SGI defines stub routines for all functions it didn't
+   implement, no SGI-specific wrappers are required.
+*/
+
+
+#ifdef VERITAS_21
+
+/* The Veritas version of dm_downgrade_right has two additional parameters
+   not defined in the XDSM spec.  Provide values that make dm_downgrade_right
+   work according to the spec.
+*/
+
+extern int
+xvfs_dm_downgrade_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token)
+{
+#undef dm_downgrade_right
+       return(dm_downgrade_right(sid, hanp, hlen, token, 0, DM_RIGHT_SHARED));
+}
+
+
+/* The last byte in a Veritas handle is a 'pad' byte which they don't bother
+   to initialize to zero.  As a result, you can't do binary compares of
+   two handles to see if they are the same.  This stub (along with others)
+   forces the pad byte to zero so that binary compares are possible
+*/
+
+extern int
+xvfs_dm_fd_to_handle(
+       int             fd,
+       void            **hanpp,
+       size_t          *hlenp)
+{
+#undef dm_fd_to_handle
+       int             rc;
+
+       if ((rc = dm_fd_to_handle(fd, hanpp, hlenp)) == 0) {
+               if (*hlenp == 16) {
+                       char    *cp = (char *)*hanpp;
+                       cp[15] = '\0';
+               }
+       }
+       return(rc);
+}
+
+
+/* The Veritas version of dm_get_config_events has a slightly different name.
+*/
+
+extern int
+dm_get_config_events(
+       void            *hanp,
+       size_t          hlen,
+       u_int           nelem,
+       dm_eventset_t   *eventsetp,
+       u_int           *nelemp)
+{
+       return(dm_get_config_event(hanp, hlen, nelem, eventsetp, nelemp));
+}
+
+
+/* In version 2.1 uflags was defined as 'int nowait', so a value of zero in
+   this field means that the caller wants to wait.  In XDSM this was reversed,
+   where if the bottom bit of uflags is set then the caller wants to wait.
+   This routine makes the conversion.
+*/
+
+extern int
+xvfs_dm_get_events(
+       dm_sessid_t     sid,
+       u_int           maxmsgs,
+       u_int           uflags,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp)
+{
+#undef dm_get_events
+       int     nowait = 1;
+
+       if (uflags & DM_EV_WAIT)
+               nowait = 0;
+
+       return(dm_get_events(sid, maxmsgs, nowait, buflen, bufp, rlenp));
+}
+
+
+/* The Veritas version of dm_get_mountinfo has the parameters in a different
+   order than in the XDSM spec.  Hide this in the wrapper.
+*/
+
+extern int
+xvfs_dm_get_mountinfo(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp)
+{
+#undef dm_get_mountinfo
+       return(dm_get_mountinfo(sid, token, hanp, hlen, buflen, bufp, rlenp));
+}
+
+
+/* Veritas does not support the dm_getall_disp function.  Furthermore, their
+   dm_dispinfo_t structure is missing the _link field that is needed for the
+   DM_STEP_TO_NEXT() macro to work.
+*/
+
+extern int
+dm_getall_disp(
+       dm_sessid_t     sid,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp)
+{
+       return(ENOSYS);
+}
+
+
+/* Veritas does not support the dm_getall_dmattr function.  Furthermore, their
+   dm_attrlist_t structure is missing the _link field that is needed for the
+   DM_STEP_TO_NEXT() macro to work.
+*/
+
+extern int
+dm_getall_dmattr(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       size_t          buflen,
+       void            *bufp,
+       size_t          *rlenp)
+{
+       return(ENOSYS);
+}
+
+
+/* Veritas does not support dm_handle_is_valid.  We emulate it by checking
+   fields which have known values, as DMF uses this a lot.
+*/
+
+extern dm_boolean_t
+dm_handle_is_valid(
+       void            *hanp,
+       size_t          hlen)
+{
+       char            *cp = (char *)hanp;
+
+       if (hlen != 16) {
+               return(DM_FALSE);
+       }
+       if (cp[15] != '\0') {
+               return(DM_FALSE);
+       }
+       switch (cp[14]) {
+       case 1:
+       case 2:
+       case 4:
+               break;
+       default:
+               return(DM_FALSE);
+       }
+       switch (cp[13]) {
+       case 0:
+       case 1:
+               break;
+       default:
+               return(DM_FALSE);
+       }
+       return(DM_TRUE);
+}
+
+
+/* Veritas uses a dev_t for their dm_fsid_t, and named their routines
+   accordingly.  Hide this in the wrapper.  Note that a dev_t is 32 bits
+   and the SGI dm_fsid_t is defined to be a uint64_t.  If this gets to
+   be a problem (e.g. %x verus %llx), the Veritas dm_fsid_t could be made
+   to match SGI with a little casting here and there.
+*/
+
+extern int
+dm_handle_to_fsid(
+       void            *hanp,
+       size_t          hlen,
+       dm_fsid_t       *fsidp)
+{
+       dev_t           dev;
+
+       dev = dm_handle_to_dev(hanp, hlen);
+       *fsidp = (dm_fsid_t)dev;
+       return(0);
+}
+
+
+/* The Veritas dm_handle_to_fgen returns a long which is really the
+   file's generation number.  dm_igen_t is typedef'd to be a long also,
+   so the cast here is safe.
+*/
+
+extern int
+dm_handle_to_igen(
+       void            *hanp,
+       size_t          hlen,
+       dm_igen_t       *igenp)
+{
+#undef dm_handle_to_igen
+       long            igen;
+
+       igen = (dm_igen_t)dm_handle_to_fgen(hanp, hlen);
+       *igenp = (dm_igen_t)igen;
+       return(0);
+}
+
+
+/* Veritas uses a long for their dm_ino_t, which is really an ino_t.
+   Hide this in the wrapper.  Note that a ino_t is 32 bits and the SGI
+   dm_ino_t is defined to be a uint64_t.  If this gets to be a problem
+   (e.g. %x verus %llx), the Veritas dm_ino_t could be made to match SGI
+   with a little casting here and there.
+*/
+
+
+extern int
+xvfs_dm_handle_to_ino(
+       void            *hanp,
+       size_t          hlen,
+       dm_ino_t        *inop)
+{
+#undef dm_handle_to_ino
+       long            ino;
+
+       ino = (dm_ino_t)dm_handle_to_ino(hanp, hlen);
+       *inop = (dm_ino_t)ino;
+       return(0);
+}
+
+
+/* Version 2.1 of the spec did not specify the versionstrpp parameter.  This
+   code makes the routine appear to work correctly to the caller, but it
+   is not really able to do the runtime check that the parameter is
+   supposed to provide.
+*/
+
+extern int
+xvfs_dm_init_service(
+       char            **versionstrpp)
+{
+#undef dm_init_service
+       *versionstrpp = DM_VER_STR_CONTENTS;
+       return(dm_init_service());
+}
+
+
+extern int
+xvfs_dm_make_fshandle(
+       dm_fsid_t       *fsidp,
+       void            **hanpp,
+       size_t    *hlenp)
+{
+#undef dm_make_fshandle
+       dev_t           dev;
+
+       dev = (dev_t)*fsidp;
+       return(dm_make_fshandle(dev, hanpp, hlenp));
+}
+
+
+extern int
+xvfs_dm_make_handle(
+       dm_fsid_t       *fsidp,
+       dm_ino_t        *inop,
+       dm_igen_t       *igenp,
+       void            **hanpp,
+       size_t    *hlenp)
+{
+#undef dm_make_handle
+       dev_t           dev;
+       long            ino;
+       long            igen;
+
+       dev = (dev_t)*fsidp;
+       ino = (long)*inop;
+       igen = (long)*igenp;
+       return(dm_make_handle(dev, ino, igen, hanpp, hlenp));
+}
+
+
+/* The last byte in a Veritas handle is a 'pad' byte which they don't bother
+   to initialize to zero.  As a result, you can't do binary compares of
+   two handles to see if they are the same.  This stub (along with others)
+   forces the pad byte to zero so that binary compares are possible
+*/
+
+extern int
+xvfs_dm_path_to_fshandle(
+       char            *path,
+       void            **fshanpp,
+       size_t          *fshlenp)
+{
+#undef dm_path_to_fshandle
+       int             rc;
+
+       if ((rc = dm_path_to_fshandle(path, fshanpp, fshlenp)) == 0) {
+               if (*fshlenp == 16) {
+                       char    *cp = (char *)*fshanpp;
+                       cp[15] = '\0';
+               }
+       }
+       return(rc);
+}
+
+
+/* The last byte in a Veritas handle is a 'pad' byte which they don't bother
+   to initialize to zero.  As a result, you can't do binary compares of
+   two handles to see if they are the same.  This stub (along with others)
+   forces the pad byte to zero so that binary compares are possible
+*/
+
+extern int
+xvfs_dm_path_to_handle(
+       char            *path,
+       void            **hanpp,
+       size_t          *hlenp)
+{
+#undef dm_path_to_handle
+       int             rc;
+
+       if ((rc = dm_path_to_handle(path, hanpp, hlenp)) == 0) {
+               if (*hlenp == 16) {
+                       char    *cp = (char *)*hanpp;
+                       cp[15] = '\0';
+               }
+       }
+       return(rc);
+}
+
+
+/* Veritas has a prototype for this function even though it is not
+   implemented.
+*/
+
+extern int
+xvfs_dm_pending(
+       dm_sessid_t     sid,
+       dm_token_t      token,
+       dm_timestruct_t *delay)
+{
+#undef dm_pending
+       return(ENOSYS);
+}
+
+
+extern int
+xvfs_dm_read_invis(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_off_t        off,
+       dm_size_t       len,
+       void            *bufp)
+{
+#undef dm_read_invis
+       return(dm_read_invis(sid, hanp, hlen, token, off, (dm_ssize_t)len, bufp));
+}
+
+
+/* In version 2.1 uflags was defined as 'int nowait', so a value of zero in
+   this field means that the caller wants to wait.  In XDSM this was reversed,
+   where if the bottom bit of uflags is set then the caller wants to wait.
+   This routine makes the conversion.
+*/
+
+extern int
+xvfs_dm_request_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           uflags,
+       dm_right_t      right)
+{
+#undef dm_request_right
+       int     nowait = 1;
+
+       if (uflags & DM_RR_WAIT)
+               nowait = 0;
+       return(dm_request_right(sid, hanp, hlen, token, nowait, right));
+}
+
+
+extern int
+xvfs_dm_set_inherit(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrname_t   *attrnamep,
+       mode_t          mode)
+{
+#undef dm_set_inherit
+       return(dm_set_inherit(sid, hanp, hlen, token, attrnamep, (u_int)mode));
+}
+
+
+extern int
+xvfs_dm_set_region(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       u_int           nelem,
+       dm_region_t     *regbufp,
+       dm_boolean_t    *exactflagp)
+{
+#undef dm_set_region
+       return(dm_set_region(sid, hanp, hlen, token, nelem, regbufp, (u_int *)exactflagp));
+}
+
+
+extern int
+dm_set_return_on_destroy(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       dm_attrname_t   *attrnamep,
+       dm_boolean_t    enable)
+{
+       return(dm_set_return_ondestroy(sid, hanp, hlen, token,  attrnamep, (int)enable));
+}
+
+
+extern int
+xvfs_dm_sync_by_handle(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token)
+{
+#undef dm_sync_by_handle
+       return((int)dm_sync_by_handle(sid, hanp, hlen, token));
+}
+
+extern int
+xvfs_dm_upgrade_right(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token)
+{
+#undef dm_upgrade_right
+       return(dm_upgrade_right(sid, hanp, hlen, token, 0, DM_RIGHT_EXCL));
+}
+
+
+extern int
+xvfs_dm_write_invis(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       dm_token_t      token,
+       int             flags,
+       dm_off_t        off,
+       dm_size_t       len,
+       void            *bufp)
+{
+#undef dm_write_invis
+       return(dm_write_invis(sid, hanp, hlen, token, off, (dm_ssize_t)len, bufp, flags));
+}
+
+#endif
diff --git a/dmapi/src/common/lib/util.c b/dmapi/src/common/lib/util.c
new file mode 100644 (file)
index 0000000..9e92eed
--- /dev/null
@@ -0,0 +1,1004 @@
+/*
+ * Utility routines
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+#include <stdarg.h>
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <time.h>
+#define S_IAMB (S_IRWXU|S_IRWXG|S_IRWXO)
+#endif
+
+#define        S_MASK  (S_ISUID|S_ISGID|S_ISVTX|S_IAMB)
+
+extern char    *Progname;
+extern int      errno;
+
+void            err_msg(char *, ...);
+void            errno_msg(char *, ...);
+
+struct ev_name_to_value ev_names[] = {
+       { "DM_EVENT_CANCEL",            DM_EVENT_CANCEL         },
+       { "DM_EVENT_MOUNT",             DM_EVENT_MOUNT          },
+       { "DM_EVENT_PREUNMOUNT",        DM_EVENT_PREUNMOUNT     },
+       { "DM_EVENT_UNMOUNT",           DM_EVENT_UNMOUNT        },
+       { "DM_EVENT_DEBUT",             DM_EVENT_DEBUT          },
+       { "DM_EVENT_CREATE",            DM_EVENT_CREATE         },
+       { "DM_EVENT_CLOSE",             DM_EVENT_CLOSE          },
+       { "DM_EVENT_POSTCREATE",        DM_EVENT_POSTCREATE     },
+       { "DM_EVENT_REMOVE",            DM_EVENT_REMOVE         },
+       { "DM_EVENT_POSTREMOVE",        DM_EVENT_POSTREMOVE     },
+       { "DM_EVENT_RENAME",            DM_EVENT_RENAME         },
+       { "DM_EVENT_POSTRENAME",        DM_EVENT_POSTRENAME     },
+       { "DM_EVENT_LINK",              DM_EVENT_LINK           },
+       { "DM_EVENT_POSTLINK",          DM_EVENT_POSTLINK       },
+       { "DM_EVENT_SYMLINK",           DM_EVENT_SYMLINK        },
+       { "DM_EVENT_POSTSYMLINK",       DM_EVENT_POSTSYMLINK    },
+       { "DM_EVENT_READ",              DM_EVENT_READ           },
+       { "DM_EVENT_WRITE",             DM_EVENT_WRITE          },
+       { "DM_EVENT_TRUNCATE",          DM_EVENT_TRUNCATE       },
+       { "DM_EVENT_ATTRIBUTE",         DM_EVENT_ATTRIBUTE      },
+       { "DM_EVENT_DESTROY",           DM_EVENT_DESTROY        },
+       { "DM_EVENT_NOSPACE",           DM_EVENT_NOSPACE        },
+       { "DM_EVENT_USER",              DM_EVENT_USER           }
+};
+
+int    ev_namecnt = sizeof(ev_names) / sizeof(ev_names[0]);
+
+dm_eventtype_t
+ev_name_to_value(
+       char            *name)
+{
+       int             i;
+
+       for (i = 0; i < ev_namecnt; i++) {
+               if (!strcmp(name, ev_names[i].name)) 
+                       return(ev_names[i].value);
+       }
+       return(DM_EVENT_INVALID);
+}
+
+char *
+ev_value_to_name(
+       dm_eventtype_t  event)
+{
+       static char             buffer[100];
+       int             i;
+
+       for (i = 0; i < ev_namecnt; i++) {
+               if (event == ev_names[i].value)
+                       return(ev_names[i].name);
+       }
+       sprintf(buffer, "Unknown Event Number %d\n", event);
+       return(buffer);
+}
+
+
+
+struct rt_name_to_value rt_names[] = {
+       { "DM_RIGHT_NULL",              DM_RIGHT_NULL           },
+       { "DM_RIGHT_SHARED",            DM_RIGHT_SHARED         },
+       { "DM_RIGHT_EXCL",              DM_RIGHT_EXCL           }
+};
+
+int    rt_namecnt = sizeof(rt_names) / sizeof(rt_names[0]);
+
+int
+rt_name_to_value(
+       char            *name,
+       dm_right_t      *rightp)
+{
+       int             i;
+
+       for (i = 0; i < rt_namecnt; i++) {
+               if (!strcmp(name, rt_names[i].name)) {
+                       *rightp = rt_names[i].value;
+                       return(0);
+               }
+       }
+       return(1);
+}
+
+
+char *
+rt_value_to_name(
+       dm_right_t      right)
+{
+       int             i;
+
+       for (i = 0; i < rt_namecnt; i++) {
+               if (right == rt_names[i].value)
+                       return(rt_names[i].name);
+       }
+       return(NULL);
+}
+/*
+ * Convert a handle from (possibly) binary to ascii. 
+ */
+void
+hantoa(
+       void    *hanp,
+       size_t   hlen,
+       char    *handle_str)
+{
+       int     i;
+       u_char  *cp;
+
+       cp = (u_char *)hanp;
+       for (i=0;i<hlen; i++)  {
+               sprintf(handle_str, "%.2x", *cp++);
+               handle_str += 2;
+       }
+       *handle_str = '\0';     /* Null-terminate to make it printable */
+}
+
+/*
+ * Convert a handle from ascii back to it's native binary representation
+ */
+
+int
+atohan(
+       char    *handle_str,
+       void    **hanpp,
+       size_t   *hlenp) 
+{
+       u_char  handle[HANDLE_LEN];
+       char    cur_char[3];
+       int     i = 0;
+       u_long  num;
+
+       if (strlen(handle_str) > HANDLE_LEN * 2){
+               return(EBADF);
+       }
+
+       while (*handle_str && *(handle_str + 1)) {
+               if (i == HANDLE_LEN){
+                       return(EBADF);
+               }
+               cur_char[0] = *handle_str;
+               cur_char[1] = *(handle_str + 1);
+               cur_char[2] = '\0';
+               num = strtol(cur_char, (char **)0, 16);
+               handle[i++] = num & 0xff;
+               handle_str += 2;
+       }
+       if (*handle_str){
+               return(EBADF);
+       }
+       *hlenp = i;
+       if ((*hanpp = malloc(*hlenp)) == NULL)
+               return(ENOMEM);
+       memcpy(*hanpp, handle, *hlenp);
+       return(0);
+}
+
+
+int
+opaque_to_handle(
+       char            *name,
+       void            **hanpp,
+       size_t          *hlenp)
+{
+       if (atohan(name, hanpp, hlenp)) {
+               /* not a handle */
+       } else if (dm_handle_is_valid(*hanpp, *hlenp) == DM_FALSE) {
+               dm_handle_free(*hanpp, *hlenp);
+               /* not a handle */
+       } else {
+               return(0);
+       }
+
+       /* Perhaps it is a pathname */
+
+       if (dm_path_to_handle(name, hanpp, hlenp)) {
+               return(errno);
+       }
+       return(0);
+}
+
+
+void
+print_handle(
+       void    *hanp,
+       size_t   hlen)
+{
+       char    handle_str[HANDLE_STR];
+
+       if (hlen > HANDLE_LEN)  {
+               printf("-- invalid hlen length %d --\n", hlen);
+               return;
+       }
+
+       printf("print_handle: ");
+       printf("%d\t", hlen);
+       hantoa(hanp, hlen, handle_str);
+       printf("%s\n ", handle_str);
+}
+
+void
+print_victim(
+       void            *hanp, 
+       size_t           hlen,
+       dm_off_t         fsize)
+{
+       char    handle_str[HANDLE_STR];
+
+       if (hlen > HANDLE_LEN)  {
+               printf("-- invalid length --\n");
+               return;
+       }
+
+       printf("%d\t", hlen);   
+       hantoa(hanp, hlen, handle_str);
+       printf("%s ", handle_str);
+#ifdef __sgi
+       printf("\t%lld \n", fsize);
+#else
+       printf("\t%ld \n", fsize);
+#endif
+}
+
+
+/*
+ * Print out a simple error message, and include the errno
+ * string with it.
+ */
+void
+errno_msg(char *fmt, ...)
+{
+       va_list         ap;
+       int             old_errno;
+
+       old_errno = errno;
+       fprintf(stderr, "%s: ", Progname);
+
+       va_start(ap, fmt );
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+
+       errno = old_errno;
+       perror("\n\tError");
+}
+
+/*
+ * Print out a simple error message
+ */
+void
+err_msg(char *fmt, ...)
+{
+       va_list         ap;
+       
+       fprintf(stderr, "%s: ", Progname);
+
+       va_start(ap, fmt );
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+
+}
+
+
+/*
+ * Initialize the interface to the DMAPI
+ */
+int
+setup_dmapi(dm_sessid_t         *sidp)
+{
+       char    *cp;
+
+       if (dm_init_service(&cp) == -1)  {
+               err_msg("%s/%d: Can't init dmapi", __FILE__, __LINE__);
+               return(1);
+       }
+       if (strcmp(cp, DM_VER_STR_CONTENTS)) {
+               err_msg("%s/%d: Compiled for a different version", __FILE__, __LINE__);
+               return(1);
+       }
+
+       find_test_session(sidp);
+       return(0);
+}
+
+/*
+ * Get the file's change indicator
+ */
+int
+get_dmchange(
+       dm_sessid_t      sid,
+       void            *hanp, 
+       size_t           hlen, 
+       dm_token_t       token,
+       u_int           *change_start)
+{
+       int             error;
+       dm_stat_t       statbuf;
+
+
+       error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_CFLAG, &statbuf);
+       if (error == -1) {
+               errno_msg("%s/%d: Can't stat file (%d)", __FILE__, __LINE__, errno);
+               return(1);
+       }
+       *change_start = statbuf.dt_change;
+       return(0);
+}
+
+
+/*
+ * Write a file's data to the staging file. We write the file out
+ * in 4meg chunks.
+ */
+int
+save_filedata(
+       dm_sessid_t      sid, 
+       void            *hanp, 
+       size_t           hlen, 
+       int              stg_fd, 
+       dm_size_t        fsize)
+{
+       char            *filebuf;
+       int              i, nbufs;
+       int              retval;
+       dm_ssize_t       nread, lastbuf;
+       ssize_t          nwrite;
+       dm_off_t         off;
+
+        nbufs  = fsize / CHUNKSIZE;
+       off    = 0;
+       retval = 0;
+       filebuf = malloc(CHUNKSIZE);
+       if (filebuf == NULL) {
+               err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
+               goto out;
+       }
+
+        for (i = 0; i<nbufs; i++) {
+               nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off, 
+                                       (dm_ssize_t)CHUNKSIZE, filebuf);
+               if (nread != CHUNKSIZE) {
+#ifdef __sgi
+                       errno_msg("%s/%d: invis read err: got %lld, expected %lld, buf %d",
+#else
+                       errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
+#endif
+                               __FILE__, __LINE__,
+                               nread, (dm_ssize_t)CHUNKSIZE, i);
+                       retval = 1;
+                       goto out;
+               }
+               off += nread;
+
+                nwrite = write(stg_fd, filebuf, CHUNKSIZE);
+               if (nwrite != CHUNKSIZE) {
+                       errno_msg("%s/%d: write err %d, expected %d, buf %d",
+                                 __FILE__, __LINE__,
+                                 nwrite, CHUNKSIZE, i);
+                       retval = 1;
+                       goto out;
+               }
+        }
+
+        lastbuf = fsize % CHUNKSIZE;
+       nread  = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off, 
+                               (dm_ssize_t)lastbuf, filebuf);
+       if (nread != lastbuf) {
+#ifdef __sgi
+               errno_msg("%s/%d: invis read error- got %lld, expected %lld, last buf",
+#else
+               errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
+#endif
+                               __FILE__, __LINE__,
+                               nread, lastbuf);
+               retval = 1;
+               goto out;
+       }
+
+       nwrite = write(stg_fd, filebuf, (int)lastbuf);
+       if (nwrite != lastbuf) {
+#ifdef __sgi
+               errno_msg("%s/%d: write error %d, expected %lld, last buffer", 
+#else
+               errno_msg("%s/%d: write error %d, expected %d, last buffer", 
+#endif
+                               __FILE__, __LINE__,
+                               nwrite, lastbuf);
+               retval = 1;
+       }
+out:
+       if (filebuf)
+               free(filebuf);
+
+       close(stg_fd);
+       return(retval);
+}
+
+
+
+/*
+ * Read a file's data from the staging file. 
+ * Since we only have the staging file handle (not a file descriptor)
+ * we use dm_read_invis() to read the data. 
+ *
+ * We stage the entire file in, regardless of how much was asked for, 
+ * starting at the faulting offset.
+ */
+int
+restore_filedata(
+       dm_sessid_t      sid, 
+       void            *hanp, 
+       size_t           hlen, 
+       dm_token_t       token,
+       void            *stg_hanp,
+       size_t           stg_hlen,
+       dm_off_t         off)
+{
+       char            *filebuf;
+       int              i, nbufs;
+       int              error, retval;
+       dm_ssize_t       nread, nwrite, lastbuf;
+       dm_off_t         fsize;
+       dm_stat_t        dm_statbuf;
+
+       error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_STAT,
+                               &dm_statbuf);
+       if (error == -1) {
+               errno_msg("%s/%d: Can't get dm stats of file (%d)", __FILE__, __LINE__, errno);
+               return(1);
+       }
+
+       fsize  = dm_statbuf.dt_size;
+        nbufs  = fsize / CHUNKSIZE;
+       retval = 0;
+
+       filebuf = malloc(CHUNKSIZE);
+       if (filebuf == NULL) {
+               err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
+               goto out;
+       }
+
+        for (i = 0; i<nbufs; i++) {
+               nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN, 
+                                       off, (dm_ssize_t)CHUNKSIZE, filebuf);
+               if (nread != CHUNKSIZE) {
+                       errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
+                                 __FILE__, __LINE__,
+                               nread, CHUNKSIZE, i);
+                       retval = 1;
+                       goto out;
+               }
+
+                nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, nread,
+                                       filebuf);
+               if (nwrite != nread) {
+                       errno_msg("%s/%d: write error -got %d, expected %d, buf %d", 
+                                 __FILE__, __LINE__,
+                               nwrite, nread, i);
+                       retval = 1;
+                       goto out;
+               }
+               off += CHUNKSIZE;
+        }
+
+        lastbuf = fsize % CHUNKSIZE;
+       nread  = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN, off, 
+                               (dm_ssize_t)lastbuf, filebuf);
+       if (nread != lastbuf) {
+               errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
+                               __FILE__, __LINE__,
+                               nread, lastbuf);
+               retval = 1;
+               goto out;
+       }
+
+       nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, lastbuf, filebuf);
+       if (nwrite != lastbuf) {
+               errno_msg("%s/%d: write error - got %d, expected %d, last buffer", 
+                               __FILE__, __LINE__,
+                               nwrite, lastbuf);
+               retval = 1;
+       }
+out:
+       if (filebuf)
+               free(filebuf);
+       return(retval);
+}
+
+
+extern mode_t
+field_to_mode(
+       mode_t  mode)
+{
+       switch (mode & S_IFMT) {
+
+       case S_IFBLK:
+               return(S_IFBLK);
+
+       case S_IFREG:
+               return(S_IFREG);
+
+       case S_IFDIR:
+               return(S_IFDIR);
+
+       case S_IFCHR:
+               return(S_IFCHR);
+
+       case S_IFIFO:
+               return(S_IFIFO);
+
+       case S_IFLNK:
+               return(S_IFLNK);
+
+       case S_IFSOCK:
+               return(S_IFSOCK);
+
+       default:
+               return(0);
+       }
+}
+
+
+extern int
+validate_state(
+       dm_stat_t       *dmstat,
+       char            *pathname,
+       int             report_errors)
+{
+       struct  stat    statb;
+       int             errors = 0;
+
+       /* Get the stat block for the file. */
+
+       if (lstat(pathname, &statb)) {
+               perror("stat failed");
+               exit(1);
+       }
+
+       /* Compare its fields against the dm_stat_t structure. */
+
+       if (dmstat->dt_dev != statb.st_dev) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_dev 0x%x, "
+                               "statb.st_dev 0x%x\n", dmstat->dt_dev,
+                               statb.st_dev);
+               }
+               errors++;
+       }
+       if (dmstat->dt_ino != statb.st_ino) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_ino %llx, "
+#if    defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+                               "statb.st_ino %llx\n",
+#else
+                               "statb.st_ino %x\n",
+#endif
+                               dmstat->dt_ino, statb.st_ino);
+               }
+               errors++;
+       }
+       if ((dmstat->dt_mode & S_IFMT) != field_to_mode(statb.st_mode)) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_mode (mode) %s, "
+                               "statb.st_mode (mode) %s\n",
+                               mode_to_string(dmstat->dt_mode),
+                               mode_to_string(field_to_mode(statb.st_mode)));
+               }
+               errors++;
+       }
+       if ((dmstat->dt_mode & S_MASK) != (statb.st_mode & S_MASK)) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_mode (perm) 0%o, "
+                               "statb.st_mode (perm) 0%o\n",
+                               dmstat->dt_mode & S_MASK,
+                               statb.st_mode & S_MASK);
+               }
+               errors++;
+       }
+       if (dmstat->dt_nlink != statb.st_nlink) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_nlink %d, "
+                               "statb.st_nlink %d\n", dmstat->dt_nlink,
+                               statb.st_nlink);
+               }
+               errors++;
+       }
+       if (dmstat->dt_uid !=  statb.st_uid) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_uid %d, "
+                               "statb.st_uid %d\n", dmstat->dt_uid,
+                               statb.st_uid);
+               }
+               errors++;
+       }
+       if (dmstat->dt_gid != statb.st_gid) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_gid %d, "
+                               "statb.st_gid %d\n", dmstat->dt_gid,
+                               statb.st_gid);
+               }
+               errors++;
+       }
+       if (dmstat->dt_rdev != statb.st_rdev) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_rdev 0x%x, "
+                               "statb.st_rdev 0x%x\n", dmstat->dt_rdev,
+                               statb.st_rdev);
+               }
+               errors++;
+       }
+       if (dmstat->dt_size != statb.st_size) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_size %lld, "
+#if    defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+                               "statb.st_size %lld\n",
+#else
+                               "statb.st_size %d\n",
+#endif
+                               dmstat->dt_size, statb.st_size);
+               }
+               errors++;
+       }
+       if (dmstat->dt_atime != statb.st_atime) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_atime %d, "
+                               "statb.st_atime %d\n", dmstat->dt_atime,
+                               statb.st_atime);
+               }
+               errors++;
+       }
+       if (dmstat->dt_mtime != statb.st_mtime) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_mtime %d, "
+                               "statb.st_mtime %d\n", dmstat->dt_mtime,
+                               statb.st_mtime);
+               }
+               errors++;
+       }
+       if (dmstat->dt_ctime != statb.st_ctime) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_ctime %d, "
+                               "statb.st_ctime %d\n", dmstat->dt_ctime,
+                               statb.st_ctime);
+               }
+               errors++;
+       }
+       if (dmstat->dt_dtime != statb.st_ctime) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_dtime %d, "
+                               "statb.st_ctime %d\n", dmstat->dt_dtime,
+                               statb.st_ctime);
+               }
+               errors++;
+       }
+       if (dmstat->dt_blksize != statb.st_blksize) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_blksize %d, "
+                               "statb.st_blksize %d\n", dmstat->dt_blksize,
+                               statb.st_blksize);
+               }
+               errors++;
+       }
+       if (dmstat->dt_blocks != statb.st_blocks) {
+               if (report_errors) {
+                       fprintf(stdout, "ERROR:dmstat->dt_blocks %lld, "
+#if    defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32)
+                               "statb.st_blocks %lld\n",
+#else
+                               "statb.st_blocks %d\n",
+#endif
+                               dmstat->dt_blocks, statb.st_blocks);
+               }
+               errors++;
+       }
+
+       if (errors && report_errors)
+               fprintf(stdout, "There were %d differences\n", errors);
+       return(errors);
+}
+
+
+extern char *
+date_to_string(
+       time_t          timeval)
+{
+static char            buffer[21];
+       char            *tmstr;
+
+       if (timeval == (time_t)0) {
+               strcpy(buffer, "0");
+       } else {
+               tmstr = asctime(localtime(&timeval));
+               tmstr += 4;
+               strncpy(buffer, tmstr, 20);
+               buffer[20] = '\0';
+       }
+       return(buffer);
+}
+
+
+extern char *
+mode_to_string(
+       mode_t  mode)
+{
+static char            buffer[256];
+
+       switch (mode & S_IFMT) {
+
+       case S_IFBLK:
+               return("S_IFBLK");
+
+       case S_IFREG:
+               return("S_IFREG");
+
+       case S_IFDIR:
+               return("S_IFDIR");
+
+       case S_IFCHR:
+               return("S_IFCHR");
+
+       case S_IFIFO:
+               return("S_IFIFO");
+
+       case S_IFLNK:
+               return("S_IFLNK");
+
+       case S_IFSOCK:
+               return("S_IFSOCK");
+
+       default:
+               sprintf(buffer, "Invalid mode 0%o", mode & S_IFMT);
+               return(buffer);
+       }
+}
+
+
+extern char *
+emask_to_string(
+       dm_eventset_t   emask)
+{
+static char            buffer[256];
+       char            *name;
+       int             len = 0;
+       int             i;
+
+       for (i = 0; i < 32; i++) {
+               if (!DMEV_ISSET(i, emask))
+                       continue;
+
+               switch (i) {
+               case DM_EVENT_CREATE:
+                       name = "DM_EVENT_CREATE";
+                       break;
+               case DM_EVENT_POSTCREATE:
+                       name = "DM_EVENT_POSTCREATE";
+                       break;
+               case DM_EVENT_REMOVE:
+                       name = "DM_EVENT_REMOVE";
+                       break;
+               case DM_EVENT_POSTREMOVE:
+                       name = "DM_EVENT_POSTREMOVE";
+                       break;
+               case DM_EVENT_RENAME:
+                       name = "DM_EVENT_RENAME";
+                       break;
+               case DM_EVENT_POSTRENAME:
+                       name = "DM_EVENT_POSTRENAME";
+                       break;
+               case DM_EVENT_LINK:
+                       name = "DM_EVENT_LINK";
+                       break;
+               case DM_EVENT_POSTLINK:
+                       name = "DM_EVENT_POSTLINK";
+                       break;
+               case DM_EVENT_SYMLINK:
+                       name = "DM_EVENT_SYMLINK";
+                       break;
+               case DM_EVENT_POSTSYMLINK:
+                       name = "DM_EVENT_POSTSYMLINK";
+                       break;
+               case DM_EVENT_READ:
+                       name = "DM_EVENT_READ";
+                       break;
+               case DM_EVENT_WRITE:
+                       name = "DM_EVENT_WRITE";
+                       break;
+               case DM_EVENT_TRUNCATE:
+                       name = "DM_EVENT_TRUNCATE";
+                       break;
+               case DM_EVENT_ATTRIBUTE:
+                       name = "DM_EVENT_ATTRIBUTE";
+                       break;
+               case DM_EVENT_DESTROY:
+                       name = "DM_EVENT_DESTROY";
+                       break;
+               default:
+                       fprintf(stderr, "Unknown event type %d\n", i);
+                       exit(1);
+               }
+               sprintf(buffer + len, "%c%s", (len ? '|' : '('), name);
+               len = strlen(buffer);
+       }
+
+       if (len == 0) {
+               sprintf(buffer, "(none)");
+       } else {
+               sprintf(buffer + len, ")");
+       }
+       return(buffer);
+}
+
+
+#if defined(__sgi) || defined(linux)
+
+extern char *
+xflags_to_string(
+       u_int           xflags)
+{
+static char            buffer[256];
+       int             len = 0;
+
+       if (xflags & ~(DM_XFLAG_REALTIME|DM_XFLAG_PREALLOC|DM_XFLAG_HASATTR)) {
+               sprintf(buffer, "Invalid xflags 0%o", xflags);
+               return(buffer);
+       }
+
+       if (xflags & DM_XFLAG_REALTIME) {
+               sprintf(buffer + len, "%cREALTIME", (len ? '|' : '('));
+               len = strlen(buffer);
+       }
+       if (xflags & DM_XFLAG_PREALLOC) {
+               sprintf(buffer + len, "%cPREALLOC", (len ? '|' : '('));
+               len = strlen(buffer);
+       }
+       if (xflags & DM_XFLAG_HASATTR) {
+               sprintf(buffer + len, "%cHASATTR", (len ? '|' : '('));
+               len = strlen(buffer);
+       }
+       if (len == 0) {
+               sprintf(buffer, "(none)");
+       } else {
+               sprintf(buffer + len, ")");
+       }
+       return(buffer);
+}
+
+#endif
+
+
+extern void
+print_state(
+       dm_stat_t       *dmstat)
+{
+       /* Print all the stat block fields. */
+
+       fprintf(stdout, "dt_dev         0x%x\n",  dmstat->dt_dev);
+#ifdef __sgi
+       fprintf(stdout, "dt_ino         %llx\n",  dmstat->dt_ino);
+#else
+       fprintf(stdout, "dt_ino         %x\n",  dmstat->dt_ino);
+#endif
+       fprintf(stdout, "dt_mode (type) %s\n",
+               mode_to_string(dmstat->dt_mode));
+       fprintf(stdout, "dt_mode (perm) 0%o\n", dmstat->dt_mode & S_MASK);
+       fprintf(stdout, "dt_nlink       %d\n",  dmstat->dt_nlink);
+       fprintf(stdout, "dt_uid         %d\n",  dmstat->dt_uid);
+       fprintf(stdout, "dt_gid         %d\n", dmstat->dt_gid);
+       fprintf(stdout, "dt_rdev        0x%x\n", dmstat->dt_rdev);
+#ifdef __sgi
+       fprintf(stdout, "dt_size        %lld\n", dmstat->dt_size);
+#else
+       fprintf(stdout, "dt_size        %d\n", dmstat->dt_size);
+#endif
+
+       fprintf(stdout, "dt_atime       %s\n",
+               date_to_string(dmstat->dt_atime));
+       fprintf(stdout, "dt_mtime       %s\n",
+               date_to_string(dmstat->dt_mtime));
+       fprintf(stdout, "dt_ctime       %s\n",
+               date_to_string(dmstat->dt_ctime));
+
+       fprintf(stdout, "dt_blksize     %d\n", dmstat->dt_blksize);
+#ifdef __sgi
+       fprintf(stdout, "dt_blocks      %lld\n", dmstat->dt_blocks);
+#else
+       fprintf(stdout, "dt_blocks      %d\n", dmstat->dt_blocks);
+#endif
+
+#if defined(__sgi) || defined(linux)
+       fprintf(stdout, "dt_xfs_igen    %d\n",  dmstat->dt_xfs_igen);
+       fprintf(stdout, "dt_xfs_xflags  %s\n",
+               xflags_to_string(dmstat->dt_xfs_xflags));
+       fprintf(stdout, "dt_xfs_extsize %d\n", dmstat->dt_xfs_extsize);
+       fprintf(stdout, "dt_xfs_extents %d\n", dmstat->dt_xfs_extents);
+       fprintf(stdout, "dt_xfs_aextents %d\n", dmstat->dt_xfs_aextents);
+#endif
+
+       fputc('\n', stdout);
+
+       /* Print all other fields. */
+
+       fprintf(stdout, "emask           %s\n",
+               emask_to_string(dmstat->dt_emask));
+       fprintf(stdout, "nevents         %d\n", dmstat->dt_nevents);
+       fprintf(stdout, "pmanreg         %d\n", dmstat->dt_pmanreg);
+       fprintf(stdout, "pers            %d\n", dmstat->dt_pers);
+       fprintf(stdout, "dt_dtime        %s\n",
+               date_to_string(dmstat->dt_dtime));
+       fprintf(stdout, "change          %d\n", dmstat->dt_change);
+}
+
+
+extern void
+print_line(
+       dm_stat_t       *dmstat)
+{
+       fprintf(stdout, "0x%x|",  dmstat->dt_dev);
+#ifdef __sgi
+       fprintf(stdout, "%llx|",  dmstat->dt_ino);
+#else
+       fprintf(stdout, "%x|",  dmstat->dt_ino);
+#endif
+       fprintf(stdout, "%s|", mode_to_string(dmstat->dt_mode));
+       fprintf(stdout, "0%o|", dmstat->dt_mode & S_MASK);
+       fprintf(stdout, "%d|",  dmstat->dt_nlink);
+       fprintf(stdout, "%d|",  dmstat->dt_uid);
+       fprintf(stdout, "%d|", dmstat->dt_gid);
+       fprintf(stdout, "0x%x|", dmstat->dt_rdev);
+#ifdef __sgi
+       fprintf(stdout, "%lld|", dmstat->dt_size);
+#else
+       fprintf(stdout, "%d|", dmstat->dt_size);
+#endif
+
+       fprintf(stdout, "%s|", date_to_string(dmstat->dt_atime));
+       fprintf(stdout, "%s|", date_to_string(dmstat->dt_mtime));
+       fprintf(stdout, "%s|", date_to_string(dmstat->dt_ctime));
+
+       fprintf(stdout, "%d|", dmstat->dt_blksize);
+#ifdef __sgi
+       fprintf(stdout, "%lld|", dmstat->dt_blocks);
+#else
+       fprintf(stdout, "%d|", dmstat->dt_blocks);
+#endif
+
+#ifdef __sgi
+       fprintf(stdout, "%d|",  dmstat->dt_xfs_igen);
+       fprintf(stdout, "%s|", xflags_to_string(dmstat->dt_xfs_xflags));
+       fprintf(stdout, "%d|", dmstat->dt_xfs_extsize);
+       fprintf(stdout, "%d|", dmstat->dt_xfs_extents);
+       fprintf(stdout, "%d|", dmstat->dt_xfs_aextents);
+#endif
+
+       /* Print all other fields. */
+
+       fprintf(stdout, "%s|", emask_to_string(dmstat->dt_emask));
+       fprintf(stdout, "%d|", dmstat->dt_nevents);
+       fprintf(stdout, "%d|", dmstat->dt_pmanreg);
+       fprintf(stdout, "%d|", dmstat->dt_pers);
+       fprintf(stdout, "%s|", date_to_string(dmstat->dt_dtime));
+       fprintf(stdout, "%d", dmstat->dt_change);
+
+       fputc('\n', stdout);
+}
diff --git a/dmapi/src/sample_hsm/README b/dmapi/src/sample_hsm/README
new file mode 100644 (file)
index 0000000..0648f81
--- /dev/null
@@ -0,0 +1,62 @@
+The files in this directory comprise a simple HSM example that uses 
+the DMAPI. These files are distributed in the hope that they will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  These programs
+have been tested on an SGI platform (as of April 1995) and found
+to be suitably functional; however, there is no guarantee that they
+do, in fact, provide the functationality that is advertised. This
+is a long winded way of saying they probably have bugs; if you 
+find 'em, fix 'em. 
+
+Okay, now that we have the disclaimers out of the way, here are the details.
+
+       migfind
+       =======
+This will find all files of a specified size, and print out the handles.
+It is normally used like this:
+       migfind -s 800k /migfs >& cand_file
+
+This example will find all files greater than 800K in the /migfs filesystem,
+and put the handles (converted to ascii) in the file 'cand_file'. The output
+consists of three fields per line:
+       handle length           filehandle              file size in bytes
+
+       migout
+       ======
+migout reads a list of handles as created by migfind, and migrates
+the files data. The data is stored in files that are located in 
+another directory. The usage is
+       migout /dmapi_fs/stagedir < cand_file
+
+This will all the files specified by handle in 'cand_file', and
+put their data in files located under the directory /dmapi_fs/stagedir'.
+The staging directory must be on a filesystem that supports
+the dmapi; the reason for this is to allow for a simplification
+in the code that stores the location of the data as a DM attribute
+(file handles are easier than path names).
+
+       migin
+       =====
+This daemon waits for DMAPI events and dispatches worker bees
+to actually stage the data in. The usage is:
+       migin -l dmapi_log /migfs
+migin will fork/exec a 'wbee' to either bring the data back from
+the staging directory, or to invalidate the file.
+
+
+Other programs:
+There are a couple of other programs in this directory. 
+
+       mrmean
+       ======
+Simplist cleanup/debugging tool that will print information about
+the active sessions. If desired, it can also respond to outstanding
+events and destroy sessions that may have been left around from
+a process exiting unexpectedly.
+
+       mls
+       ===
+Simple ls type program to display information about a file, such
+as the managed region info, allocation info, event lists, and
+file handle.
+
diff --git a/dmapi/src/sample_hsm/migfind.c b/dmapi/src/sample_hsm/migfind.c
new file mode 100644 (file)
index 0000000..afd24f8
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Simple utility to find all files above a certain size in 
+ * a filesystem. The output is to stdout, and is of the form:
+ *     filehandle length       filehandle      file size in bytes
+ *
+ * The list is not sorted in any way.
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include <lib/hsm.h>
+
+#define NUMLEN 16              /* arbitrary max len of input size */
+#define MAX_K   (((u_int)LONG_MAX + 1) / 1024)
+#define MAX_M   (((u_int)LONG_MAX + 1) / (1024*1024))
+
+
+
+extern char    *optarg;
+extern int      optind, optopt, opterr;
+char           *Progname;
+
+extern void    print_victim(void *, size_t, dm_off_t);
+extern void    err_msg(char *, ...);
+extern void    errno_msg(char *, ...);
+
+int            setup_dmapi(dm_sessid_t *);
+int            scan_fs(dm_sessid_t, void *, size_t, dm_off_t);
+int            verify_size(char *, dm_off_t *);
+void           usage(char *);
+
+void
+usage(
+       char *prog)
+{
+       fprintf(stderr, "Usage: %s ", prog);
+       fprintf(stderr, " [-s file threshold]");
+       fprintf(stderr, " filesystem\n");
+}
+
+/*
+ * Convert an input string on the form 10m or 128K to something reasonable
+ */
+int
+verify_size(
+        char           *str,
+        dm_off_t       *sizep)
+{
+        char           *cp;
+        dm_off_t        size;
+
+        if (strlen(str) > NUMLEN) {
+                printf("Size %s is invalid \n", str);
+                return(1);
+        }
+
+        size = strtol(str,0,0); 
+        if (size < 0 || size >= LONG_MAX ) {
+                printf("Size %d is invalid \n", size);
+                return(1);
+        }
+
+        cp = str;
+        while (isdigit(*cp))
+                cp++;
+        if (*cp == 'k' || *cp == 'K') {
+                if ( size >= (u_int) MAX_K) {
+#ifdef __sgi
+                        printf("Size %lld is invalid\n", size);
+#else
+                        printf("Size %ld is invalid\n", size);
+#endif
+                        return(1);
+                }
+                size *= 1024;
+        } else if (*cp == 'm' || *cp == 'M') {
+                if ( size >= (u_int) MAX_M) {
+#ifdef __sgi
+                        printf("Size %lld is invalid\n", size);
+#else
+                        printf("Size %ld is invalid\n", size);
+#endif
+                        return(1);
+                }
+                size *= (1024*1024);
+        }
+        *sizep = size;
+        return(0);
+}
+
+
+
+int
+main(
+       int     argc, 
+       char    *argv[])
+{
+       
+       int              c;
+       int              error;
+       dm_off_t         size;
+       char            *fsname;
+       dm_sessid_t      sid;
+       void            *fs_hanp;
+       size_t           fs_hlen;
+       char            *sizep = "0";
+
+
+       Progname = argv[0];
+       size     = 0;
+
+       while ((c = getopt(argc, argv, "s:")) != EOF) {
+               switch (c) {
+               case 's':
+                       sizep = optarg;
+                       break;
+
+               case '?':
+               default:
+                       usage(Progname);
+                       exit(1);
+               }
+       }
+       if (optind >= argc) {
+               usage(Progname);
+               exit(1);
+       }
+       /*
+        * Verify the input size string is legit
+        */
+       error = verify_size(sizep, &size);
+       if (error) 
+               exit(1);
+
+       fsname = argv[optind];
+
+       /*
+        * Now we have our filesystem name and possibly a size threshold
+        * to look for. Init the dmapi, and get a filesystem handle so
+        * we can scan the filesystem
+        */
+       error = setup_dmapi(&sid);
+       if (error) 
+               exit(1);
+       
+       if (dm_path_to_fshandle(fsname, &fs_hanp, &fs_hlen) == -1) {
+               errno_msg("Can't get filesystem handle");
+               exit(1);
+       }
+
+
+
+       /*
+        * Get the attributes of all files in the filesystem
+        */
+       error = scan_fs(sid, fs_hanp, fs_hlen, size);
+       if (error) 
+               exit(1);
+       
+
+       /*
+        * We're done, so we can shut down our session.
+        */
+       if (dm_destroy_session(sid) == -1) {
+               errno_msg("Can't close session");
+               exit(1);
+       }
+
+       return(0);
+
+}
+
+/*
+ * Get the attributes for all the files in a filesystem in bulk,
+ * and print out the handles and sizes of any that meet our target
+ * criteria.
+ *
+ * We are not interested in file names; if we were, then we would 
+ * have to do a dm_get_dirattrs() on each directroy, then use 
+ * dm_handle_to_path() to get the pathname. 
+ */
+int
+scan_fs(
+       dm_sessid_t      sid, 
+       void            *fs_hanp, 
+       size_t           fs_hlen, 
+       dm_off_t         target_size)
+{
+       u_int            mask;                  /* attributes to scan for */
+       dm_stat_t       *dm_statbuf, *sbuf;     /* attributes buffer */
+       dm_attrloc_t     locp;                  /* opaque location in fs */
+       size_t           rlenp;                 /* ret length of stat info */
+       size_t           buflen;                /* length of stat buffer */
+       void            *hanp;                  /* file handle */
+       size_t           hlen;                  /* file handle */
+       int              more;                  /* loop terminator */
+       int              error; 
+
+
+       /*
+        * Size the stat buffer to return info on 1K files at a time
+        */
+       buflen     = sizeof(dm_stat_t) * 1024;
+#ifdef VERITAS_21
+       if (buflen > 65536)
+               buflen = 65536;
+#endif
+       dm_statbuf = (dm_stat_t *)calloc(1, buflen);
+       if (dm_statbuf == NULL)  {
+               err_msg("Can't get memory for stat buffer");
+               return(1);
+       }
+
+
+       /*
+        * Initialize the offset opaque offset cookie that
+        * we use in successive calls to dm_get_bulkattr()
+        */
+       error = dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &locp);
+       if (error == -1) {
+               errno_msg("%s/%d: Can't initialize offset cookie (%d)", __FILE__, __LINE__, errno);
+               free(dm_statbuf);
+               return(1);
+       }
+
+       /*
+        * Set our stat mask so that we'll only get the normal stat(2)
+        * info and the file's handle
+        */
+       mask = DM_AT_HANDLE | DM_AT_STAT;
+       do {
+               more = dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
+                                      mask, &locp, buflen, dm_statbuf, &rlenp);
+               if (more == -1) {
+                       errno_msg("%s/%d: Can't get bulkattr for filesystem", __FILE__, __LINE__, errno);
+                       break;
+               }
+
+               /*
+                * Walk through the stat buffer and pull out files 
+                * that are of interest
+                *
+                * The stat buffer is variable length, so we must
+                * use the DM_STEP_TO_NEXT macro to access each individual
+                * dm_stat_t structure in the returned buffer.
+                */
+               sbuf = dm_statbuf;
+               while (sbuf != NULL) {
+                       if (S_ISREG(sbuf->dt_mode) &&
+                           sbuf->dt_size >= target_size) {     
+                               hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
+                               hlen = DM_GET_LEN(sbuf, dt_handle);
+
+                               print_victim(hanp, hlen, sbuf->dt_size);
+                       }
+                       sbuf = DM_STEP_TO_NEXT(sbuf, dm_stat_t *);
+               }
+       } while (more == 1);
+
+       free(dm_statbuf);
+       if (more == -1) 
+               return(1);
+
+       return(0);
+}
+
diff --git a/dmapi/src/sample_hsm/migin.c b/dmapi/src/sample_hsm/migin.c
new file mode 100644 (file)
index 0000000..32551f0
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * Master migration daemon
+ *
+ * The master migration daemon waits for events on a file and
+ * spawns a child process to handle the event
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <signal.h>
+
+#include <lib/hsm.h>
+
+extern char    *optarg;
+extern int      optind, optopt, opterr;
+extern int      errno;
+char           *Progname;
+int             Verbose;
+
+extern int      setup_dmapi(dm_sessid_t *);
+extern void     err_msg(char *, ...);
+extern void     errno_msg(char *, ...);
+
+void            event_loop(dm_sessid_t);
+int             set_events(dm_sessid_t, void *, size_t);
+int             mk_daemon(char *);
+void            spawn_kid(dm_sessid_t, dm_token_t, char *);
+void            migin_exit(void);
+void            usage(char *);
+
+
+void
+usage(
+       char *prog)
+{
+       fprintf(stderr, "Usage: %s ", prog);
+       fprintf(stderr, " <-v verbose> ");
+       fprintf(stderr, " <-l logfile> ");
+       fprintf(stderr, "filesystem \n");
+}
+
+
+int
+main(
+       int     argc, 
+       char    *argv[])
+{
+       
+       int              c;
+       int              error;
+       char            *fsname, *logfile;
+       dm_sessid_t      sid;
+       void            *fs_hanp;
+       size_t           fs_hlen;
+
+
+       Progname  = argv[0];
+       fsname  = NULL;
+       logfile = NULL;
+
+       while ((c = getopt(argc, argv, "vl:")) != EOF) {
+               switch (c) {
+               case 'v':
+                       Verbose = 1;
+                       break;
+               case 'l':
+                       logfile = optarg;
+                       break;
+               case '?':
+               default:
+                       usage(Progname);
+                       exit(1);
+               }
+       }
+       if (optind >= argc) {
+               usage(Progname);
+               exit(1);
+       }
+       fsname = argv[optind];
+       if (fsname == NULL) {
+               usage(Progname);
+               exit(1);
+       }
+       /*
+        * If no logfile name is specified, we'll just send
+        * all output to some file in /tmp
+        */
+       if (logfile == NULL)
+               logfile = LOG_DEFAULT;
+        
+
+       /*
+        * Now we have our filesystem name and possibly a size threshold
+        * to look for. Init the dmapi, and get a filesystem handle so
+        * we can set up our events
+        */
+       error = setup_dmapi(&sid);
+       if (error) 
+               exit(1);
+       
+       if (dm_path_to_fshandle(fsname, &fs_hanp, &fs_hlen) == -1) {
+               errno_msg("Can't get filesystem handle");
+               exit(1);
+       }
+
+       /*
+        * Turn ourselves into a daemon
+        */
+       error = mk_daemon(logfile);
+       if (error) 
+               exit(1);
+       
+
+       /*
+        * Set the event disposition so that our session will receive 
+        * the managed region events (read, write, and truncate)
+        */
+       error = set_events(sid, fs_hanp, fs_hlen);
+       if (error) 
+               exit(1);
+       
+
+       /*
+        * Now wait forever for messages, spawning kids to
+        * do the actual work
+        */
+       event_loop(sid);
+       return(0);
+}
+
+/*
+ * Main event loop processing
+ */
+void
+event_loop(
+       dm_sessid_t     sid)
+{
+       void            *msgbuf;
+       size_t           bufsize, rlen;
+       int              error;
+       dm_eventmsg_t   *msg;
+
+       /*
+        * 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 *= 16;
+       msgbuf  = (void *)malloc(bufsize);
+       if (msgbuf == NULL) {
+               err_msg("Can't allocate memory for buffer");
+               goto out;
+       }
+
+       for (;;) {      
+               error = dm_get_events(sid, ALL_AVAIL_MSGS, DM_EV_WAIT, bufsize,
+                                       msgbuf, &rlen);
+               if (error == -1) {
+                       if (errno == E2BIG) {
+                               free(msgbuf);
+                               msgbuf = (void *)malloc(rlen);
+                               if (msgbuf == NULL) {
+                                       err_msg("Can't resize msg buffer");
+                                       goto out;
+                               }
+                               continue;
+                       }
+                       errno_msg("Error getting events from DMAPI");
+                       goto out;
+               }
+
+               /*
+                * Walk thru the message buffer, pull out each individual
+                * message, and dispatch the messages to child processes
+                * with the sid, token, and data. The children will
+                * respond to the events.
+                */
+               msg = (dm_eventmsg_t *)msgbuf;
+               while (msg != NULL ) {
+                       if (Verbose) {
+                               fprintf(stderr, "Received %s, token %d\n",
+                                   (msg->ev_type == DM_EVENT_READ ? "read" : 
+                                   (msg->ev_type == DM_EVENT_WRITE ? "write" : "trunc")), msg->ev_token);
+                       }
+                       switch (msg->ev_type) {
+
+                       case DM_EVENT_READ:
+                               spawn_kid(sid, msg->ev_token, RESTORE_FILE);
+                               break;
+
+                       case DM_EVENT_WRITE:
+                       case DM_EVENT_TRUNCATE:
+                               spawn_kid(sid, msg->ev_token, INVAL_FILE);
+                               break;
+
+                       default:
+                               err_msg("Invalid msg type %d\n", msg->ev_type);
+                               break;
+                       }
+                       msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
+               }
+       }
+out:
+       if (msgbuf != NULL)
+               free(msgbuf);
+
+       migin_exit();
+}
+
+/*
+ * Fork and exec our worker bee to work on  the file. If 
+ * there is any error in fork/exec'ing the file, we have to
+ * supply the error return to the event. Once the child gets
+ * started, he/she/it will respond to the event for us.
+ */
+void
+spawn_kid(
+       dm_sessid_t      sid,
+       dm_token_t       token,
+       char            *action)
+{
+       pid_t   pid;
+       char    sidbuf[sizeof(dm_sessid_t)];
+       char    tokenbuf[sizeof(dm_token_t)];
+
+       pid = fork();
+       if (pid == 0) {
+               /*
+                * We're in the child. Try and exec the worker bee
+                */
+               sprintf(sidbuf, "%d", sid);
+               sprintf(tokenbuf, "%d", token);
+               if (Verbose) {
+                       fprintf(stderr, "execl(%s, %s, %s, -s, %s, -t, xs, 0)\n",
+                               WORKER_BEE, WORKER_BEE, action, sidbuf, tokenbuf);
+               }
+               if (execl(WORKER_BEE, WORKER_BEE, action, "-s", sidbuf, 
+                       "-t", tokenbuf, NULL)) 
+               {
+                       (void)dm_respond_event(sid, token, DM_RESP_ABORT, 
+                                               errno, 0, 0);
+                       exit(1);
+               }
+       }
+
+       if (pid < 0) {
+               err_msg("Can't fork worker bee");
+               (void)dm_respond_event(sid, token, DM_RESP_ABORT, errno,
+                                       0, 0);
+               return;
+       }
+       return;
+
+}
+
+
+/*
+ * Set the event disposition of the managed region events
+ */
+int
+set_events(
+       dm_sessid_t      sid,
+       void            *fs_hanp,
+       size_t           fs_hlen)
+{
+       dm_eventset_t   eventlist;
+
+       DMEV_ZERO(eventlist);
+       DMEV_SET(DM_EVENT_READ, eventlist);
+       DMEV_SET(DM_EVENT_WRITE, eventlist);
+       DMEV_SET(DM_EVENT_TRUNCATE, eventlist);
+
+       if (dm_set_disp(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &eventlist, 
+                       DM_EVENT_MAX) == -1) 
+       {
+               errno_msg("Can't set event disposition");
+               return(1);
+       }
+       return(0);
+}
+
+
+
+
+/*
+ * Dissassociate ourselves from our tty, and close all files
+ */
+int
+mk_daemon(
+       char    *logfile)
+{
+       int                     fd, pid;
+       int                     i;
+       struct rlimit           lim;
+       struct sigaction        act;
+
+#ifdef NOTYET
+       if ((pid = fork()) == -1)
+               return (-1);
+       if (pid)
+               exit(0);
+
+       (void) setsid();
+
+       (void) chdir("/");
+
+#endif /* NOTYET */
+       /*
+        * Determine how many open files we've got and close
+        * then all
+        */
+       if (getrlimit(RLIMIT_NOFILE, &lim) < 0 ) {
+               errno_msg("Can't determine max number of open files");
+               return(1);
+       }
+       for (i=0; i<lim.rlim_cur; i++)
+               (void)close(i);
+
+       /*
+        * For error reporting, we re-direct stdout and stderr to a 
+        * logfile. 
+        */
+       if ((fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, 0755)) < 0) {
+               errno_msg("Can't open logfile %s", logfile);
+               return(1);
+       }
+       (void)dup2(fd, STDOUT_FILENO);
+       (void)dup2(fd, STDERR_FILENO);
+       close(fd);
+
+       /*
+        * Set up signals so that we can wait for spawned children 
+        */
+       act.sa_handler = migin_exit;
+       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);
+}
+
+void
+migin_exit(void)
+{
+       dm_sessid_t     *sidbuf, *sid;
+       void            *infobuf;
+       char            *cp;
+       u_int            nsessions, nret;
+       int              i, found, error;
+       size_t           buflen, retlen;
+
+       sidbuf  = NULL;
+       infobuf = NULL;
+       
+       /*
+        * We could try and kill off all our kids, but we're not
+        * 'Mr. Mean', so we just wait for them to die.
+        */
+       err_msg("%s: waiting for all children to die...", Progname);
+       while (wait3((int *)0, WNOHANG, (struct rusage *)0) > 0)
+               ;
+
+       fprintf(stdout, "\n");
+
+       /*
+        * Now search for our session and try and shut it down. We
+        * could just as easily make the session ID a global, but
+        * this demonstrates how sessions can be queried
+        */
+       nsessions = 4;
+       sidbuf = (dm_sessid_t *)malloc(nsessions * sizeof(dm_sessid_t));
+       if (sidbuf == NULL) {
+               err_msg("Can't alloc mem to shut down session");
+               goto out;
+       }
+       error = dm_getall_sessions(nsessions, sidbuf, &nret);
+       if (error == -1) {
+               if (errno != E2BIG) {
+                       errno_msg("Can't get list of active sessions");
+                       goto out;
+               }
+               free(sidbuf);
+               nsessions = nret;
+               sidbuf = (dm_sessid_t *)malloc(nsessions * sizeof(dm_sessid_t));
+               if (sidbuf == NULL) {
+                       err_msg("Can't alloc mem to shut down session");
+                       goto out;
+               }
+               error = dm_getall_sessions(nsessions, sidbuf, &nret);
+               if (error == -1) {
+                       errno_msg("Can't get list of active sessions");
+                       goto out;
+               }
+       }
+
+       /*
+        * Now we have all the active sessions in our system.
+        * Query each one until we find ourselves.
+        */
+       sid    = sidbuf;
+       buflen = DM_SESSION_INFO_LEN;
+       infobuf = malloc(buflen);
+       if (infobuf == NULL) {
+               err_msg("Can't alloc memory for session info buffer");
+               goto out;
+       }
+
+       /*
+        * When we registered our session, we just hammered the last component
+        * of the path name, so that's all we look for here. This prevents
+        * mismatches when running at ./migin or some other such foo
+        */
+        cp = strrchr(Progname, '/');
+        if (cp)
+                cp++;
+        else
+                cp = Progname;
+
+
+       found = 0;
+       for (i=0; i<nret; i++) {
+               error = dm_query_session(*sid, buflen, infobuf, &retlen);
+               if (error == -1)
+                       continue;               /* We just punt on errors */
+
+               if (strstr(infobuf, cp)) {
+                       found = 1;
+                       break;
+               }
+               sid++;
+       }
+
+       /*
+        * XXXX         FIXME           XXX
+        * 
+        *      Should do a set_disp to 0 and then drain the session
+        *      queue as well. On the SGI, we'll need to make the
+        *      filesystem handle global so that we can get at it
+        */
+
+       if (!found) {
+               err_msg("Can't find session to shut down");
+               goto out;
+       }
+       error = dm_destroy_session(*sid);
+       if (error == -1) {
+               errno_msg("Can't shut down session");
+       }
+
+
+out:
+       if (infobuf)
+               free(infobuf);
+       if (sidbuf)
+               free(sidbuf);
+
+       exit(0);
+}
+
diff --git a/dmapi/src/sample_hsm/migout.c b/dmapi/src/sample_hsm/migout.c
new file mode 100644 (file)
index 0000000..f62b1ec
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ * Simple utility to migrate a group of specified files.
+ * The unsorted input is from migfind, and is of the form:
+ *     filehandle length       filehandle      file size
+ *
+ * The data for each file will be stored in another file located
+ * in a different directory. This 'staging directory' should be on
+ * another filesystem. The staging file will be named the same as
+ * the file handle. This simple-minded scheme suffices, since we're
+ * not interested in showing any media management in this example.
+ *
+ * ASSUMPTIONS:
+ *     Persistent managed regions are supported
+ *     Persistent DM attributes are supported
+ *
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <lib/hsm.h>
+
+extern char    *optarg;
+extern int      optind, optopt, opterr;
+char           *Progname;
+int             Verbose;
+
+int    mig_files(dm_sessid_t, char *);
+int    mk_nonrez(dm_sessid_t, void *, size_t, dm_token_t, dm_off_t);
+int    set_mrgns(dm_sessid_t, void *, size_t, dm_token_t, dm_off_t,
+                 dm_off_t *);
+void   clear_mrgns(dm_sessid_t, void *, dm_size_t, dm_token_t);
+int    lock_file(dm_sessid_t, void *, size_t, dm_right_t, dm_token_t *);
+void   unlock_file(dm_sessid_t, dm_token_t);
+int    get_dmchange(dm_sessid_t, void *, size_t, dm_token_t, u_int *);
+int    create_stgfile(char *, void *, size_t, char *, int *);
+int    setup_dmapi(dm_sessid_t *);
+int    save_filedata(dm_sessid_t, void *, size_t, int, dm_size_t);
+int    extract_fields(char *, char *, size_t *, dm_size_t *);
+int    save_dataloc(dm_sessid_t, void *, size_t, dm_token_t, char *);
+
+void   usage(char *);
+
+void
+usage(
+       char *prog)
+{
+       fprintf(stderr, "Usage: %s ", prog);
+       fprintf(stderr, " <-v verbose> ");
+       fprintf(stderr, "<staging directory>\n");
+}
+
+
+int
+main(
+       int     argc,
+       char    *argv[])
+{
+
+       int              c;
+       int              error;
+       char            *stage_dir;
+       dm_sessid_t      sid;
+
+
+       error     = 0;
+       Progname  = argv[0];
+       stage_dir = NULL;
+
+       while ((c = getopt(argc, argv, "v")) != EOF) {
+               switch (c) {
+               case 'v':
+                       Verbose++;
+                       break;
+
+               case '?':
+               default:
+                       usage(Progname);
+                       exit(1);
+               }
+       }
+       if (optind >= argc) {
+               usage(Progname);
+               exit(1);
+       }
+       stage_dir = argv[optind];
+       if (stage_dir == NULL) {
+               usage(Progname);
+               exit(1);
+       }
+
+       /*
+        * Init the dmapi, and get a session.
+        */
+       error = setup_dmapi(&sid);
+       if (error)
+               exit(1);
+
+       /*
+        * Migrate all the files given to us via stdin
+        */
+       error = mig_files(sid, stage_dir);
+
+
+       if (dm_destroy_session(sid))
+               errno_msg("Can't shut down session, line=%d, errno=%d", __LINE__, errno);
+
+       return(error);
+}
+
+/*
+ * Migrate all the files given in stdin
+ */
+
+int
+mig_files(
+       dm_sessid_t      sid,
+       char            *stage_dir)
+{
+       void            *hanp;
+       size_t           hlen;
+       dm_size_t        fsize;
+       int              error;
+       u_int            change_start, change_end;
+       int              stg_fd;                /* staging file descriptor */
+       dm_off_t         off;                   /* starting offset */
+       dm_token_t       token;                 /* file token */
+       char             ibuf[IBUFSIZE];
+       char             handle_buf[HANDLE_LEN];
+       char             stgpath[MAXPATHLEN];
+
+       /*
+        * Read all the lines in std input and migrate each file.
+        * This simple-minded migout does no batching, sorting, or
+        * anything else that a real HSM might do.
+        */
+       while (fgets(ibuf, IBUFSIZE, stdin) != NULL) {
+               error = extract_fields(ibuf, handle_buf, &hlen, &fsize);
+               if (error) {
+                       err_msg("%s/%d: mangled input line, '%s' ", __FILE__, __LINE__, ibuf);
+                       continue;
+               }
+               hanp = (void *)handle_buf;
+               if (Verbose) {
+                       print_handle(hanp, hlen);
+               }
+
+               /*
+                * Create and open the file in the staging directory.
+                */
+               error = create_stgfile(stage_dir, hanp, hlen, stgpath, &stg_fd);
+               if (error)
+                       continue;
+
+               /*
+                * Get the file's DMAPI change indicator so that we
+                * can tell if it changed (either via a data mod, or
+                * a DM attribute update) while we are staging it out
+                */
+               error = get_dmchange(sid, hanp, hlen, DM_NO_TOKEN,
+                                       &change_start);
+               if (error) {
+                       close(stg_fd);
+                       continue;
+               }
+
+               /*
+                * Write all the file's data to our file in the
+                * staging directory. In a real HSM, the data would
+                * be copied off to tertiary storage somewhere.
+                *
+                * The staging file descriptor will be closed for us
+                * in all cases.
+                */
+               error = save_filedata(sid, hanp, hlen, stg_fd, fsize);
+               if (error)
+                       continue;
+
+
+               /*
+                * Get exclusive access to the file so we can blow
+                * away its data
+                */
+               error = lock_file(sid, hanp, hlen, DM_RIGHT_EXCL, &token);
+               if (error) {
+                       err_msg("Can't get exclusive access to file, ignoring");
+                       continue;
+               }
+
+               /*
+                * Make sure the file did not change
+                */
+               error = get_dmchange(sid, hanp, hlen, token, &change_end);
+               if (error) {
+                       unlock_file(sid, token);
+                       continue;
+               }
+               if (change_start != change_end) {
+                       unlock_file(sid, token);
+                       err_msg("File changed during stageout, ignoring");
+                       continue;
+               }
+
+               /*
+                * Save the location of the data (the staging file)
+                * in a private DM attribute so that we can get the
+                * file back in the future
+                */
+               error = save_dataloc(sid, hanp, hlen, token, stgpath);
+               if (error) {
+                       err_msg("Can't save location of file data");
+                       unlock_file(sid, token);
+                       continue;
+               }
+
+
+               /*
+                * Set up the managed regions on the file so that
+                * a foray past the fencepost will cause an event to
+                * be generated.
+                */
+               error = set_mrgns(sid, hanp, hlen, token, fsize, &off);
+               if (error) {
+                       unlock_file(sid, token);
+                       err_msg("Can't set managed regions");
+                       continue;
+               }
+
+               /*
+                * Now we can safely blow away the data.
+                */
+               error = mk_nonrez(sid, hanp, hlen, token, off);
+               if (error)  {
+                       clear_mrgns(sid, hanp, hlen, token);
+               }
+
+               /*
+                * Unlock the file, which releases the token
+                */
+               unlock_file(sid, token);
+
+       }
+
+       return(0);
+}
+
+
+/*
+ * Remove the data for a file
+ */
+int
+mk_nonrez(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen,
+       dm_token_t       token,
+       dm_off_t         off)
+{
+       int     error;
+
+       error = dm_punch_hole(sid, hanp, hlen, token, off, 0);
+       if (error == -1) {
+               errno_msg("Can't punch hole in file, line=%d, errno=%d", __LINE__, errno);
+               return(1);
+       }
+       return(0);
+}
+
+
+/*
+ * Set up the managed regions on a file. We try to leave some of the
+ * file resident; the actual amount left on-disk is dependent
+ * on the rounding enforced by the DMAPI implementation.
+ */
+int
+set_mrgns(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen,
+       dm_token_t       token,
+       dm_off_t         fsize,
+       dm_off_t        *start_off)
+{
+       dm_off_t        rroff;
+       dm_size_t       rlenp;
+       dm_region_t     rgn;
+       u_int           exact_flag;
+       int             error;
+
+       if (fsize > FENCEPOST_SIZE) {
+               error = dm_probe_hole(sid, hanp, hlen, token, FENCEPOST_SIZE, 0,
+                                       &rroff, &rlenp);
+               if (error == -1) {
+                       errno_msg("Can't probe hole in file, line=%d, errno=%d", __LINE__, errno);
+                       return(1);
+               }
+       } else {
+               rroff = 0;
+       }
+       *start_off = rroff;
+
+       /*
+        * Now we know what the DMAPI and filesystem will support with
+        * respect to rounding of holes. We try to set our managed region
+        * to begin at this offset and continue to the end of the file.
+        * We set the event mask so that we'll trap on all events that
+        * occur in the managed region.
+        *
+        * Note that some implementations may not be able to support
+        * a managed region that starts someplace other than the beginning
+        * of the file. If we really cared, we could check the exact_flag.
+        */
+       rgn.rg_offset = rroff;
+       rgn.rg_size   = 0;
+       rgn.rg_flags  = DM_REGION_READ | DM_REGION_WRITE | DM_REGION_TRUNCATE;
+       error = dm_set_region(sid, hanp, hlen, token, 1, &rgn, &exact_flag);
+       if (error == -1) {
+               errno_msg("Can't set managed region, line=%d, errno=%d", __LINE__, errno);
+               return(1);
+       }
+       return(0);
+}
+
+
+/*
+ * Clear a managed region on a file
+ */
+void
+clear_mrgns(
+       dm_sessid_t     sid,
+       void            *hanp,
+       dm_size_t       hlen,
+       dm_token_t      token)
+{
+       dm_region_t     rgn;
+       u_int           exact_flag;
+       int             error;
+
+       rgn.rg_offset = 0;
+       rgn.rg_size = 0;
+       rgn.rg_flags = DM_REGION_NOEVENT;
+       error = dm_set_region(sid, hanp, hlen, token, 1, &rgn, &exact_flag);
+       if (error)
+               errno_msg("Can't clear managed regions from file, line=%d, errno=%d", __LINE__, errno);
+
+       return;
+}
+
+
+/*
+ * File rights are accessed via a token. The token must be associated
+ * with a synchronous event message. So, to obtain either shared or
+ * exclusive rights to a file, we first associate a token with a message,
+ * and then request our desired right
+ */
+int
+lock_file(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen,
+       dm_right_t       right,
+       dm_token_t      *token)
+{
+       int     error;
+
+       error = dm_create_userevent(sid,  (size_t)0, (void *)0, token);
+       if (error == -1) {
+               errno_msg("Can't create user event for token context, line=%d, errno=%d", __LINE__, errno);
+               return(1);
+       }
+       error = dm_request_right(sid, hanp, hlen, *token, DM_RR_WAIT, right);
+       if (error == -1) {
+               errno_msg("Can't get requested right for token, line=%d, errno=%d", __LINE__, errno);
+               return(1);
+       }
+       return(0);
+}
+
+
+/*
+ * Release the lock on a file
+ */
+void
+unlock_file(
+       dm_sessid_t      sid,
+       dm_token_t       token)
+{
+       int     error;
+
+       error = dm_respond_event(sid, token, DM_RESP_CONTINUE, 0, 0, 0);
+       if (error == -1)
+               errno_msg("Can't respond to event and release token, line=%d, errno=%d", __LINE__, errno);
+
+       return;
+}
+
+
+int
+create_stgfile(
+       char    *stage_dir,
+       void    *hanp,
+       size_t   hlen,
+       char    *path,
+       int     *stg_fd)
+{
+       char    handle_str[HANDLE_STR];
+
+       if (hlen > HANDLE_LEN) {
+               err_msg("Handle length (%d) too long for file", hlen);
+               return(1);
+       }
+
+       strcpy(path, stage_dir);
+       strcat(path, "/");
+       hantoa(hanp, hlen, handle_str);
+
+       /*
+        * Concat the ascii representation of the file handle
+        * (which is two times longer than the binary version)
+        * onto the staging path name
+        */
+       strncat(path, (char *)handle_str, hlen*2);
+
+       if ( (*stg_fd = open(path, O_RDWR | O_CREAT, 0644)) < 0) {
+               errno_msg("Can't open file %s, line=%d, errno=%d\n", path, __LINE__, errno);
+               return(1);
+       }
+
+       return(0);
+}
+
+
+/*
+ * Extract the three fields from the input line. THe input is of
+ * the form
+ *     filehandle length       filehandle      file size
+ *
+ * The length of the file handle is expected to be less than 64 bytes.
+ */
+int
+extract_fields(
+       char            *ibuf,
+       char            *handle_buf,
+       size_t          *hlen,
+       dm_size_t       *fsize)
+{
+       char    *cp, *start;
+       size_t   len;
+       char *hanp;
+
+       /*
+        * Skip any leading white space, and check the length
+        * of the file handle
+        */
+       cp = ibuf;
+       while (!isalnum(*cp))
+               cp++;
+
+if( cp != ibuf )
+printf("%s/%d: found leading whitspace to skip\n", __FILE__, __LINE__);
+
+       start = cp;
+       while (isalnum(*cp))
+               cp++;
+       *cp = '\0';
+
+printf("%s/%d: start=(%s)\n", __FILE__, __LINE__, start);
+
+       len = strtol(start, 0, 0);
+       if (len > HANDLE_LEN) {
+               err_msg("%s/%d: Handle length %d too long in input line", __FILE__, __LINE__, len);
+               return(1);
+       }
+
+printf("%s/%d: len=%ld\n", __FILE__, __LINE__, len);
+
+       *hlen = len;
+
+       /*
+        * Skip over white space, and extract the file handle
+        */
+       while (!isalnum(*cp))
+               cp++;
+       hanp = cp;
+
+       /*
+        * Skip over the ascii length of the file handle, and
+        * then extract the file's length
+        */
+       cp += len*2;
+       *cp = '\0';
+
+printf("%s/%d: handle buf is (%s)\n", __FILE__, __LINE__, hanp );
+
+       atohan( hanp, (void**)&handle_buf, &len );
+
+printf("%s/%d: len now=%ld\n", __FILE__, __LINE__, len);
+
+
+       /* skip over white space */
+       while (!isalnum(*cp))
+               cp++;
+
+       /* read file length */
+       start = cp;
+       while (isalnum(*cp))
+               cp++;
+       *cp = '\0';
+
+printf("%s/%d: file len=%s\n", __FILE__, __LINE__, start);
+
+       *fsize = strtol(start, 0, 0);
+
+printf("%s/%d: fsize=%ld\n", __FILE__, __LINE__, *fsize);
+       return(0);
+
+}
+
+
+/*
+ * Save the location of the file's data so that we can find
+ * it again when we're staging the file back in. Rather than store
+ * the full pathname of the staging file, we just store the handle.
+ * This means the staging dir must be on a filesystem that supports
+ * the DMAPI.
+ */
+int
+save_dataloc(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen,
+       dm_token_t       token,
+       char            *stgpath)
+{
+       void            *stg_hanp;
+       size_t           stg_hlen;
+       int              error;
+       dm_attrname_t    hanp_attrname;
+       dm_attrname_t    hlen_attrname;
+
+       if (dm_path_to_handle(stgpath, &stg_hanp, &stg_hlen) == -1) {
+               errno_msg("Can't get handle for path %s, line=%d, errno=%d", stgpath, __LINE__, errno);
+               return(1);
+       }
+
+       /*
+        * Since handles are in two parts, they become two attributes.
+        * This can be useful, since we can extract the length
+        * separately when we stage the file back in
+        */
+       memcpy((void *)&hanp_attrname.an_chars[0], DLOC_HAN, DM_ATTR_NAME_SIZE);
+       error = dm_set_dmattr(sid, hanp, hlen, token, &hanp_attrname,
+                               0, stg_hlen, stg_hanp);
+       if (error == -1) {
+               errno_msg("Can't set DM attr of staging filehandle, line=%d, errno=%d",__LINE__, errno);
+               return(1);
+       }
+
+       memcpy((void *)&hlen_attrname.an_chars[0], DLOC_HANLEN, DM_ATTR_NAME_SIZE);
+       error = dm_set_dmattr(sid, hanp, hlen, token, &hlen_attrname,
+                               0, sizeof(stg_hlen), (void *)&stg_hlen);
+       if (error == -1) {
+               errno_msg("Can't set DM attr of staging filehandle length, line=%d, errno=%d", __LINE__, errno);
+               return(1);
+       }
+       return(0);
+}
diff --git a/dmapi/src/sample_hsm/mls.c b/dmapi/src/sample_hsm/mls.c
new file mode 100644 (file)
index 0000000..838793b
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Simple util to print out DMAPI info about a file
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <lib/hsm.h>
+
+#define MAX_RGNS       8       /* Arbitrary for this release */
+#define NUM_EXTENTS    4
+
+extern char    *optarg;
+extern int      optind, optopt, opterr;
+char           *Progname;
+
+void            usage(char *);
+int             mr_info(dm_sessid_t, void *, size_t);
+int             alloc_info(dm_sessid_t, void *, size_t);
+int             event_info(dm_sessid_t, void *, size_t);
+int             handle_info(dm_sessid_t, void *, size_t);
+
+extern int      setup_dmapi(dm_sessid_t *);
+extern void     errno_msg(char *, ...);
+extern void     print_handle(void *, size_t);
+
+
+void
+usage(
+       char *prog)
+{
+       fprintf(stderr, "Usage: %s <options> filename \n ", prog);
+       fprintf(stderr, "\t-m   managed region info\n");
+       fprintf(stderr, "\t-a   allocation info\n");
+       fprintf(stderr, "\t-e   event info\n");
+       fprintf(stderr, "\t-h   handle\n");
+}
+
+
+int
+main(
+       int     argc, 
+       char    *argv[])
+{
+       int              c;
+       int              error;
+       int              mr_flag, alloc_flag, handle_flag, event_flag;
+       void            *hanp;
+       size_t           hlen;
+       char            *filename;
+       dm_sessid_t      sid;
+
+
+       Progname = argv[0];
+       mr_flag  = alloc_flag =  handle_flag = event_flag = 0;
+       
+       while ((c = getopt(argc, argv, "maeh")) != EOF) {
+               switch (c) {
+               case 'm':
+                       mr_flag = 1;
+                       break;
+               case 'a':
+                       alloc_flag = 1;
+                       break;
+               case 'e':
+                       event_flag = 1;
+                       break;
+               case 'h':
+                       handle_flag = 1;
+                       break;
+               case '?':
+               default:
+                       usage(Progname);
+                       exit(1);
+               }
+       }
+       if (optind >= argc) {
+               usage(Progname);
+               exit(1);
+       }
+       filename = argv[optind];
+       if (filename == NULL) {
+               usage(Progname);
+               exit(1);
+       }
+       
+
+       /*
+        * Set up our link to the DMAPI, and get a handle for
+        * the file we want to query
+        */
+       error = setup_dmapi(&sid);
+       if (error)
+               exit(1);
+
+       if (dm_path_to_handle(filename, &hanp, &hlen) == -1) {
+               printf("Can't get handle for path %s", filename);
+               error = 1;
+               goto out;
+       }
+
+       printf("File %s:\n", filename);
+       if (mr_flag) {
+               error = mr_info(sid, hanp, hlen);
+               if (error) {
+                       error = 1;
+                       goto out;
+               }
+       }
+       if (alloc_flag) {
+               error = alloc_info(sid, hanp, hlen);
+               if (error) {
+                       error = 1;
+                       goto out;
+               }
+       }
+       if (event_flag) {
+               error = event_info(sid, hanp, hlen);
+               if (error) {
+                       error = 1;
+                       goto out;
+               }
+       }
+       if (handle_flag) {
+               error = handle_info(sid, hanp, hlen);
+               if (error) {
+                       error = 1;
+                       goto out;
+               }
+       }
+
+out:
+       if (dm_destroy_session(sid)) {
+               errno_msg("Can't shut down session");
+               error = 1;
+       }
+
+       return(error);
+}
+
+/*
+ * Get the complete list of all managed regions for a file. For now,
+ * we know that most implementations only support a small number of
+ * regions, so we don't handle the E2BIG error here.
+ */
+int
+mr_info(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen)
+{
+       u_int           i;
+       u_int           ret;
+       dm_region_t     rgn[MAX_RGNS];
+
+       memset((char *)&rgn, 0, (sizeof(dm_region_t) * MAX_RGNS));
+       if (dm_get_region(sid, hanp, hlen, DM_NO_TOKEN, MAX_RGNS, rgn, &ret)) {
+               errno_msg("Can't get list of managed regions");
+               return(1);
+       }
+       printf("\n");
+       for (i=0; i<ret; i++) {
+               printf("\tRegion %d:\n", i);
+#ifdef __sgi
+               printf("\t\toffset %lld, ", rgn[i].rg_offset);
+               printf("size %lld, ", rgn[i].rg_size);
+#else
+               printf("\t\toffset %ld, ", rgn[i].rg_offset);
+               printf("size %ld, ", rgn[i].rg_size);
+#endif
+               printf("flags 0x%x", rgn[i].rg_flags);
+               printf(" ( ");
+               if (rgn[i].rg_flags & DM_REGION_NOEVENT)
+                       printf("noevent ");
+               if (rgn[i].rg_flags & DM_REGION_READ)
+                       printf("read ");
+               if (rgn[i].rg_flags & DM_REGION_WRITE)
+                       printf("write ");
+               if (rgn[i].rg_flags & DM_REGION_TRUNCATE)
+                       printf("trunc ");
+               printf(" )\n");
+       }
+       return(0);
+}
+
+/*
+ * Get the complete list of events for a file.
+ */
+int
+event_info(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen)
+{
+       u_int           i;
+       u_int           ret;
+       dm_eventset_t   eventlist;
+
+       DMEV_ZERO(eventlist);
+       if (dm_get_eventlist(sid, hanp, hlen, DM_NO_TOKEN, DM_EVENT_MAX, 
+                               &eventlist, &ret)) {
+               errno_msg("Can't get list of events");
+               return(1);
+       }
+       printf("\n\tEvent list: \n\t\t");
+       if (DMEV_ISSET(DM_EVENT_MOUNT, eventlist)) 
+               printf("mount ");
+       if (DMEV_ISSET(DM_EVENT_PREUNMOUNT, eventlist)) 
+               printf("preunmount ");
+       if (DMEV_ISSET(DM_EVENT_UNMOUNT, eventlist)) 
+               printf("unmount ");
+       if (DMEV_ISSET(DM_EVENT_DEBUT, eventlist)) 
+               printf("debut ");
+       if (DMEV_ISSET(DM_EVENT_CREATE, eventlist)) 
+               printf("create ");
+       if (DMEV_ISSET(DM_EVENT_POSTCREATE, eventlist)) 
+               printf("postcreate ");
+       if (DMEV_ISSET(DM_EVENT_REMOVE, eventlist)) 
+               printf("remove ");
+       if (DMEV_ISSET(DM_EVENT_POSTREMOVE, eventlist)) 
+               printf("postmount ");
+       if (DMEV_ISSET(DM_EVENT_RENAME, eventlist)) 
+               printf("rename ");
+       if (DMEV_ISSET(DM_EVENT_POSTRENAME, eventlist)) 
+               printf("postrename ");
+       if (DMEV_ISSET(DM_EVENT_LINK, eventlist)) 
+               printf("link ");
+       if (DMEV_ISSET(DM_EVENT_POSTLINK, eventlist)) 
+               printf("postlink ");
+       if (DMEV_ISSET(DM_EVENT_SYMLINK, eventlist)) 
+               printf("symlink ");
+       if (DMEV_ISSET(DM_EVENT_POSTSYMLINK, eventlist)) 
+               printf("postsymlink ");
+       if (DMEV_ISSET(DM_EVENT_READ, eventlist)) 
+               printf("read ");
+       if (DMEV_ISSET(DM_EVENT_WRITE, eventlist)) 
+               printf("write ");
+       if (DMEV_ISSET(DM_EVENT_TRUNCATE, eventlist)) 
+               printf("truncate ");
+       if (DMEV_ISSET(DM_EVENT_ATTRIBUTE, eventlist)) 
+               printf("attribute ");
+       if (DMEV_ISSET(DM_EVENT_DESTROY, eventlist)) 
+               printf("destroy ");
+       if (DMEV_ISSET(DM_EVENT_NOSPACE, eventlist)) 
+               printf("nospace ");
+       if (DMEV_ISSET(DM_EVENT_USER, eventlist)) 
+               printf("user ");
+
+       printf("\n");
+       return(0);
+}
+
+/*
+ * Print out the handle for a file
+ */
+int
+handle_info(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen)
+{
+       printf("\n\tHandle (handle length, value) \n\t\t");
+       print_handle(hanp, hlen);
+       return(0);
+}
+
+/*
+ * Get the allocation info for a file. We pick some small number
+ * of extents to get the residency info on at one time
+ */
+int
+alloc_info(
+       dm_sessid_t      sid,
+       void            *hanp,
+       size_t           hlen)
+{
+       int             i, more;
+       dm_off_t        offset;
+       u_int           nextents, nret;
+       dm_extent_t     ext[NUM_EXTENTS];
+
+
+       nextents = NUM_EXTENTS;
+       offset   = 0;
+       printf("\n\tAllocation info \n");
+       do {
+               more = dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN, &offset, 
+                                       nextents, ext, &nret);
+               if (more == -1) {
+                       errno_msg("Can't get alloc info for file");
+                       return(1);
+               }
+               for (i=0; i<nret; i++) {
+                       printf("\t\tExtent %d ", i);
+                       if (ext[i].ex_type == DM_EXTENT_RES)
+                               printf("(resident): ");
+                       if (ext[i].ex_type == DM_EXTENT_HOLE)
+                               printf("(hole): ");
+#ifdef __sgi
+                       printf("offset %lld, ", ext[i].ex_offset);
+                       printf("len %lld\n", ext[i].ex_length);
+#else
+                       printf("offset %ld, ", ext[i].ex_offset);
+                       printf("len %ld\n", ext[i].ex_length);
+#endif
+               }
+       } while (more == 1);
+       return(0);
+}
diff --git a/dmapi/src/sample_hsm/mrmean.c b/dmapi/src/sample_hsm/mrmean.c
new file mode 100644 (file)
index 0000000..4b02eb5
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Simple Mr. Mean that can manipulate and torch sessions
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <lib/dmport.h>
+
+extern char    *optarg;
+extern int      optind, opterr, optopt;
+extern int      errno;
+
+int             Verbose;
+char           *Progname;
+
+extern void    err_msg(char *, ...);
+extern void    errno_msg(char *, ...);
+
+int            get_sessions(dm_sessid_t **, u_int *);
+int            get_tokens(dm_sessid_t, dm_token_t **, u_int *);
+void           print_session(dm_sessid_t);
+void           print_tokens(dm_sessid_t);
+void           kill_session(dm_sessid_t);
+
+void
+usage(char *s)
+{
+       fprintf(stderr, "Usage: %s <options>\n", s);
+       fprintf(stderr, "\t-t   list tokens\n");
+       fprintf(stderr, "\t-l   list sessions\n");
+       fprintf(stderr, "\t-k   kill sessions\n");
+       fprintf(stderr, "\t-s   <specific_sid>\n");
+       fprintf(stderr, "\t-v   verbose (for kill)\n");
+}
+
+int
+main(
+       int      argc,
+       char    *argv[])
+{
+       int              c;
+       int              error;
+       u_int            i, nsids;
+       int              list_flag, kill_flag, token_flag, sid_flag;
+       dm_sessid_t     *sidbuf, *sidp, onesid;
+       char            *cp;
+
+
+       Progname = argv[0];
+       list_flag = sid_flag = kill_flag = token_flag = 0;
+
+       while ((c = getopt(argc, argv, "vlkts:")) != EOF) {
+               switch (c) {
+               case 'l':
+                       list_flag = 1;
+                       break;
+               case 'k':
+                       kill_flag = 1;
+                       break;
+               case 't':
+                       token_flag = 1;
+                       break;
+               case 's':
+                       if (sscanf(optarg, "%d", &onesid) <=0 ) {
+                               err_msg("Can't convert sid %s", optarg);
+                               exit(2);
+                       }
+                       sid_flag = 1;
+                       break;
+               case 'v':
+                       Verbose = 1;
+                       break;
+               case '?':
+               default:
+                       usage(Progname);
+                       exit(1);
+               }
+       }
+       if (!list_flag && !sid_flag && !kill_flag && !token_flag) {
+               usage(Progname);
+               exit(1);
+       }
+
+        if (dm_init_service(&cp) == -1)  {
+                err_msg("Can't init dmapi");
+                return(1);
+        }
+        if (strcmp(cp, DM_VER_STR_CONTENTS)) {
+                err_msg("Compiled for a different version");
+                return(1);
+        }
+
+
+       /*
+        * Get the list of all sessions in the system
+        */
+       error = get_sessions(&sidbuf, &nsids);
+       if (error)
+               exit(1);
+
+       /*
+        * Walk through the list of sessions do what is right
+        */
+       sidp = sidbuf;
+       for (i=0; i<nsids; i++, sidp++) {
+               if (sid_flag) {
+                       /*
+                        * If we're only looking for one sid, then
+                        * we can skip this one if there's no match
+                        */
+                       if (onesid != *sidp)
+                               continue;
+               }
+               if (list_flag)
+                       print_session(*sidp);
+               if (token_flag)
+                       print_tokens(*sidp);
+               if (kill_flag)
+                       kill_session(*sidp);
+       }
+       return(0);
+}
+
+/*
+ * Print out info about a sessions
+ */
+void
+print_session(dm_sessid_t sid)
+{
+       char    buf[DM_SESSION_INFO_LEN];
+       size_t  ret;
+
+       if (dm_query_session(sid,DM_SESSION_INFO_LEN,(void *)buf, &ret) == -1) {
+               errno_msg("Can't get session info");
+               return;
+       }
+
+       printf("Session (%d) name: %s\n", sid, buf);
+       return;
+}
+
+/*
+ * Get all the tokens for a session
+ */
+void
+print_tokens(dm_sessid_t sid)
+{
+       dm_token_t      *tbuf;
+       int              error;
+       u_int            i, ntokens;
+
+       error = get_tokens(sid, &tbuf, &ntokens);
+       if (error)
+               return;
+
+       printf("\tTokens (%d): ", ntokens);
+       for (i=0; i<ntokens; i++) 
+               printf("%d ", *tbuf++);
+
+       printf("\n");
+
+       free(tbuf);
+       return;
+}
+
+/*
+ * Try and kill a session
+ */
+void
+kill_session(dm_sessid_t sid)
+{
+       dm_token_t      *tbuf;
+       int              error;
+       u_int            i, ntokens;
+
+       /*
+        * Get all the tokens in the system so we can respond to them
+        */
+       error = get_tokens(sid, &tbuf, &ntokens);
+       if (error)
+               return;
+
+       if (ntokens && Verbose) 
+               printf("\tResponding to events for sid %d, tokens: \n", sid);
+
+       for (i=0; i<ntokens; i++) {
+               if (Verbose)
+                       printf("\t\t%d ", *tbuf);
+
+               if (dm_respond_event(sid, *tbuf, DM_RESP_ABORT, EIO, 0, NULL) == -1) 
+                       errno_msg("Can't respond to event, sid %d token %d", 
+                                  sid, *tbuf);
+               tbuf++;
+       }
+
+       if (Verbose)
+               printf("\tDestroying session %d\n", sid);
+       if (dm_destroy_session(sid) == -1) 
+               errno_msg("Can't shut down session %d", sid);
+       return;
+}
+
+int
+get_sessions(
+       dm_sessid_t **sidpp,
+       u_int        *nsidp)
+{
+       dm_sessid_t     *sidbuf;
+       int              more, error;
+       u_int            nsids, nret;
+
+       /*
+        * Pick an arbitrary number of sessions to get info for.
+        * If it's not enough, then we can always resize our buffer
+        */
+       error = 0;
+       nsids = 32;
+       sidbuf = malloc(nsids * sizeof(dm_sessid_t));
+       if (sidbuf == NULL) {
+               err_msg("Can't malloc memory");
+               error = 1;
+               goto out;
+       }
+               
+       if (dm_getall_sessions(nsids, sidbuf, &nret) == -1) {
+               if (errno != E2BIG) {
+                       errno_msg("Can't get list of sessions");
+                       error = 1;
+                       goto out;
+               }
+               free(sidbuf);
+               nsids = nret;
+               sidbuf = malloc(nsids * sizeof(dm_sessid_t));
+               if (sidbuf == NULL) {
+                       err_msg("Can't malloc memory");
+                       error = 1;
+                       goto out;
+               }
+               if (dm_getall_sessions(nsids, sidbuf, &nret) == -1) {
+                       if (error == -1) {
+                               errno_msg("Can't get sessions with new buf");
+                               error = 1;
+                               goto out;
+                       }
+               }
+       }
+out:
+       if (error && (sidbuf != NULL) )
+               free(sidbuf);
+       else {
+               *sidpp = sidbuf;
+               *nsidp = nret;
+       }
+       
+       return(error);
+}
+
+
+/*
+ * Get all tokens in the session
+ */
+int
+get_tokens(
+       dm_sessid_t       sid,
+       dm_token_t      **bufpp,
+       u_int            *nretp)
+{
+       dm_token_t      *tbuf;
+       u_int            ntokens, nret;
+       int              error;
+
+       error   = 0;
+       ntokens = 1024;
+       tbuf = (dm_token_t *)malloc(ntokens * sizeof(dm_token_t));
+       if (tbuf == NULL)  
+               goto out;
+       
+       if (dm_getall_tokens(sid, ntokens, tbuf, &nret) == -1) {
+               if (errno != E2BIG) {
+                       errno_msg("Can't get all tokens");
+                       goto out;
+               }
+               free(tbuf);
+               ntokens = nret;
+               tbuf = (dm_token_t *)malloc(ntokens * sizeof(dm_token_t));
+               if (tbuf == NULL)  
+                       goto out;
+               
+               if (dm_getall_tokens(sid, ntokens, tbuf, &nret) == -1) {
+                       errno_msg("Can't get all tokens");
+                       goto out;
+               }
+       }
+out:
+       if (error && (tbuf != NULL))
+               free(tbuf);
+       else {
+               *bufpp = tbuf;
+               *nretp = nret;
+       }
+
+       return(error);
+}
diff --git a/dmapi/src/sample_hsm/wbee.c b/dmapi/src/sample_hsm/wbee.c
new file mode 100644 (file)
index 0000000..07b7a0c
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ * Worker bees.
+ *
+ * The bees perform the grunt work of handling a file event
+ *
+ * This code was written by Peter Lawthers, and placed in the public
+ * domain for use by DMAPI implementors and app writers.
+ *
+ * Standard disclaimer:
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <lib/hsm.h>
+
+extern char    *optarg;
+extern int      optind, optopt, opterr;
+extern int      errno;
+char           *Progname;
+int             Verbose;
+
+extern int      restore_filedata(dm_sessid_t, void *, size_t, dm_token_t, 
+                               void *, size_t, dm_off_t);
+extern int      get_dmchange(dm_sessid_t, void *, size_t, dm_token_t, u_int *);
+extern int      setup_dmapi(dm_sessid_t *);
+extern void     err_msg(char *, ...);
+extern void     errno_msg(char *, ...);
+
+int    stagein_file(dm_sessid_t, dm_token_t, dm_eventmsg_t *);
+int    inval_file(dm_sessid_t, dm_token_t, dm_eventmsg_t *);
+int    check_lockstate(dm_sessid_t, void *, size_t, dm_token_t);
+int    clear_mrgns(dm_sessid_t, void *, size_t, dm_token_t);
+int    find_msg(dm_sessid_t, dm_token_t, dm_eventmsg_t **);
+int    get_stghandle(dm_sessid_t, void *, size_t, dm_token_t, void **, 
+                       size_t *);
+void    usage(char *);
+
+
+
+void
+usage(
+       char *prog)
+{
+       fprintf(stderr, "Usage: %s ", prog);
+       fprintf(stderr, " <-i invalidate file> ");
+       fprintf(stderr, " <-r restore file> ");
+       fprintf(stderr, "[-s sid] [-t token] \n");
+}
+
+
+int
+main(
+       int     argc, 
+       char    *argv[])
+{
+       
+       dm_eventmsg_t   *msgheader;
+       char            *sid_str, *token_str;
+       dm_sessid_t      sid;
+       dm_token_t       token;
+       int              c;
+       int              error;
+       int              restore_flag, inval_flag;
+       char            *cp;
+
+       Progname  = argv[0];
+       sid_str   = NULL;
+       token_str = NULL;
+       restore_flag = 0;
+       inval_flag   = 0;
+
+       while ((c = getopt(argc, argv, "s:t:ri")) != EOF) {
+               switch (c) {
+               case 'r':
+                       restore_flag++;
+                       break;
+
+               case 'i':
+                       inval_flag++;
+                       break;
+
+               case 's':
+                       sid_str = optarg;
+                       break;
+
+               case 't':
+                       token_str = optarg;
+                       break;
+
+               case '?':
+               default:
+                       usage(Progname);
+                       exit(1);
+               }
+       }
+       if (optind < argc) {
+               usage(Progname);
+               exit(1);
+       }
+       if (sid_str == NULL || token_str == NULL) {
+               usage(Progname);
+               exit(1);
+       }
+       if ((restore_flag > 0) && (inval_flag > 0)) {
+               usage(Progname);
+               exit(1);
+       }
+
+       if (sscanf(sid_str, "%d", &sid) <= 0) {
+               err_msg("Can't convert sid");
+               exit(1);
+       }
+       if (sscanf(token_str, "%d", &token) <= 0) {
+               err_msg("Can't convert token");
+               exit(1);
+       }
+
+       /*
+        * Now we have our session and token. We just need to
+        * let the DMAPI know we exist so we can use the interface.
+        * We don't need to create a session since we'll be using
+        * the session of our parent.
+        */
+       error = dm_init_service(&cp);
+       if (error == -1) {
+               errno_msg("Can't init DMAPI");
+               exit(1);
+       }
+       if (strcmp(cp, DM_VER_STR_CONTENTS)) {
+               err_msg("Compiled for a different version");
+               exit(1);
+       }
+       
+       /*
+        * Find the message our caller wants us to handle
+        */
+       error = find_msg(sid, token, &msgheader);
+       if (error) 
+               exit(1);
+
+       /*
+        * Now service the particular event type
+        */
+       if (restore_flag) 
+               error = stagein_file(sid, token, msgheader);
+       else
+               error = inval_file(sid, token, msgheader);
+
+       return(error);
+}
+
+
+/*
+ * Find the data event message that correponds to the token.
+ *
+ * RETURNS:
+ *     A pointer to malloc'd memory that contains the message
+ *     we're supposed to handle in the 'msgheader' param.
+ */
+int
+find_msg(
+       dm_sessid_t       sid,
+       dm_token_t        token,
+       dm_eventmsg_t   **msgheader)
+{
+       void    *buf;
+       size_t   buflen, rlen;
+       int      error;
+
+       /*
+        * Malloc a buffer that we think is large enough for
+        * the common message header and the event specific part. 
+        * If it's not large enough, we can always resize it.
+        */
+       buflen = sizeof(dm_eventmsg_t) + sizeof(dm_data_event_t) + HANDLE_LEN;
+       buf = (void *)malloc(buflen);
+       if (buf == NULL) {
+               err_msg("Can't alloc memory for event buffer");
+               return(1);
+       }
+
+       error = dm_find_eventmsg(sid, token, buflen, buf, &rlen);
+       if (error == -1) {
+               if (errno != E2BIG) {
+                       free(buf);
+                       errno_msg("Can't obtain message from token");
+                       return(1);
+               }
+               free(buf);
+               buflen = rlen;
+               buf = (void *)malloc(buflen);
+               if (buf == NULL) {
+                       err_msg("Can't resize event buffer");
+                       return(1);
+               }
+               error = dm_find_eventmsg(sid, token, buflen, buf, &rlen);
+               if (error == -1) {
+                       errno_msg("Can't get message with resized buffer");
+                       return(1);
+               }
+       }
+       
+       *msgheader = (dm_eventmsg_t *)buf;
+       return(0);
+}
+
+
+/*
+ * Check the lock state associated with the file. If the token
+ * does not reference exclusive access, try to upgrade our lock.
+ * If we can't upgrade, drop the lock and start over
+ */
+int
+check_lockstate(
+       dm_sessid_t      sid, 
+       void            *hanp, 
+       size_t           hlen, 
+       dm_token_t       token)
+{
+       int             error;
+       dm_right_t      right;
+       u_int           change_start, change_end;
+
+       error = dm_query_right(sid, hanp, hlen, token, &right);
+       if (error == -1) {
+               errno_msg("Can't query file access rights");
+               return(1);
+       }
+#ifdef __sgi
+       /*
+        * There are no access rights on the SGI. 1 means it's
+        * there.
+        */
+       if (right == DM_RIGHT_SHARED)
+               return 0;
+#endif
+
+       if (right != DM_RIGHT_EXCL) {
+               error = dm_request_right(sid, hanp, hlen, token, 0,
+                                        DM_RIGHT_EXCL);
+               if (error == -1) {
+                       if (errno != EAGAIN) {
+                               errno_msg("Can't upgrade lock");
+                               return(1);
+                       }
+                       error = get_dmchange(sid, hanp, hlen, token, 
+                                               &change_start);
+                       if (error) 
+                               return(1);
+                               
+                       
+                       error = dm_release_right(sid, hanp, hlen, token);
+                       if (error == -1) {
+                               errno_msg("Can't release file access rights");
+                               return(1);
+                       }
+                       error = dm_request_right(sid, hanp, hlen, token, 
+                                               DM_RR_WAIT, DM_RIGHT_EXCL);
+                       if (error == -1)  {
+                               errno_msg("Can't get exclusive right to file");
+                               return(1);
+                       }
+
+                       /*
+                        * If the file changed while we slept, then someone
+                        * must have modified the file
+                        */
+                       error = get_dmchange(sid, hanp, hlen, token, 
+                                               &change_end);
+                       if (error == -1) 
+                               return(1);
+                       
+                       if (change_start != change_end) {
+                               err_msg("File changed while waiting for lock");
+                               return(1);
+                       }
+               }
+       }
+       return(0);
+}
+
+
+/*
+ * Stage in the data for a file
+ */
+int
+stagein_file(
+       dm_sessid_t      sid, 
+       dm_token_t       token,
+       dm_eventmsg_t   *msgheader)
+{
+
+       void            *stg_hanp, *hanp;
+       size_t           stg_hlen, hlen;
+       int              error, ret_errno;
+       dm_response_t    reply;
+       dm_data_event_t *msg;
+
+       /*
+        * Extract the event-specific info from the message header,
+        * then get the file handle.
+        */
+       msg  = DM_GET_VALUE(msgheader, ev_data, dm_data_event_t *);
+       hanp = DM_GET_VALUE(msg, de_handle, void *);
+       hlen = DM_GET_LEN(msg, de_handle);
+
+       /*
+        * Check our permissions. We need exclusive access to the 
+        * file to stage it back in.
+        */
+       error = check_lockstate(sid, hanp, hlen, token);
+       if (error) 
+               goto out;
+
+       /*
+        * get the staging file handle from it's DM attributes
+        */
+       stg_hanp = NULL;
+       error = get_stghandle(sid, hanp, hlen, token, &stg_hanp, &stg_hlen);
+       if (error) 
+               goto out;
+
+       /*
+        * We keep the exclusive lock held for the *entire* duration
+        * of the stagein. This is not required, but just quick and
+        * [sl]easy. For a large file, it is typically better to release
+        * the lock, and have a sliding window of managed regions to allow
+        * people to consume the data as it is being read in.
+        */
+       error = restore_filedata(sid, hanp, hlen, token, stg_hanp, stg_hlen,
+                          msg->de_offset);
+       if (error) 
+               goto out;
+
+       /*
+        * Now that the data is restored, and while we still have exclusive
+        * access to the file, clear the managed regions.
+        */
+       error = clear_mrgns(sid, hanp, hlen, token);
+       if (error) 
+               goto out;
+
+out:
+       if (stg_hanp)
+               free((char *)stg_hanp);
+
+       /*
+        * Figure out what our response to the event will be. Once
+        * we've responded to the event, the token is no longer valid.
+        * On error, we pick the (less than helpful) errno EIO to signal
+        * to the user that something went wrong.
+        */
+       if (error) {
+               reply = DM_RESP_ABORT;
+               ret_errno = EIO;
+       } else {
+               reply = DM_RESP_CONTINUE;
+               ret_errno = 0;
+       }
+       (void)dm_respond_event(sid, token, reply, ret_errno, 0, 0);
+
+       return(ret_errno);
+
+}
+
+/*
+ * Turn off event monitoring for a file. In a real HSM, we would
+ * probably want to either invalidate the file's data on 
+ * tertiary storage, or start some aging process so that it will
+ * eventually go away.
+ *
+ * The assumption is that for write and truncate events, the file
+ * data is about to be invalidated.
+ */
+int
+inval_file(
+       dm_sessid_t      sid, 
+       dm_token_t       token,
+       dm_eventmsg_t   *msgheader)
+{
+       dm_data_event_t *msg;
+       void            *hanp;
+       size_t           hlen;
+       int              error, ret_errno;
+       dm_response_t    reply;
+
+       /*
+        * Extract the event-specific info from the message header,
+        * then get the file handle.
+        */
+       msg  = DM_GET_VALUE(msgheader, ev_data, dm_data_event_t *);
+       hanp = DM_GET_VALUE(msg, de_handle, void *);
+       hlen = DM_GET_LEN(msg, de_handle);
+
+       /*
+        * Check our permissions. We need exclusive access to the 
+        * file to clear our managed regions.
+        */
+       error = check_lockstate(sid, hanp, hlen, token);
+       if (error) 
+               goto out;
+
+       /*
+        * Clear all the managed regions for the file.
+        */
+       error = clear_mrgns(sid, hanp, hlen, token);
+
+out:
+       /*
+        * Figure out what our response to the event will be. Once
+        * we've responded to the event, the token is no longer valid.
+        * On error, we pick the (less than helpful) errno EIO to signal
+        * to the user that something went wrong.
+        */
+       if (error) {
+               reply = DM_RESP_ABORT;
+               ret_errno = EIO;
+       } else {
+               reply = DM_RESP_CONTINUE;
+               ret_errno = 0;
+       }
+       (void)dm_respond_event(sid, token, reply, ret_errno, 0, 0);
+       
+       return(ret_errno);
+}
+
+/*
+ * Clear all of the managed regions for a file. 
+ */
+int
+clear_mrgns(
+       dm_sessid_t      sid, 
+       void            *hanp, 
+       size_t           hlen, 
+       dm_token_t       token)
+{
+       dm_region_t     *rgn;
+       u_int            nregions, nret;
+       u_int            exact_flag;
+       int              i;
+       int              error, retval;
+
+       /*
+        * We take a guess first and assume there is only one managed
+        * region per file. There should'nt be more than this, but
+        * it never hurts to check, since we want to make sure that
+        * all regions are turned off.
+        *
+        * The main purpose of this is to demonstrate the use of the 
+        * E2BIG paradigm.
+        */
+       retval = 1;
+       nregions = 1;
+       rgn = (dm_region_t *)malloc(nregions * sizeof(dm_region_t));
+       if (rgn == NULL) {
+               err_msg("Can't allocate memory for region buffers");
+               goto out;
+       }
+
+       error = dm_get_region(sid, hanp, hlen, token, nregions, rgn, &nret);
+       if (error == -1) {
+               if (errno != E2BIG) {
+                       errno_msg("Can't get list of managed regions for file");
+                       goto out;
+               }
+
+               /*
+                * Now we know how many managed regions there are, so we can
+                * resize our buffer
+                */
+               nregions = nret;
+               free(rgn);
+               rgn = (dm_region_t *)malloc(nregions * sizeof(dm_region_t));
+               if (rgn == NULL) {
+                       err_msg("Can't resize region buffers");
+                       goto out;
+               }
+               error = dm_get_region(sid, hanp, hlen, token, nregions, rgn, 
+                                       &nret);
+               if (error == -1) {
+                       errno_msg("Can't get list of managed regions for file");
+                       goto out;
+               }
+       }
+
+       /*
+        * Clear all the managed regions
+        */
+       for (i=0; i<nregions; i++) {
+               rgn->rg_offset = 0;
+               rgn->rg_size   = 0;
+               rgn->rg_flags  = DM_REGION_NOEVENT;
+               rgn++;
+       }
+       error = dm_set_region(sid, hanp, hlen, token, nregions, rgn, 
+                               &exact_flag);
+       if (error == -1) {
+               errno_msg("Can't clear list of managed regions for file");
+       }
+       retval = 0;
+
+out:
+       if (rgn != NULL) 
+               free(rgn);
+
+       return(retval);
+}
+
+
+/*
+ * Extract the staging file handle from a file's DM attributes
+ */
+int
+get_stghandle(
+       dm_sessid_t       sid, 
+       void             *hanp, 
+       size_t            hlen, 
+       dm_token_t        token,
+       void            **stg_hanp,
+       size_t           *stg_hlen)
+{
+       void            *han_buf;
+       size_t           han_len;
+       int              error;
+       size_t           rlen;
+       dm_attrname_t    hanp_attrname;
+       dm_attrname_t    hlen_attrname;
+
+       /*
+        * First get the length of the file handle, so we
+        * can size our buffer correctly
+        */
+       memcpy((void *)&hlen_attrname.an_chars[0], DLOC_HANLEN, DM_ATTR_NAME_SIZE);
+       error = dm_get_dmattr(sid, hanp, hlen, token, &hlen_attrname,
+                               sizeof(size_t), &han_len, &rlen);
+       if (error == -1) {
+               /*
+                * On any error, even E2BIG, we bail since the size of
+                * the file handle should be a constant
+                */
+               errno_msg("Can't get size of staging file handle");
+               return(1);
+       }
+       if (rlen != sizeof(size_t)) {
+               err_msg("File handle length component incorrect");
+               return(1);
+       }
+
+       /*
+        * Malloc space for our staging file handle, and 
+        * extract it from our DM attributes
+        */
+       han_buf = (void *)malloc(han_len);
+       if (han_buf == NULL) {
+               err_msg("Can't alloc memory for file handle");
+               return(1);
+       }
+
+       memcpy((void *)&hanp_attrname.an_chars[0], DLOC_HAN, DM_ATTR_NAME_SIZE);
+       error = dm_get_dmattr(sid, hanp, hlen, token, &hanp_attrname, 
+                               han_len, han_buf, &rlen);
+       if (error == -1) {
+               errno_msg("Can't get staging file handle");
+               free(han_buf);
+               return(1);
+       }
+       if (rlen != han_len) {
+               err_msg("File handle is incorrect length");
+               free(han_buf);
+               return(1);
+       }
+       *stg_hanp = han_buf;
+       *stg_hlen = han_len;
+       return(0);
+}
+
diff --git a/dmapi/src/simple/dm_create_session.c b/dmapi/src/simple/dm_create_session.c
new file mode 100644 (file)
index 0000000..a30165b
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <linux/dmapi_kern.h>
+
+main( int argc, char **argv )
+{
+       extern char *optarg;
+       extern int optind;
+       int c;
+       int ret;
+       dm_sessid_t oldsid = DM_NO_SESSION;
+       dm_sessid_t newsid = 0;
+       char *sessinfo = "test1";
+       char *versionstr;
+
+       while( (c = getopt(argc, argv, "hs:i:")) != -1 ) {
+               switch(c){
+               case 's':
+                       oldsid = atoi( optarg );
+                       break;
+               case 'i':
+                       sessinfo = optarg;
+                       break;
+               case 'h':
+                       fprintf(stderr, "Usage: %s [-s oldsid] [-i sessinfo_txt]\n", argv[0]);
+                       exit(2);
+               }
+       }
+
+       if( dm_init_service( &versionstr ) < 0 )
+               exit(1);
+
+       ret = dm_create_session( oldsid, sessinfo, &newsid);
+       printf( "ret=%d\n", ret );
+       printf( "newsid=%d\n", newsid );
+
+}
+
diff --git a/dmapi/src/simple/dm_destroy_session.c b/dmapi/src/simple/dm_destroy_session.c
new file mode 100644 (file)
index 0000000..68ed8c5
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <linux/dmapi_kern.h>
+
+main( int argc, char **argv )
+{
+       extern char *optarg;
+       extern int optind;
+       int c;
+       int ret;
+       dm_sessid_t sid = 0;
+       char *versionstr;
+
+       while( (c = getopt(argc, argv, "hs:")) != -1 ) {
+               switch(c){
+               case 's':
+                       sid = atoi( optarg );
+                       break;
+               case 'h':
+                       fprintf(stderr, "Usage: %s <-s sid>\n", argv[0] );
+                       exit(2);
+               }
+       }
+
+       if( sid == 0 ){
+               fprintf(stderr, "%s: must specify -s\n", argv[0] );
+               exit(1);
+       }
+
+       if( dm_init_service( &versionstr ) < 0 )
+               exit(1);
+
+       ret = dm_destroy_session( sid );
+       printf( "ret=%d\n", ret );
+}
diff --git a/dmapi/src/simple/dm_find_eventmsg.c b/dmapi/src/simple/dm_find_eventmsg.c
new file mode 100644 (file)
index 0000000..d993879
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <linux/dmapi_kern.h>
+
+main( int argc, char **argv )
+{
+       extern char *optarg;
+       extern int optind;
+       int c;
+       int ret;
+       dm_sessid_t sid = 0;
+       dm_token_t token = 0;
+       dm_eventmsg_t msg;
+       size_t rlen;
+       int buflen = sizeof(dm_eventmsg_t) + 100;
+       char *versionstr;
+
+       while( (c = getopt(argc, argv, "hs:t:l:q")) != -1 ) {
+               switch(c){
+               case 's':
+                       sid = atoi( optarg );
+                       break;
+               case 't':
+                       token = atoi( optarg );
+                       break;
+               case 'l':
+                       buflen = atoi( optarg );
+                       break;
+               case 'q':
+                       printf("dm_eventmsg_t=%d\n", sizeof(dm_eventmsg_t) );
+                       exit(0);
+               case 'h':
+                       fprintf(stderr, "Usage: %s <-s sid> <-t token> [-l buflen]\n", argv[0]);
+                       fprintf(stderr, "       %s -q\n", argv[0]);
+                       exit(2);
+               }
+       }
+
+       if( sid == 0 ){
+               fprintf(stderr, "%s: must specify -s\n", argv[0] );
+               exit(1);
+       }
+
+       if( token == 0 ){
+               fprintf(stderr, "%s: must specify -t\n", argv[0] );
+               exit(1);
+       }
+
+       if( dm_init_service( &versionstr ) < 0 )
+               exit(1);
+
+       ret = dm_find_eventmsg( sid, token, buflen, &msg, &rlen );
+       printf( "ret=%d\n", ret );
+       printf( "rlen=%d\n", rlen );
+}
diff --git a/dmapi/src/simple/dm_getall_sessions.c b/dmapi/src/simple/dm_getall_sessions.c
new file mode 100644 (file)
index 0000000..622e0b4
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <string.h>
+#include <malloc.h>
+#include <linux/dmapi_kern.h>
+
+main( int argc, char **argv )
+{
+       extern char *optarg;
+       extern int optind;
+       int c;
+       int ret;
+       dm_sessid_t *sidbuf;
+       u_int nelem = 100;
+       u_int rnelem = 0;
+       int i;
+       char *versionstr;
+       int anyway = 0; /* attempt to show this many elements anyway,
+                        * even if it looks like nothing was returned.
+                        */
+
+       while( (c = getopt(argc, argv, "hn:x:")) != -1 ) {
+               switch(c){
+               case 'n':
+                       nelem = atoi( optarg );
+                       break;
+               case 'x':
+                       anyway = atoi( optarg );
+                       break;
+               case 'h':
+                       fprintf(stderr, "Usage: %s [-n nelem]\n", argv[0]);
+                       exit(2);
+               }
+       }
+       
+       if( (sidbuf = malloc( sizeof(*sidbuf) * nelem )) == NULL ){
+               fprintf(stderr, "%s: malloc failed\n", argv[0] );
+               exit(1);
+       }
+
+       memset( sidbuf, 0, sizeof(*sidbuf) * nelem );
+
+       if( dm_init_service( &versionstr ) < 0 )
+               exit(1);
+
+       ret = dm_getall_sessions( nelem, sidbuf, &rnelem );
+       printf( "ret=%d\n", ret );
+       printf( "rnelem=%d\n", rnelem );
+
+       /* user wants us to try to show a specific number of elements */
+       if( anyway > 0 )
+               rnelem = anyway;
+
+       printf("sids=\"");
+       for( i = 0; i < rnelem; i++ ){
+               printf("%d ", sidbuf[i]);
+       }
+       printf("\"\n");
+}
+
diff --git a/dmapi/src/simple/dm_getall_tokens.c b/dmapi/src/simple/dm_getall_tokens.c
new file mode 100644 (file)
index 0000000..87dd301
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <malloc.h>
+#include <linux/dmapi_kern.h>
+
+main( int argc, char **argv )
+{
+       extern char *optarg;
+       extern int optind;
+       int c;
+       int ret;
+       dm_token_t *tokenbuf;
+       u_int nelem = 100;
+       u_int rnelem = 0;
+       dm_sessid_t sid = 0;
+       int i;
+       char *versionstr;
+
+       while( (c = getopt(argc, argv, "hs:n:")) != -1 ) {
+               switch(c){
+               case 's':
+                       sid = atoi( optarg );
+                       break;
+               case 'n':
+                       nelem = atoi( optarg );
+                       break;
+               case 'h':
+                       fprintf(stderr, "Usage: %s <-s sid> [-n nelem]\n", argv[0]);
+                       exit(2);
+               }
+       }
+
+       if( sid == 0 ){
+               fprintf(stderr, "%s: must specify -s\n", argv[0] );
+               exit(1);
+       }
+
+       if( (tokenbuf = malloc( sizeof(dm_token_t) * nelem )) == NULL ){
+               fprintf(stderr, "%s: malloc failed\n", argv[0] );
+               exit(1);
+       }
+
+       if( dm_init_service( &versionstr ) < 0 )
+               exit(1);
+
+       ret = dm_getall_tokens( sid, nelem, tokenbuf, &rnelem );
+       printf( "ret=%d\n", ret );
+       printf( "rnelem=%d\n", rnelem );
+
+       printf("tokens=\"");
+       for( i = 0; i < rnelem; i++ ){
+               printf("%d ", tokenbuf+i);
+       }
+       printf("\"\n");
+}
diff --git a/dmapi/src/simple/dm_query_session.c b/dmapi/src/simple/dm_query_session.c
new file mode 100644 (file)
index 0000000..3dedb69
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/errno.h>
+#include <linux/dmapi_kern.h>
+
+main( int argc, char **argv )
+{
+       extern char *optarg;
+       extern int optind;
+       int c;
+       int ret;
+       char *sessinfo;
+       size_t rlen = 0;
+       dm_sessid_t sid = 0;
+       int buflen = 100;
+       char *versionstr;
+
+       while( (c = getopt(argc, argv, "hs:l:")) != -1 ) {
+               switch(c){
+               case 's':
+                       sid = atoi( optarg );
+                       break;
+               case 'l':
+                       buflen = atoi( optarg );
+                       break;
+               case 'h':
+                       fprintf(stderr, "Usage: %s <-s sid> [-l buflen]\n", argv[0]);
+                       exit(2);
+               }
+       }
+
+       if( sid == 0 ){
+               fprintf(stderr, "%s: must specify -s\n", argv[0] );
+               exit(1);
+       }
+
+       if( (sessinfo = malloc( sizeof(char*) * buflen )) == NULL ){
+               fprintf(stderr, "%s: malloc failed\n", argv[0] );
+               exit(1);
+       }
+
+       if( dm_init_service( &versionstr ) < 0 )
+               exit(1);
+
+       ret = dm_query_session( sid, buflen, sessinfo, &rlen );
+       printf( "ret=%d\n", ret );
+       printf( "rlen=%d\n", rlen );
+       if( ret != -1 )
+               printf( "sessinfo=%s\n", sessinfo );
+}
diff --git a/dmapi/src/suite1/cmd/create_userevent.c b/dmapi/src/suite1/cmd/create_userevent.c
new file mode 100644 (file)
index 0000000..721378a
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function create_userevent().  The
+command line is:
+
+       create_userevent [-s sid] string
+
+where string is the msgdata to be stored in the event.
+sid is the session ID to use for the event.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-s sid] string\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *string;
+       dm_token_t      token;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "s:")) != EOF) {
+               switch (opt) {
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       string = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       if (dm_create_userevent(sid, strlen(string)+ 1, string, &token)) {
+               fprintf(stderr, "dm_create_userevent failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       fprintf(stdout, "New token %d\n", token);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/dm_handle.c b/dmapi/src/suite1/cmd/dm_handle.c
new file mode 100644 (file)
index 0000000..b69986f
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test all the DMAPI functions in dm_handle.c.  The
+command line is:
+
+        dm_handle pathname
+
+where pathname is the name of a file.  If any function fails, an error message
+containing the work ERROR will be written to stderr.
+
+Tested DMAPI functions are:
+       dm_fd_to_handle
+       dm_handle_cmp
+       dm_handle_free
+       dm_handle_hash
+       dm_handle_is_valid
+       dm_handle_to_fshandle
+       dm_handle_to_fsid
+       dm_handle_to_ino
+       dm_handle_to_igen
+       dm_make_handle
+       dm_make_fshandle
+       dm_path_to_handle
+       dm_path_to_fshandle
+
+----------------------------------------------------------------------------*/
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+       char            *pathname;
+       char            *name;
+       void            *hanp1, *hanp2, *hanp3, *fshanp1, *fshanp2, *fshanp3;
+       size_t          hlen1, hlen2, hlen3, fshlen1, fshlen2, fshlen3;
+       u_int           hash1, hash2, hash3, fshash1, fshash2, fshash3;
+       dm_fsid_t       fsid;
+       dm_ino_t        ino;
+       dm_igen_t       igen;
+       char            buffer[100];
+       char            buffer1[100];
+       char            fsbuffer1[100];
+       char            buffer2[100];
+       char            fsbuffer2[100];
+       char            buffer3[100];
+       char            fsbuffer3[100];
+       int             fd;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       if (argc != 2) {
+               fprintf(stderr, "usage: %s path\n", argv[0]);
+               exit(1);
+       }
+       pathname = argv[1];
+
+       (void)dm_init_service(&name);
+
+       if (dm_path_to_handle(pathname, &hanp1, &hlen1) != 0) {
+               fprintf(stderr, "dm_path_to_handle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       hash1 = dm_handle_hash(hanp1, hlen1);
+       hantoa(hanp1, hlen1, buffer1);
+       fprintf(stdout, "  han1:  hash %u  value %s  (dm_path_to_handle)\n",
+               hash1, buffer1);
+       if (dm_handle_is_valid(hanp1, hlen1) == DM_FALSE) {
+               fprintf(stderr, "ERROR: han1 is not valid\n");
+       }
+
+       if (dm_path_to_fshandle(pathname, &fshanp1, &fshlen1) != 0) {
+               fprintf(stderr, "dm_path_to_fshandle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       fshash1 = dm_handle_hash(fshanp1, fshlen1);
+       hantoa(fshanp1, fshlen1, fsbuffer1);
+       fprintf(stdout, "fshan1:  hash %u  value %s  (dm_path_to_fshandle\n",
+               fshash1, fsbuffer1);
+       if (dm_handle_is_valid(fshanp1, fshlen1) == DM_FALSE) {
+               fprintf(stderr, "ERROR: fshan1 is not valid\n");
+       }
+
+       if ((fd = open(pathname, O_RDONLY)) < 0) {
+               fprintf(stderr, "open of %s failed, %s\n", pathname,
+                       strerror(errno));
+               exit(1);
+       }
+       if (dm_fd_to_handle(fd, &hanp2, &hlen2) != 0) {
+               fprintf(stderr, "dm_fd_to_handle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       (void)close(fd);
+       hash2 = dm_handle_hash(hanp2, hlen2);
+       hantoa(hanp2, hlen2, buffer2);
+       fprintf(stdout, "  han2:  hash %u  value %s  (dm_fd_to_handle)\n",
+               hash2, buffer2);
+       if (dm_handle_is_valid(hanp2, hlen2) == DM_FALSE) {
+               fprintf(stderr, "ERROR: han2 is not valid\n");
+       }
+
+       if (dm_handle_to_fshandle(hanp2, hlen2, &fshanp2, &fshlen2) != 0) {
+               fprintf(stderr, "dm_handle_to_fshandle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       fshash2 = dm_handle_hash(fshanp2, fshlen2);
+       hantoa(fshanp2, fshlen2, fsbuffer2);
+       fprintf(stdout, "fshan2:  hash %u  value %s  (dm_handle_to_fshandle)\n",
+               fshash2, fsbuffer2);
+       if (dm_handle_is_valid(fshanp2, fshlen2) == DM_FALSE) {
+               fprintf(stderr, "ERROR: fshan2 is not valid\n");
+       }
+
+       if (dm_handle_cmp(hanp1, hlen1, hanp2, hlen2)) {
+               fprintf(stderr, "ERROR: han1 and han2 differ in dm_handle_cmp\n");
+       }
+       if (strcmp(buffer1, buffer2)) {
+               fprintf(stderr, "ERROR: han1 and han2 differ in strcmp\n");
+       }
+       if (hash1 != hash2) {
+               fprintf(stderr, "ERROR: hash1 and hash2 differ\n");
+       }
+
+       if (dm_handle_cmp(fshanp1, fshlen1, fshanp2, fshlen2)) {
+               fprintf(stderr, "ERROR: fshan1 and fshan2 differ in dm_handle_cmp\n");
+       }
+       if (strcmp(fsbuffer1, fsbuffer2)) {
+               fprintf(stderr, "ERROR: fshan1 and fshan2 differ in strcmp\n");
+       }
+       if (fshash1 != fshash2) {
+               fprintf(stderr, "ERROR: fshash1 and fshash2 differ\n");
+       }
+
+       /* Break the handle into its component parts and display them.  Use
+          hantoa() instead of printing the parts directly because some are
+          32 bits on Veritas and 64 bits on SGI.
+       */
+
+       if (dm_handle_to_fsid(hanp1, hlen1, &fsid) != 0) {
+               fprintf(stderr, "dm_handle_to_fsid failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       hantoa(&fsid, sizeof(fsid), buffer);
+       fprintf(stdout, "fsid  %s       (dm_handle_to_fsid)\n", buffer);
+
+       if (dm_handle_to_ino(hanp1, hlen1, &ino) != 0) {
+               fprintf(stderr, "dm_handle_to_ino failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       hantoa(&ino, sizeof(ino), buffer);
+       fprintf(stdout, "ino   %s       (dm_handle_to_ino)\n", buffer);
+
+       if (dm_handle_to_igen(hanp1, hlen1, &igen) != 0) {
+               fprintf(stderr, "dm_handle_to_igen failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       hantoa(&igen, sizeof(igen), buffer);
+       fprintf(stdout, "igen  %s       (dm_handle_to_igen)\n", buffer);
+
+       /* Now use the parts to remake the handle and verify we get the same
+          answer.
+       */
+
+       if (dm_make_handle(&fsid, &ino, &igen, &hanp3, &hlen3) != 0) {
+               fprintf(stderr, "dm_make_handle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       hash3 = dm_handle_hash(hanp3, hlen3);
+       hantoa(hanp3, hlen3, buffer3);
+       fprintf(stdout, "  han3:  hash %u  value %s  (dm_make_handle)\n",
+               hash3, buffer3);
+       if (dm_handle_is_valid(hanp3, hlen3) == DM_FALSE) {
+               fprintf(stderr, "ERROR: han3 is not valid\n");
+       }
+
+       if (dm_handle_cmp(hanp1, hlen1, hanp3, hlen3)) {
+               fprintf(stderr, "ERROR: hanp1 and hanp3 differ in dm_handle_cmp\n");
+       }
+       if (strcmp(buffer1, buffer3)) {
+               fprintf(stderr, "ERROR: hanp1 and hanp3 differ in strcmp\n");
+       }
+       if (hash1 != hash3) {
+               fprintf(stderr, "ERROR: hash1 and hash3 differ\n");
+       }
+
+       if (dm_make_fshandle(&fsid, &fshanp3, &fshlen3) != 0) {
+               fprintf(stderr, "dm_make_fshandle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       fshash3 = dm_handle_hash(fshanp3, fshlen3);
+       hantoa(fshanp3, fshlen3, fsbuffer3);
+       fprintf(stdout, "fshan3:  hash %u  value %s  (dm_make_fshandle)\n",
+               fshash3, fsbuffer3);
+       if (dm_handle_is_valid(fshanp3, fshlen3) == DM_FALSE) {
+               fprintf(stderr, "ERROR: fshan3 is not valid\n");
+       }
+
+       if (dm_handle_cmp(fshanp1, fshlen1, fshanp3, fshlen3)) {
+               fprintf(stderr, "ERROR: fshan1 and fshan3 differ in dm_handle_cmp\n");
+       }
+       if (strcmp(fsbuffer1, fsbuffer3)) {
+               fprintf(stderr, "ERROR: fshan1 and fshan3 differ in strcmp\n");
+       }
+       if (fshash1 != fshash3) {
+               fprintf(stderr, "ERROR: fshash1 and fshash3 differ\n");
+       }
+
+       dm_handle_free(hanp1, hlen1);
+       dm_handle_free(hanp2, hlen2);
+       dm_handle_free(hanp3, hlen3);
+       dm_handle_free(fshanp1, fshlen1);
+       dm_handle_free(fshanp2, fshlen2);
+       dm_handle_free(fshanp3, fshlen3);
+}
diff --git a/dmapi/src/suite1/cmd/downgrade_right.c b/dmapi/src/suite1/cmd/downgrade_right.c
new file mode 100644 (file)
index 0000000..fb2ef25
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_downgrade_right().  The
+command line is:
+
+       downgrade_right {-F} [-s sid] token {pathname|handle}
+
+where:
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-s sid] token {pathname|handle}\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       char            *object;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fs:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (dm_downgrade_right(sid, hanp, hlen, token)) {
+               fprintf(stderr, "dm_downgrade_right failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/cmd/fd_to_handle.c b/dmapi/src/suite1/cmd/fd_to_handle.c
new file mode 100644 (file)
index 0000000..8b7df44
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/* Given a file object's pathname, print the object's handle. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <lib/dmport.h>
+
+
+static void
+hantoa(
+        void    *hanp,
+        size_t   hlen,
+        char    *handle_str)
+{
+        u_char  *cp= (u_char *)hanp;
+        int     i;
+
+        for (i = 0;i < hlen; i++, handle_str += 2)
+                sprintf(handle_str, "%.2x", *cp++);
+        *handle_str = '\0';
+}
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+       char            *name;
+       void            *hanp;
+       size_t          hlen;
+       char            buffer[100];
+       int             fd;
+
+       if (argc != 2) {
+               fprintf(stderr, "usage: %s path\n", argv[0]);
+               exit(1);
+       }
+
+       (void)dm_init_service(&name);
+
+       if ((fd = open(argv[1], O_RDONLY)) < 0) {
+               fprintf(stderr, "open of %s failed, %s\n", argv[1],
+                       strerror(errno));
+               exit(1);
+       }
+       if (dm_fd_to_handle(fd, &hanp, &hlen) != 0) {
+               fprintf(stderr, "dm_fd_to_handle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       hantoa(hanp, hlen, buffer);
+
+       fprintf(stdout, "handle %s, path %s\n", buffer, argv[1]);
+}
diff --git a/dmapi/src/suite1/cmd/get_allocinfo.c b/dmapi/src/suite1/cmd/get_allocinfo.c
new file mode 100644 (file)
index 0000000..f6f3660
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_allocinfo().  The
+command line is:
+
+       get_allocinfo [-D] [-n nelem] [-o offp] [-s sid] pathname
+
+where pathname is the name of a file, 'offp' is a byte offset from the
+beginning of the file where you want to start dumping, and 'nelem' allows
+you to specify how many extent structures to use in each dm_get_allocinfo
+call.
+
+The code checks the returned extents as much as possible for errors.
+It detects bad ex_type values, verifies that there is always a trailing
+hole at the end of the file, that the ex_offset of each extent matches the
+ex_offset+ex_length of the previous extent, and that ex_offset+ex_length
+is always an even multiple of 512.  It verifies that all ex_offset values
+after the first fall on a 512-byte boundary.  It verifies that the '*offp'
+value returned by dm_get_allocinfo() is 0 at the end of the file, and
+equals ex_offset+ex_length of the last extent if not at the end of the file.
+Any error is reported to stderr, and the program then terminates with a
+non-zero exit status.
+
+The program produces output similar to xfs_bmap in order to make comparison
+easier.  Here is some sample output.
+
+f1: offset 1
+        rc 0, nelemp 17
+        0: [0..127]: resv       [1..511]
+
+Line 1 gives the name of the file and the byte offset within the file where
+the dump started.  Line 2 appears once for each dm_get_allocinfo() call,
+giving the return value (rc) and the number of extents which were returned.
+Line 3 is repeated once for each extent.  The first field "0:" is the extent
+number.  The second field "[0..127]:" give the starting and ending block for
+the extent in 512-byte units.  The third field is either "resv" to indicate
+allocated space or "hole" if the extent is a hole.  The fourth field
+"[1..511]" only appears if the dump did not start with byte zero of the
+first block.  In that case, the first number shows the actual byte offset
+within the block (1 in this case).  The second number should always be
+511 since we always dump to the end of a block.
+
+Possible tests
+--------------
+
+Dump some holey files and compare the output of this program with xfs_bmap.
+
+Produce a file with holes, and perform the following tests using just one
+extent (-e 1).
+        Dump extents from beginning of the file.
+        Dump from byte 1 of the file.
+        Dump from the last byte of the first extent.
+        Dump from the first byte of the second extent.
+        Dump from the middle of the second extent.
+        Dump the first byte of the last extent.
+        Dump the last byte of the last extent.
+        Dump the first byte after the last extent.
+        Dump starting at an offset way past the end of the file.
+
+Produce a fragmented file with many adjacent DM_EXTENT_RES extents.
+        Repeat the above tests.
+
+Produce a GRIO file with holes.
+        Repeat the above tests.
+
+Run the following shell script.
+
+#!/bin/ksh
+
+#       Dump the same holey file $max times, each time using one less extent
+#       structure than the previous time.  The grep and diff code
+#       checks to make sure that you get the same answer each time, no matter
+#       how many extents you use.  If all is okay, The only messages you will
+#       see are the "trial $num" messages.
+
+max=20          # should be bigger than the number extents in the file
+
+num=$max
+while [ $num -gt 0 ]
+do
+        echo "trial $num"
+        ./test_alloc -e $num f1 | grep '\[' > x.$num
+        if [ $num -lt $max ]
+        then
+                diff x.$num x.$max
+        fi
+        num=`expr $num - 1`
+done
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+static int print_alloc(dm_sessid_t sid, void* hanp, size_t hlen,
+       char *pathname, dm_off_t startoff, u_int nelem);
+
+char   *Progname;
+int    Dflag = 0;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-D] [-n nelem] [-o off] [-s sid] "
+               "pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t      sid = DM_NO_SESSION;
+       dm_off_t        startoff = 0;           /* starting offset */
+       u_int           nelem = 100;
+       char            *pathname;
+       void            *hanp;
+       size_t           hlen;
+       dm_stat_t       sbuf;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Dn:o:s:")) != EOF) {
+               switch(opt) {
+               case 'D':
+                       Dflag++;
+                       break;
+               case 'n':
+                       nelem = atol(optarg);
+                       break;
+               case 'o':
+                       startoff = atoll(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       if (dm_init_service(&name)) {
+               fprintf(stderr, "dm_init_service failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle and verify that it is a regular file. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for %s\n", pathname);
+               exit(1);
+       }
+       if (dm_get_fileattr(sid, hanp, hlen, DM_NO_TOKEN, DM_AT_STAT, &sbuf)) {
+               fprintf(stderr, "dm_get_fileattr failed\n");
+               exit(1);
+       }
+       if (!S_ISREG(sbuf.dt_mode)) {
+               fprintf(stderr, "%s is not a regular file\n", pathname);
+               exit(1);
+       }
+
+       /* Print the allocation. */
+
+       if (print_alloc(sid, hanp, hlen, pathname, startoff, nelem))
+               exit(1);
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
+
+
+static int
+print_alloc(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       char            *pathname,
+       dm_off_t        startoff,
+       u_int           nelem)
+{
+       dm_off_t        endoff;
+       dm_extent_t     *extent;
+       u_int           nelemp;
+       u_int           num = 0;
+       u_int           i;
+       char            *type = NULL;
+       int             rc;
+
+#ifdef __sgi
+       fprintf(stdout, "%s: starting offset %lld\n", pathname, startoff);
+#else
+       fprintf(stdout, "%s: starting offset %d\n", pathname, startoff);
+#endif
+
+       /* Allocate space for the number of extents requested by the user. */
+
+       if ((extent = malloc(nelem * sizeof(*extent))) == NULL) {
+               fprintf(stderr, "can't malloc extent structures\n");
+               return(1);
+       }
+
+       rc = 1;
+       endoff = startoff;
+
+       while (rc != 0) {
+               rc = dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN, &startoff,
+                       nelem, extent, &nelemp);
+
+               if (rc < 0) {
+                       fprintf(stderr, "dm_get_allocinfo failed, %s\n",
+                               strerror(errno));
+                       return(1);
+               }
+
+               fprintf(stdout, "\treturned %d, nelemp %d\n", rc, nelemp);
+               if (Dflag && nelemp)
+                       fprintf(stdout, " ex_type    ex_offset       ex_length\n");
+
+               /* Note: it is possible for nelemp to be zero! */
+
+               for (i = 0; i < nelemp; i++) {
+                       /* The extent must either be reserved space or a hole.
+                       */
+
+                       switch (extent[i].ex_type) {
+                       case DM_EXTENT_RES:
+                               type = "resv";
+                               break;
+                       case DM_EXTENT_HOLE:
+                               type = "hole";
+                               break;
+                       default:
+                               fprintf(stderr, "invalid extent type %d\n",
+                                       extent[i].ex_type);
+                               return(1);
+                       }
+
+                       if (!Dflag) {
+#if    __sgi
+                               fprintf(stdout, "\t%d: [%lld..%lld]: %s", num,
+#else
+                               fprintf(stdout, "\t%d: [%d..%d]: %s", num,
+#endif
+                                       extent[i].ex_offset / 512,
+                                       (extent[i].ex_offset +
+                                       extent[i].ex_length - 1) / 512, type);
+                               if ((extent[i].ex_offset % 512 != 0) ||
+                                   (endoff % 512 != 0)) {
+#if    __sgi
+                                       fprintf(stdout, "\t[%lld..%lld]\n",
+#else
+                                       fprintf(stdout, "\t[%d..%d]\n",
+#endif
+                                               extent[i].ex_offset % 512,
+                                               (endoff-1) % 512);
+                               } else {
+                                       fprintf(stdout, "\n");
+                               }
+                       } else {
+#ifdef __sgi
+                               fprintf(stdout, "%5s    %13lld  %13lld\n",
+#else
+                               fprintf(stdout, "%5s    %13d    %13d\n",
+#endif
+                                       type, extent[i].ex_offset,
+                                       extent[i].ex_length);
+                       }
+
+                       /* The ex_offset of the first extent should match the
+                          'startoff' specified by the caller.  The ex_offset
+                          in subsequent extents should always match
+                          (ex_offset + ex_length) of the previous extent,
+                          and should always start on a 512 byte boundary.
+                       */
+
+                       if (extent[i].ex_offset != endoff) {
+#ifdef __sgi
+                               fprintf(stderr, "new extent (%lld)is not "
+                                       "adjacent to previous one (%lld)\n",
+#else
+                               fprintf(stderr, "new extent (%d)is not "
+                                       "adjacent to previous one (%d)\n",
+#endif
+                                       extent[i].ex_offset, endoff);
+                               return(1);
+                       }
+                       if (num && (extent[i].ex_offset % 512) != 0) {
+#ifdef __sgi
+                               fprintf(stderr, "non-initial ex_offset (%lld) "
+#else
+                               fprintf(stderr, "non-initial ex_offset (%d) "
+#endif
+                                       "is not a 512-byte multiple\n",
+                                       extent[i].ex_offset);
+                               return(1);
+                       }
+
+                       /* Non-initial extents should have ex_length values
+                          that are an even multiple of 512.  The initial
+                          extent should be a multiple of 512 less the offset
+                          into the starting 512-byte block.
+                       */
+
+                       if (((extent[i].ex_offset % 512) + extent[i].ex_length) % 512 != 0) { 
+                               fprintf(stderr, "ex_length is incorrect based "
+                                       "upon the ex_offset\n");
+                               return(1);
+                       }
+
+                       endoff = extent[i].ex_offset + extent[i].ex_length;
+                       num++;          /* count of extents printed */
+               }
+
+               /* If not yet at end of file, the startoff parameter should
+                  match the ex_offset plus ex_length of the last extent
+                  retrieved.
+               */
+
+               if (rc && startoff != endoff) {
+#ifdef __sgi
+                       fprintf(stderr, "startoff is %lld, should be %lld\n",
+#else
+                       fprintf(stderr, "startoff is %d, should be %d\n",
+#endif
+                               startoff, endoff);
+                       return(1);
+               }
+
+               /* If we are at end of file, the last extent should be a
+                  hole.
+               */
+
+               if (!rc && type && strcmp(type, "hole")) {
+                       fprintf(stderr, "file didn't end with a hole\n");
+                       return(1);
+               }
+       }
+
+       /* At end of file, startoff should always equal zero. */
+
+       if (startoff != 0) {
+               fprintf(stderr, "ERROR: startoff was not zero at end of file\n");
+               return(1);
+       }
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/get_config_events.c b/dmapi/src/suite1/cmd/get_config_events.c
new file mode 100644 (file)
index 0000000..abf0926
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_config_events().  The
+command line is:
+
+       get_config_events [-n nelem] handle
+
+where handle is the handle of a file or filesystem, and nelem is the value
+to use for the nelem parameter to dm_get_eventlist().
+
+----------------------------------------------------------------------------*/
+
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-n nelem] handle\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       u_int           nelem = DM_EVENT_MAX;
+       char            *han_str;
+       dm_eventset_t   eventset;
+       void            *hanp;
+       size_t           hlen;
+       u_int           nelemp;
+       char            *name;
+       int             error;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "n:")) != EOF) {
+               switch (opt) {
+               case 'n':
+                       nelem = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       han_str = argv[optind];
+       if ((error = atohan(han_str, &hanp, &hlen)) != 0) {
+               fprintf(stderr, "atohan() failed, %s\n", strerror(error));
+               return(1);
+       }
+
+       if (dm_init_service(&name))  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               return(1);
+       }
+
+       DMEV_ZERO(eventset);
+
+       if (dm_get_config_events(hanp, hlen, nelem, &eventset, &nelemp)) {
+               fprintf(stderr, "dm_get_config_events failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       fprintf(stdout, "Events supported (0x%llx), nelemp %d:\n",
+               eventset, nelemp);
+
+       for (i = 0; i < nelemp; i++) {
+               if (!DMEV_ISSET(i, eventset))
+                       continue;
+               switch (i) {
+               case DM_EVENT_CANCEL:
+                       fprintf(stdout, "DM_EVENT_CANCEL");
+                       break;
+               case DM_EVENT_MOUNT:
+                       fprintf(stdout, "DM_EVENT_MOUNT");
+                       break;
+               case DM_EVENT_PREUNMOUNT:
+                       fprintf(stdout, "DM_EVENT_PREUNMOUNT");
+                       break;
+               case DM_EVENT_UNMOUNT:
+                       fprintf(stdout, "DM_EVENT_UNMOUNT");
+                       break;
+               case DM_EVENT_DEBUT:
+                       fprintf(stdout, "DM_EVENT_DEBUT");
+                       break;
+               case DM_EVENT_CREATE:
+                       fprintf(stdout, "DM_EVENT_CREATE");
+                       break;
+               case DM_EVENT_CLOSE:
+                       fprintf(stdout, "DM_EVENT_CLOSE");
+                       break;
+               case DM_EVENT_POSTCREATE:
+                       fprintf(stdout, "DM_EVENT_POSTCREATE");
+                       break;
+               case DM_EVENT_REMOVE:
+                       fprintf(stdout, "DM_EVENT_REMOVE");
+                       break;
+               case DM_EVENT_POSTREMOVE:
+                       fprintf(stdout, "DM_EVENT_POSTREMOVE");
+                       break;
+               case DM_EVENT_RENAME:
+                       fprintf(stdout, "DM_EVENT_RENAME");
+                       break;
+               case DM_EVENT_POSTRENAME:
+                       fprintf(stdout, "DM_EVENT_POSTRENAME");
+                       break;
+               case DM_EVENT_LINK:
+                       fprintf(stdout, "DM_EVENT_LINK");
+                       break;
+               case DM_EVENT_POSTLINK:
+                       fprintf(stdout, "DM_EVENT_POSTLINK");
+                       break;
+               case DM_EVENT_SYMLINK:
+                       fprintf(stdout, "DM_EVENT_SYMLINK");
+                       break;
+               case DM_EVENT_POSTSYMLINK:
+                       fprintf(stdout, "DM_EVENT_POSTSYMLINK");
+                       break;
+               case DM_EVENT_READ:
+                       fprintf(stdout, "DM_EVENT_READ");
+                       break;
+               case DM_EVENT_WRITE:
+                       fprintf(stdout, "DM_EVENT_WRITE");
+                       break;
+               case DM_EVENT_TRUNCATE:
+                       fprintf(stdout, "DM_EVENT_TRUNCATE");
+                       break;
+               case DM_EVENT_ATTRIBUTE:
+                       fprintf(stdout, "DM_EVENT_ATTRIBUTE");
+                       break;
+               case DM_EVENT_DESTROY:
+                       fprintf(stdout, "DM_EVENT_DESTROY");
+                       break;
+               case DM_EVENT_NOSPACE:
+                       fprintf(stdout, "DM_EVENT_NOSPACE");
+                       break;
+               case DM_EVENT_USER:
+                       fprintf(stdout, "DM_EVENT_USER");
+                       break;
+               case DM_EVENT_MAX:
+                       fprintf(stdout, "DM_EVENT_23");
+                       break;
+               }
+               fprintf(stdout, " (%d)\n", i);
+       }
+
+       dm_handle_free(hanp, hlen);
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/get_dirattrs.c b/dmapi/src/suite1/cmd/get_dirattrs.c
new file mode 100644 (file)
index 0000000..c247367
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_dirattrs().  The
+command line is:
+
+       get_dirattrs [-b buflen] [-l loc] [-s sid] dirpath
+
+where dirpath is the name of a directory, buflen is the size of the buffer
+to use in the call, loc is a starting location, and sid is the session ID
+whose attributes you are interested in.
+
+----------------------------------------------------------------------------*/
+
+extern char    *sys_errlist[];
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-b buflen] [-l loc] [-s sid] dirpath\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_attrloc_t    loc = 0;
+       char            *dirpath;
+       char            buffer[100];
+       void            *bufp;
+       size_t          buflen = 10000;
+       u_int           mask;
+       size_t          rlenp;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             error;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:l:s:")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       buflen = atol(optarg);
+                       break;
+               case 'l':
+                       loc = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       dirpath = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the diretory's handle. */
+
+       if (dm_path_to_handle(dirpath, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s, %s\n",
+                       dirpath, strerror(errno));
+               exit(1);
+       }
+
+       if ((bufp = malloc(buflen == 0 ? 1 : buflen)) == NULL) {
+               fprintf(stderr, "malloc failed, %s\n", strerror(errno));
+               exit(1);
+       }
+
+       mask = DM_AT_HANDLE|DM_AT_EMASK|DM_AT_PMANR|DM_AT_PATTR|DM_AT_DTIME|DM_AT_CFLAG|DM_AT_STAT;
+
+       if ((error = dm_get_dirattrs(sid, hanp, hlen, DM_NO_TOKEN, mask,
+                       &loc, buflen, bufp, &rlenp)) < 0) {
+               if (errno == E2BIG) {
+                       fprintf(stderr, "dm_get_dirattrs buffer too small, "
+                               "should be %d bytes\n", rlenp);
+               } else {
+                       fprintf(stderr, "dm_get_dirattrs failed, %s\n",
+                               strerror(errno));
+               }
+               exit(1);
+       }
+       fprintf(stdout, "rc = %d, rlenp is %d, loc is %lld\n", error,
+               rlenp, loc);
+       if (rlenp > 0) {
+               dm_stat_t       *statp;
+
+               statp = (dm_stat_t *)bufp;
+               while (statp != NULL) {
+
+                       hantoa((char *)statp + statp->dt_handle.vd_offset,
+                               statp->dt_handle.vd_length, buffer);
+                       fprintf(stdout, "handle %s\n", buffer);
+                       fprintf(stdout, "name %s\n",
+                               (char *)statp + statp->dt_compname.vd_offset);
+                       print_line(statp);
+
+                       statp = DM_STEP_TO_NEXT(statp, dm_stat_t *);
+               }
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/get_dmattr.c b/dmapi/src/suite1/cmd/get_dmattr.c
new file mode 100644 (file)
index 0000000..7001bda
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_dmattr().  The
+command line is:
+
+       get_dmattr [-b buflen] [-s sid] [-t token] pathname attr
+
+where pathname is the name of a file, buflen is the size of the buffer to use
+in the call, attr is the name of the DMAPI attribute, and sid is the session ID
+whose attributes you you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-b buflen] [-s sid] [-t token] "
+               "pathname attr\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token = DM_NO_TOKEN;
+       char            *pathname;
+       dm_attrname_t   *attrnamep;
+       void            *bufp;
+       size_t          buflen = 10000;
+       size_t          rlenp;
+       void            *hanp;
+       size_t           hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:s:t:")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       buflen = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 't':
+                       token = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       pathname = argv[optind++];
+       attrnamep = (dm_attrname_t *)argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s, %s\n",
+                       pathname, strerror(errno));
+               exit(1);
+       }
+
+       if (buflen > 0) {
+               if ((bufp = malloc(buflen)) == NULL) {
+                       fprintf(stderr, "malloc failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+       }
+
+       if (dm_get_dmattr(sid, hanp, hlen, token, attrnamep, buflen,
+           bufp, &rlenp)) {
+               if (errno == E2BIG) {
+                       fprintf(stderr, "dm_get_dmattr buffer too small, "
+                               "should be %d bytes\n", rlenp);
+               } else {
+                       fprintf(stderr, "dm_get_dmattr failed, %s\n",
+                               strerror(errno));
+               }
+               exit(1);
+       }
+       fprintf(stdout, "rlenp is %d, value is '%s'\n", rlenp, bufp);
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/get_eventlist.c b/dmapi/src/suite1/cmd/get_eventlist.c
new file mode 100644 (file)
index 0000000..53740fe
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_eventlist().  The
+command line is:
+
+       get_eventlist [-F] [-n nelem] [-s sid] [-t token] {pathname|handle}
+
+where:
+{pathname|handle}
+       is the pathname of a file or filesystem or a handle.
+-n nelem
+       is the value to use for the nelem parameter to dm_get_eventlist().
+-s sid
+       is the dm_sessid_t to use in place of the default test session.
+-t token
+       is the dm_token_t to use in place of DM_NO_TOKEN.
+-F
+       is used when a pathname is specified to indicate that you want its
+       filesystem handle, not its file handle.
+
+----------------------------------------------------------------------------*/
+
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-n nelem] [-s sid] [-t token] "
+               "{pathname|handle}\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t      sid = DM_NO_SESSION;
+       dm_token_t      token = DM_NO_TOKEN;
+       u_int           nelem = DM_EVENT_MAX;
+       char            *object;
+       dm_eventset_t   eventset;
+       void            *hanp;
+       size_t           hlen;
+       u_int           nelemp;
+       char            *name;
+       int             Fflag = 0;
+       int             error;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fn:s:t:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 'n':
+                       nelem = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 't':
+                       token = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       object = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+
+       if ((error = opaque_to_handle(object, &hanp, &hlen)) != 0) {
+               fprintf(stderr, "can't get a handle from %s, %s\n",
+                       object, strerror(error));
+               return(1);
+       }
+
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       DMEV_ZERO(eventset);
+
+       if (dm_get_eventlist(sid, hanp, hlen, token, nelem,
+           &eventset, &nelemp)) {
+               fprintf(stderr, "dm_get_eventlist failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+#ifdef VERITAS_21
+       fprintf(stdout, "Events on object %s (0x%x), nelemp %d:\n",
+#else
+       fprintf(stdout, "Events on object %s (0x%llx), nelemp %d:\n",
+#endif
+               object, eventset, nelemp);
+
+       for (i = 0; i < nelemp; i++) {
+               if (!DMEV_ISSET(i, eventset))
+                       continue;
+               switch (i) {
+               case DM_EVENT_CANCEL:
+                       fprintf(stdout, "DM_EVENT_CANCEL");
+                       break;
+               case DM_EVENT_MOUNT:
+                       fprintf(stdout, "DM_EVENT_MOUNT");
+                       break;
+               case DM_EVENT_PREUNMOUNT:
+                       fprintf(stdout, "DM_EVENT_PREUNMOUNT");
+                       break;
+               case DM_EVENT_UNMOUNT:
+                       fprintf(stdout, "DM_EVENT_UNMOUNT");
+                       break;
+               case DM_EVENT_DEBUT:
+                       fprintf(stdout, "DM_EVENT_DEBUT");
+                       break;
+               case DM_EVENT_CREATE:
+                       fprintf(stdout, "DM_EVENT_CREATE");
+                       break;
+               case DM_EVENT_CLOSE:
+                       fprintf(stdout, "DM_EVENT_CLOSE");
+                       break;
+               case DM_EVENT_POSTCREATE:
+                       fprintf(stdout, "DM_EVENT_POSTCREATE");
+                       break;
+               case DM_EVENT_REMOVE:
+                       fprintf(stdout, "DM_EVENT_REMOVE");
+                       break;
+               case DM_EVENT_POSTREMOVE:
+                       fprintf(stdout, "DM_EVENT_POSTREMOVE");
+                       break;
+               case DM_EVENT_RENAME:
+                       fprintf(stdout, "DM_EVENT_RENAME");
+                       break;
+               case DM_EVENT_POSTRENAME:
+                       fprintf(stdout, "DM_EVENT_POSTRENAME");
+                       break;
+               case DM_EVENT_LINK:
+                       fprintf(stdout, "DM_EVENT_LINK");
+                       break;
+               case DM_EVENT_POSTLINK:
+                       fprintf(stdout, "DM_EVENT_POSTLINK");
+                       break;
+               case DM_EVENT_SYMLINK:
+                       fprintf(stdout, "DM_EVENT_SYMLINK");
+                       break;
+               case DM_EVENT_POSTSYMLINK:
+                       fprintf(stdout, "DM_EVENT_POSTSYMLINK");
+                       break;
+               case DM_EVENT_READ:
+                       fprintf(stdout, "DM_EVENT_READ");
+                       break;
+               case DM_EVENT_WRITE:
+                       fprintf(stdout, "DM_EVENT_WRITE");
+                       break;
+               case DM_EVENT_TRUNCATE:
+                       fprintf(stdout, "DM_EVENT_TRUNCATE");
+                       break;
+               case DM_EVENT_ATTRIBUTE:
+                       fprintf(stdout, "DM_EVENT_ATTRIBUTE");
+                       break;
+               case DM_EVENT_DESTROY:
+                       fprintf(stdout, "DM_EVENT_DESTROY");
+                       break;
+               case DM_EVENT_NOSPACE:
+                       fprintf(stdout, "DM_EVENT_NOSPACE");
+                       break;
+               case DM_EVENT_USER:
+                       fprintf(stdout, "DM_EVENT_USER");
+                       break;
+               case DM_EVENT_MAX:
+                       fprintf(stdout, "DM_EVENT_23");
+                       break;
+               }
+               fprintf(stdout, " (%d)\n", i);
+       }
+
+       dm_handle_free(hanp, hlen);
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/get_events.c b/dmapi/src/suite1/cmd/get_events.c
new file mode 100644 (file)
index 0000000..5e437a1
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_events().  The
+command line is:
+
+       get_events [-b buflen] [-m maxmsgs] [-f] sid
+
+where buflen is the size of the buffer to use, maxmsgs is the number of messages
+to read, -f, if selected, is DM_EV_WAIT, and sid is the session ID
+whose dispositions you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-b buflen] [-m maxmsgs] [-f] sid\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_eventmsg_t   *msg;
+       dm_sessid_t     sid;
+       u_int           flags = 0;
+       void            *bufp;
+       size_t          buflen = 10000;
+       void            *hanp;
+       size_t          hlen;
+       char            hans1[HANDLE_STR];
+       u_int           maxmsgs = 1;
+       size_t          rlenp;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:m:f")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       buflen = atol(optarg);
+                       break;
+               case 'm':
+                       maxmsgs = atol(optarg);
+                       break;
+               case 'f':
+                       flags = DM_EV_WAIT;
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       sid = atol(argv[optind]);
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+
+       if (buflen > 0) {
+               if ((bufp = malloc(buflen)) == NULL) {
+                       fprintf(stderr, "malloc failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+       }
+
+       if (dm_get_events(sid, maxmsgs, flags, buflen, bufp, &rlenp)) {
+               if (errno == E2BIG) {
+                       fprintf(stderr, "dm_get_events buffer too small, "
+                               "should be %d bytes\n", rlenp);
+               } else {
+                       fprintf(stderr, "dm_get_events failed, (%d)%s\n",
+                               errno, strerror(errno));
+               }
+               exit(1);
+       }
+       fprintf(stdout, "rlenp is %d\n", rlenp);
+
+       if (rlenp == 0)
+               return(0);
+
+       msg = bufp;
+       while (msg != NULL) {
+               print_one_message(msg);
+               msg = DM_STEP_TO_NEXT(msg, dm_eventmsg_t *);
+       }
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/get_fileattr.c b/dmapi/src/suite1/cmd/get_fileattr.c
new file mode 100644 (file)
index 0000000..e66ae60
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+extern int     optind;
+extern int     opterr;
+extern char    *optarg;
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "Usage: %s [-a|-A] [-s sid] [-t token] pathname\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token = DM_NO_TOKEN;
+       char            buffer[500];
+       void            *hanp;
+       size_t          hlen;
+       dm_stat_t       dmstat;
+       char            *pathname;
+       int             a_flag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       opterr = 0;
+       while ((opt = getopt(argc, argv, "Aas:t:")) != EOF) {
+               switch (opt) {
+               case 'A':
+                       a_flag = 2;
+                       break;
+               case 'a':
+                       a_flag = 1;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 't':
+                       token = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc) {
+               usage();
+       }
+       pathname = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       if (!a_flag) {
+               fprintf(stdout, "path            %s\n", pathname);
+
+               /* Get the file's state, print it, then verify it against
+                  what is in the file's stat block.
+               */
+
+               if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+                       fprintf(stderr, "dm_path_to_handle failed, %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+
+               if (dm_get_fileattr(sid, hanp, hlen, token,
+       DM_AT_EMASK|DM_AT_PMANR|DM_AT_PATTR|DM_AT_DTIME|DM_AT_CFLAG|DM_AT_STAT,
+                   &dmstat)) {
+                       fprintf(stderr, "dm_get_fileattr failed, %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+
+               print_state(&dmstat);
+               (void)validate_state(&dmstat, pathname, 1);
+/* XXX Shut off for now
+       } else {
+               if ((rc = filesys_bulkscan_init(pathname, &scanp)) != 0) {
+                       fprintf(stderr, "filesys_bulkscan failed, %s\n",
+                               fileio_err_image(rc));
+                       exit(1);
+               }
+               for (;;) {
+                       rc = filesys_bulkscan_read(scanp, &fhandle, &fullstat);
+                       if (rc != FILEIO_NOERROR)
+                               break;
+
+                       (void)fhandle_to_buffer(&fhandle, buffer, sizeof(buffer));
+                       if (a_flag == 1) {
+                               fprintf(stdout, "handle          %s\n", buffer);
+                               print_state(&fullstat);
+                               fprintf(stdout, "--------------------------\n");
+                       } else {
+                               fprintf(stdout, "%s|", buffer);
+                               print_line(&fullstat);
+                       }
+               }
+
+               if (rc != FILEIO_ENDOFSCAN) {
+                       fprintf(stderr, "filesys_bulkscan_read failed, %s\n",
+                               fileio_err_image(rc));
+                       exit(1);
+               }
+               if ((rc = filesys_bulkscan_close(&scanp)) != 0) {
+                       fprintf(stderr, "filesys_bulkscan_close failed, %s\n",
+                               fileio_err_image(rc));
+                       exit(1);
+               }
+XXX Shut off for now.  */
+       }
+}
diff --git a/dmapi/src/suite1/cmd/get_mountinfo.c b/dmapi/src/suite1/cmd/get_mountinfo.c
new file mode 100644 (file)
index 0000000..763e044
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <string.h>
+
+#include <lib/hsm.h>
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_mountinfo().  The
+command line is:
+
+       get_mountinfo [-b buflen] [-s sid] pathname
+
+where pathname is the name of a file, buflen is the size of the buffer to use
+in the call, and sid is the session ID whose attributes you are interested in.
+
+----------------------------------------------------------------------------*/
+
+  /*
+   * 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"
+#ifdef __sgi
+#define VALLLD "\t%-15s %lld\n"
+#else
+#define VALLLD "\t%-15s %ld\n"
+#endif
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-b buflen] [-s sid] pathname\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname;
+       void            *bufp;
+       size_t          buflen = 10000;
+       size_t          rlenp;
+       void            *fshanp;
+       size_t           fshlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:s:")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       buflen = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_fshandle(pathname, &fshanp, &fshlen)) {
+               fprintf(stderr, "can't get fshandle for file %s, %s\n",
+                       pathname, strerror(errno));
+               exit(1);
+       }
+
+       if (buflen > 0) {
+               if ((bufp = malloc(buflen)) == NULL) {
+                       fprintf(stderr, "malloc failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+       }
+
+       if (dm_get_mountinfo(sid, fshanp, fshlen, DM_NO_TOKEN, buflen,
+           bufp, &rlenp)) {
+               if (errno == E2BIG) {
+                       fprintf(stderr, "dm_get_mountinfo buffer too small, "
+                               "should be %d bytes\n", rlenp);
+               } else {
+                       fprintf(stderr, "dm_get_mountinfo failed, %s\n",
+                               strerror(errno));
+               }
+               exit(1);
+       }
+       fprintf(stdout, "rlenp is %d\n", rlenp);
+       print_one_mount_event(bufp);
+
+       dm_handle_free(fshanp, fshlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/get_region.c b/dmapi/src/suite1/cmd/get_region.c
new file mode 100644 (file)
index 0000000..aa8a6fa
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_set_region().  The
+command line is:
+
+       get_region [-n nelem] [-s sid] pathname
+
+where pathname is the name of a file, nelem is the number of regions to pass
+in the call, and sid is the session ID whose events you you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static struct  {
+       char    *name;
+       int     value;
+} rg_events[3] = {
+       { "DM_REGION_READ", DM_REGION_READ },
+       { "DM_REGION_WRITE", DM_REGION_WRITE },
+       { "DM_REGION_TRUNCATE", DM_REGION_TRUNCATE }
+};
+static int     nevents = sizeof(rg_events)/sizeof(rg_events[0]);
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-n nelem] [-s sid] pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_region_t     *regbufp = NULL;
+       char            *pathname = NULL;
+       u_int           nelemp;
+       u_int           nelem = 1;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "n:s:")) != EOF) {
+               switch (opt) {
+               case 'n':
+                       nelem = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       if (nelem > 0) {
+               if ((regbufp = calloc(nelem, sizeof(*regbufp))) == NULL) {
+                       fprintf(stderr, "calloc failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+       }
+
+       if (dm_get_region(sid, hanp, hlen, DM_NO_TOKEN, nelem, regbufp,
+           &nelemp)) {
+               fprintf(stderr, "dm_get_region failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       fprintf(stdout, "%d regions\n", nelemp);
+
+       for (i = 0; i < nelemp; i++) {
+#ifdef VERITAS_21
+               fprintf(stdout, "offset %d, size %d, flags 0x%x\n",
+#else
+               fprintf(stdout, "offset %lld, size %lld, flags 0x%x\n",
+#endif
+                       regbufp[i].rg_offset, regbufp[i].rg_size,
+                       regbufp[i].rg_flags);
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/getall_disp.c b/dmapi/src/suite1/cmd/getall_disp.c
new file mode 100644 (file)
index 0000000..dd0608e
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_getall_disp().  The
+command line is:
+
+       getall_disp [-b buflen] sid
+
+where buflen is the size of the buffer to use, and sid is the session ID
+whose dispositions you you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-b buflen] sid\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_dispinfo_t   *disp;
+       dm_sessid_t     sid;
+       void            *bufp;
+       size_t          buflen = 10000;
+       void            *hanp;
+       size_t          hlen;
+       char            hans1[HANDLE_STR];
+       size_t          rlenp;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       buflen = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       sid = atol(argv[optind]);
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+
+       if (buflen > 0) {
+               if ((bufp = malloc(buflen)) == NULL) {
+                       fprintf(stderr, "malloc failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+       }
+
+       if (dm_getall_disp(sid, buflen, bufp, &rlenp)) {
+               if (errno == E2BIG) {
+                       fprintf(stderr, "dm_getall_disp buffer too small, "
+                               "should be %d bytes\n", rlenp);
+               } else {
+                       fprintf(stderr, "dm_getall_disp failed, %s\n",
+                               strerror(errno));
+               }
+               exit(1);
+       }
+       fprintf(stdout, "rlenp is %d\n", rlenp);
+       if (rlenp == 0)
+               return(0);
+
+       disp = bufp;
+       while (disp != NULL) {
+               hanp = DM_GET_VALUE(disp, di_fshandle, void *);
+               hlen = DM_GET_LEN(disp, di_fshandle);
+               if (hanp && hlen) {
+                       hantoa(hanp, hlen, hans1);
+               } else {
+                       sprintf(hans1, "<BAD HANDLE, hlen %d>", hlen);
+               }
+               printf("%-15s %s dm_eventset_t 0%llo\n",
+                       "fshandle", hans1,
+                       disp->di_eventset);
+
+               disp = DM_STEP_TO_NEXT(disp, dm_dispinfo_t *);
+       }
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/getall_dmattr.c b/dmapi/src/suite1/cmd/getall_dmattr.c
new file mode 100644 (file)
index 0000000..3c3bc40
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_getall_dmattr().  The
+command line is:
+
+       getall_dmattr [-b buflen] [-s sid] pathname
+
+where pathname is the name of a file, buflen is the size of the buffer to use
+in the call, and sid is the session ID whose attributes you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-b buflen] [-s sid] pathname\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname;
+       void            *bufp;
+       size_t          buflen = 10000;
+       size_t          rlenp;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:s:")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       buflen = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s, %s\n",
+                       pathname, strerror(errno));
+               exit(1);
+       }
+
+       if ((bufp = malloc(buflen == 0 ? 1 : buflen)) == NULL) {
+               fprintf(stderr, "malloc failed, %s\n", strerror(errno));
+               exit(1);
+       }
+
+       if (dm_getall_dmattr(sid, hanp, hlen, DM_NO_TOKEN, buflen,
+           bufp, &rlenp)) {
+               if (errno == E2BIG) {
+                       fprintf(stderr, "dm_getall_dmattr buffer too small, "
+                               "should be %d bytes\n", rlenp);
+               } else {
+                       fprintf(stderr, "dm_getall_dmattr failed, %s\n",
+                               strerror(errno));
+               }
+               exit(1);
+       }
+       fprintf(stdout, "rlenp is %d\n", rlenp);
+       if (rlenp > 0) {
+               dm_attrlist_t   *attrlist;
+
+               fprintf(stdout, "DMAPI attributes are:\n");
+
+               attrlist = (dm_attrlist_t *)bufp;
+               while (attrlist != NULL) {
+                       fprintf(stdout, "Name: %s, length %d, value '%s'\n",
+                               attrlist->al_name.an_chars,
+                               DM_GET_LEN(attrlist, al_data),
+                               DM_GET_VALUE(attrlist, al_data, char *));
+
+                       attrlist = DM_STEP_TO_NEXT(attrlist, dm_attrlist_t *);
+               }
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/handle_to_fshandle.c b/dmapi/src/suite1/cmd/handle_to_fshandle.c
new file mode 100644 (file)
index 0000000..b7d33df
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/* Given an object's handle, print the filesystem handle. */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test dm_handle_to_fshandle().  The command line is:
+
+        path_to_fshandle handle
+
+where handle is an object's handle.
+
+----------------------------------------------------------------------------*/
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s handle\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+       char            *han_str;
+       char            *name;
+       void            *hanp, *fshanp;
+       size_t          hlen, fshlen;
+       char            buffer[100];
+       int             error;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       if (argc != 2)
+               usage();
+       han_str = argv[1];
+
+       (void)dm_init_service(&name);
+
+       if ((error = atohan(han_str, &hanp, &hlen)) != 0) {
+               fprintf(stderr, "atohan() failed, %s\n", strerror(error));
+               return(1);
+       }
+
+       if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen) != 0) {
+               fprintf(stderr, "dm_handle_to_fshandle failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+       hantoa(fshanp, fshlen, buffer);
+       fprintf(stdout, "%s\n", buffer);
+
+       dm_handle_free(hanp, hlen);
+       dm_handle_free(fshanp, fshlen);
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/handle_to_path.c b/dmapi/src/suite1/cmd/handle_to_path.c
new file mode 100644 (file)
index 0000000..305023a
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lib/dmport.h>
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_handle_to_path().  The
+command line is:
+
+        handle_to_path [-b buflen] dirpath objpath
+
+There are two parameters.  The first is the pathname of a directory,
+and the second is the pathname of a file, directory, or symbolic link
+within that directory.  The second parameter can also be the same as
+the first if you want to specify "." (this is how EMASS uses it).
+Pathnames can either be relative or full.
+
+buflen is the size of the buffer to use in the call.
+
+This program will return the full pathname of the object which is the
+second parameter using the dm_handle_to_path() function.
+
+The program should work successfully for files, directories, and
+symbolic links, and does not have to work for any other type of
+object.  It doesn't have to work across mount points.  There shouldn't
+be any "/." crud on the end of the returned pathname either.
+
+----------------------------------------------------------------------------*/
+
+extern int     optind;
+extern char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-b buflen] dirpath objpath\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+       char            *dirpath;
+       char            *objpath;
+       void            *hanp1, *hanp2, *hanp1a;
+       size_t          hlen1, hlen2, hlen1a;
+       void            *pathbufp;
+       size_t          buflen = 1024;
+       size_t          rlenp;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       buflen = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       dirpath = argv[optind++];
+       objpath = argv[optind];
+
+       if (dm_init_service(&name)) {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               return(1);
+       }
+
+printf("about to call dm_path_to_handle for %s\n", dirpath);
+       if (dm_path_to_handle(dirpath, &hanp1, &hlen1)) {
+               fprintf(stderr, "dm_path_to_handle failed for %s, (%d) %s\n",
+                       dirpath, errno, strerror(errno));
+               return(1);
+       }
+printf("about to call path_to_handle for %s\n", dirpath);
+       if (path_to_handle(dirpath, &hanp1a, &hlen1a)) {
+               fprintf(stderr, "path_to_handle failed for %s, (%d) %s\n",
+                       dirpath, errno, strerror(errno));
+               return(1);
+       }
+       if(hlen1 != hlen1a){
+               fprintf(stderr, "dm_path_to_handle != path_to_handle, %d != %d\n",
+                       hlen1, hlen1a);
+       }
+       if( memcmp(hanp1, hanp1a, hlen1) != 0 ){
+               fprintf(stderr, "dm_path_to_handle != path_to_handle, handles differ\n");
+       }
+printf("about to call dm_path_to_handle for %s\n", objpath);
+       if (dm_path_to_handle(objpath, &hanp2, &hlen2)) {
+               fprintf(stderr, "dm_path_to_handle failed for %s, (%d) %s\n",
+                       objpath, errno, strerror(errno));
+               return(1);
+       }
+
+       if ((pathbufp = malloc(buflen == 0 ? 1 : buflen)) == NULL) {
+               fprintf(stderr, "malloc failed\n");
+               return(1);
+       }
+
+printf("about to call handle_to_path\n");
+       if (dm_handle_to_path(hanp1, hlen1, hanp2, hlen2,
+           buflen, pathbufp, &rlenp)) {
+               if (errno == E2BIG) {
+                       fprintf(stderr, "dm_handle_to_path buffer too small, "
+                               "should be %d bytes\n", rlenp);
+               } else {
+                       fprintf(stderr, "dm_handle_to_path failed, (%d) %s\n",
+                               errno, strerror(errno));
+               }
+               return(1);
+       }
+       fprintf(stderr, "rlenp is %d, pathbufp is %s\n", rlenp, pathbufp);
+       if (strlen(pathbufp) + 1 != rlenp) {
+               fprintf(stderr, "rlenp is %d, should be %d\n", rlenp,
+                       strlen(pathbufp) + 1);
+               return(1);
+       }
+}
diff --git a/dmapi/src/suite1/cmd/init_service.c b/dmapi/src/suite1/cmd/init_service.c
new file mode 100644 (file)
index 0000000..c9843d2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test dm_init_service().  The command line is:
+
+        init_service
+
+----------------------------------------------------------------------------*/
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+       char            *name;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       if (argc != 1)
+               usage();
+
+       (void)dm_init_service(&name);
+       fprintf(stdout, "%s\n", name);
+
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/link_test.c b/dmapi/src/suite1/cmd/link_test.c
new file mode 100644 (file)
index 0000000..e63a2ad
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/dmport.h>
+
+/*
+       The variable 'flags' was used with two different meanings within
+        the spec.  Sometimes it was an int, and sometimes a u_int.  I 
+        changed all the u_int references to use the new symbol uflags.
+
+        The variable 'rlenp' was also used with two different meanings;
+        sometimes size_t, and sometimes dm_size_t.  I introduced the new
+       symbol 'dmrlenp' for the dm_size_t cases.
+*/
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid, oldsid, targetsid, *newsidp, *sidbufp;
+       dm_token_t      token, *tokenp, *rtokenp, *tokenbufp;
+       dm_attrname_t   *attrnamep;
+       dm_off_t        off, *offp, *roffp;
+       dm_extent_t     *extentp;
+       dm_inherit_t    *inheritbufp;
+       dm_stat_t       *statp;
+       dm_size_t       len, *dmrlenp, *retvalp;
+       dm_attrloc_t    *locp;
+       dm_eventset_t   *eventsetp;
+       dm_config_t     flagname;
+       dm_region_t     *regbufp;
+       dm_response_t   response;
+       dm_right_t      right, *rightp;
+       dm_igen_t       igen, *igenp;
+       dm_msgtype_t    msgtype;
+       dm_fileattr_t   *attrp;
+       dm_boolean_t    enable, *exactflagp;
+       dm_timestruct_t *delay;
+       mode_t          mode;
+       size_t          hlen, dirhlen, hlen1, hlen2, targhlen, *fshlenp, *hlenp;
+       size_t          msglen, buflen, *rlenp;
+       u_int           nelem, mask, maxmsgs, uflags, *nelemp, maxevent;
+       void            *hanp, *dirhanp, *hanp1, *hanp2, *targhanp;
+       void            *msgdatap, *bufp, **hanpp, *respbufp, **fshanpp;
+       dm_fsid_t       fsid, *fsidp;
+       dm_ino_t        ino, *inop;
+       char            *cname, *sessinfop, *path, *pathbufp, **versionstrpp;
+       int             flags, fd, setdtime, reterror;
+       u_int   urc;
+       int     rc;
+       dm_ssize_t      ssrc;
+
+/* Definitions per the prototypes in dmport.h, in the same order. */
+
+       rc = dm_clear_inherit(sid, hanp, hlen, token, attrnamep);
+       rc = dm_create_by_handle(sid, dirhanp, dirhlen, token,
+               hanp, hlen, cname);
+       rc = dm_create_session(oldsid, sessinfop, newsidp);
+       rc = dm_create_userevent(sid, msglen, msgdatap, tokenp);
+       rc = dm_destroy_session(sid);
+       rc = dm_downgrade_right(sid, hanp, hlen, token);
+       rc = dm_fd_to_handle(fd, hanpp, hlenp);
+       rc = dm_find_eventmsg(sid, token, buflen, bufp, rlenp);
+       rc = dm_get_allocinfo(sid, hanp, hlen,
+               token, offp, nelem, extentp, nelemp);
+       rc = dm_get_bulkall(sid, hanp, hlen, token, mask, attrnamep,
+               locp, buflen, bufp, rlenp);
+       rc = dm_get_bulkattr(sid, hanp, hlen, token, mask, locp, buflen, 
+               bufp, rlenp);
+       rc = dm_get_config(hanp, hlen, flagname, retvalp);
+       rc = dm_get_config_events(hanp, hlen, nelem, eventsetp, nelemp);
+       rc = dm_get_dirattrs(sid, hanp, hlen, token, mask, locp, buflen,
+               bufp, rlenp);
+       rc = dm_get_dmattr(sid, hanp, hlen, token, attrnamep, buflen,
+               bufp, rlenp);
+       rc = dm_get_eventlist(sid, hanp, hlen, token, nelem, eventsetp, nelemp);
+       rc = dm_get_events(sid, maxmsgs, flags, buflen, bufp, rlenp);
+       rc = dm_get_fileattr(sid, hanp, hlen, token, mask, statp);
+       rc = dm_get_mountinfo(sid, hanp, hlen, token, buflen, bufp, rlenp);
+       rc = dm_get_region(sid, hanp, hlen, token, nelem, regbufp, nelemp);
+       rc = dm_getall_disp(sid, buflen, bufp, rlenp);
+       rc = dm_getall_dmattr(sid, hanp, hlen, token, buflen, bufp, rlenp);
+       rc = dm_getall_inherit(sid, hanp, hlen,
+               token, nelem, inheritbufp, nelemp);
+       rc = dm_getall_sessions(nelem, sidbufp, nelemp);
+       rc = dm_getall_tokens(sid, nelem, tokenbufp, nelemp);
+       rc = dm_handle_cmp(hanp1, hlen1, hanp2, hlen2);
+       dm_handle_free(hanp, hlen);
+       urc = dm_handle_hash(hanp, hlen);
+       rc = dm_handle_is_valid(hanp, hlen);
+       rc = dm_handle_to_fshandle(hanp, hlen, fshanpp, fshlenp);
+       rc = dm_handle_to_fsid(hanp, hlen, fsidp);
+       rc = dm_handle_to_igen(hanp, hlen, igenp);
+       rc = dm_handle_to_ino(hanp, hlen, inop);
+       rc = dm_handle_to_path(dirhanp, dirhlen, targhanp, targhlen, 
+               buflen, pathbufp, rlenp);
+       rc = dm_init_attrloc(sid, hanp, hlen, token, locp);
+       rc = dm_init_service(versionstrpp);
+       rc = dm_make_handle(&fsid, &ino, &igen, hanpp, hlenp);
+       rc = dm_make_fshandle(&fsid, hanpp, hlenp);
+       rc = dm_mkdir_by_handle(sid, dirhanp, dirhlen, token,
+               hanp, hlen, cname); 
+       rc = dm_move_event(sid, token, targetsid, rtokenp);
+       rc = dm_obj_ref_hold(sid, token, hanp, hlen);
+       rc = dm_obj_ref_query(sid, token, hanp, hlen);
+       rc = dm_obj_ref_rele(sid, token, hanp, hlen);
+       rc = dm_path_to_fshandle(path, hanpp, hlenp);
+       rc = dm_path_to_handle(path, hanpp, hlenp);
+       rc = dm_pending(sid, token, delay);
+       rc = dm_probe_hole(sid, hanp, hlen, token, off, len, roffp, dmrlenp);
+       rc = dm_punch_hole(sid, hanp, hlen, token, off, len);
+       rc = dm_query_right(sid, hanp, hlen, token, rightp);
+       rc = dm_query_session(sid, buflen, bufp, rlenp);
+       ssrc = dm_read_invis(sid, hanp, hlen, token, off, len, bufp);
+       rc =  dm_release_right(sid, hanp, hlen, token);
+       rc = dm_remove_dmattr(sid, hanp, hlen, token, setdtime, attrnamep);
+       rc = dm_request_right(sid, hanp, hlen, token, uflags, right);
+       rc = dm_respond_event(sid, token, response, reterror, buflen, respbufp);
+       rc = dm_send_msg(sid, msgtype, buflen, bufp);
+       rc = dm_set_disp(sid, hanp, hlen, token, eventsetp, maxevent);
+       rc = dm_set_dmattr(sid, hanp, hlen,
+               token, attrnamep, setdtime, buflen, bufp);
+       rc = dm_set_eventlist(sid, hanp, hlen, token, eventsetp, maxevent);
+       rc = dm_set_fileattr(sid, hanp, hlen, token, mask, attrp);
+       rc = dm_set_inherit(sid, hanp, hlen, token, attrnamep, mode);
+       rc = dm_set_region(sid, hanp, hlen, token, nelem, regbufp, exactflagp);
+       rc = dm_set_return_on_destroy(sid, hanp, hlen,
+               token,  attrnamep, enable);
+       rc = dm_symlink_by_handle(sid, dirhanp, dirhlen, token,
+               hanp, hlen, cname, path); 
+       rc = dm_sync_by_handle(sid, hanp, hlen, token);
+       rc = dm_upgrade_right(sid, hanp, hlen, token);
+       ssrc = dm_write_invis(sid, hanp, hlen, flags, token, off, len, bufp);
+}
diff --git a/dmapi/src/suite1/cmd/make_rt_sparse.c b/dmapi/src/suite1/cmd/make_rt_sparse.c
new file mode 100644 (file)
index 0000000..078d12b
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/*
+ *     Create file with XFS_XFLAG_REALTIME set.
+ */
+
+#include <sys/types.h>
+/* #include <sys/fs/xfs_itable.h> */
+#ifdef linux
+#else
+#include <sys/syssgi.h>
+#include <sys/uuid.h>
+#include <sys/fs/xfs_fsops.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+/* Note: In order to figure out the filesystem geometry, you have to run this
+   program as root.  Creating the file itself can be done by anyone.
+*/
+
+
+static char *  prog;
+
+static void
+Usage(void)
+{
+       fprintf(stderr,"Usage: %s filename\n", prog);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       xfs_fsop_geom_t geom;
+       struct  fsxattr fsx;
+       struct  dioattr dio;
+       char    *pathname;
+       u_int   buflen;
+       char    *buf;
+       ssize_t offset;
+       ssize_t count;
+       int     fd;
+       int     i;
+
+       if (prog = strrchr(argv[0], '/')) {
+               *prog++;
+       } else {
+               prog = argv[0];
+       }
+
+       if (argc != 2)
+               Usage();
+       pathname = argv[1];
+
+       /* Create the file. */
+
+       if ((fd = open(pathname, O_RDWR|O_CREAT|O_EXCL|O_DIRECT, 0600)) < 0) {
+               fprintf(stderr,"%s: Cannot open %s, %s\n", prog,
+                       pathname, strerror(errno));
+               exit(1);
+       }
+
+       /* Determine the filesystem's realtime partition geometry. */
+
+       if (syssgi(SGI_XFS_FSOPERATIONS, fd, XFS_FS_GEOMETRY, NULL, &geom)) {
+               fprintf(stderr,"%s: syssgi(,XFS_FS_GEOMETRY) failed, %s\n",
+                       prog, strerror(errno));
+               exit(1);
+       }
+
+       /* Make the file a realtime file. */
+
+       fsx.fsx_xflags = 1; /*XFS_XFLAG_REALTIME*/
+       fsx.fsx_extsize = 4 * geom.blocksize * geom.rtextsize;
+       if (fcntl(fd, F_FSSETXATTR, &fsx) < 0) {
+               fprintf(stderr,"%s: fcntl(,F_FSSETXATTR) failed, %s\n", prog,
+                       strerror(errno));
+               exit(1);
+       }
+
+       /* Obtain the direct I/O parameters. */
+
+       if (fcntl(fd, F_DIOINFO, &dio) < 0) {
+               fprintf(stderr,"%s: fcntl(,F_DIOINFO) failed,%s\n",
+                       prog, strerror(errno));
+               exit(1);
+       }
+       fprintf(stdout, "%s: file %s direct io requirements.\n", prog,
+               pathname);
+       fprintf(stdout, "%7d memory alignment.\n", dio.d_mem);
+       fprintf(stdout, "%7d minimum io size.\n", dio.d_miniosz);
+       fprintf(stdout, "%7d maximum io size.\n", dio.d_maxiosz);
+
+       if (fcntl(fd, F_FSGETXATTR, &fsx) < 0) {
+               fprintf(stderr,"%s: fcntl(,F_FSGETXATTR) failed, %s\n", prog,
+                       strerror(errno));
+               exit(1);
+       }
+       fprintf(stdout, "%7d realtime extent size.\n", fsx.fsx_extsize);
+
+       /* Malloc and zero a buffer to use for writes. */
+
+       buflen = dio.d_miniosz;
+       if ((buf = memalign(dio.d_mem, buflen)) == NULL) {
+               fprintf(stderr,"%s: memalign(%d,%d) returned NULL\n",
+                               prog, dio.d_mem, buflen);
+               exit(1);
+       }
+       memset(buf, '\0', buflen);
+
+       for (i = 0; i < 10; i += 2) {
+               offset = i * fsx.fsx_extsize;
+               if (lseek(fd, offset, SEEK_SET) < 0) {
+                       fprintf(stderr, "seek to %d failed, %s\n", offset,
+                               strerror(errno));
+                       exit(1);
+               }
+               if ((count = write(fd, buf, buflen)) < 0) {
+                       fprintf(stderr, "write of %d bytes failed at offset "
+                               "%d, , %s\n", buflen, offset, strerror(errno));
+                       exit(1);
+               }
+               if (count != buflen) {
+                       fprintf(stderr, "expected to write %d bytes at offset "
+                               "%d, actually wrote %d\n", buflen, offset,
+                               count);
+                       exit(1);
+               }
+       }
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/make_sparse.c b/dmapi/src/suite1/cmd/make_sparse.c
new file mode 100644 (file)
index 0000000..0869b3d
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/*
+ *
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static char *  prog;
+
+static void
+Usage(void)
+{
+       fprintf(stderr,"Usage: %s filename\n", prog);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       char    *pathname;
+       u_int   buflen;
+       char    *buf;
+       ssize_t offset;
+       ssize_t count;
+       int     fd;
+       int     i;
+
+       prog = argv[0];
+
+       if (argc != 2)
+               Usage();
+       pathname = argv[1];
+
+       /* Create the file and make it a regular file. */
+
+       if ((fd = open(pathname, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0) {
+               fprintf(stderr,"%s: Cannot open %s, %s\n", prog,
+                       pathname, strerror(errno));
+               exit(1);
+       }
+
+       /* Malloc and zero a buffer to use for writes. */
+
+       buflen = 1;
+       if ((buf = malloc(buflen)) == NULL) {
+               fprintf(stderr,"%s: malloc(%d) returned NULL\n",
+                       prog, buflen);
+               exit(1);
+       }
+       memset(buf, '\0', buflen);
+
+       for (i = 0; i < 200; i += 2) {
+               offset = i * 65536;
+               if (lseek(fd, offset, SEEK_SET) < 0) {
+                       fprintf(stderr, "seek to %d failed, %s\n", offset,
+                               strerror(errno));
+                       exit(1);
+               }
+               if ((count = write(fd, buf, buflen)) < 0) {
+                       fprintf(stderr, "write of %d bytes failed at offset "
+                               "%d, , %s\n", buflen, offset, strerror(errno));
+                       exit(1);
+               }
+               if (count != buflen) {
+                       fprintf(stderr, "expected to write %d bytes at offset "
+                               "%d, actually wrote %d\n", buflen, offset,
+                               count);
+                       exit(1);
+               }
+       }
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/obj_ref_hold.c b/dmapi/src/suite1/cmd/obj_ref_hold.c
new file mode 100644 (file)
index 0000000..e962a1d
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_obj_ref_hold().  The
+command line is:
+
+       obj_ref_hold {-F} [-s sid] token {pathname|handle}
+
+where:
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-s sid] token {pathname|handle}\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       char            *object;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fs:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (dm_obj_ref_hold(sid, token, hanp, hlen)) {
+               fprintf(stderr, "dm_obj_ref_hold failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/cmd/obj_ref_query.c b/dmapi/src/suite1/cmd/obj_ref_query.c
new file mode 100644 (file)
index 0000000..df4055e
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_obj_ref_query().  The
+command line is:
+
+       obj_ref_query {-F} [-s sid] token {pathname|handle}
+
+where:
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-s sid] token {pathname|handle}\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       char            *object;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       char            *name;
+       int             error;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fs:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if ((error = dm_obj_ref_query(sid, token, hanp, hlen)) < 0) {
+               fprintf(stderr, "dm_obj_ref_query failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       if (error == 1) {
+               fprintf(stdout, "there is a hold\n");
+       } else {
+               fprintf(stdout, "there is no hold\n");
+       }
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/cmd/obj_ref_rele.c b/dmapi/src/suite1/cmd/obj_ref_rele.c
new file mode 100644 (file)
index 0000000..ca88bbb
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_obj_ref_rele().  The
+command line is:
+
+       obj_ref_rele {-F} [-s sid] token {pathname|handle}
+
+where:
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-s sid] token {pathname|handle}\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       char            *object;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fs:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (dm_obj_ref_rele(sid, token, hanp, hlen)) {
+               fprintf(stderr, "dm_obj_ref_rele failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/cmd/path_to_fshandle.c b/dmapi/src/suite1/cmd/path_to_fshandle.c
new file mode 100644 (file)
index 0000000..329dcd7
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/* Given a file object's pathname, print the filesystem handle. */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test dm_path_to_fshandle().  The command line is:
+
+        path_to_fshandle pathname
+
+where pathname is the name of a file, directory, or symlink.
+
+----------------------------------------------------------------------------*/
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+       char            *pathname;
+       char            *name;
+       void            *fshanp;
+       size_t          fshlen;
+       char            buffer[100];
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       if (argc != 2)
+               usage();
+       pathname = argv[1];
+
+       (void)dm_init_service(&name);
+
+       if (dm_path_to_fshandle(pathname, &fshanp, &fshlen) != 0) {
+               fprintf(stderr, "dm_path_to_fshandle failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+       hantoa(fshanp, fshlen, buffer);
+       fprintf(stdout, "%s\n", buffer);
+
+       dm_handle_free(fshanp, fshlen);
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/path_to_handle.c b/dmapi/src/suite1/cmd/path_to_handle.c
new file mode 100644 (file)
index 0000000..162d64a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/* Given a file object's pathname, print the object's handle. */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test dm_path_to_handle().  The command line is:
+
+        path_to_handle pathname
+
+where pathname is the name of a file, directory, or symlink.
+
+----------------------------------------------------------------------------*/
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+       char            *pathname;
+       char            *name;
+       void            *hanp;
+       size_t          hlen;
+       char            buffer[100];
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       if (argc != 2)
+               usage();
+       pathname = argv[1];
+
+       (void)dm_init_service(&name);
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen) != 0) {
+               fprintf(stderr, "dm_path_to_handle failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+       hantoa(hanp, hlen, buffer);
+       fprintf(stdout, "%s\n", buffer);
+
+       dm_handle_free(hanp, hlen);
+       return(0);
+}
diff --git a/dmapi/src/suite1/cmd/pending.c b/dmapi/src/suite1/cmd/pending.c
new file mode 100644 (file)
index 0000000..2c1c0d6
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_pending().  The
+command line is:
+
+       pending sid token
+
+where sid is the session ID whose event you are responding to.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s sid token\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc, 
+       char            **argv)
+{
+       dm_sessid_t     sid;
+       char            *name;
+       dm_token_t      token;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       if (argc != 3)
+               usage();
+
+       sid = atol(argv[1]);
+       token = atol(argv[2]);
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+
+       if (dm_pending(sid, token, NULL)) {
+               fprintf(stderr, "dm_pending failed, %s\n", strerror(errno));
+               exit(1);
+       }
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/print_event.c b/dmapi/src/suite1/cmd/print_event.c
new file mode 100644 (file)
index 0000000..f2e67a9
--- /dev/null
@@ -0,0 +1,1198 @@
+
+
+/*
+ * 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"
+#ifdef __sgi
+#define VALLLD "\t%-15s %lld\n"
+#else
+#define VALLLD "\t%-15s %ld\n"
+#endif
+
+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_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   (void);
+
+#define MAXNAMELEN 256
+
+/*
+ * 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;
+
+
+void
+usage(
+      char *prog)
+{
+  fprintf(stderr, "Usage: %s ", prog);
+  fprintf(stderr, " <-S oldsid> <-v verbose> ");
+  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:")) != EOF) {
+    switch (c) {
+    case 's':
+      Sleep = atoi(optarg);
+      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_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();
+  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[MAXNAMELEN], nams2[MAXNAMELEN];
+       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 %d>", hlen1);
+       }
+       if (hanp2 && hlen2) {
+               hantoa(hanp2, hlen2, hans2);
+       } else {
+               sprintf(hans2, "<BAD HANDLE, hlen %d>", hlen2);
+       }
+       if (hanp3 && hlen3) {
+               hantoa(hanp3, hlen3, hans3);
+       } else {
+               sprintf(hans3, "<BAD HANDLE, hlen %d>", hlen3);
+       }
+       if (namp1 && nlen1) {
+               strncpy(nams1, namp1, nlen1);
+               if (nlen1 != sizeof(nams1))
+                       nams1[nlen1] = '\0';
+       } else {
+               sprintf(nams1, "<BAD STRING, nlen %d>", nlen1);
+       }
+       if (namp2 && nlen2) {
+               strncpy(nams2, namp2, nlen2);
+               if (nlen2 != sizeof(nams2))
+                       nams2[nlen2] = '\0';
+       } else {
+               sprintf(nams2, "<BAD STRING, nlen %d>", 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;
+  int                  respond, response, 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], hans3[HANDLE_STR];
+  char                 nams1[MAXNAMELEN], nams2[MAXNAMELEN];
+
+  /*
+   * 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);
+    } 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",          msg_de->de_offset,
+            "length",          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",          msg_de->de_offset,
+            "length",          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",          msg_de->de_offset,
+            "length",          msg_de->de_length);
+      break;
+    }
+  }
+
+  /***** 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));
+    } 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 *);
+               print_one_mount_event(msg_me);
+#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;
+
+    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;
+      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_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");
+       }
+
+       /* 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);
+       }
+
+       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 0
+#if    ! defined ( __sgi ) && ! defined ( VERITAS_21 )
+       DMEV_SET(DM_EVENT_CANCEL, eventlist);   /* not supported on SGI */
+#endif
+#ifndef __sgi
+       DMEV_SET(DM_EVENT_CLOSE, eventlist);    /* not supported on SGI */
+#endif
+#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) {
+               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 0
+#if    ! defined ( __sgi ) && ! defined ( VERITAS_21 )
+       DMEV_SET(DM_EVENT_CANCEL, eventlist);   /* not supported on SGI */
+#endif
+#ifndef __sgi
+       DMEV_SET(DM_EVENT_CLOSE, eventlist);    /* not supported on SGI */
+#endif
+#endif
+       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);
+}
+
+
+/*
+ * 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;
+  size_t       buflen, 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 {
+    ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
+    nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
+    tokenbuf = malloc(nbytes);
+    if (tokenbuf == NULL) {
+      err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
+      error = 1;
+      goto out;
+    }
+    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;
+  }
+
+  for (i = 0; i < ret_ntokens; i++) {
+    if (Verbose)
+      err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
+
+    /*
+     * The E2BIG dance reprise...
+     */
+    do {
+      buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
+      msgbuf = malloc(buflen);
+      if (msgbuf == NULL) {
+       err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
+       error = 1;
+       goto out;
+      }
+      error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
+    } while (error && errno == E2BIG);
+    if (error) {
+      errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
+      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 *);
+    }
+
+    tokenbuf++;
+  }
+
+ 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(void)
+{
+  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 != NULL) {
+    error = dm_destroy_session(sid);
+    if (error == -1) {
+      errno_msg("Can't shut down session - use 'mrmean -kv' to clean up!");
+    }
+  }
+
+  exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/print_fshandle.c b/dmapi/src/suite1/cmd/print_fshandle.c
new file mode 100644 (file)
index 0000000..5bfab99
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/* Given a file pathname, print the filesystem handle and the uuid_t for
+   the filesystem that contains the file.
+*/
+
+#include <sys/types.h>
+#ifdef linux
+#else
+#include <sys/syssgi.h>
+#include <sys/uuid.h>
+#include <sys/fs/xfs_fsops.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <lib/dmport.h>
+
+
+static void
+hantoa(
+        void    *hanp,
+        size_t   hlen,
+        char    *handle_str)
+{
+        u_char  *cp= (u_char *)hanp;
+        int     i;
+
+        for (i = 0;i < hlen; i++, handle_str += 2)
+                sprintf(handle_str, "%.2x", *cp++);
+        *handle_str = '\0';
+}
+
+int
+main(
+       int             argc,
+       char            **argv)
+{
+/*     xfs_fsop_geom_t geom;*/
+       char            *uuid_str;
+       u_int           status;
+       char            *name;
+       int             fd;
+       void            *fshanp;
+       size_t          fshlen;
+       char            buffer[100];
+
+       if (argc != 2) {
+               fprintf(stderr, "usage: %s path\n", argv[0]);
+               exit(1);
+       }
+       (void)dm_init_service(&name);
+
+       if (dm_path_to_fshandle(argv[1], &fshanp, &fshlen) != 0) {
+               fprintf(stderr, "dm_path_to_fshandle failed, %s\n",
+                       strerror(errno));
+       }
+       hantoa(fshanp, fshlen, buffer);
+
+       if ((fd = open(argv[1], O_RDONLY)) < 0) {
+               fprintf(stderr, "Open of %s failed, %s\n", argv[1],
+                       strerror(errno));
+               exit(1);
+       }
+
+/*
+       syssgi(SGI_XFS_FSOPERATIONS, fd, XFS_FS_GEOMETRY, NULL, &geom);
+
+       uuid_to_string(&geom.uuid, &uuid_str, &status);
+
+       fprintf(stdout, "fshandle %s, uuid %s, %s\n",
+               buffer, uuid_str, argv[1]);
+*/
+       fprintf(stdout, "fshandle %s, %s\n",
+               buffer, argv[1]);
+}
diff --git a/dmapi/src/suite1/cmd/probe_hole.c b/dmapi/src/suite1/cmd/probe_hole.c
new file mode 100644 (file)
index 0000000..4c3f3bc
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_probe_hole().  The
+command line is:
+
+       probe_hole [-o offset] [-l length] [-s sid] pathname
+
+where pathname is the name of a file, offset is the offset of the start of
+the proposed punch, and length is the length of the punch.  sid is the
+session ID whose events you you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-o offset] [-l length] "
+               "[-s sid] pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname = NULL;
+       dm_off_t        offset = 0;
+       dm_size_t       length = 0;
+       dm_off_t        roffp;
+       dm_size_t       rlenp;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "o:l:s:")) != EOF) {
+               switch (opt) {
+               case 'o':
+                       offset = atol(optarg);
+                       break;
+               case 'l':
+                       length = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
+           &roffp, &rlenp)) {
+               fprintf(stderr, "dm_probe_hole failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       fprintf(stdout, "roffp is %lld, rlenp is %lld\n", roffp, rlenp);
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/punch_hole.c b/dmapi/src/suite1/cmd/punch_hole.c
new file mode 100644 (file)
index 0000000..e1137ed
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_punch_hole().  The
+command line is:
+
+       punch_hole [-o offset] [-l length] [-s sid] pathname
+
+where pathname is the name of a file, offset is the offset of the start of
+the punch, and length is the length of the punch.  sid is the
+session ID whose events you you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-o offset] [-l length] "
+               "[-s sid] pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname = NULL;
+       dm_off_t        offset = 0;
+       dm_size_t       length = 0;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "o:l:s:")) != EOF) {
+               switch (opt) {
+               case 'o':
+                       offset = atol(optarg);
+                       break;
+               case 'l':
+                       length = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       if (dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length)) {
+               fprintf(stderr, "dm_punch_hole failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/query_right.c b/dmapi/src/suite1/cmd/query_right.c
new file mode 100644 (file)
index 0000000..7b1251a
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_query_right().  The
+command line is:
+
+       query_right [-F] [-s sid] token {pathname|handle}
+
+where
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-s sid] token "
+               "{pathname|handle}\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       dm_right_t      right;
+       char            *object;
+       char            *rightstr;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       int             wflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fs:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (dm_query_right(sid, hanp, hlen, token, &right)) {
+               fprintf(stderr, "dm_query_right failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       fprintf(stderr, "right is %s\n", rt_value_to_name(right));
+
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/cmd/randomize_file.c b/dmapi/src/suite1/cmd/randomize_file.c
new file mode 100644 (file)
index 0000000..c99e382
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+       This program reads the file specified on the command line and
+       produces a new file on stdout which contains the lines from the
+       input file scrambled into a random order.  This is useful for
+       'randomizing' a database to simulate the kind of I/O that will
+       occur when many records have been added and deleted over time.
+*/
+
+#define        FIELD_WIDTH 21
+
+static char    buffer[4096];
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       FILE    *infile;
+       FILE    *tmpfile;
+       char    *path;
+       int     line_count = 0;
+       int     i;
+       int     j;
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: %s infile\n", argv[0]);
+               exit(1);
+       }
+
+       /* Read through the input file and count how many lines are present. */
+
+       if ((infile = fopen(argv[1], "r")) == NULL) {
+               fprintf(stderr, "can't open %s\n", argv[1]);
+               exit(1);
+       }
+       for (;;) {
+               if (fgets(buffer, sizeof(buffer), infile) == NULL) {
+                       if (!ferror(infile))
+                               break;
+                       fprintf(stderr, "Error on infile\n");
+                       exit(1);
+               }
+               line_count++;
+       }
+       fprintf(stderr, "%d lines in input file\n", line_count);
+
+       /* Create a temp file.  Copy the input file to the temp file,
+          prepending a random number in the range
+               0 <= X <= linecount-1
+          to each line copied.
+       */
+
+       path = tmpnam(NULL);
+       if ((tmpfile = fopen(path, "w")) == NULL) {
+               fprintf(stderr, "error opening temp file %s\n", path);
+               exit(1);
+       }
+       rewind(infile);
+       srand48((long)getpid());
+
+       for (i = line_count - 1; i >= 0; i--) {
+               if (fgets(buffer, sizeof(buffer), infile) == NULL) {
+                       if (!ferror(infile))
+                               break;
+                       fprintf(stderr, "Error on infile\n");
+                       exit(1);
+               }
+               j = (int)(drand48() * (float)i);
+               fprintf(tmpfile, "%*d ", FIELD_WIDTH - 1, j);
+               fputs(buffer, tmpfile);
+       }
+       if (fclose(infile)) {
+               fprintf(stderr, "close of input file failed\n");
+               exit(1);
+       }
+       if (fclose(tmpfile)) {
+               fprintf(stderr, "close of temp file %s failed\n", path);
+               exit(1);
+       }
+       fprintf(stderr, "random mapping complete\n");
+
+       /* Use the system sort routine to sort the file into order on the
+          first field, effectively randomizing the lines.
+       */
+
+       sprintf(buffer, "sort +0 -1 -o %s %s", path, path);
+       if (system(buffer)) {
+               fprintf(stderr, "sort call failed\n");
+               exit(1);
+       }
+       fprintf(stderr, "sort complete\n");
+
+       /* Copy the temp file to stdout, removing the prepended field. */
+
+       if ((tmpfile = fopen(path, "rw")) == NULL) {
+               fprintf(stderr, "error reopening temp file %s\n", path);
+               exit(1);
+       }
+
+       for (i = 0; i < line_count; i++) {
+               if (fgets(buffer, sizeof(buffer), tmpfile) == NULL) {
+                       if (!ferror(tmpfile))
+                               break;
+                       fprintf(stderr, "Error on tmpfile\n");
+                       exit(1);
+               }
+               if (fputs(buffer + FIELD_WIDTH, stdout) < 0) {
+                       fprintf(stderr, "Error on outfile\n");
+                       exit(1);
+               }
+       }
+       if (unlink(path)) {
+               fprintf(stderr, "can't unlink %s\n", path);
+               exit(1);
+       }
+}
diff --git a/dmapi/src/suite1/cmd/release_right.c b/dmapi/src/suite1/cmd/release_right.c
new file mode 100644 (file)
index 0000000..40849aa
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_release_right().  The
+command line is:
+
+       release_right {-F} [-s sid] token {pathname|handle}
+
+where:
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-s sid] token {pathname|handle}\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       char            *object;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fs:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (dm_release_right(sid, hanp, hlen, token)) {
+               fprintf(stderr, "dm_release_right failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/cmd/remove_dmattr.c b/dmapi/src/suite1/cmd/remove_dmattr.c
new file mode 100644 (file)
index 0000000..163adbe
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_remove_dmattr().  The
+command line is:
+
+       remove_dmattr [-s sid] [-u] pathname attr
+
+where pathname is the name of a file, attr is the name of the DMAPI attribute,
+and sid is the session ID whose attributes you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-s sid] [-u] pathname attr\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname;
+       dm_attrname_t   *attrnamep;
+       int             setdtime = 0;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "s:u")) != EOF) {
+               switch (opt) {
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 'u':
+                       setdtime = 1;
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       pathname = argv[optind++];
+       attrnamep = (dm_attrname_t *)argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       if (dm_remove_dmattr(sid, hanp, hlen, DM_NO_TOKEN, setdtime,
+          attrnamep)) {
+               fprintf(stderr, "dm_remove_dmattr failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/request_right.c b/dmapi/src/suite1/cmd/request_right.c
new file mode 100644 (file)
index 0000000..3859b38
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_request_right().  The
+command line is:
+
+       request_right [-F] [-w] [-s sid] token {pathname|handle} right
+
+where
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+-w
+       if specified, the DM_RR_WAIT flag will be used.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+right
+       is the dm_right_t to use.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-F] [-w] [-s sid] token "
+               "{pathname|handle} right\n", Progname);
+       fprintf(stderr, "possible rights are:\n");
+       for (i = 0; i < rt_namecnt; i++) {
+               fprintf(stderr, "%s (%d)\n", rt_names[i].name,
+                       rt_names[i].value);
+       }
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       dm_right_t      right;
+       char            *object;
+       char            *rightstr;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       int             wflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fws:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 'w':
+                       wflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 3 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind++];
+       rightstr = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (rt_name_to_value(rightstr, &right)) {
+               fprintf(stderr, "invalid right %s\n", rightstr);
+               usage();
+       }
+
+       if (dm_request_right(sid, hanp, hlen, token,
+           (wflag ? DM_RR_WAIT : 0), right)) {
+               fprintf(stderr, "dm_request_right failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/cmd/respond_event.c b/dmapi/src/suite1/cmd/respond_event.c
new file mode 100644 (file)
index 0000000..59447cf
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_respond_event().  The
+command line is:
+
+       respond_event sid token response reterror
+
+where sid is the session ID whose event you are responding to.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s sid token response reterror\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int             argc, 
+       char            **argv)
+{
+       dm_sessid_t     sid;
+       char            *name;
+       dm_token_t      token;
+       dm_response_t   response;
+       int             reterror;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       if (argc != 5)
+               usage();
+
+       sid = atol(argv[1]);
+       token = atol(argv[2]);
+       response = atol(argv[3]);
+       reterror = atol(argv[4]);
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+
+       if (dm_respond_event(sid, token, response, reterror, 0, NULL)) {
+               fprintf(stderr, "dm_respond_event failed, %d/%s\n",
+                       errno, strerror(errno));
+               exit(1);
+       }
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/rwt.c b/dmapi/src/suite1/cmd/rwt.c
new file mode 100644 (file)
index 0000000..429ffe2
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test DMAPI by issuing read, write, and trunc calls to a
+file.  The command line is:
+
+       rwt [-r|-w|-t] [-o offset] [-l length] pathname
+
+where:
+-r
+       indicates that a read should be done (the default if none specified)
+-w
+       indiates that a write should be done
+-t
+       indicates that a truncate should be done, in which case the -l
+       parameter is ignored.
+-o offset
+       offset at which to begin the read, write or truncate (default is 0).
+-l length
+       the length in bytes to read or write (default is 1).
+pathname
+       the file to be used by the test.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-r|-w|-t] [-o offset] [-l length] "
+               "pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       char            *pathname = NULL;
+       off_t           offset = 0;
+       size_t          length = 1;
+       u_char          ch = 'X';
+       void            *bufp = NULL;
+       off_t           seek_off;
+       int             rflag = 0;
+       int             wflag = 0;
+       int             tflag = 0;
+       int             fd;
+       ssize_t         rc;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "rwto:l:")) != EOF) {
+               switch (opt) {
+               case 'r':
+                       rflag++;
+                       break;
+               case 'w':
+                       wflag++;
+                       break;
+               case 't':
+                       tflag++;
+                       break;
+               case 'o':
+                       offset = atol(optarg);
+                       break;
+               case 'l':
+                       length = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       if (rflag + wflag + tflag > 1)
+               usage();
+       pathname = argv[optind];
+
+       if ((fd = open(pathname, O_RDWR)) < 0) {
+               fprintf(stderr, "open of %s failed, %s\n", pathname,
+                       strerror(errno));
+               exit(1);
+       }
+       if (length > 0) {
+               if ((bufp = malloc(length)) == NULL) {
+                       fprintf(stderr, "malloc of %d bytes failed\n", length);
+                       exit(1);
+               }
+               if (wflag)
+                       memset(bufp, ch, length);
+       }
+
+       if (!tflag) {
+               if ((seek_off = lseek(fd, offset, SEEK_SET)) < 0) {
+                       fprintf(stderr, "seek failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+               if (seek_off != offset) {
+                       fprintf(stderr, "seeked to offset %d, actually "
+                               "arrived at %d\n", offset, seek_off);
+                       exit(1);
+               }
+       }
+
+       if (wflag) {
+               if ((rc = write(fd, bufp, length)) < 0) {
+                       fprintf(stderr, "write failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+               if (rc != length) {
+                       fprintf(stderr, "expected to write %d bytes, actually "
+                               "wrote %d bytes\n", length, rc);
+                       exit(1);
+               }
+       } else if (tflag) {
+               if (ftruncate(fd, offset) != 0) {
+                       fprintf(stderr, "truncate failed, %s\n",
+                               strerror(errno));
+                       exit(1);
+               }
+       } else {
+               if ((rc = read(fd, bufp, length)) < 0) {
+                       fprintf(stderr, "read failed, %s\n", strerror(errno));
+                       exit(1);
+               }
+               if (rc != length) {
+                       fprintf(stderr, "expected to read %d bytes, actually "
+                               "read %d bytes\n", length, rc);
+                       exit(1);
+               }
+       }
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/security_hole.c b/dmapi/src/suite1/cmd/security_hole.c
new file mode 100644 (file)
index 0000000..1bfdbdd
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*
+       To read unallocated disk blocks in a filesystem, do
+               cc -o test thisfile.c
+               ./test myfile
+               cat myfile
+*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+static char    *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-s size] pathname\n", Progname);
+       fprintf(stderr, "\t-s size\t\tsize of file (default 10,000,000 bytes)\n");
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       char    *pathname = NULL;
+       off_t   size = 10000000;
+       char    buff[1];
+       int     method = F_RESVSP;
+       flock_t flock;
+       int     opt;
+       int     fd;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "s:")) != EOF) {
+               switch (opt) {
+               case 's':
+                       size = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       /* Create the file and write one byte at a large offset to create a
+          big hole in the middle of the file.
+       */
+
+       if ((fd = open(pathname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
+               perror("open failed");
+               exit(1);
+       }
+       if (lseek(fd, size, 0) < 0) {
+               perror("lseek failed");
+               exit(1);
+       }
+       buff[0] = '\0';
+       if (write(fd, buff, 1) != 1) {
+               perror("write failed");
+               exit(1);
+       }
+
+       /* Now fill in the hole with uninitialized blocks. */
+
+       flock.l_whence = 0;
+       flock.l_start = 0;
+       flock.l_len = size;
+
+       if (fcntl(fd, method, &flock) < 0) {
+               perror("fcntl failed");
+               exit(1);
+       }
+       printf("%s created\n", pathname);
+}
diff --git a/dmapi/src/suite1/cmd/security_hole2.c b/dmapi/src/suite1/cmd/security_hole2.c
new file mode 100644 (file)
index 0000000..dac11d6
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+       To read unallocated disk blocks in a filesystem, do
+               cc -o test thisfile.c
+               ./test myfile
+               cat myfile
+*/
+
+extern char    *sys_errlist[];
+extern  int     optind;
+extern  char    *optarg;
+
+static char    *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-s size] pathname\n", Progname);
+       fprintf(stderr, "\t-s size\t\tsize of file (default 10,000,000 bytes)\n");
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       char    *pathname = NULL;
+       off_t   size = 10000000;
+       char    buff[1];
+       int     method = F_RESVSP;
+       flock_t flock;
+       int     opt;
+       int     fd;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "s:")) != EOF) {
+               switch (opt) {
+               case 's':
+                       size = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       /* Create the file and write one byte at a large offset to create a
+          big hole in the middle of the file.
+       */
+
+       if ((fd = open(pathname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) {
+               perror("open failed");
+               exit(1);
+       }
+
+       /* First allocate uninitialized blocks. */
+
+       flock.l_whence = 0;
+       flock.l_start = 0;
+       flock.l_len = size;
+
+       if (fcntl(fd, method, &flock) < 0) {
+               perror("fcntl failed");
+               exit(1);
+       }
+
+       /* Now seek out and write the byte. */
+
+       if (lseek(fd, size, 0) < 0) {
+               perror("lseek failed");
+               exit(1);
+       }
+       buff[0] = '\0';
+       if (write(fd, buff, 1) != 1) {
+               perror("write failed");
+               exit(1);
+       }
+       printf("%s created\n", pathname);
+}
diff --git a/dmapi/src/suite1/cmd/set_disp.c b/dmapi/src/suite1/cmd/set_disp.c
new file mode 100644 (file)
index 0000000..736414c
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_set_eventlist().  The
+command line is:
+
+       set_disp [-m max] [-s sid] [-t token] {pathname|handle} [event...]
+       set_disp [-m max] [-s sid] -G [DM_EVENT_MOUNT]
+
+where
+{pathname|handle}
+       is the name of a file or handle whose filesystem is of interest.
+-G
+       if the global handle should be used
+max
+       is the value to use for the maxevent parameter of dm_set_disp(),
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use in place of DM_NO_TOKEN.
+event
+       is zero or more events to set.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-m max] [-s sid] [-t token] "
+               "{pathname|handle} [event...]\n", Progname);
+       fprintf(stderr, "usage:\t%s [-m max] [-s sid] -G [DM_EVENT_MOUNT]\n",
+               Progname);
+       fprintf(stderr, "possible events are:\n");
+       for (i = 0; i < ev_namecnt; i++) {
+               fprintf(stderr, "%s (%d)\n", ev_names[i].name,
+                       ev_names[i].value);
+       }
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token = DM_NO_TOKEN;
+       u_int           maxevent = DM_EVENT_MAX;
+       dm_eventset_t   eventset;
+       void            *fshanp;
+       size_t          fshlen;
+       int             Gflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Gm:s:t:")) != EOF) {
+               switch (opt) {
+               case 'G':
+                       Gflag++;
+                       break;
+               case 'm':
+                       maxevent = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 't':
+                       token = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (Gflag && token != DM_NO_TOKEN)
+               usage();
+       if (optind + (Gflag ? 0 : 1) > argc)
+               usage();
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       DMEV_ZERO(eventset);
+
+       /* Get the file or filesystem's handle. */
+
+       if (Gflag) {
+               fshanp = DM_GLOBAL_HANP;
+               fshlen = DM_GLOBAL_HLEN;
+       } else {
+               char    *object;
+               void    *hanp;
+               size_t  hlen;
+
+               object = argv[optind++];
+
+               if (opaque_to_handle(object, &hanp, &hlen)) {
+                       fprintf(stderr, "can't get handle from %s\n", object);
+                       exit(1);
+               }
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+       }
+
+       for (; optind < argc; optind++) {
+               dm_eventtype_t  event;
+
+               event = ev_name_to_value(argv[optind]);
+               if (event == DM_EVENT_INVALID) {
+                       fprintf(stderr, "invalid event %s\n", argv[optind]);
+                       usage();
+               }
+               DMEV_SET(event, eventset);
+       }
+
+       if (dm_set_disp(sid, fshanp, fshlen, token, &eventset, maxevent)) {
+               fprintf(stderr, "dm_set_disp failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       if (!Gflag)
+               dm_handle_free(fshanp, fshlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/set_dmattr.c b/dmapi/src/suite1/cmd/set_dmattr.c
new file mode 100644 (file)
index 0000000..b510eb5
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_set_dmattr().  The
+command line is:
+
+       set_dmattr [-b buflen] [-s sid] [-u] pathname attr value
+
+where pathname is the name of a file, buflen is the size of the buffer to use
+in the call, attr is the name of the DMAPI attribute, -u is selected if 
+setdtime should be updated, and sid is the session ID whose attributes you
+are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-b buflen] [-s sid] [-u] pathname "
+               "attr value\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname;
+       dm_attrname_t   *attrnamep;
+       char            *bufp;
+       size_t          buflen;
+       int             bflag = 0;
+       int             setdtime = 0;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "b:s:u")) != EOF) {
+               switch (opt) {
+               case 'b':
+                       bflag++;
+                       buflen = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 'u':
+                       setdtime = 1;
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 3 != argc)
+               usage();
+       pathname = argv[optind++];
+       attrnamep = (dm_attrname_t *)argv[optind++];
+       bufp = argv[optind];
+       if (!bflag)
+               buflen = strlen(bufp) + 1;
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s, %s\n",
+                       pathname, strerror(errno));
+               exit(1);
+       }
+
+       if (dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN, attrnamep, setdtime,
+           buflen, bufp)) {
+               fprintf(stderr, "dm_set_dmattr failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/set_eventlist.c b/dmapi/src/suite1/cmd/set_eventlist.c
new file mode 100644 (file)
index 0000000..4300bb9
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_set_eventlist().  The
+command line is:
+
+       set_eventlist [-F] [-m max] [-s sid] [-t token] {pathname|handle} event [...]
+
+where:
+{pathname|handle}
+       is either the pathname of a file or a handle.
+max
+       is the value to use for the maxevent parameter of dm_set_eventlist().
+sid
+       is the dm_sessid_t value to use.
+token
+       is the dm_token_t value to use (DM_NO_TOKEN is the default).
+event
+       is one or more events to set.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-F] [-m max] [-s sid] "
+               "{pathname|handle} event [...]\n", Progname);
+       fprintf(stderr, "possible events are:\n");
+       for (i = 0; i < ev_namecnt; i++) {
+               fprintf(stderr, "%s (%d)\n", ev_names[i].name,
+                       ev_names[i].value);
+       }
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token = DM_NO_TOKEN;
+       char            *object;
+       dm_eventset_t   eventset;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       u_int           maxevent = DM_EVENT_MAX;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fm:s:t:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 'm':
+                       maxevent = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 't':
+                       token = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 > argc)
+               usage();
+       object = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       DMEV_ZERO(eventset);
+
+       /* Get the file's handle or convert the external handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for %s\n", object);
+               exit(1);
+       }
+
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       for (; optind < argc; optind++) {
+               dm_eventtype_t  event;
+
+               event = ev_name_to_value(argv[optind]);
+               if (event == DM_EVENT_INVALID) {
+                       fprintf(stderr, "invalid event %s\n", argv[optind]);
+                       usage();
+               }
+               DMEV_SET(event, eventset);
+       }
+
+       if (dm_set_eventlist(sid, hanp, hlen, token, &eventset, maxevent)) {
+               fprintf(stderr, "dm_set_eventlist failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/set_fileattr.c b/dmapi/src/suite1/cmd/set_fileattr.c
new file mode 100644 (file)
index 0000000..f22e47e
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <ctype.h>
+#include <time.h>
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+
+extern int     optind;
+extern int     opterr;
+extern char    *optarg;
+
+static char            *Progname;
+
+#define MIN_HD_DATE     19800101
+#define MIN_HD_TMSTAMP  315554400       /* timestamp of 19800101 */
+
+static int     dayno, day_of_week;
+static int     leap_year;
+
+/*
+ * The following table is used for USA daylight savings time and
+ * gives the day number of the first day after the Sunday of the
+ * change.
+ */
+static struct {
+       int     yrbgn;
+       int     daylb;
+       int     dayle;
+} daytab[] = {
+       1987,   96,     303,    /* new legislation - 1st Sun in April */
+       1976,   119,    303,    /* normal Last Sun in Apr - last Sun in Oct */
+       1975,   58,     303,    /* 1975: Last Sun in Feb - last Sun in Oct */
+       1974,   5,      333,    /* 1974: Jan 6 - last Sun. in Nov */
+       1970,   119,    303,    /* start GMT */
+};
+#define DAYTABSIZE (sizeof(daytab)/sizeof(daytab[0]))
+
+
+/******************************************************************************
+* NAME
+*      dysize
+*
+* DESCRIPTION
+*      Return number of days in year y.
+*
+******************************************************************************/
+
+int
+dysize(int y)
+{
+       int     temp;
+       temp = (y%4)==0;
+       if (temp) {
+               if ( (y%100)==0) 
+                       temp = ( (y%400) != 0);
+       }
+       return(365+temp);
+}
+
+/******************************************************************************
+* NAME
+*      sunday
+*
+* DESCRIPTION
+*      sunday - return sunday daynumber.  Argument d is the day number of the
+*      first Sunday on or before the special day.  Variables leap_year, dayno,
+*      and day_of_week must have been set before sunday is called.
+*
+* RETURN VALUE
+*      The sunday daynumber.
+*
+******************************************************************************/
+
+static int
+sunday(int d)
+{
+       if(d >= 58)
+               d += leap_year;
+       return(d - (d - dayno + day_of_week + 700) % 7);
+}
+
+
+extern long 
+cnvdate(int mon, int mday, int year, int hour, int min, int sec)
+{
+       int     t, i;
+       int     daylbegin, daylend;
+       int     ly_correction;  /* Leap Year Correction */
+       int     dl_correction;  /* Daylight Savings Time Correction */
+       long    s;
+       static int days[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
+
+       days[2] = 28;
+
+       /* Verify Input Parameters. */
+       /*      Set  year. */
+
+       if( year < 0) {
+               return(-1);
+       }
+       if( year < 100) {
+               if (year < 70) year += 2000;
+               else year += 1900;
+       }
+       if (year < 1970) {
+               return(-1);
+       }
+       if( year>2099 ) {
+               return(-1);
+       }
+
+       if (dysize(year) == 366) {
+               leap_year = 1;
+               days[2]++;
+       } else  
+               leap_year = 0;
+       /*
+        * Set ly_correction = number of leap year days from 1/1/1970 to
+        * 1/1/year.
+        */
+       ly_correction =  ((year-1969) / 4);
+
+       /* Check Month */
+
+       if( (mon < 1) || (mon > 12)) {
+               return(-1);
+       }
+
+       /* Check Day */
+
+       if ( (mday < 1) || (mday > days[mon]) ) {
+               return(-1);
+       }
+
+       /* Check Time */
+
+       if( (hour<0) || (hour>23)) {
+               return(-1);
+       }
+       if( (min<0) || (min>59)) {
+               return(-1);
+       }
+       if( (sec<0) || (sec>59)) {
+               return(-1);
+       }
+
+       /* Calculate Correction for Daylight Savings Time (U.S.) */
+
+       dayno = mday-1;
+       for (t=0; t<mon;)
+               dayno += days[t++];
+       s = (year-1970)*365L + ly_correction + dayno;
+       day_of_week = (s + 4) % 7;
+
+       i = 0;
+       while (year < daytab[i].yrbgn) { 
+               /* fall through when in correct interval */ 
+               i++;
+               if (i>DAYTABSIZE)
+                       return(-1);
+       }
+       daylbegin = daytab[i].daylb; 
+       daylend = daytab[i].dayle;
+
+       daylbegin = sunday(daylbegin);
+       daylend = sunday(daylend);
+       if(daylight &&
+           (dayno>daylbegin || (dayno==daylbegin && hour>=2)) &&
+           (dayno<daylend || (dayno==daylend && hour<1)))
+               dl_correction = -1*60*60;
+       else
+               dl_correction = 0;
+
+       /* Calculate seconds since 00:00:00 1/1/1970. */
+
+       s = ( ( s*24 +hour)*60 +min)*60 + sec + dl_correction;
+       return(s+timezone);
+}
+
+
+/* Cracks dates in the form YYYYMMDD and YYYYMMDDHHMMSS.  */
+
+static int
+get_absolute_date(
+       char    *ptr,
+       time_t  *timestamp)
+{
+       int     l;
+       int     yr;
+       int     mon;
+       int     day;
+       int     hr;
+       int     mn;
+       int     sec;
+       char    date[9];
+       char    *last_char;
+
+       if (strlen(ptr) != 8 && strlen(ptr) != 14)
+               return(0);
+       strncpy(date, ptr, 8);
+       date[9] = '\0';
+       l = atol(date);
+       if (l < MIN_HD_DATE)
+               return(0);
+       yr = l / 10000;
+       l = l % 10000;
+       mon = l / 100;
+       if (mon < 0 || mon > 12)
+               return(0);
+       day = l % 100;
+
+       /* Note: invalid day numbers are caught in cnvdate */
+
+       ptr+=8;
+
+       l = strtol(ptr, &last_char, 10);
+       if (l < 0 || l>235959 || *last_char != '\0')
+               return(0);
+       hr = l / 10000;
+       if (hr > 23)
+               return(0);
+       l = l % 10000;
+       mn = l / 100;
+       if (mn > 59)
+               return(0);
+       sec = l % 100;
+       if (sec > 59)
+               return(0);
+
+       /* Get timestamp. */
+
+       (void)tzset();
+       if ((*timestamp = cnvdate(mon, day, yr, hr, mn, sec)) < 0) {
+               return(0);
+       }
+
+       return(1);
+}
+
+
+/* Cracks dates in the form:   NNs, NNm, NNh, or NNd which are interpreted
+   as NN seconds, minutes, hours, or days prior to the current time, 
+   respectively.
+*/
+
+static int
+get_relative_date(
+       char    *ptr,
+       time_t  *timestamp)
+{
+       int     l;
+       char    *last_char;
+
+       if (!isdigit(*ptr))
+               return(0);
+       l = strtol (ptr, &last_char, 10);
+       (void) time(timestamp);
+       if (strcmp(last_char, "s") == 0)
+               /* do nothing */;
+       else if (strcmp(last_char, "m") == 0)
+               l = l * 60;
+       else if (strcmp(last_char, "h") == 0)
+               l = l * 60 * 60;
+       else if (strcmp(last_char, "d") == 0)
+               l = l * 60 * 60 * 24;
+       else
+               return(0);
+       *timestamp -= l;
+       if (*timestamp < MIN_HD_TMSTAMP)
+               return(0);
+       return(1);
+}
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "Usage: %s [-M mode] [-u uid] [-g gid] [-a atime] \\\n"
+               "\t[-m mtime] [-c ctime] [-d dtime] [-S size] [-s sid] pathname\n",
+               Progname);
+       fprintf(stderr, "\nDates can either be absolute:\n");
+       fprintf(stderr, "\t\tYYYYMMDD or YYYYMMDDHHMMSS\n");
+       fprintf(stderr, "or relative (prior to) the current time:\n");
+       fprintf(stderr, "\tNNs (seconds), NNm (minutes), NNh (hours), "
+               " or NNd (days)\n");
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            buffer[500];
+       void            *hanp;
+       size_t          hlen;
+       dm_fileattr_t   fileattr;
+       u_int           mask = 0;
+       char            *pathname;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       opterr = 0;
+       while ((opt = getopt(argc, argv, "M:u:g:a:m:c:d:S:s:")) != EOF) {
+               switch (opt) {
+               case 'M':
+                       mask |= DM_AT_MODE;
+                       fileattr.fa_mode = strtol (optarg, NULL, 8);
+                       break;
+               case 'u':
+                       mask |= DM_AT_UID;
+                       fileattr.fa_uid = atol(optarg);
+                       break;
+               case 'g':
+                       mask |= DM_AT_GID;
+                       fileattr.fa_gid = atol(optarg);
+                       break;
+               case 'a':
+                       mask |= DM_AT_ATIME;
+                       if (get_absolute_date(optarg, &fileattr.FA_ATIME))
+                               break;
+                       if (get_relative_date(optarg, &fileattr.FA_ATIME))
+                               break;
+                       usage();
+               case 'm':
+                       mask |= DM_AT_MTIME;
+                       if (get_absolute_date(optarg, &fileattr.FA_MTIME))
+                               break;
+                       if (get_relative_date(optarg, &fileattr.FA_MTIME))
+                               break;
+                       usage();
+               case 'c':
+                       mask |= DM_AT_CTIME;
+                       if (get_absolute_date(optarg, &fileattr.FA_CTIME))
+                               break;
+                       if (get_relative_date(optarg, &fileattr.FA_CTIME))
+                               break;
+                       usage();
+               case 'd':
+                       mask |= DM_AT_DTIME;
+                       if (get_absolute_date(optarg, &fileattr.FA_DTIME))
+                               break;
+                       if (get_relative_date(optarg, &fileattr.FA_DTIME))
+                               break;
+                       usage();
+               case 'S':
+                       mask |= DM_AT_SIZE;
+                       fileattr.fa_size = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc) {
+               usage();
+       }
+       pathname = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "dm_path_to_handle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       if (dm_set_fileattr(sid, hanp, hlen, DM_NO_TOKEN, mask, &fileattr)) {
+               fprintf(stderr, "dm_set_fileattr failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+}
diff --git a/dmapi/src/suite1/cmd/struct_test.c b/dmapi/src/suite1/cmd/struct_test.c
new file mode 100644 (file)
index 0000000..9453d21
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+       
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef linux
+#include <linux/dmapi.h>
+#else
+#include <sys/dmi.h>
+#endif
+
+/* The purpose of this test is to make sure that each field in each structure
+   defined in dmi.h is properly aligned so that there is no dead space, and
+   that the sizes and offsets of those fields remain constant no matter what
+   mode the program is compiled with, i.e. -32, -n32 or -64.
+
+   Run the program with no parameters.  If everything is correct, no message
+   will start with the word "ERROR:".  Compile and run the test in each of
+   the three mods and diff the outputs.  They must all be identical.
+
+   Note: this test cannot detect the addition of new structures to dmi.h, so
+   it will have to periodically be compared with dmi.h manually to ensure that
+   all the structures are still being validated!
+*/
+
+#define        S_START(struct_name)    { offset = 0; s_name = #struct_name; }
+
+#define        S_NEXT(struct_name, field_name) \
+{ \
+       struct_name     X; \
+ \
+       f_name = #field_name; \
+       printf("field %s.%s offset is %d\n", s_name, f_name, offset); \
+       if (offsetof(struct_name, field_name) != offset) { \
+               printf("ERROR: field %s should be %d\n", \
+                       #struct_name "." #field_name, \
+                       offsetof(struct_name, field_name)); \
+       } \
+       offset = offsetof(struct_name, field_name) + sizeof(X.field_name); \
+}
+
+#define        S_END(struct_name) \
+{ \
+       printf("struct %s size is %d\n", s_name, offset); \
+       if (sizeof(struct_name) != offset) { \
+               printf("ERROR: struct %s should be %d\n", \
+                       s_name, sizeof(struct_name)); \
+       } \
+}
+
+
+
+int main(
+       int     argc,
+       char    **argv)
+{
+       char    *s_name = NULL;
+       char    *f_name = NULL;
+       int     offset = 0;
+
+
+       S_START(dm_vardata_t);
+       S_NEXT(dm_vardata_t, vd_offset);
+       S_NEXT(dm_vardata_t, vd_length);
+       S_END(dm_vardata_t);
+
+
+       S_START(dm_attrname_t);
+       S_NEXT(dm_attrname_t, an_chars);
+       S_END(dm_attrname_t);
+
+
+       S_START(dm_attrlist_t);
+       S_NEXT(dm_attrlist_t,   _link);
+       S_NEXT(dm_attrlist_t, al_name);
+       S_NEXT(dm_attrlist_t, al_data);
+       S_END(dm_attrlist_t);
+
+
+       S_START(dm_dispinfo_t);
+       S_NEXT(dm_dispinfo_t, _link);
+       S_NEXT(dm_dispinfo_t, di_pad1);
+       S_NEXT(dm_dispinfo_t, di_fshandle);
+       S_NEXT(dm_dispinfo_t, di_eventset);
+       S_END(dm_dispinfo_t);
+
+
+       S_START(dm_eventmsg_t);
+       S_NEXT(dm_eventmsg_t, _link);
+       S_NEXT(dm_eventmsg_t, ev_type);
+       S_NEXT(dm_eventmsg_t, ev_token);
+       S_NEXT(dm_eventmsg_t, ev_sequence);
+       S_NEXT(dm_eventmsg_t, ev_data);
+       S_END(dm_eventmsg_t);
+
+
+       S_START(dm_cancel_event_t);
+       S_NEXT(dm_cancel_event_t, ce_sequence);
+       S_NEXT(dm_cancel_event_t, ce_token);
+       S_END(dm_cancel_event_t);
+
+
+       S_START(dm_data_event_t);
+       S_NEXT(dm_data_event_t, de_handle);
+       S_NEXT(dm_data_event_t, de_offset);
+       S_NEXT(dm_data_event_t, de_length);
+       S_END(dm_data_event_t);
+
+
+       S_START(dm_destroy_event_t);
+       S_NEXT(dm_destroy_event_t, ds_handle);
+       S_NEXT(dm_destroy_event_t, ds_attrname);
+       S_NEXT(dm_destroy_event_t, ds_attrcopy);
+       S_END(dm_destroy_event_t);
+
+
+       S_START(dm_mount_event_t);
+       S_NEXT(dm_mount_event_t, me_mode);
+       S_NEXT(dm_mount_event_t, me_handle1);
+       S_NEXT(dm_mount_event_t, me_handle2);
+       S_NEXT(dm_mount_event_t, me_name1);
+       S_NEXT(dm_mount_event_t, me_name2);
+       S_NEXT(dm_mount_event_t, me_roothandle);
+       S_END(dm_mount_event_t);
+
+
+       S_START(dm_namesp_event_t);
+       S_NEXT(dm_namesp_event_t, ne_mode);
+       S_NEXT(dm_namesp_event_t, ne_handle1);
+       S_NEXT(dm_namesp_event_t, ne_handle2);
+       S_NEXT(dm_namesp_event_t, ne_name1);
+       S_NEXT(dm_namesp_event_t, ne_name2);
+       S_NEXT(dm_namesp_event_t, ne_retcode);
+       S_END(dm_namesp_event_t);
+
+
+       S_START(dm_extent_t);
+       S_NEXT(dm_extent_t, ex_type);
+       S_NEXT(dm_extent_t, ex_pad1);
+       S_NEXT(dm_extent_t, ex_offset);
+       S_NEXT(dm_extent_t, ex_length);
+       S_END(dm_extent_t);
+
+
+       S_START(dm_fileattr_t);
+       S_NEXT(dm_fileattr_t, fa_mode);
+       S_NEXT(dm_fileattr_t, fa_uid);
+       S_NEXT(dm_fileattr_t, fa_gid);
+       S_NEXT(dm_fileattr_t, fa_atime);
+       S_NEXT(dm_fileattr_t, fa_mtime);
+       S_NEXT(dm_fileattr_t, fa_ctime);
+       S_NEXT(dm_fileattr_t, fa_dtime);
+       S_NEXT(dm_fileattr_t, fa_pad1);
+       S_NEXT(dm_fileattr_t, fa_size);
+       S_END(dm_fileattr_t);
+
+
+       S_START(dm_inherit_t);
+       S_NEXT(dm_inherit_t, ih_name);
+       S_NEXT(dm_inherit_t, ih_filetype);
+       S_END(dm_inherit_t);
+
+
+       S_START(dm_region_t);
+       S_NEXT(dm_region_t, rg_offset);
+       S_NEXT(dm_region_t, rg_size);
+       S_NEXT(dm_region_t, rg_flags);
+       S_NEXT(dm_region_t, rg_pad1);
+       S_END(dm_region_t);
+
+
+       S_START(dm_stat_t);
+       S_NEXT(dm_stat_t, _link);
+       S_NEXT(dm_stat_t, dt_handle);
+       S_NEXT(dm_stat_t, dt_compname);
+       S_NEXT(dm_stat_t, dt_nevents);
+       S_NEXT(dm_stat_t, dt_emask);
+       S_NEXT(dm_stat_t, dt_pers);
+       S_NEXT(dm_stat_t, dt_pmanreg);
+       S_NEXT(dm_stat_t, dt_dtime);
+       S_NEXT(dm_stat_t, dt_change);
+       S_NEXT(dm_stat_t, dt_pad1);
+
+       S_NEXT(dm_stat_t, dt_dev);
+       S_NEXT(dm_stat_t, dt_ino);
+       S_NEXT(dm_stat_t, dt_mode);
+       S_NEXT(dm_stat_t, dt_nlink);
+       S_NEXT(dm_stat_t, dt_uid);
+       S_NEXT(dm_stat_t, dt_gid);
+       S_NEXT(dm_stat_t, dt_rdev);
+       S_NEXT(dm_stat_t, dt_pad2);
+       S_NEXT(dm_stat_t, dt_size);
+       S_NEXT(dm_stat_t, dt_atime);
+       S_NEXT(dm_stat_t, dt_mtime);
+       S_NEXT(dm_stat_t, dt_ctime);
+       S_NEXT(dm_stat_t, dt_blksize);
+       S_NEXT(dm_stat_t, dt_blocks);
+
+       S_NEXT(dm_stat_t, dt_pad3);
+       S_NEXT(dm_stat_t, dt_fstype);
+
+       S_NEXT(dm_stat_t, dt_xfs_igen);
+       S_NEXT(dm_stat_t, dt_xfs_xflags);
+       S_NEXT(dm_stat_t, dt_xfs_extsize);
+       S_NEXT(dm_stat_t, dt_xfs_extents);
+       S_NEXT(dm_stat_t, dt_xfs_aextents);
+       S_NEXT(dm_stat_t, dt_xfs_dmstate);
+       S_END(dm_stat_t);
+
+
+       S_START(dm_xstat_t);
+       S_NEXT(dm_xstat_t, dx_statinfo);
+       S_NEXT(dm_xstat_t, dx_attrdata);
+       S_END(dm_xstat_t);
+}
diff --git a/dmapi/src/suite1/cmd/sync_by_handle.c b/dmapi/src/suite1/cmd/sync_by_handle.c
new file mode 100644 (file)
index 0000000..3a248b9
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_sync_by_handle().  The
+command line is:
+
+       sync_by_handle [-s sid] pathname
+
+where:
+'sid' is the session ID to use for the call.
+'pathname' is the name of the file to be sync'd.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-s sid] pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname = NULL;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "s:")) != EOF) {
+               switch (opt) {
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", pathname);
+               exit(1);
+       }
+
+       if (dm_sync_by_handle(sid, hanp, hlen, DM_NO_TOKEN)) {
+               fprintf(stderr, "dm_sync_by_handle failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite1/cmd/test_assumption.c b/dmapi/src/suite1/cmd/test_assumption.c
new file mode 100644 (file)
index 0000000..a92fd33
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <lib/hsm.h>
+
+/*
+       Test that the new session ID is correctly returned to the caller on
+       dm_create_session when the oldsid parameter is not DM_NO_SESSION.
+
+       Test to make sure that DM_NO_TOKEN does not work if the session ID
+       is invalid.
+
+       Both are needed so that session assumption works correctly.  The
+       test creates a session, queries the session, assumes the session,
+       then attempts to check the event list of the old session ID while
+       using DM_NO_TOKEN.
+
+       The only parameter is the pathname of a DMAPI filesystem.  If it is
+       working correctly, you should get the error message:
+
+               SUCCESS!
+
+       Any message containing the word FAILURE indicates a problem.
+*/
+
+char           *Progname;
+dm_sessid_t    sid = DM_NO_SESSION;    /* session ID of original session */
+dm_sessid_t    newsid = DM_NO_SESSION; /* session ID after session resumed */
+dm_eventset_t  eventlist;
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       char            buffer[DM_SESSION_INFO_LEN];
+       void            *hanp;
+       size_t          hlen;
+       u_int           nelem;
+       size_t           rlen;
+
+       Progname = argv[0];
+
+       if (argc != 2) {
+               fprintf(stderr, "usage:\t%s filesystem\n", Progname);
+               exit(1);
+       }
+
+       /* Initialize the DMAPI interface and obtain a session ID, then verify
+          that the filesystem supports DMAPI.
+       */
+
+       if (setup_dmapi(&sid))
+               exit(1);
+
+       if (dm_path_to_handle(argv[1], &hanp, &hlen)) {
+               perror("FAILURE: can't get handle for filesystem");
+               exit(1);
+       }
+
+       /* Query the session just to make sure things are working okay. */
+
+        if (dm_query_session(sid, sizeof(buffer), buffer, &rlen)) {
+                errno_msg("FAILURE: can't query the original session ID %d",
+                       sid);
+                exit(1);
+        }
+       fprintf(stdout, "Initial session ID: %d\n", sid);
+       fprintf(stdout, "Initial session message length: '%d'\n", rlen);
+       if (rlen > 0) {
+               fprintf(stdout, "Initial session message: '%s'\n", buffer);
+       }
+
+       /* Now try to assume the session. */
+
+       if (dm_create_session(sid, "this is a new message", &newsid))  {
+               fprintf(stderr, "FAILURE: can't assume session %d\n", sid);
+               exit(1);
+       }
+
+       /* Now query the new session. */
+
+        if (dm_query_session(newsid, sizeof(buffer), buffer, &rlen)) {
+                errno_msg("FAILURE: can't query the assumed session ID %d",
+                       newsid);
+                exit(1);
+        }
+       fprintf(stdout, "Assumed session ID: %d\n", newsid);
+       fprintf(stdout, "Assumed session message length: '%d'\n", rlen);
+       if (rlen > 0) {
+               fprintf(stdout, "Assumed session message: '%s'\n", buffer);
+       }
+
+       /* Get rid of the new session as we are done with it. */
+
+       if (dm_destroy_session(newsid))  {
+               fprintf(stderr, "FAILURE: Can't shut down assumed session %d\n",
+                       newsid);
+               exit(1);
+       }
+
+       /* Now verify that DM_NO_TOKEN will not work with the old session ID,
+          which is now invalid.
+       */
+
+       DMEV_ZERO(eventlist);
+
+       if (dm_get_eventlist(sid, hanp, hlen, DM_NO_TOKEN, DM_EVENT_MAX,
+                       &eventlist, &nelem) == 0) {
+               fprintf(stderr, "FAILURE: dm_get_eventlist() worked when it "
+                       "should have failed!\n");
+       }
+#ifdef VERITAS_21
+       if (errno != ESRCH) {
+#else
+       if (errno != EINVAL) {
+#endif
+               errno_msg("FAILURE: unexpected errno");
+               exit(1);
+       }
+       fprintf(stdout, "SUCCESS!\n");
+}
diff --git a/dmapi/src/suite1/cmd/upgrade_right.c b/dmapi/src/suite1/cmd/upgrade_right.c
new file mode 100644 (file)
index 0000000..375d8f7
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_upgrade_right().  The
+command line is:
+
+       upgrade_right {-F} [-s sid] token {pathname|handle}
+
+where:
+-F
+       when a pathname is specified, -F indicates that its filesystem handle
+       should be used rather than its file object handle.
+sid
+       is the dm_sessid_t to use rather than the default test session.
+token
+       is the dm_token_t to use.
+{pathname|handle}
+       is either a handle, or is the pathname of a file whose handle is
+       to be used.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-F] [-s sid] token {pathname|handle}\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token;
+       char            *object;
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Fs:")) != EOF) {
+               switch (opt) {
+               case 'F':
+                       Fflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       token = atol(argv[optind++]);
+       object = argv[optind];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file or filesystem's handle. */
+
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle from %s\n", object);
+               exit(1);
+       }
+       if (Fflag) {
+               void    *fshanp;
+               size_t  fshlen;
+
+               if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+                       fprintf(stderr, "can't get filesystem handle from %s\n",
+                               object);
+                       exit(1);
+               }
+               dm_handle_free(hanp, hlen);
+               hanp = fshanp;
+               hlen = fshlen;
+       }
+
+       if (dm_upgrade_right(sid, hanp, hlen, token)) {
+               fprintf(stderr, "dm_upgrade_right failed, %s\n",
+                       strerror(errno));
+               return(1);
+       }
+
+       dm_handle_free(hanp, hlen);
+}
diff --git a/dmapi/src/suite1/function_coverage b/dmapi/src/suite1/function_coverage
new file mode 100644 (file)
index 0000000..99956ee
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+/* functions for which there is a test program. */
+
+dm_downgrade_right(
+dm_fd_to_handle(
+dm_get_allocinfo(
+dm_get_config_events(
+dm_get_dmattr(
+dm_get_eventlist(
+dm_get_events(
+dm_get_fileattr(
+dm_get_mountinfo(
+dm_get_region(
+dm_getall_disp(
+dm_getall_dmattr(
+dm_handle_cmp(
+dm_handle_free(
+dm_handle_hash(
+dm_handle_is_valid(
+dm_handle_to_fshandle(
+dm_handle_to_fsid(
+dm_handle_to_igen(
+dm_handle_to_ino(
+dm_handle_to_path(
+dm_init_service(
+dm_make_handle(
+dm_make_fshandle(
+dm_path_to_fshandle(
+dm_path_to_handle(
+dm_obj_ref_hold(
+dm_obj_ref_query(
+dm_obj_ref_rele(
+dm_pending(
+dm_probe_hole(
+dm_punch_hole(
+dm_read_invis(
+dm_release_right(
+dm_request_right(
+dm_remove_dmattr(
+dm_respond_event(
+dm_set_disp(
+dm_set_dmattr(
+dm_set_eventlist(
+dm_set_fileattr(
+dm_set_region(
+dm_set_return_on_destroy(
+dm_sync_by_handle(
+dm_upgrade_right(
+dm_write_invis(
+
+
+/* Functions which don't yet have a specific test program. */
+
+dm_create_session(
+dm_create_userevent(
+dm_destroy_session(
+dm_find_eventmsg(
+dm_get_bulkattr(
+dm_get_config(
+dm_get_dirattrs(
+dm_getall_sessions(
+dm_getall_tokens(
+dm_init_attrloc(
+dm_move_event(
+dm_query_session(
+dm_send_msg(
+
+/* Non-standard SGI additions to the DMAPI interface. */
+
+dm_get_dioinfo
diff --git a/dmapi/src/suite2/DMAPI_aliases b/dmapi/src/suite2/DMAPI_aliases
new file mode 100644 (file)
index 0000000..f8fb420
--- /dev/null
@@ -0,0 +1,147 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+#---------------------------------------------------------------------------
+# CONFIGURATION SECTION:  
+#    Configure this script by changing the variables in this section.
+#    Please change ONLY this section!
+#---------------------------------------------------------------------------
+
+# Base directory:
+base_dir="~jayw/test"
+
+# Primary username:
+p_user="jayw"
+
+# Path to the mountpoint of the test filesystem:
+m_main="/dmitest"
+
+# m_main concatenated with d_name == the full test directory path
+#
+# EXAMPLE:  If m_main is "/dmitest", and the test directory
+# is "/dmitest/test", set this to "/test"
+#
+d_name="/test"
+
+# Path to the mountpoint of the nfs2 test filesystem:
+m_nfs2="/dmiv2"
+
+# Path to the mountpoint of the nfs3 test filesystem:
+m_nfs3="/dmiv3"
+
+# Path to the mountpoint of the realtime test filesystem:
+m_rt="/dmf"
+# Path to the realtime test directory:
+d_rt="$m_rt/kcm"
+
+#--------------------------------------------------------------------
+# END OF CONFIGURATION SECTION:
+#    No changes should be made past this point!  Please change only   
+#    the above shell variables to configure this script.
+#--------------------------------------------------------------------
+
+# Path to the "bindir" directory:
+bin="$base_dir/bindir"
+
+# Path to the "generic file" (a copy of ls): 
+ls_path="$bin/ls_to_copy"
+
+# Path to the main test directory:
+d_main="$m_main$d_name"
+
+# Path to the nfs2 test directory:
+d_nfs2="$m_nfs2$d_name"
+
+# Path to the nfs3 test directory:
+d_nfs3="$m_nfs2$d_name"
+
+#---------------------------------------------------------------------------
+# Tests that run without a daemon
+#---------------------------------------------------------------------------
+
+# Automated C programs to test DMAPI functions 
+alias do_dmattr="$bin/test_dmattr $ls_path $tdir"
+alias do_eventlist="$bin/test_eventlist $ls_path $tdir"
+alias do_fileattr="$bin/test_fileattr $ls_path $tdir"
+alias do_hole="$bin/test_hole $ls_path $tdir"
+alias do_invis="$bin/test_invis $ls_path $tdir"
+alias do_region="$bin/test_region  $ls_path $tdir"
+alias do_efault="$bin/test_efault $ls_path $tdir"
+alias do_rights="$bin/test_rights $ls_path $tdir"
+
+# Verbose versions of the above
+alias dov_dmattr="$bin/test_dmattr -v $ls_path $tdir"
+alias dov_eventlist="$bin/test_eventlist -v $ls_path $tdir"
+alias dov_fileattr="$bin/test_fileattr -v $ls_path $tdir"
+alias dov_hole="$bin/test_hole -v $ls_path $tdir"
+alias dov_invis="$bin/test_invis -v $ls_path $tdir"
+alias dov_region="$bin/test_region -v $ls_path $tdir"
+alias dov_efault="$bin/efault -v $ls_path $tdir"
+alias dov_rights="$bin/test_rights -v $ls_path $tdir"
+
+# Scripts to test dm_get_allocinfo
+alias do_allocinfo_1="$bin/test_allocinfo_1 $bin $tdir"
+alias do_allocinfo_2="$bin/test_allocinfo_2  $bin $tdir"
+
+#-------------------------------------------------------------------------------------------------
+# Tests that load a DMAPI daemon and examine the generated events
+#-------------------------------------------------------------------------------------------------
+
+# Standard battery of tests:
+alias do_standard="$bin/run_test -u $p_user -f standard.dat $bin $tdir $mdir"
+alias do_standard_nfs2="$bin/run_test -u $p_user -F nfs2 -M $m_nfs2 -R $tdir -f standard_nfs.dat $bin $d_nfs2 $mdir"
+alias do_standard_nfs3="$bin/run_test -u $p_user -F nfs3 -M $m_nfs3 -R $tdir -f standard_nfs.dat $bin $d_nfs3 $mdir"
+
+# Some other, more specific tests:
+alias do_main="$bin/run_test -u $p_user $bin $tdir $mdir"
+alias do_nfs2="$bin/run_test -u $p_user -F nfs2 -M $m_nfs2 -R $tdir -f nfs.dat $bin $d_nfs2 $mdir"
+alias do_nfs3="$bin/run_test -u $p_user -F nfs3 -M $m_nfs3 -R $tdir -f nfs.dat $bin $d_nfs3 $mdir"
+
+alias do_pending="$bin/run_test -u $p_user -f pending.dat $bin $tdir $mdir"
+alias do_pending_nfs2="$bin/run_test -u $p_user -F nfs2 -M $m_nfs2 -R $tdir -f pending_nfs.dat $bin $d_nfs2 $mdir"
+alias do_pending_nfs3="$bin/run_test -u $p_user -F nfs3 -M $m_nfs3 -R $tdir -f pending_nfs.dat $bin $d_nfs3 $mdir"
+
+alias do_failure="$bin/run_test -u $p_user -f fail.dat $bin $tdir $mdir"
+alias do_failure_nfs2="$bin/run_test -u $p_user -F nfs2 -M $m_nfs2 -R $tdir -f fail.dat $bin $d_nfs2 $mdir"
+alias do_failure_nfs3="$bin/run_test -u $p_user -F nfs3 -M $m_nfs3 -R $tdir -f fail.dat $bin $d_nfs3 $mdir"
+
+# Realtime test:
+alias do_realtime="$bin/run_test -u $p_user -f realtime.dat $bin $m_rt $d_rt"
+
+# Small event queue test:  Set dm_max_queued to about 5 or so before running!
+alias do_smallq="$bin/run_test -u $p_user -s 2 -f smallq.dat $bin $tdir $mdir"
+
+#-------------------------------------------------------------------------------------------------
+# Additional tools (these are NOT tests):
+#-------------------------------------------------------------------------------------------------
+
+alias check_for_daemon="ps -el | grep daemon"
+alias do_daemon="$bin/dm_test_daemon $mdir"
diff --git a/dmapi/src/suite2/README b/dmapi/src/suite2/README
new file mode 100644 (file)
index 0000000..c3fdf40
--- /dev/null
@@ -0,0 +1,633 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+
+                           DMAPI Test Suite 
+                          Informational File
+                          ------------------
+
+I) Getting Started
+
+   A) Extracting from DMAPI_test.cpio
+
+      1) Create a new directory for storing the tests.  We will refer to 
+         this as the "base" directory.  The base directory can be
+         located anywhere; it does NOT need to be in a DMAPI filesystem.
+
+      2) Move the archive file DMAPI_test.cpio to the base directory
+         and execute the following command to extract from the archive:
+             cpio -icvd < DMAPI_test.cpio 
+
+      3) There should now be several files and subdirectories in the base
+         directory, including the file "file_list".  Read this file for a
+         complete listing of which files should be present in which
+         directories.  Compare "file_list" with the output of "ls -Rpl" 
+         to be sure that you have the necessary files.
+
+      4) The base directory contains the files and programs that are of
+         immediate use for testing.  The "bindir" subdirectory contains
+         the test programs and datafiles.  The "lib" and "src" subdirectories
+         contain C libraries and source code for the C programs. 
+
+   B) Checking the Existence and Version of DMAPI
+      The program check_dmapi can verify that you have the correct
+      version of DMAPI installed.  NOTE: it can only be run as root.
+      Execute this command (from the "base" directory):
+      bindir/check_dmapi
+      It should report that you have a current version of DMAPI.  If it
+      does not, it will also suggest which components of your DMAPI are 
+      not current, and where to find a patch to update them.
+
+   C) Configuration
+
+      1) Creating the Test Directories
+
+         a) The Test Filesystem
+            Mount a DMAPI filesystem, or use an existing one.
+            This filesystem's mount info MUST be listed in /etc/fstab.
+            Write down the path to this filesystem's mountpoint, and label
+            it as "m_main" for future use.
+         b) The Main Test Directory
+            
+            Create a new directory in the "m_main" filesystem. 
+            Write down the path to this directory.  Note ONLY the part
+            that comes AFTER "m_main".  Label this as "d_name".
+            EXAMPLE: You have a DMAPI filesystem /dmi_main  
+                     You name the test directory /dmi_main/test_dir
+            "m_main" is /dmi_main 
+            "d_name" is /test_dir
+         c) The Cross-NFS Test Directories 
+            For NFS tests, all you must do is create two empty directories
+            (one for nfs2, one for nfs3). They do NOT need to be in a 
+            DMAPI filesystem.  
+            Your main test directory will be mounted across NFS, into these
+            two directories.  Normally, the tests will do this automatically.
+            However, if you need to do this mount manually, the command
+            would look like this example:
+            mount -t nfs2 localhost:/dmi_main /dmi_nfs2
+            Write down the paths to these nfs2 and nfs3 test directories.
+            Label them "m_nfs2" and "m_nfs3" respectively.
+         c) The Realtime Test Filesystem and Directory
+            If you wish to test realtime i/o, you'll need a filesystem 
+            mounted with a realtime partition, and a directory in that
+            filesystem.  
+            Label the path to the filesystem mountpoint as "m_rt".
+            Label the path to the test directory as "d_rt".
+      2) Configuring menu_test
+         The Korn-shell script named menu_test is an interface to the
+         other test programs.  At the beginning of the script, there
+         is a "configuration section", in which is sets several variables
+         for use in the rest of the script.  
+         
+         Open menu_test in any text editor and change the following
+         variable assignments in the configuration section:
+         a) base_dir:
+            Set this to the pathname of your "base" directory 
+            (where you un-archived "DMAPI_test.cpio").
+         b) p_user:
+            Tests that do not run as root will run as this "primary" user.
+            Set this to any username. 
+         c) m_main:
+            The mountpoint of the main test filesystem.
+            Set this to the value of "m_main" that you wrote down above.  
+  
+         d) d_name:  
+            m_main concatenated with d_name is the main test directory path.
+            Set this to the value for "d_name" that you wrote down above.
+         e) m_nfs2:  
+            The mountpoint of the nfs2 test filesystem.
+            Set this to the value of "m_nfs2" that you wrote down above.
+         f) m_nfs2:   
+            The mountpoint of the nfs3 test filesystem.
+            Set this to the value of "m_nfs3" that you wrote down above.
+         g) m_rt:   
+            The mountpoint of the realtime test filesystem.
+            Set this to the value of "m_rt" that you wrote down above.
+         h) d_rt:   
+            The path to the realtime test directory.
+            Set this to the value of "d_rt" that you wrote down above.
+      3) Configuring "DMAPI_aliases"
+         This is an optional alternative to the menu interface. It runs
+         as a Korn shell "dot" script and creates an alias to each test. 
+         It was made for those who wish to run tests directly from the
+         command line.
+         DMAPI_aliases has exactly the same configuration section as
+         menu_test.  If you wish to use DMAPI_aliases, make the same
+         changes to its configuration section. 
+II) Running the Tests
+
+   A) Using "menu_test" to run tests
+
+      1) You must be superuser, using the Korn shell, to run menu_test.
+         You also must have adjusted the variables in menu_test's 
+         "configuration section", as was explained above.
+
+      2) menu_test is (surprise!) menu based.  Choose options by entering
+         their numbers.    
+      3) The names of the menu options explain which DMAPI functions
+         or DMAPI events are being tested.  Some of the options, labeled
+         accordingly, run more than one test programs.
+
+      4) See section SECTION# for a list of the test scripts and programs,
+         and a brief explanation of each script or program's function.  
+
+   B) Using "DMAPI_aliases" to run tests   
+
+      1) NOTE: The aliases in DMAPI_aliases are meant to be used by
+         those who are familiar with the test programs and wish to run
+         them more directly.  [Designer's note: I included the alias
+         file more out of nostalgia than necessity.]
+      
+      2) You should be superuser, using the Korn shell, to run DMAPI_aliases.
+         You also must have adjusted the variables in DMAPI_aliases's 
+         "configuration section", as was explained above.
+
+      3) DMAPI_aliases should be invoked as a Korn shell "dot" script:
+
+         . ./DMAPI_aliases 
+
+         It sets an alias for each test program; each alias begins with
+         the characters "do_" and is followed by some appropriate name.
+         Read DMAPI_aliases, or execute "alias | grep do", to 
+
+      4) "Verbose mode"
+         In the menu of function tests, one of the options is an on/off
+         toggle of "verbose mode".  When verbose mode is on, the function
+         tests will print semi-explanatory output.  Verbose mode affects
+         only the function tests (this does include check_dmapi).
+
+      5) "Pausing after each command"
+         In the menu of event tests, one of the options is a toggle of 
+         "pausing after each command".  When this is on, the event tests
+         will pause for a carriage return after running each command.
+         This affects only the event tests.
+
+   C) Running tests directly
+
+      1) For the VERY adventurous, all the tests in the "bindir" directory
+         can be run directly from the command line.  Only some of the files
+         in "bindir" are test scripts/programs.  Read section III for a list 
+         of function tests and section IV for a list of run_test (.dat)
+         testfiles.
+
+      2) Running a test program without parameters will produce a list of
+         correct options.  (The exception to this is check_dmapi, which 
+         normally has no parameters.  check_dmapi takes only one option,
+         [-v] for verbose output.)
+
+      3) It is suggested that you read a program's source before running
+         it directly.  (The source of the C programs is included in the
+         "src" directory.)  Specifically, in each source file, an initial
+         comment explains the program's options/parameters in detail.
+
+III) DMAPI Function tests:
+     
+     This section offers a terse description of the DMAPI function tests.
+     For those tests written in C, the source code is given in the "src" 
+     directory.  The ksh scripts can, of course, be read directly.
+     In all cases except check_dmapi, running the program without
+     parameters will produce a list of correct options. 
+  
+   A) check_dmapi
+      Written in: C 
+      Test of: presence (and correct version) of DMAPI library and kernel.  
+      Options: [-v] flag for verbose output.
+   B) test_dmattr
+      Written in: C 
+      Test of: dm_get_dmattr, dm_set_dmattr, dm_remove_dmattr.
+
+   C) test_efault
+      Written in: C 
+      Test of: various bad function calls that should generate EFAULT,
+               according to the DMAPI specification.
+
+   D) test_eventlist
+      Written in: C 
+      Test of: dm_get_eventlist, dm_set_eventlist.
+
+   E) test_fileattr
+      Written in: C 
+      Test of: dm_get_fileattr, dm_set_fileattr,
+               dm_get_dirattrs, dm_get_bulkattr.
+
+   F) test_hole
+      Written in: C 
+      Test of: dm_probe_hole, dm_punch_hole.
+
+   G) test_invis
+      Written in: C 
+      Test of: dm_read_invis, dm_write_invis.
+
+   H) test_region
+      Written in:  C 
+      Test of: dm_get_region, dm_set,region.
+
+   I) test_rights
+      Written in: C 
+      Test of: various bad function calls that should generate EACCES,
+               and other conditions pertaining to DMAPI rights.
+
+   J) test_allocinfo_1
+      Written in: ksh
+      Test of: dm_get_allocinfo.  
+
+   K) test_allocinfo_2
+      Written in: ksh
+      Test of: dm_get_allocinfo.
+
+IV) DMAPI Event tests and the "run_test" ksh script
+
+   A) How to use the "run_test" script
+
+      1) A quick description of run_test's behavior:
+         run_test invokes a DMAPI daemon (as a ksh coprocess).  It then
+         proceeds in a loop, in which it reads a command from a "testfile",
+         executes that command, reads a description of expected events from
+         the testfile, and compares the expected events with the actual
+         events, as returned by the DMAPI daemon.
+
+      2) You must be superuser, using the Korn shell, to execute run_test.
+
+      3) Executing run_test without parameters will produce a list of
+         correct options.  For a much more in-depth explanation of the 
+         options to run_test, read its own initial comment.      
+
+   B) The existing .dat testfiles
+
+      1) fail.dat
+         Tests the events from: a user trying to access files owned
+         by someone else (in this case, root). 
+
+      2) main.dat
+         Tests the events from: events getting DM_RESP_ABORT, dm_send_msg(),
+         invisible i/o, and direct i/o.
+
+      3) nfs.dat
+         Tests the events from: events getting DM_RESP_ABORT over nfs,
+         EAGAIN over nfs.
+
+      4) pending.dat
+         Tests the events from: running dm_pending() while trying to 
+         do standard i/o.
+
+      5) pending_nfs.dat
+         Tests the events from: running dm_pending() while trying to
+         do standard i/o over NFS
+
+      6) realtime.dat
+         Tests the events from: Invisible, direct, and standard i/o
+         on realtime files in a realtime filesystem.
+
+      7) smallq.dat
+         Tests the events from: Slow i/o due to a small event queue.
+
+      8) standard.dat
+         Tests the events from: various kinds of standard i/o, 
+         memory-mapped i/o and remounting the filesystem.
+
+      9) standard_nfs.dat
+         Tests the events from: various kinds of standard i/o, over NFS.
+
+   C) How to write new ".dat" testfiles
+      
+      1) Overview
+
+         A testfile contains a complete description of a DMAPI event test.
+         Testfiles are divided into sections: the first two contain
+         test initialization, while the remaining sections each contain ONE
+         command, followed by a list of expected events.
+
+         The following is a description of testfile syntax.  If you wish to 
+         fully understand testfile syntax, PLEASE examine the existing
+         testfiles and the "run_test" script.
+
+      2) Event information variables
+         
+         a) From the daemon, "run_test" gets information about DMAPI events.
+            This information is stored in event information variables.  
+
+         b) NOTE: event information variables are not persistent. 
+            After "run_test" has compared the expected and actual events
+            for a command, and before it executes the next command, it
+            unsets the values of all these variables.
+
+         c) Most of these variables are arrays, indexed by the number of
+            the event (starting with 0). For example, if the initial event
+            is a read event, then we have "event[0]" set to "read", and
+            "file_handle[0]" set to the handle of whatever file was read.
+
+         d) "event_count" is a special variable.  It holds the number of
+            events that were generated by the most recent command.   
+
+         e) These are all the event information variables:
+
+            contents event event_count fs_handle handle length
+            offset media_designator mode mountpoint_handle
+            mountpoint_path msg_str name new_name new_parent
+            parent_handle ret_code root_handle sequence token  
+            tries_left unmount_mode
+
+         f) PLEASE examine the run_test script to see which variables 
+            are set by which events.  (The scheme corresponds, roughly, 
+            to the "Event Types" section of the DMAPI specification.)
+
+      3) Testfile section 1:  List of required files
+
+         a) A testfile's first section is a list of the files it requires.   
+            If these files are not present in the "bindir" directory, 
+            "run_test" will abort the test and inform the user of which 
+            files are missing.  
+         
+         b) Each line of this section may contain ANY NUMBER of filenames.
+
+         c) Lines beginning with // will be treated as comments.  The
+            entirety of such lines will be ignored.
+          
+         d) The last line of this section should begin with three hyphens
+            ---  Other characters on that line will be ignored. 
+
+      4) Testfile section 2:  Initialization commands
+         
+         a) A testfile's second section consists of a list of commands.
+            "run_test" will execute these commands before starting the
+            DMAPI daemon.  Any necessary initialization should be done 
+            here. 
+
+         b) Each line of this section should be ONE shell command.
+
+         c) Lines beginning with // will be treated as comments.  
+            The entirety of such lines will be ignored.
+          
+         d) The last line of this section should begin with three hyphens
+            "---"  Other characters on that line will be ignored.
+
+      5) Testfile sections 3 and on:  Individual tests
+
+         a) The remaining sections of a testfile consist of a single
+            shell command, followed by descriptions of events that should
+            be generated by the command.  
+            
+         b) Comments
+
+            1) Comments are valid ONLY before the command. 
+
+            2) Lines beginning with // will be treated as comments.  
+               The entirety of such lines will be ignored.
+
+            3) Lines beginning with @@ will be treated as "print" comments.
+               Such lines will not be parsed, but they will be printed to
+               standard output during the test.  This is useful for
+               describing what each test does.
+
+         c) Valid grammar for the command itself
+
+            1) Standard command syntax: 
+               This should be ONE shell command, on a line by itself.  
+               
+            2) Alternate command syntax:
+               A) run_as_root:  
+                  If the test is preceded by the metacommand "run_as_root"
+                  (on a line by itself) then the command will be run as
+                  root rather than as "p_user".  The command should still
+                  be one command on a line by itself.
+
+               B) run_without_test:
+                  If the test is preceded by the metacommand 
+                  "run_without_test" (on a line by itself), then ALL
+                  subsequent lines in the section will be executed as
+                  commands, and NO testing will be performed.  Note that
+                  the commands will be executed as root.  This is useful
+                  for re-initialization sections during a test.
+                  NOTE: A testfile cannot end with a "run_without_test" 
+                  section.  The last section must contain a test. 
+
+         d) Valid grammar for the "expected events" lines
+
+            1) [variable_name] [value]
+               This specifies that the variable [variable_name] should be
+               set to [value].  
+
+            2) [variable_name_1] matches [variable_name_2]
+               This specifies that both variables should be set to 
+               the same value.  A list of valid variables
+
+            3) [variable_name] store_in [string]
+               This specifies that the contents of [variable_name] 
+               should be stored in a variable named [string].
+               The variable [string] can then be referenced as a
+               variable in later tests.
+   
+               EXAMPLE: if two commands deal with the file "foobar",
+               you might want to check that they both use the same handle.
+               In the first section, write
+                "handle[0] store_in old_handle_0" 
+               In the second section, write
+                "old_handle_0 matches handle[0]" 
+
+            4) failure
+               This specifies that the command is expected to fail
+               (return some non-zero exit status).  If "failure"
+               is not specified, the command is expected to succeed.
+            
+         e) The last line of these sections should begin with three
+            hyphens "---".  Other characters on that line will be ignored.
+      6) Sending messages to the DMAPI daemon
+
+         a) Overview
+            Normally, run_test only reads from the DMAPI daemon, and never
+            sends messages back.  However, sometimes we need the daemon to
+            execute some function or change its behavior in some way.  This
+            is accomplished by calling "send_msg" as a command in the
+            testfile.  The test daemon has been coded to respond to the
+            following user events generated by send_msg:
+            
+         b) unfriendly_X
+            Replace X here with an integer, as in "send_msg unfriendly_6".
+            This causes the daemon to respond to all messages (other than
+            user events) with DM_RESP_ABORT instead of DM_RESP_CONTINUE,
+            and with errno X.  If the message is just "unfriendly", the
+            default errno is EBADMSG.
+
+         c) friendly
+            This returns the test_daemon to normal operation after it
+            was set to be "unfriendly".  
+
+         d) countdown_X_Y
+            Replace X and Y with integers, as in "send_msg countdown_6_8".
+            This causes the daemon to respond to the next X messages  (other
+            than user events) with DM_RESP_ABORT instead of DM_RESP_CONTINUE,
+            and with errno Y.  If the message is just "countdown", the
+            default count is 5 and the default errno is EAGAIN.
+
+         e) pending_X
+            Replace X here with an integer, as in "send_msg pending_4".
+            This causes the daemon to call dm_pending() rather than 
+            responding to the next X messages.  If the message is just
+            "pending", the default count is 1.  After the count reaches
+            zero, the messages will be responded to.
+
+         f) reset_fs
+            This message MUST be sent after remounting the test filesystem.
+            It causes the daemon to re-register for all events.
+
+         g) over
+            This message is sent by run_test itself, and should not be
+            sent in a testfile.  "send_msg over" is called after each
+            command is executed, as an indicator that the batch of events
+            from that command is complete.  When run_test sees a user
+            event with the data "over", it knows to stop reading events
+            and move on to the next command.
+
+      7) Other "helper functions" for testfiles
+
+         a) ctf  (create test files)
+            purpose: creates 20 copies of "bindir/ls_to_copy".
+            parameters: location of "bindir", location of target directory.
+            written in: ksh
+
+         b) crttf  (create realtime test files)
+            purpose: creates 10 realtime files.
+            parameters: location of "bindir", location of target directory.
+            written in: ksh
+
+         c) stf  (setup test files)
+            purpose: set dm attributes and managed regions on target files.
+            parameters: location of "bindir", pathnames of target files.
+            written in: ksh
+
+         d) fcntl 
+            purpose: do fcntl() syscall
+            parameters: see "usage" by running without parameters.
+            written in: C (source not included)
+
+         e) open_test 
+            purpose: do open() syscall 
+            parameters: see "usage" by running without parameters.
+            written in: C 
+
+         f) rd  
+            purpose: do read() syscall 
+            parameters: see "usage" by running without parameters.
+            written in: C (source not included)
+
+         g) new_wf 
+            purpose: do write() syscall  (new version of wf)
+            parameters: see "usage" by running without parameters.
+            written in: C (source not included)
+
+         h) wf 
+            purpose: do write() syscall
+            parameters: see "usage" by running without parameters.
+            written in: C (source not included)
+
+         i) truncate 
+            purpose: truncate a file
+            parameters: see "usage" by running without parameters.
+            written in: C (source not included)
+
+         j) read_invis
+            purpose: do dm_read_invis()
+            parameters: see "usage" by running without parameters.
+            written in: C
+
+         k) write_invis
+            purpose: do dm_write_invis(). 
+            parameters: see "usage" by running without parameters.
+            written in: C
+
+         l) set_region
+            purpose: do dm_set_region()
+            parameters: see "usage" by running without parameters.
+            written in: C
+
+         m) set_return_on_destroy
+            purpose: do dm_set_return_on_destroy()
+            parameters: see "usage" by running without parameters.
+            written in: C 
+
+         n) ctest.c
+            purpose: test memory mapping used by cc during compilation 
+                     (really a helper file, not a helper function)
+
+         o) mmap_cp
+            purpose: test memory mapping by using it to copy a file
+            parameters: source pathname, destination pathname
+            written in: C (source not included)
+
+         p) dump_allocinfo
+            purpose: test dm_get_allocinfo by using it to dump
+                     a list of file extents, much like to xfs_bmap.
+            parameters: see "usage" by running without parameters
+            written in: C 
+
+         q) mm_fill
+            purpose: fill a filesystem, using memory-mapped i/o
+            parameters: pathname of target file
+            written in: C 
+
+         r) make_holey
+            purpose: create a hole-filled file, using wf
+            parameters: path to "bindir", pathname of target file, 
+                        count of how many holes should be created
+            written in: ksh
diff --git a/dmapi/src/suite2/README_for_check_dmapi b/dmapi/src/suite2/README_for_check_dmapi
new file mode 100644 (file)
index 0000000..e32cda0
--- /dev/null
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+###  README for check_dmapi  ###
+
+check_dmapi tests the version of DMAPI library & kernel code.
+
+command line:  check_dmapi [-v] 
+(v is a verbose-output flag)
+
+Functionality:
+
+1) Ensures that the user is running as root, using getuid().  
+
+2) Tries to stat() /usr/include/sys/dmi.h to verify its
+   presence and its size.
+
+3) Verifies the presence of the DMAPI kernel, using a 
+   direct call to dmi().  The call is invalid, so it should
+   return EINVAL if the kernel code is in place, ENOPKG if not.
+
+4) Determines the status of the kernel (if it is present) using
+   a direct call to dmi().  The call is invalid, and uses an opcode
+   not present in the old kernel.  So ENOSYS means old kernel;
+   EINVAL means new kernel.
+
+5) Determines the status of the library by calling dm_init_service().
+   If this fails, libraries are missing.  In the old library, this call
+   did not change its "name" parameter, but in the new library it does.
+   Same name means old library; changed name means new library. 
+
+6) Outputs its findings.
diff --git a/dmapi/src/suite2/bindir/crttf b/dmapi/src/suite2/bindir/crttf
new file mode 100755 (executable)
index 0000000..766661c
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/ksh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+if [[ $# != 2 ]]
+then  print -u2 "USAGE: ${0##*/} bindir testdir"
+      exit 2
+fi
+
+for i in 0 1 2 3 4 5 6 7 8 9
+        do
+       $1/new_wf -l 32768 -b 4096 -R $2/realtime.$i
+        done
+
diff --git a/dmapi/src/suite2/bindir/ctf b/dmapi/src/suite2/bindir/ctf
new file mode 100755 (executable)
index 0000000..a375b14
--- /dev/null
@@ -0,0 +1,44 @@
+#!/bin/ksh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+if [[ $# != 2 ]]
+then  print -u2 "USAGE: ${0##*/} bindir testdir"
+      exit 2
+fi
+
+for i in 0 1 2 3 4 5 6 7 8 9
+        do
+       cp $1/ls_to_copy $2/ls"$i"
+       cp $1/ls_to_copy $2/ll"$i"
+        done
+
diff --git a/dmapi/src/suite2/bindir/make_holey b/dmapi/src/suite2/bindir/make_holey
new file mode 100755 (executable)
index 0000000..42dd087
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/ksh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+if [[ $# != 3 ]] 
+then print "usage: ${0##*/} bindir target_file count"
+     exit 1
+fi
+
+typeset -i offset
+typeset -i length
+typeset -i count
+
+RANDOM=$SECONDS
+offset=0
+length=$RANDOM
+count=$3
+
+while (( count > 0 ))
+do 
+       print "Count: $count"
+       $1/wf -l $length -L $offset -b 512 $2
+       (( offset = RANDOM * 512 + offset + length )) 
+       (( length = RANDOM ))
+       (( count = count - 1 ))
+done
+
+
diff --git a/dmapi/src/suite2/bindir/run_test b/dmapi/src/suite2/bindir/run_test
new file mode 100755 (executable)
index 0000000..6b592f5
--- /dev/null
@@ -0,0 +1,552 @@
+#!/bin/ksh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+#-----------------------------------------------------------------#
+# run_test:  a ksh script for testing the DMAPI.
+#
+# USAGE: run_test [-p] [-x] [-u user] 
+#        [-F fs_type -M fs_mtpt -R "real" directory] 
+#        [-f datafile] [-s sleeptime]
+#        bindir testdir fsdir
+#
+# p:  Causes pausing after every test (not just ones with errors).
+#
+# x:  Prints an execution trace as the script runs.
+#
+# user:  Most tests don't need root access, so they will be run
+#        under this username. 
+#
+# (NOTE: the following three must be used together)
+#
+#     fs_type: For NFS tests; the type of filesystem (ie nfs2, nfs3).
+#
+#     fs_mtpt: For NFS tests, the path to the mount of your 
+#              "real" filesystem.
+#              (ie, "mount -t nfs2 localhost:/dmitest $fs_mtpt")
+#
+#     "real" directory:  For NFS tests, the path to the "real" test directory.
+#
+# datafile:  The name of the file which contains the tests to run.
+#   
+# sleeptime: time, in seconds, for the daemon to sleep after  
+#            responding to an event. (Useful for testing small
+#            outstanding-events queues.)
+#
+# bindir:  The path to the directory that holds dm_test_daemon, send_msg,
+#          the datafile, and any other files required by the datafile.
+#    
+# testdir:  The path to the test directory.  All DMAPI testing
+#           occurs here -- this is where the tests will actually
+#           be run.  (For NFS tests, this will be an NFS mount 
+#           of the "real" directory.)
+#          
+# fsdir:  The path name of the test filesystem.  The daemon will start
+#         using this path, and the mount and unmount of the DMAPI
+#         filesystem will be done here.  (Even for NFS tests, this 
+#         should still be the same test filesystem.)
+#
+#-----------------------------------------------------------------#
+
+# For most reads, we'll want spaces to be the field separators.
+IFS=" "
+
+typeset -i fail_flag
+typeset -i pause_flag
+typeset -i sleeptime
+
+# To run tests that don't require root access, we'll change to
+# a user specified by lname.
+lname=$LOGNAME
+
+# Set the default external files to use.
+datafile=main.dat
+sleeptime=0
+
+unset fs_type fs_mtpt
+real_dir=set_me_later
+
+# Parse the command-line options
+while getopts :pxu:F:M:R:f:b:s: option
+do  case $option in
+    p) pause_flag=1;;
+    x) set -x;;
+    u) lname=$OPTARG;;
+    F) fs_type=$OPTARG;;
+    M) fs_mtpt=$OPTARG;;
+    R) real_dir=$OPTARG;;
+    f) datafile=$OPTARG;;
+    b) bindir=$OPTARG;;
+    s) sleeptime=$OPTARG;;
+    :) print -u2 "${0##*/}: $OPTARG requires a value"
+       exit 2;;
+   \?) print -nu2 "USAGE: ${0##*/} [-p] [-x] [-u user] "
+       print -nu2 "[-F fs type -M mountpoint directory -R \"real\" directory] "
+       print -u2 "[-s sleeptime] [-f datafile] bindir testdir fsdir"
+       exit 2;;
+    esac
+done
+
+# Shift out the examined options, then check that we have
+# exactly three arguments left: (the paths to the "bindir", 
+# the test directory, and the filesystem).
+shift OPTIND-1
+if [[ $# != 3 ]]
+then  print -nu2 "USAGE: ${0##*/} [-p] [-x] [-u user] "
+      print -nu2 "[-F fs type -M mountpoint directory -R \"real\" directory] "
+      print -u2 "[-s sleeptime] [-f datafile] bindir testdir fsdir"
+      exit 2
+fi
+
+# For NFS tests, $2 will be an NFS mount of the test directory;
+# real_dir should be the test directory's actual path.
+# Otherwise, real_dir should just be $2.
+if [[ $real_dir = set_me_later ]]
+then real_dir=$2
+fi
+
+# Check bindir for the existence of our three critical external files.
+error_count=0
+for i in dm_test_daemon send_msg $datafile 
+do
+    if [[ ! ( -r "$1/$i" ) ]]
+    then if ((error_count==0)) 
+        then print "Aborting: the directory $1/ is missing critical files:"
+        fi
+         print "$1/$i"
+         (( error_count = error_count + 1 ))
+    fi
+done
+if (( error_count > 0 )) 
+then exit 1
+fi
+
+# Open the datafile on file descriptor 3
+exec 3< $1/$datafile
+
+# Read datafile and determine what files it needs from bindir;
+# then, check for the existence of these files.
+error_count=0
+while read -u3 file_list
+do case $file_list in
+   ---*) break;;
+    //*) continue;;
+      *) for i in $file_list
+         do if [[ ! ( -r "$1/$i" ) ]]
+           then if ((error_count==0)) 
+                then print "The directory $1/ is missing these files:"
+                fi
+                 print "$1/$i"
+                 (( error_count = error_count + 1 ))
+            fi
+         done;;
+   esac
+done
+if (( error_count > 0 )) 
+ then exit 1
+fi
+
+# Run initialization stuff without daemon.
+while read -u3 cmd
+do    case $cmd in
+       //*) continue;;
+      ---*) break;;
+         *) eval "$cmd";;
+      esac
+done
+
+# If we're testing over nfs, remount the filesystem to clear the cache.
+case $fs_type in
+   nfs2) print "Clearing nfs2 cache by remounting filesystem..."
+         eval "umount $fs_mtpt"
+         eval "mount -t nfs2 localhost:$3 $fs_mtpt";;
+   nfs3) print "Clearing nfs3 cache by remounting filesystem..."
+         eval "umount $fs_mtpt"
+         eval "mount -t nfs3 localhost:$3 $fs_mtpt";;
+      *) if [[ $fs_type != "" ]] 
+        then print "ERROR: $fs_type not a known or testable filesystem type"
+        fi;;
+esac
+    
+
+# Check with the user before starting up daemon
+print "\n** Using testfile ${datafile##*/} **"
+print "** Using userid $lname for tests not requiring root access **"
+print "Press enter to begin, or enter q or n to abort..."
+read go
+case "$go" in
+    n|N|q|Q) exit 1;;
+    *);;
+esac
+
+# Now, the user will need ownership of the test directory 
+# ($2, not $real_dir, since real_dir is accessed only as root).
+eval "chown $lname $2"
+
+# Now it's time to begin running the daemon as a coprocess.
+# The daemon will use a : as its internal field separator.
+IFS=":"
+if (($sleeptime > 0)) then 
+    $1/dm_test_daemon -s $sleeptime $3 |&
+else
+    $1/dm_test_daemon $3 |&
+fi
+
+#Keep track of the coprocess id... "$!" may change.
+coproc=$!
+
+# Initialize the count of errors
+error_count=0;
+
+# dm_test_daemon starts with a spurious line feed.
+read -p junk
+
+# Finally, we've reached the actual loop to read in the testfile.
+while true
+do    
+      clear
+      while read -u3 cmd
+      do
+           case $cmd in
+           run_without_test)
+               while read -u3 cmd
+                do  case $cmd in
+                   ---*) clear; continue 2;;
+                    //*) continue;;
+                    @@*) cmd=${cmd#@@*}
+                         print "!!  ${cmd# *}"
+                         continue;;
+                       *) eval $cmd;;
+                   esac
+               done;;
+           run_as_root)
+               read -u3 cmd
+               root_flag=1
+                break;;
+           //*)  continue;;
+           @@*) cmd=${cmd#@@*}
+                 print "!!  ${cmd# *}"
+                continue;;
+              *) root_flag=0
+                break;;
+           esac
+      done
+      if (( $root_flag == 1 ))
+      then print "Command to execute (as root):\n\n   $cmd\n"
+           eval "$cmd"
+      else print "Command to execute:\n\n   $cmd\n"
+           eval "su $lname -c \"$cmd\""
+      fi
+
+      # Note failure of the command.  Also, send a message
+      # that the command is done.  We will know we're done
+      # reading from the daemon when we see this message. 
+      fail_flag=$?
+      $1/send_msg over
+      print
+
+      # Reset variables for reading this command.
+      event_count=0
+      unset contents event fs_handle handle length offset
+      unset media_designator mode mountpoint_handle
+      unset mountpoint_path msg_str name new_name new_parent
+      unset parent_handle ret_code root_handle sequence token  
+      unset tries_left unmount_mode
+
+      # Read events, report them, and store their data.
+      while true 
+      do 
+        read -p event[event_count]
+        case "${event[event_count]}" in
+        mount) 
+           print "Report: found mount event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk fs_handle[event_count]
+           read -p junk mountpoint_handle[event_count]
+           read -p junk mountpoint_path[event_count]
+           read -p junk media_designator[event_count]
+           read -p junk root_handle[event_count]
+           read -p junk mode[event_count]
+           read -p junk;;
+        preunmount) 
+           print "Report: found preunmount event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk fs_handle[event_count]
+           read -p junk root_handle[event_count]
+           read -p junk unmount_mode[event_count]
+           read -p junk;;
+        unmount) 
+           print "Report: found unmount event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk fs_handle[event_count]
+           read -p junk unmount_mode[event_count]
+           read -p junk ret_code[event_count]
+           read -p junk;;
+        nospace) 
+           print "Report: found nospace event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk fs_handle[event_count]
+           read -p junk;;
+        create|remove) 
+           print "Report: found ${event[event_count]} event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk name[event_count]
+           read -p junk mode[event_count]
+           read -p junk;;
+        postcreate) 
+           print "Report: found postcreate event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk handle[event_count]
+           read -p junk name[event_count]
+           read -p junk mode[event_count]
+           read -p junk ret_code[event_count]
+           read -p junk;;
+        postremove) 
+           print "Report: found postremove event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk name[event_count]
+           read -p junk mode[event_count]
+           read -p junk ret_code[event_count]
+           read -p junk;;
+        rename) 
+           print "Report: found rename event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk new_parent[event_count]
+           read -p junk name[event_count]
+           read -p junk new_name[event_count]
+           read -p junk;;
+        postrename) 
+           print "Report: found postrename event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk new_parent[event_count]
+           read -p junk name[event_count]
+           read -p junk new_name[event_count]
+           read -p junk ret_code[event_count]
+           read -p junk;;
+        symlink) 
+           print "Report: found symlink event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk name[event_count]
+           read -p junk contents[event_count]
+           read -p junk;;
+        postsymlink) 
+           print "Report: found postsymlink event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk handle[event_count]
+           read -p junk name[event_count]
+           read -p junk contents[event_count]
+           read -p junk ret_code[event_count]
+           read -p junk;;
+        link) 
+           print "Report: found link event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk handle[event_count]
+           read -p junk name[event_count]
+           read -p junk;;
+        postlink) 
+           print "Report: found postlink event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk parent_handle[event_count]
+           read -p junk handle[event_count]
+           read -p junk name[event_count]
+           read -p junk ret_code[event_count]
+           read -p junk;;
+        read|write|truncate) 
+           print "Report: found ${event[event_count]} event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk handle[event_count]
+           read -p junk offset[event_count]
+           read -p junk length[event_count]
+           read -p junk;;
+        attribute) 
+           print "Report: found attribute event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk handle[event_count]
+           read -p junk;;
+        destroy) 
+           print "Report: found destroy event."
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk handle[event_count]
+           read -p junk name[event_count]
+            read -p junk contents[event_count]
+           read -p junk;;
+        user) 
+           read -p junk token[event_count]
+           read -p junk sequence[event_count]
+           read -p junk msg_str[event_count]
+           case "${msg_str[event_count]}" in
+               "over") read -p junk 
+                        event[event_count]=end_of_tests
+                        print "Report: found \"end of test\" user event. "
+                       break;;
+               *) print "Report: found user event. "
+                  read -p junk;; 
+           esac;;
+        pending)
+           read -p junk tries_left[event_count]
+           print -n "Report: process pending. "
+           print "Tries left: ${tries_left[event_count]}"
+           read -p junk;;
+        *) 
+           print -n "Report: found ${event[event_count]} event. "
+           print    "(unknown to this version)"
+           while read -p msg_str[event_count]
+           do case "${msg_str[event_count]}" in
+                   "end_of_message") break;;
+                   *);;
+              esac
+           done;;
+        esac
+        ((event_count=event_count+1))
+      done
+      ((old_error_count=error_count));
+
+      IFS=" "
+
+      while read -u3 val_one val_two val_tre
+      do case $val_one in
+        ---*)  if [[ $fail_flag != -1 ]]
+                then if [[ $fail_flag != 0 ]]
+                     then print -n "ERROR: command failed; it was "
+                          print "expected to succeed."
+                         ((error_count=error_count+1))
+                    fi
+                fi
+                if (( error_count>old_error_count || pause_flag==1 )) 
+                then print "\nEnter q to quit, or press enter to continue..."
+                     read go
+                    case "$go" in
+                    q|Q) break;;
+                    *);;
+                    esac
+               fi
+                IFS=":"
+                continue 2;;
+        failure)
+           if [[ $fail_flag = 0 ]] 
+           then print "ERROR: command succeeded; it was expected to fail."
+          ((error_count=error_count+1))
+          else print "Note: command is expected to fail."
+          fi
+          fail_flag=-1;;
+         *) case $val_two in
+           matches)  
+               if [[ $(eval "print $"{$val_one}) = $(eval "print $"{$val_tre}) ]] 
+               then print "Report: $val_one and $val_tre match; both are "
+                   if [[ $(eval "print $"{$val_one}) = "" ]]
+                   then print "unset"
+                   else print "$(eval "print $"{$val_one})"
+                   fi
+              else print -n "ERROR: $val_one was "
+                   if [[ $(eval "print $"{$val_one}) = "" ]]
+                   then print -n "unset "
+                    else print -n "equal to $(eval "print $"{$val_one})"
+                   fi
+                   print -n ", while $val_tre was "
+                   if [[ $(eval "print $"{$val_tre}) = "" ]]
+                   then print "unset."
+                   else print "equal to $(eval "print $"{$val_tre})."
+                   fi
+                   ((error_count=error_count+1))
+              fi;;
+           store_in) 
+              eval ${val_tre}=$(eval "print $"{$val_one})
+              print -n "Report: value of ${val_one} copied into "
+              print "${val_tre}.";;
+           *) 
+               if [[ $(eval "print $"{$val_one}) = $val_two ]] 
+              then :
+              else if [[ "$val_one" = event_count ]]
+                   then print -n "ERROR: expected $val_two event(s), "
+                         print "but found $event_count."
+                        else print -n "ERROR: $val_one was "
+                        if [[ $(eval "print $"{$val_one}) = "" ]]
+                        then print -n "unset "
+                        else print -n "equal to $(eval "print $"{$val_one}) "
+                        fi
+                        print "rather than $val_two as expected."
+                   fi 
+                      ((error_count=error_count+1))
+              fi;;
+           esac;;
+        esac
+      done
+      if [[ $fail_flag != -1 ]] 
+      then if [[ $fail_flag != 0 ]]
+          then print -n "ERROR: command failed; it was "
+                print "expected to succeed."
+                ((error_count=error_count+1))
+           fi
+      fi
+      if (( error_count>old_error_count || pause_flag==1 )) 
+      then print "\nTests complete.  Press enter to quit..."
+           read go
+      fi
+      break
+done
+
+# Close the datafile
+exec 3<&-
+
+# End the daemon
+kill $coproc
+wait $coproc
+
+clear
+if ((error_count==1)) 
+then print "Test result: 1 error found."
+else print "Test result: $error_count errors found."
+fi
diff --git a/dmapi/src/suite2/bindir/stf b/dmapi/src/suite2/bindir/stf
new file mode 100755 (executable)
index 0000000..a0fe3c8
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/ksh
+#
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+sr_dir=$1
+shift 1
+
+for i in $*
+  do
+  attr -Rq -s SGI_DMI_test -V123456789abcdefghijklmnopqrstuvwxyz $i 
+  $sr_dir/set_region $i DM_REGION_READ DM_REGION_WRITE DM_REGION_TRUNCATE > /dev/null
+  done
diff --git a/dmapi/src/suite2/bindir/test_allocinfo_1 b/dmapi/src/suite2/bindir/test_allocinfo_1
new file mode 100755 (executable)
index 0000000..b37b316
--- /dev/null
@@ -0,0 +1,100 @@
+#!/bin/ksh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+
+#       Dump the same holey file using both xfs_bmap and 
+#       dump_allocinfo (a C wrapper for get_allocinfo).
+#      Run awk on the xfs_bmap output, since xfs_bmap
+#       gives specific block allocation info that get_allocinfo
+#       does not.  Then diff the two outputs.
+
+if [[ $# != 2 ]]
+then   print "USAGE:  ${0##*/} bindir testdir"
+       exit 1
+fi
+
+# Check bindir for needed programs.
+if [[ ! ( -r "$1/wf" ) ]]
+then print "Aborting: necessary program wf is not in $1/."
+     if [[ ! ( -r "$1/dump_allocinfo" ) ]]
+     then print "          necessary program dump_allocinfo is also missing."
+     fi
+     exit 1
+fi
+if [[ ! ( -r "$1/dump_allocinfo" ) ]]
+then print "Aborting: necessary program dump_allocinfo is not in $1/."
+     exit 1
+fi
+
+print "Comparison test (get_allocinfo vs. xfs_bmap) beginning..."
+
+typeset -i offset
+typeset -i length
+typeset -i count
+
+RANDOM=$SECONDS
+offset=0
+length=$RANDOM
+count=100
+filename=DMAPI_test_allocinfo
+
+# Create a random holey file
+while (( count > 0 ))
+do 
+       $1/wf -l $length -L $offset -b 512 $2/$filename > /dev/null
+       (( offset = RANDOM * 512 + offset + length )) 
+       (( length = RANDOM ))
+       (( count = count - 1 ))
+done
+
+# Get output from xfs_bmap
+xfs_bmap $2/DMAPI_test_allocinfo > $2/$filename.xfs
+
+# Get output from dump_allocinfo (DMAPI)
+$1/dump_allocinfo $2/DMAPI_test_allocinfo > $2/$filename.da
+       
+# Alter xfs_bmap ouput to match get_allocinfo
+awk '{ if (NR > 1)
+       if ($3 == "hole") 
+               print $1, $2, $3
+       else
+               print $1, $2, "resv"
+}' $2/DMAPI_test_allocinfo.xfs > $2/$filename.ok
+
+# Compare the ouput
+diff -w $2/$filename.ok $2/$filename.da
+
+# Remove the test file
+rm $2/$filename*
+
+print "Test complete."
diff --git a/dmapi/src/suite2/bindir/test_allocinfo_2 b/dmapi/src/suite2/bindir/test_allocinfo_2
new file mode 100755 (executable)
index 0000000..e3a3e36
--- /dev/null
@@ -0,0 +1,100 @@
+#!/bin/ksh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+#       Dump the same holey file a random number of times, each time
+#       using one less extent structure than the previous time.  
+#      The grep and diff code checks to make sure that you get the
+#      same answer each time, no matter how many extents you use.
+
+typeset -i offset
+typeset -i length
+typeset -i max
+
+# Verify correct usage
+if [[ $# != 2 ]] 
+then print "usage:  ${0##*/} bindir testdir"
+     exit 1
+fi
+
+# Check bindir for needed programs.
+if [[ ! ( -r "$1/wf" ) ]]
+then print "Aborting: necessary program wf is not in $1/."
+     if [[ ! ( -r "$1/dump_allocinfo" ) ]]
+     then print "          necessary program dump_allocinfo is also missing."
+     fi
+     exit 1
+fi
+if [[ ! ( -r "$1/dump_allocinfo" ) ]]
+then print "Aborting: necessary program dump_allocinfo is not in $1/."
+     exit 1
+fi
+
+print "Multiple-buffer-sizes test of get_allocinfo beginning..."
+
+RANDOM=$SECONDS
+offset=0
+length=$RANDOM
+filename=DMAPI_alloc_test_2
+((max = $RANDOM/256))
+count=$max
+
+# Holey file creation: put about $max holes into the file.
+while (( count > 0 ))
+do 
+       $1/wf -l $length -L $offset -b 512 $2/$filename > /dev/null
+       (( offset = RANDOM * 512 + offset + length )) 
+       (( length = RANDOM ))
+       (( count = count - 1 ))
+done
+count=$max
+
+# Now count down from $max to 1 and try dump_allocinfo with a buffer that
+# can hold that many dm_extent_t structures.
+while [[ $count > 0 ]]
+do
+        $1/dump_allocinfo -n $count $2/$filename | grep '\[' > $2/x.$count
+        if (( count < max ))
+        then diff $2/x.$count $2/x.$max > /dev/null
+            if [[ $? != 0 ]]
+            then print "ERROR in trial #$count:"
+                 diff $2/x.$count $2/x.$max
+            fi
+            rm $2/x.$count
+        fi
+        (( count = count - 1 ))
+done
+
+rm $2/x.$max
+rm $2/$filename
+
+print "Test complete."
diff --git a/dmapi/src/suite2/create_cpio b/dmapi/src/suite2/create_cpio
new file mode 100644 (file)
index 0000000..92f626b
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+rm /home/hickory43/jayw/test/dist/DMAPI_test.cpio
+cd /home/hickory43/jayw/test
+find * \( ! -name '*.o' ! -name '*~' ! -name './dist/*' \) | cpio -oc > /home/hickory43/jayw/test/dist/DMAPI_test.cpio
+cp /home/hickory43/jayw/test/README /home/hickory43/jayw/test/dist/README
+cd /home/hickory43/jayw/test/dist
+
diff --git a/dmapi/src/suite2/data/fail.dat b/dmapi/src/suite2/data/fail.dat
new file mode 100644 (file)
index 0000000..c8dfb0b
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy ctest.c
+fcntl open_test truncate rd wf 
+set_region set_return_on_destroy 
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state, and they ensure that the NFS
+//
+rm $real_dir/???
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+rm $real_dir/ctest.c
+cp $1/ctest.c $real_dir
+chown $lname $real_dir/*
+$1/set_return_on_destroy $real_dir test
+rmdir $real_dir/fail_tempdir/fail_subdir
+rm $real_dir/fail_tempdir/*
+rmdir $real_dir/fail_tempdir
+mkdir $real_dir/fail_tempdir
+mkdir $real_dir/fail_tempdir/fail_subdir
+echo "Temporary file" > $real_dir/fail_tempdir/temp_file
+chown root $real_dir/fail_tempdir
+--------------------------------------------
+@@ Failure checks (1 of 8):  symlink
+@@
+ln -s $2/fail_tempdir/temp_file $2/fail_tempdir/failed_symlink
+event_count 2
+event[0] symlink
+event[1] postsymlink
+ret_code[1] 13
+failure
+--------------------------------------------
+@@ Failure checks (2 of 8):  link
+@@
+ln $2/fail_tempdir/temp_file $2/fail_tempdir/failed_link
+event_count 2
+event[0] link
+event[1] postlink
+ret_code[1] 13
+failure
+--------------------------------------------
+@@ Failure checks (3 of 8):  mkdir
+@@
+mkdir $2/fail_tempdir/failed_subdir
+event_count 2
+event[0] create
+event[1] postcreate
+ret_code[1] 13
+failure
+--------------------------------------------
+@@ Failure checks (4 of 8):  rmdir
+@@
+rmdir $2/fail_tempdir/fail_subdir
+event_count 2
+event[0] remove
+event[1] postremove
+ret_code[1] 13
+failure
+--------------------------------------------
+@@ Failure checks (5 of 8):  open
+@@
+$1/open_test $2/fail_tempdir/temp_file o_rdwr
+event_count 0
+failure
+--------------------------------------------
+@@ Failure checks (6 of 8):  open/create
+@@
+$1/open_test $2/fail_tempdir/temp_file o_rdwr o_creat
+event_count 0
+failure
+--------------------------------------------
+@@ Failure checks (7 of 8):  open/truncate
+@@
+$1/open_test $2/fail_tempdir/temp_file o_rdwr o_trunc
+event_count 0
+failure
+--------------------------------------------
+@@ Failure checks (8 of 8):  remove
+@@
+rm -f $2/fail_tempdir/temp_file
+event_count 2
+event[0] remove
+event[1] postremove
+ret_code[1] 13
+failure
diff --git a/dmapi/src/suite2/data/main.dat b/dmapi/src/suite2/data/main.dat
new file mode 100644 (file)
index 0000000..ae2f4b5
--- /dev/null
@@ -0,0 +1,159 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy ctest.c
+fcntl open_test truncate rd wf 
+read_invis write_invis
+set_region set_return_on_destroy 
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/???
+rm $real_dir/ctest.c
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+cp $1/ctest.c $real_dir
+chown $lname $real_dir/l??
+chown $lname $real_dir/ctest.c
+$1/set_return_on_destroy $real_dir test
+--------------------------------------------
+@@ Aborted events testing (1 of 7):
+@@     Read ls0 successfully.
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Aborted events testing (2 of 7):
+@@    Set the daemon to halt events with DM_RESP_ABORT
+@@    and errno EEXIST. 
+@@
+run_as_root
+$1/send_msg unfriendly_17
+event_count 1
+event[0] user
+msg_str[0] unfriendly_17
+--------------------------------------------
+@@ Aborted events testing (3 of 7):
+@@    Try to read ls0.  this should fail with EEXIST.
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 1
+event[0] read
+failure
+--------------------------------------------
+@@ Aborted events testing (4 of 7):
+@@    Try to read ls1.  This should fail with EEXIST.
+@@
+$1/open_test $2/ls1 o_rdwr o_trunc
+event_count 1
+event[0] truncate
+failure
+--------------------------------------------
+@@ Aborted events testing (5 of 7):
+@@    Reset the daemon to respond with DM_RESP_CONTINUE.
+@@
+run_as_root
+$1/send_msg friendly
+event_count 1
+event[0] user
+msg_str[0] friendly
+--------------------------------------------
+@@ Aborted events testing (6 of 7):
+@@    Again, try to read ls0.  This should succeed.
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Aborted events testing (7 of 7):
+@@    Again, try to read ls1.  This time, 
+@@    it should succeed.
+@@
+$1/open_test $2/ls1 o_rdwr o_trunc
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ dm_send_msg test
+@@
+run_as_root
+$1/send_msg dmapi-test-foo-abc123
+event_count 1
+event[0] user
+msg_str[0] dmapi-test-foo-abc123
+--------------------------------------------
+@@ Test of invisible i/o (1 of 2):  write
+@@
+run_as_root
+$1/write_invis -o 64 -l 16 $2/ls0
+event_count 0
+--------------------------------------------
+@@ Test of invisible i/o (2 of 2):  read
+@@
+run_as_root
+$1/read_invis -o 64 -l 16 $2/ls0
+event_count 0
+--------------------------------------------
+@@ Test of direct i/o (1 of 2):  write
+@@
+$1/wf  -l 327680 -b 32768 -d $2/ls9
+event_count 10
+event[0] write
+event[1] write
+event[2] write
+event[3] write
+event[4] write
+event[5] write
+event[6] write
+event[7] write
+event[8] write
+event[9] write
+--------------------------------------------
+@@ Test of direct i/o (2 of 2):  read
+@@
+$1/rd -b 32768 -d $2/ls9
+event_count 11
+event[0] read
+event[1] read
+event[2] read
+event[3] read
+event[4] read
+event[5] read
+event[6] read
+event[7] read
+event[8] read
+event[9] read
+event[10] read
diff --git a/dmapi/src/suite2/data/nfs.dat b/dmapi/src/suite2/data/nfs.dat
new file mode 100644 (file)
index 0000000..601f811
--- /dev/null
@@ -0,0 +1,174 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy ctest.c
+fcntl open_test truncate rd wf 
+set_region set_return_on_destroy 
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/???
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+chown $lname $real_dir/l??
+$1/set_return_on_destroy $real_dir test
+--------------------------------------------
+@@ Aborted events testing (1 of 7):
+@@    Bring ls0 across NFS, causing it to be cached.
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Aborted events testing (2 of 7):
+@@    Set the daemon to halt events with DM_RESP_ABORT
+@@    and errno EEXIST. 
+@@
+run_as_root
+$1/send_msg unfriendly_17
+event_count 1
+event[0] user
+msg_str[0] unfriendly_17
+--------------------------------------------
+@@ Aborted events testing (3 of 7):
+@@    Try to read ls0.  Since it is cached, this should succeed.
+@@    and should not generate any events.
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 0
+--------------------------------------------
+@@ Aborted events testing (4 of 7):
+@@    Try to read ls1.  This should fail with EEXIST.
+@@
+$1/open_test $2/ls1 o_rdwr o_trunc
+event_count 1
+event[0] truncate
+failure
+--------------------------------------------
+@@ Aborted events testing (5 of 7):
+@@    Reset the daemon to respond with DM_RESP_CONTINUE.
+@@
+run_as_root
+$1/send_msg friendly
+event_count 1
+event[0] user
+msg_str[0] friendly
+--------------------------------------------
+@@ Aborted events testing (6 of 7):
+@@    Again, try to read ls0.  It will be in the cache, 
+@@    so no events should occur.
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 0
+--------------------------------------------
+@@ Aborted events testing (7 of 7):
+@@    Again, try to read ls1.  This time, 
+@@    it should succeed.
+@@
+$1/open_test $2/ls1 o_rdwr o_trunc
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ dm_send_msg test
+@@
+run_as_root
+$1/send_msg dmapi-test-foo-abc123
+event_count 1
+event[0] user
+msg_str[0] dmapi-test-foo-abc123
+--------------------------------------------
+@@ NFS test:  DM_RESP_ABORT (1 of 3)
+@@
+// For the next two events, respond with
+// DM_RESP_ABORT and errno 4  The first 
+// open test of ls1 should fail; the
+// second should succeed.
+//
+run_as_root
+$1/send_msg countdown_2_4
+event_count 1
+event[0] user
+msg_str[0] countdown_2_4
+--------------------------------------------
+@@ NFS test:  DM_RESP_ABORT (2 of 3)
+@@
+$1/open_test $2/ls2 o_rdwr
+event_count 1
+event[0] read
+failure
+--------------------------------------------
+@@ NFS test:  DM_RESP_ABORT (3 of 3)
+@@
+$1/open_test $2/ls2 o_rdwr
+event_count 1
+event[0] read
+--------------------------------------------
+@@ NFS test:  EAGAIN (1 of 4)
+@@
+// For the next two events, respond with
+// DM_RESP_ABORT and errno 11 -- EAGAIN.
+// NFS should retry sending the event as
+// long as EAGAIN is returned.
+//
+run_as_root
+$1/send_msg countdown_2_11
+event_count 1
+event[0] user
+msg_str[0] countdown_2_11
+--------------------------------------------
+@@ NFS test:  EAGAIN (2 of 4)
+@@
+$1/open_test $2/ls3 o_rdwr
+event_count 2
+event[0] read
+event[1] read
+--------------------------------------------
+@@ NFS test:  EAGAIN (3 of 4)
+@@
+run_as_root
+$1/send_msg countdown_4_11
+event_count 1
+event[0] user
+msg_str[0] countdown_4_11
+--------------------------------------------
+@@ NFS test:  EAGAIN (4 of 4)
+@@
+$1/open_test $2/ls4 o_rdwr
+event_count 4
+event[0] read
+event[1] read
+event[2] read
+event[3] read
diff --git a/dmapi/src/suite2/data/pending.dat b/dmapi/src/suite2/data/pending.dat
new file mode 100644 (file)
index 0000000..794b586
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy set_region
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/???
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+chown $lname $real_dir/l??
+--------------------------------------------
+@@ Pending test (1 of 5):
+@@
+// Run "pending" for the next 3 events,
+// so that a non-blocking open_test
+// will see EAGAIN three times before
+// it can finish.
+//
+run_as_root
+$1/send_msg pending_3
+event_count 1
+event[0] user
+msg_str[0] pending_3
+--------------------------------------------
+@@ Pending test (2 of 5):
+@@    (should fail)
+@@
+$1/open_test $2/ls1 o_rdwr o_nonblock
+event_count 1
+event[0] pending
+tries_left[0] 2
+failure
+--------------------------------------------
+@@ Pending test (3 of 5):
+@@    (should fail)
+@@
+$1/open_test $2/ls1 o_rdwr o_ndelay
+event_count 1
+event[0] pending
+tries_left[0] 1
+failure
+--------------------------------------------
+@@ Pending test (4 of 5):
+@@    (should fail)
+@@
+$1/open_test $2/ls1 o_rdwr o_nonblock o_ndelay
+event_count 1
+event[0] pending
+tries_left[0] 0
+failure
+--------------------------------------------
+@@ Pending test (5 of 5):
+@@    (should succeed)
+@@
+$1/open_test $2/ls1 o_rdwr o_nonblock
+event_count 1
+event[0] read
diff --git a/dmapi/src/suite2/data/pending_nfs.dat b/dmapi/src/suite2/data/pending_nfs.dat
new file mode 100644 (file)
index 0000000..3b677af
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy set_region
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/???
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+chown $lname $real_dir/l??
+--------------------------------------------
+@@ NFS test:  pending (1 of 2)
+@@
+// Run "pending" for the next 3 events,
+// so that ls0 will trigger 3 pending
+// pseudo-events before succeeding
+//
+run_as_root
+$1/send_msg pending_3
+event_count 1
+event[0] user
+msg_str[0] pending_3
+--------------------------------------------
+@@ NFS test:  pending (2 of 2)
+@@
+@@    (this will take a while...)
+@@
+$2/ls0 -l $real_dir
+event_count 7
+event[0] pending
+event[1] pending
+event[2] pending
+event[3] read
+event[4] read
+event[5] read
+event[6] read
+tries_left[0] 2
+tries_left[1] 1
+tries_left[2] 0
diff --git a/dmapi/src/suite2/data/realtime.dat b/dmapi/src/suite2/data/realtime.dat
new file mode 100644 (file)
index 0000000..a74e16c
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+stf crttf new_wf
+fcntl open_test truncate rd wf 
+read_invis write_invis
+set_region set_return_on_destroy 
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/realtime.?
+$1/crttf $1 $real_dir
+chown $lname $real_dir/* 
+$1/stf $1 $real_dir/realtime.?
+$1/set_return_on_destroy $real_dir test
+--------------------------------------------
+@@ Test of invisible i/o (1 of 2):  write
+@@
+run_as_root
+$1/write_invis -o 64 -l 16 $2/realtime.0
+event_count 0
+--------------------------------------------
+@@ Test of invisible i/o (2 of 2):  read
+@@
+run_as_root
+$1/read_invis -o 64 -l 16 $2/realtime.0
+event_count 0
+--------------------------------------------
+@@ Test of direct i/o (1 of 2):  write
+@@
+$1/wf  -l 327680 -b 32768 -d $2/realtime.1
+event_count 10
+event[0] write
+event[1] write
+event[2] write
+event[3] write
+event[4] write
+event[5] write
+event[6] write
+event[7] write
+event[8] write
+event[9] write
+--------------------------------------------
+@@ Test of direct i/o (2 of 2):  read
+@@
+$1/rd -b 32768 -d $2/realtime.1
+event_count 11
+event[0] read
+event[1] read
+event[2] read
+event[3] read
+event[4] read
+event[5] read
+event[6] read
+event[7] read
+event[8] read
+event[9] read
+event[10] read
+--------------------------------------------
+@@ Standard i/o tests (1 of 7):  open
+@@
+$1/open_test $2/realtime.2 o_rdwr
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Standard i/o tests (2 of 7):  open/trunc
+@@
+$1/open_test $2/realtime.3 o_rdwr o_trunc
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (3 of 7):  open/trunc/create
+@@
+$1/open_test $2/realtime.4 o_rdwr o_trunc o_creat
+event_count 1
+event[0] truncate
+--------------------------------------------
+@@ Standard i/o tests (4 of 7):  open/create
+@@
+$1/open_test $2/realtime.5 o_rdwr o_creat
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Standard i/o tests (5 of 7):  append #1
+@@
+echo j >> $2/realtime.6
+event_count 1
+event[0] write
+file_handle[0] store_in ls4temp
+--------------------------------------------
+@@ Standard i/o tests (6 of 7):  append #2
+@@
+echo w >> $2/realtime.6
+event_count 1
+event[0] write
+file_handle[0] matches ls4temp
+--------------------------------------------
+@@ Standard i/o tests (7 of 7):  remove
+@@
+/bin/rm $2/realtime.6
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+name[1] test
+contents[1] 123456789abcdefghijklmnopqrstuvwxyz
diff --git a/dmapi/src/suite2/data/smallq.dat b/dmapi/src/suite2/data/smallq.dat
new file mode 100644 (file)
index 0000000..dfc7fcb
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy ctest.c
+fcntl open_test truncate rd wf mmap_cp
+read_invis write_invis
+set_region set_return_on_destroy 
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/???
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+rm $real_dir/ctest.c
+cp $1/ctest.c $real_dir
+chown $lname $real_dir/l??
+chown $lname $real_dir/ctest.c
+$1/set_return_on_destroy $real_dir test
+print 
+print "Please resize your DMAPI event queue to hold about 2 to 10 events."
+--------------------------------------------
+@@ Slow i/o test:  Do 10 open_tests
+@@
+run_without_test
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+$1/open_test $2/ls0 o_rdwr &
+--------------------------------------------
+@@ Slow i/o test:  Append ten bytes to ls1
+@@
+run_without_test
+echo J >> $2/ls1 &
+echo a >> $2/ls1 &
+echo y >> $2/ls1 &
+echo w >> $2/ls1 &
+echo a >> $2/ls1 &
+echo s >> $2/ls1 &
+echo h >> $2/ls1 &
+echo e >> $2/ls1 &
+echo r >> $2/ls1 &
+echo e >> $2/ls1 &
+--------------------------------------------
+@@ Slow i/o test:  Do one more, then stand back and wait!
+@@ 
+$1/open_test $2/ls0 o_rdwr 
+event_count 21
+event[0] read
+event[1] read
+event[2] read
+event[3] read
+event[4] read
+event[5] read
+event[6] read
+event[7] read
+event[8] read
+event[9] read
+event[10] write
+event[11] write
+event[12] write
+event[13] write
+event[14] write
+event[15] write
+event[16] write
+event[17] write
+event[18] write
+event[19] write
+event[20] read
diff --git a/dmapi/src/suite2/data/standard.dat b/dmapi/src/suite2/data/standard.dat
new file mode 100644 (file)
index 0000000..684dff9
--- /dev/null
@@ -0,0 +1,323 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy ctest.c
+fcntl open_test truncate rd wf mmap_cp
+read_invis write_invis
+set_region set_return_on_destroy 
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/???
+rm $real_dir/mmap_cp_testfile
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+rm $real_dir/ctest.c
+cp $1/ctest.c $real_dir
+chown $lname $real_dir/l??
+chown $lname $real_dir/ctest.c
+$1/set_return_on_destroy $real_dir test
+--------------------------------------------
+@@  Memory-mapped copying test: (1 of 3)
+@@
+$1/mmap_cp $2/ll1 $2/mmap_cp_testfile
+event_count 3
+event[0] create
+event[1] postcreate
+event[2] read
+--------------------------------------------
+@@  Memory-mapped copying test: (2 of 3)
+@@
+$1/mmap_cp $2/ll1 $2/mmap_cp_testfile
+event_count 1
+event[0] read
+--------------------------------------------
+@@  Memory-mapped copying test: (3 of 3)
+@@
+$1/mmap_cp $2/ll1 $2/ll2
+event_count 2
+event[0] read
+event[1] write
+--------------------------------------------
+@@  Preunmount/unmount test 
+@@     (note: if you abort before the next test, the 
+@@      filesystem will remain unmounted)
+@@
+run_as_root
+umount $3
+event_count 2
+event[0] preunmount
+event[1] unmount
+fs_handle[0] matches fs_handle[1]
+fs_handle[0] store_in fsh
+root_handle[0] store_in rh
+unmount_mode[0] NOFORCE
+unmount_mode[1] NOFORCE
+--------------------------------------------
+@@  Mount test  
+@@     (Note: assorted settings will be restored in next tests)
+@@
+run_as_root
+mount $3
+event_count 1
+event[0] mount
+fs_handle[0] matches fsh
+mountpoint_handle[0] <BAD_HANDLE_hlen_0>
+mountpoint_path[0] /dmitest
+mode[0] 0
+root_handle matches rh 
+--------------------------------------------
+@@  (after remount: restoring event dispositions on fs)
+@@
+run_as_root
+$1/send_msg reset_fs
+event_count 1
+event[0] user
+msg_str[0] reset_fs
+--------------------------------------------
+@@  (after remount: restoring managed regions on files
+@@   and setting destroy events to return "test" attribute)
+@@
+run_without_test
+$1/stf $1 $real_dir/l??
+$1/set_return_on_destroy $real_dir test
+-------------------------------------------
+@@ Standard i/o tests (1 of 26):  open
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Standard i/o tests (2 of 26):  open/trunc
+@@
+$1/open_test $2/ls1 o_rdwr o_trunc
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (3 of 26):  open/trunc/create
+@@
+$1/open_test $2/ls2 o_rdwr o_trunc o_creat
+event_count 1
+event[0] truncate
+--------------------------------------------
+@@ Standard i/o tests (4 of 26):  open/create
+@@
+$1/open_test $2/ls3 o_rdwr o_creat
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Standard i/o tests (5 of 26):  new file
+@@
+$1/open_test $2/LS3 o_rdwr o_creat
+event_count 2
+event[0] create
+event[1] postcreate
+--------------------------------------------
+@@ Standard i/o tests (6 of 26):  append #1
+@@
+echo j >> $2/ls4
+event_count 1
+event[0] write
+file_handle[0] store_in ls4temp
+--------------------------------------------
+@@ Standard i/o tests (7 of 26):  append #2
+@@
+echo j >> $2/ls4
+event_count 1
+event[0] write
+file_handle[0] matches ls4temp
+--------------------------------------------
+@@ Standard i/o tests (8 of 26):  remove
+@@
+/bin/rm $2/ls4
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+name[1] test
+contents[1] 123456789abcdefghijklmnopqrstuvwxyz
+--------------------------------------------
+@@ Standard i/o tests (9 of 26):  link
+@@
+ln $2/ls5 $2/LS5
+event_count 2
+event[0] link
+event[1] postlink
+--------------------------------------------
+@@ Standard i/o tests (10 of 26):  deleting link
+@@
+/bin/rm $2/LS5
+event_count 2
+event[0] remove
+event[1] postremove
+--------------------------------------------
+@@ Standard i/o tests (11 of 26):  return_on_destroy #1
+@@
+run_without_test
+$1/set_return_on_destroy $real_dir
+--------------------------------------------
+@@ Standard i/o tests (12 of 26):  return_on_destroy #2
+@@
+/bin/rm $2/ls5
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+name[1] <NONE>
+contents[1] <NONE>
+--------------------------------------------
+@@ Standard i/o tests (13 of 26)
+@@
+$1/fcntl f_freesp -o 99999 -l 199999 $2/ls6
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (14 of 26)
+@@
+$1/fcntl f_freesp -o 1000 -l 10000 $2/ls6
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (15 of 26) truncate #1
+@@
+$1/truncate $2/ls7 99999
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (16 of 26) truncate #2
+@@
+$1/truncate $2/ls7 1000
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (17 of 26) execute
+@@
+$2/ls8 -l $real_dir
+event[0] read
+event[1] read
+event[2] read
+event[3] read
+event[4] read
+offset[0] 0
+length[0] 29604
+file_handle[0] matches file_handle[1]
+file_handle[0] matches file_handle[2]
+file_handle[0] matches file_handle[3]
+--------------------------------------------
+@@ Standard i/o tests (18 of 26) symlink
+@@
+ln -s $2/junk $2/symlink
+event_count 2
+event[0] symlink
+event[1] postsymlink
+--------------------------------------------
+@@ Standard i/o tests (19 of 26) deleting symlink
+@@
+/bin/rm $2/symlink
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+--------------------------------------------
+@@ Standard i/o tests (20 of 26) mkdir
+@@
+mkdir $2/unlikely-named-test-dir
+event_count 2
+event[0] create
+event[1] postcreate
+--------------------------------------------
+@@ Standard i/o tests (21 of 26) rmdir
+@@
+rmdir $2/unlikely-named-test-dir
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+--------------------------------------------
+@@ Standard i/o tests (22 of 26) rename
+@@
+mv $2/ls8 $2/LS8
+event_count 2
+event[0] rename
+event[1] postrename
+--------------------------------------------
+@@ Standard i/o tests (23 of 26) copy (new)
+@@
+cp $2/ls9 $2/LS9
+event_count 9
+event[0] create
+event[1] postcreate
+event[2] attribute
+event[3] read
+event[4] read
+event[5] read
+event[6] read
+event[7] read
+event[8] attribute
+--------------------------------------------
+@@ Standard i/o tests (24 of 26) copy (onto old)
+@@
+cp $2/LS9 $2/ls9
+event_count 5
+event[0] truncate
+event[1] write
+event[2] write
+event[3] write
+event[4] write
+--------------------------------------------
+@@ Standard i/o tests (25 of 26) memory-mapped i/o
+@@
+// Note to self: don't check event_count
+//
+cc -o $2/ll0 $2/ctest.c
+event[0] truncate
+event[1] write
+event[2] attribute
+event[3] read
+event[4] write
+--------------------------------------------
+@@ Standard i/o tests (26 of 26) executing
+@@
+$2/ll0
+event[0] read
+event[1] read
+event[2] read
+event[3] read
+event[4] read
diff --git a/dmapi/src/suite2/data/standard_nfs.dat b/dmapi/src/suite2/data/standard_nfs.dat
new file mode 100644 (file)
index 0000000..8acf3f9
--- /dev/null
@@ -0,0 +1,247 @@
+//
+// Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+// 
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of version 2 of the GNU General Public License as
+// published by the Free Software Foundation.
+// 
+// This program is distributed in the hope that it would be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// 
+// Further, this software is distributed without any warranty that it is
+// free of the rightful claim of any third person regarding infringement
+// or the like.  Any license provided herein, whether implied or
+// otherwise, applies only to this software file.  Patent licenses, if
+// any, provided herein do not apply to combinations of this program with
+// other software, or any other product whatsoever.
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write the Free Software Foundation, Inc., 59
+// Temple Place - Suite 330, Boston MA 02111-1307, USA.
+// 
+// Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+// Mountain View, CA  94043, or:
+// 
+// http://www.sgi.com 
+// 
+// For further information regarding this notice, see: 
+// 
+// http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+// This test will use the following files:
+//
+ctf stf ls_to_copy ctest.c
+fcntl open_test truncate rd wf 
+read_invis write_invis
+set_region set_return_on_destroy 
+--------------------------------------------
+// These setup commands are run before the daemon starts.
+// They reset the file structure of the test directory
+// to a known state.
+//
+rm $real_dir/???
+$1/ctf $1 $real_dir
+$1/stf $1 $real_dir/l??
+rm $real_dir/ctest.c
+cp $1/ctest.c $real_dir
+chown $lname $real_dir/l??
+chown $lname $real_dir/ctest.c
+$1/set_return_on_destroy $real_dir test
+--------------------------------------------
+@@ Standard i/o tests (1 of 26):  open
+@@
+$1/open_test $2/ls0 o_rdwr
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Standard i/o tests (2 of 26):  open/trunc
+@@
+$1/open_test $2/ls1 o_rdwr o_trunc
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (3 of 26):  open/trunc/create
+@@
+$1/open_test $2/ls2 o_rdwr o_trunc o_creat
+event_count 1
+event[0] truncate
+--------------------------------------------
+@@ Standard i/o tests (4 of 26):  open/create
+@@
+$1/open_test $2/ls3 o_rdwr o_creat
+event_count 1
+event[0] read
+--------------------------------------------
+@@ Standard i/o tests (5 of 26):  new file
+@@
+$1/open_test $2/LS3 o_rdwr o_creat
+event_count 2
+event[0] create
+event[1] postcreate
+--------------------------------------------
+@@ Standard i/o tests (6 of 26):  append #1
+@@
+echo j >> $2/ls4
+event_count 2
+event[0] read
+event[1] write
+file_handle[0] store_in ls4temp
+--------------------------------------------
+@@ Standard i/o tests (7 of 26):  append #2
+@@
+echo j >> $2/ls4
+event_count 1
+event[0] write
+file_handle[0] matches ls4temp
+--------------------------------------------
+@@ Standard i/o tests (8 of 26):  remove
+@@
+/bin/rm $2/ls4
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+name[1] test
+contents[1] 123456789abcdefghijklmnopqrstuvwxyz
+--------------------------------------------
+@@ Standard i/o tests (9 of 26):  link
+@@
+ln $2/ls5 $2/LS5
+event_count 2
+event[0] link
+event[1] postlink
+--------------------------------------------
+@@ Standard i/o tests (10 of 26):  deleting link
+@@
+/bin/rm $2/LS5
+event_count 2
+event[0] remove
+event[1] postremove
+--------------------------------------------
+@@ Standard i/o tests (11 of 26):  return_on_destroy #1
+@@
+run_without_test
+$1/set_return_on_destroy $real_dir
+--------------------------------------------
+@@ Standard i/o tests (12 of 26):  return_on_destroy #2
+@@
+/bin/rm $2/ls5
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+name[1] <NONE>
+contents[1] <NONE>
+--------------------------------------------
+@@ Standard i/o tests (13 of 26)
+@@
+$1/fcntl f_freesp -o 99999 -l 199999 $2/ls6
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (14 of 26)
+@@
+$1/fcntl f_freesp -o 1000 -l 10000 $2/ls6
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (15 of 26) truncate #1
+@@
+$1/truncate $2/ls7 99999
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (16 of 26) truncate #2
+@@
+$1/truncate $2/ls7 1000
+event_count 2
+event[0] truncate
+event[1] attribute
+--------------------------------------------
+@@ Standard i/o tests (17 of 26) execute
+@@
+$2/ls8 -l $real_dir
+event_count 4
+event[0] read
+event[1] read
+event[2] read
+event[3] read
+--------------------------------------------
+@@ Standard i/o tests (18 of 26) symlink
+@@
+ln -s $2/junk $2/symlink
+event_count 2
+event[0] symlink
+event[1] postsymlink
+--------------------------------------------
+@@ Standard i/o tests (19 of 26) deleting symlink
+@@
+/bin/rm $2/symlink
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+--------------------------------------------
+@@ Standard i/o tests (20 of 26) mkdir
+@@
+mkdir $2/unlikely-named-test-dir
+event_count 2
+event[0] create
+event[1] postcreate
+--------------------------------------------
+@@ Standard i/o tests (21 of 26) rmdir
+@@
+rmdir $2/unlikely-named-test-dir
+event_count 3
+event[0] remove
+event[1] destroy
+event[2] postremove
+--------------------------------------------
+@@ Standard i/o tests (22 of 26) rename
+@@
+mv $2/ls8 $2/LS8
+event_count 2
+event[0] rename
+event[1] postrename
+--------------------------------------------
+@@ Standard i/o tests (23 of 26) copy (new)
+@@
+cp $2/ls9 $2/LS9
+event_count 8
+event[0] create
+event[1] postcreate
+event[2] attribute
+event[3] read
+event[4] read
+event[5] read
+event[6] read
+event[7] attribute
+--------------------------------------------
+@@ Standard i/o tests (24 of 26) copy (onto old)
+@@
+cp $2/LS9 $2/ls9
+event_count 5
+event[0] truncate
+event[1] write
+event[2] write
+event[3] write
+event[4] write
+--------------------------------------------
+@@ Standard i/o tests (25 of 26) memory-mapped i/o
+@@
+// Note to self: don't check event_count
+//
+cc -o $2/ll0 $2/ctest.c
+event[0] truncate
+event[1] attribute
+event[2] write
+--------------------------------------------
+@@ Standard i/o tests (26 of 26) executing
+@@
+$2/ll0
+event_count 0
diff --git a/dmapi/src/suite2/dist/README b/dmapi/src/suite2/dist/README
new file mode 100644 (file)
index 0000000..49aca8f
--- /dev/null
@@ -0,0 +1,463 @@
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+                           DMAPI Test Suite 
+                          Informational File
+                          ------------------
+
+I) Getting Started
+
+   A) Extracting from DMAPI_test.cpio
+
+      1) Create a new directory for storing the tests.  We will refer to 
+         this as the "base" directory.  The base directory can be
+         located anywhere; it does NOT need to be in a DMAPI filesystem.
+
+      2) Move the archive file DMAPI_test.cpio to the base directory
+         and execute the following command to extract from the archive:
+            cat DMAPI_test.cpio | cpio -icd
+
+      3) There should now be several files and subdirectories in the base
+         directory, including the file "file_list".  Read this file for a
+         complete listing of which files should be present in which
+         directories.  Compare "file_list" with the output of "ls -Rpl" 
+         to be sure that you have the necessary files.
+
+      4) The base directory contains the files and programs that are of
+         immediate use for testing.  The "bindir" subdirectory contains
+         the test programs and datafiles.  The "lib" and "src" subdirectories
+         contain C libraries and source code for the C programs. 
+
+   B) Checking the Existence and Version of DMAPI
+      The program check_dmapi can verify that you have the correct
+      version of DMAPI installed.  Note: it can only be run as root.
+      Execute this command (from the "base" directory):
+      bindir/check_dmapi
+      It should report that you have a current version of DMAPI.  If it
+      does not, it will also suggest which components of your DMAPI are 
+      not current, and where to find a patch to update them.
+
+   C) Configuration
+
+      1) Creating the Test Directories
+
+         a) The Test Filesystem
+            Mount a DMAPI filesystem, or use an existing one.
+            This filesystem's mount info MUST be listed in /etc/fstab.
+            Write down the path to this filesystem's mountpoint, and label
+            it as "m_main" for future use.
+         b) The Main Test Directory
+            
+            Create a new directory in the "m_main" filesystem. 
+            Write down the path to this directory.  Note ONLY the part
+            that comes AFTER "m_main".  Label this as "d_name".
+            EXAMPLE: You have a DMAPI filesystem /dmi_main  
+                     You name the test directory /dmi_main/test_dir
+            "m_main" is /dmi_main 
+            "d_name" is /test_dir
+         c) The Cross-NFS Test Directories 
+            For NFS tests, all you must do is create two empty directories
+            (one for nfs2, one for nfs3). They do NOT need to be in a 
+            DMAPI filesystem.  
+            Your main test directory will be mounted across NFS, into these
+            two directories.  Normally, the tests will do this automatically.
+            However, if you need to do this mount manually, the command
+            would look like this example:
+            mount -t nfs2 localhost:/dmi_main /dmi_nfs2
+            Write down the paths to these nfs2 and nfs3 test directories.
+            Label them "m_nfs2" and "m_nfs3" respectively.
+         c) The Realtime Test Filesystem and Directory
+            If you wish to test realtime i/o, you'll need a filesystem 
+            mounted with a realtime partition, and a directory in that
+            filesystem.  
+            Label the path to the filesystem mountpoint as "m_rt".
+            Label the path to the test directory as "d_rt".
+      2) Configuring menu_test
+         The Korn-shell script named menu_test is an interface to the
+         other test programs.  At the beginning of the script, there
+         is a "configuration section", in which is sets several variables
+         for use in the rest of the script.  
+         
+         Open menu_test in any text editor and change the following
+         variable assignments in the configuration section:
+         a) base_dir:
+            Set this to the pathname of your "base" directory 
+            (where you un-archived "DMAPI_test.cpio").
+         b) p_user:
+            Tests that do not run as root will run as this "primary" user.
+            Set this to any username. 
+         c) m_main:
+            The mountpoint of the main test filesystem.
+            Set this to the value of "m_main" that you wrote down above.  
+  
+         d) d_name:  
+            m_main concatenated with d_name is the main test directory path.
+            Set this to the value for "d_name" that you wrote down above.
+         e) m_nfs2:  
+            The mountpoint of the nfs2 test filesystem.
+            Set this to the value of "m_nfs2" that you wrote down above.
+         f) m_nfs2:   
+            The mountpoint of the nfs3 test filesystem.
+            Set this to the value of "m_nfs3" that you wrote down above.
+         g) m_rt:   
+            The mountpoint of the realtime test filesystem.
+            Set this to the value of "m_rt" that you wrote down above.
+         h) d_rt:   
+            The path to the realtime test directory.
+            Set this to the value of "d_rt" that you wrote down above.
+      3) Configuring "DMAPI_aliases"
+         This is an optional alternative to the menu interface. It runs
+         as a Korn shell "dot" script and creates an alias to each test. 
+         It was made for those who wish to run tests directly from the
+         command line.
+         DMAPI_aliases has exactly the same configuration section as
+         menu_test.  If you wish to use DMAPI_aliases, make the same
+         changes to its configuration section. 
+II) Running the Tests
+
+   A) Using "menu_test" to run tests
+
+      1) You must be superuser, using the Korn shell, to run menu_test.
+         You also must have adjusted the variables in menu_test's 
+         "configuration section", as was explained above.
+
+      2) menu_test is (surprise!) menu based.  Choose options by entering
+         their numbers.    
+      3) The names of the menu options explain which DMAPI functions
+         or DMAPI events are being tested.  Some of the options, labeled
+         accordingly, run more than one test programs.
+
+      4) See section SECTION# for a list of the test scripts and programs,
+         and a brief explanation of each script or program's function.  
+
+   B) Using "DMAPI_aliases" to run tests   
+
+      1) NOTE: The aliases in DMAPI_aliases are meant to be used by
+         those who are familiar with the test programs and wish to run
+         them more directly.  [Designer's note: I included the alias
+         file more out of nostalgia than necessity.]
+      
+      2) You should be superuser, using the Korn shell, to run DMAPI_aliases.
+         You also must have adjusted the variables in DMAPI_aliases's 
+         "configuration section", as was explained above.
+
+      3) DMAPI_aliases should be invoked as a Korn shell "dot" script:
+
+         . ./DMAPI_aliases 
+
+         It sets an alias for each test program; each alias begins with
+         the characters "do_" and is followed by some appropriate name.
+         Read DMAPI_aliases, or execute "alias | grep do", to 
+
+   C) Running tests directly
+
+      1) For the VERY adventurous, all the tests in the "bindir" directory
+         can be run directly from the command line.  Only some of the files
+         in "bindir" are test scripts/programs.  Read section III for a list 
+         of function tests and section IV for a list of run_test (.dat)
+         testfiles.
+
+      2) Running a test program without parameters will produce a list of
+         correct options.  (The exception to this is check_dmapi, which 
+         normally has no parameters.  check_dmapi takes only one option,
+         [-v] for verbose output.)
+
+      3) It is suggested that you read a program's source before running
+         it directly.  (The source of the C programs is included in the
+         "src" directory.)  Specificually, in each source file, an initial
+         comment explains the program's options/parameters in detail.
+
+III) DMAPI Function tests:
+     
+     This section offers a terse description of the DMAPI function tests.
+     For those tests written in C, the source code is given in the "src" 
+     directory.  The ksh scripts can, of course, be read directly.
+     In all cases except check_dmapi, running the program without
+     parameters will produce a list of correct options. 
+  
+   A) check_dmapi
+      Written in: C 
+      Test of: presence (and correct version) of DMAPI library and kernel.  
+      Options: [-v] flag for verbose output.
+   B) test_dmattr
+      Written in: C 
+      Test of: dm_get_dmattr, dm_set_dmattr, dm_remove_dmattr.
+
+   C) test_efault
+      Written in: C 
+      Test of: various bad function calls that should generate EFAULT,
+               according to the DMAPI specification.
+
+   D) test_eventlist
+      Written in: C 
+      Test of: dm_get_eventlist, dm_set_eventlist.
+
+   E) test_fileattr
+      Written in: C 
+      Test of: dm_get_fileattr, dm_set_fileattr,
+               dm_get_dirattrs, dm_get_bulkattr.
+
+   F) test_hole
+      Written in: C 
+      Test of: dm_probe_hole, dm_punch_hole.
+
+   G) test_invis
+      Written in: C 
+      Test of: dm_read_invis, dm_write_invis.
+
+   H) test_region
+      Written in:  C 
+      Test of: dm_get_region, dm_set,region.
+
+   I) test_rights
+      Written in: C 
+      Test of: various bad function calls that should generate EACCES,
+               and other conditions pertaining to DMAPI rights.
+
+   J) test_allocinfo_1
+      Written in: ksh
+      Test of: dm_get_allocinfo.  
+
+   K) test_allocinfo_2
+      Written in: ksh
+      Test of: dm_get_allocinfo.
+
+IV) DMAPI Event tests and the "run_test" ksh script
+
+   A) How to use the "run_test" script
+
+      1) A quick description of run_test's behavior:
+         run_test invokes a DMAPI daemon (as a ksh coprocess).  It then
+         reads a "testfile", which contains a description of the test.    
+
+      2) You must be superuser, using the Korn shell, to execute run_test.
+
+      3) Executing run_test without parameters will produce a list of
+         correct options.  For a much more in-depth explanation of the 
+         options to run_test, read its own initial comment.      
+
+   B) The existing .dat testfiles
+
+     1) fail.dat
+      2) main.dat
+      3) nfs.dat
+      4) old_nfs3.dat
+      5) pending.dat
+      6) pending_nfs.dat
+      7) realtime.dat
+      8) smallq.dat
+      9) standard.dat
+     10) standard_nfs.dat
+
+   C) How to write ".dat" testfiles
+      
+      1) Overview
+
+         A testfile contains a complete description of a DMAPI event test.
+         Testfiles are divided into sections: the first two contain
+         test initialization, while the remaining sections each contain ONE
+         command, followed by a list of expected events.
+
+         The following is a description of testfile syntax.  If you wish to 
+         fully understand testfile syntax, PLEASE examine the existing
+         testfiles and the "run_test" script.
+
+      2) Event information variables
+         
+         a) From the daemon, "run_test" gets information about DMAPI events.
+            This information is stored in event information variables.  
+
+         b) NOTE: event information variables are not persistant. 
+            After "run_test" has compared the expected and actual events
+            for a command, and before it executes the next command, it
+            unsets the values of all these variables.
+
+         c) Most of these variables are arrays, indexed by the number of
+            the event (starting with 0). For example, if the initial event
+            is a read event, then we have "event[0]" set to "read", and
+            "file_handle[0]" set to the handle of whatever file was read.
+
+         d) "event_count" is a special variable.  It holds the number of
+            events that were generated by the most recent command.   
+
+         e) These are all the event information variables:
+
+            contents event event_count fs_handle handle length
+            offset media_designator mode mountpoint_handle
+            mountpoint_path msg_str name new_name new_parent
+            parent_handle ret_code root_handle sequence token  
+            tries_left unmount_mode
+
+         f) PLEASE examine the run_test script to see which variables 
+            are set by which events.  (The scheme corresponds, roughly, 
+            to the "Event Types" section of the DMAPI specification.)
+
+      3) Testfile section 1:  List of required files
+
+         a) A testfile's first section is a list of the files it requires.   
+            If these files are not present in the "bindir" directory, 
+            "run_test" will abort the test and inform the user of which 
+            files are missing.  
+         
+         b) Each line of this section may contain ANY NUMBER of filenames.
+
+         c) Lines beginning with // will be treated as comments.  The
+            entirety of such lines will be ignored.
+          
+         d) The last line of this section should begin with three hyphens
+            ---  Other characters on that line will be ignored. 
+
+      4) Testfile section 2:  Initialization commands
+         
+         a) A testfile's second section consists of a list of commands.
+            "run_test" will execute these commands before starting the
+            DMAPI daemon.  Any necessary initialization should be done 
+            here. 
+
+         b) Each line of this section should be ONE shell command.
+
+         c) Lines beginning with // will be treated as comments.  
+            The entirety of such lines will be ignored.
+          
+         d) The last line of this section should begin with three hyphens
+            "---"  Other characters on that line will be ignored.
+
+      5) Testfile sections 3 and on:  Individual tests
+
+         a) The remaining sections of a testfile consist of a single
+            shell command, followed by descriptions of events that should
+            be generated by the command.  
+            
+         b) Comments
+
+            1) Comments are valid ONLY before the command. 
+
+            2) Lines beginning with // will be treated as comments.  
+               The entirety of such lines will be ignored.
+
+            3) Lines beginning with @@ will be treated as "print" comments.
+               Such lines will not be parsed, but they will be printed to
+               standard output during the test.  This is useful for
+               describing what each test does.
+
+         c) Valid grammar for the command itself
+
+            1) Standard command syntax: 
+               This should be ONE shell command, on a line by itself.  
+               
+            2) Alternate command syntax:
+
+               A) run_as_root:  
+                  If the test is preceeded by the metacommand "run_as_root"
+                  (on a line by itself) then the command will be run as
+                  root rather than as "p_user".  The command should still
+                  be one command on a line by itself.
+
+               B) run_without_test:
+                  If the test is preceeded by the metacommand 
+                  "run_without_test" (on a line by itself), then ALL
+                  subsequent lines in the section will be executed as
+                  commands, and NO testing will be performed.  Note that
+                  the commands will be executed as root.  This is useful
+                  for re-initialization sections during a test.
+
+         d) Valid grammar for the "expected events" lines
+
+            1) [variable_name] [value]
+               This specifies that the variable [variable_name] should be
+               set to [value].  
+
+            2) [variable_name_1] matches [variable_name_2]
+               This specifies that both variables should be set to 
+               the same value.  A list of valid variables
+
+            3) [variable_name] store_in [string]
+               This specifies that the contents of [variable_name] 
+               should be stored in a variable named [string].
+               The variable [string] can then be referenced as a
+               variable in later tests.
+   
+               EXAMPLE: if two commands deal with the file "foobar",
+               you might want to check that they both use the same handle.
+               In the first section, write
+                "handle[0] store_in old_handle_0" 
+               In the second section, write
+                "old_handle_0 matches handle[0]" 
+
+            4) failure
+               This specifies that the command is expected to fail
+               (return some non-zero exit status).  If "failure"
+               is not specified, the command is expected to succeed.
+            
+         e) The last line of these sections should begin with three
+            hyphens "---".  Other characters on that line will be ignored.
+      6) Sending messages to the DMAPI daemon
+
+
+      7) Other "helper functions" for testfiles 
+
+
+
+
+
diff --git a/dmapi/src/suite2/lib/errtest.h b/dmapi/src/suite2/lib/errtest.h
new file mode 100644 (file)
index 0000000..0c1f19a
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __ERRTEST_SEEN
+#define __ERRTEST_SEEN
+
+#include <strings.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define NUM_ERRS 100
+
+void* handle_clone(void* src_hanp, u_int hlen );
+
+char   *
+errno_names[] = {
+       "ERROR_0",
+       "EPERM",
+       "ENOENT",
+       "ESRCH",
+       "EINTR",
+       "EIO",
+       "ENXIO",
+       "E2BIG",
+       "ENOEXEC",
+       "EBADF",
+       "ECHILD",
+       "EAGAIN",
+       "ENOMEM",
+       "EACCES",
+       "EFAULT",
+       "ENOTBLK",
+       "EBUSY",
+       "EEXIST",
+       "EXDEV",
+       "ENODEV",
+       "ENOTDIR",
+       "EISDIR",
+       "EINVAL",
+       "ENFILE",
+       "EMFILE",
+       "ENOTTY",
+       "ETXTBSY",
+       "EFBIG",
+       "ENOSPC",
+       "ESPIPE",
+       "EROFS",
+       "EMLINK",
+       "EPIPE",
+       "EDOM",
+       "ERANGE",
+       "ENOMSG",
+       "EIDRM",
+       "ECHRNG",
+       "EL2NSYNC",
+       "EL3HLT",
+       "EL3RST",
+       "ELNRNG",
+       "EUNATCH",
+       "ENOCSI",
+       "EL2HLT",
+       "EDEADLK",
+       "ENOLCK",
+       "ERROR_47",
+       "ERROR_48",
+       "ERROR_49",
+       "EBADE",
+       "EBADR",
+       "EXFULL",
+       "ENOANO",
+       "EBADRQC",
+       "EBADSLT",
+       "EDEADLOCK",
+       "EBFONT",
+       "ERROR_58",
+       "ERROR_59",
+       "ENOSTR",
+       "ENODATA",
+       "ETIME",
+       "ENOSR",
+       "ENONET",
+       "ENOPKG",
+       "EREMOTE",
+       "ENOLINK",
+       "EADV",
+       "ESRMNT",
+       "ECOMM",
+       "EPROTO",
+       "ERROR_72",
+       "ERROR_73",
+       "EMULTIHOP",
+       "ERROR_75",
+       "ERROR_76",
+       "EBADMSG",
+       "ENAMETOOLONG",
+       "EOVERFLOW",
+       "ENOTUNIQ",
+       "EBADFD",
+       "EREMCHG",
+       "ELIBACC",
+       "ELIBBAD",
+       "ELIBSCN",
+       "ELIBMAX",
+       "ELIBEXEC",
+       "EILSEQ",
+       "ENOSYS",
+       "ELOOP",
+       "ERESTART",
+       "ESTRPIPE",
+       "ENOTEMPTY",
+       "EUSERS",
+       "ENOTSOCK",
+       "EDESTADDRREQ",
+       "EMSGSIZE",
+       "EPROTOTYPE",
+       "ENOPROTOOPT" };
+
+#define ERR_NAME                                                       \
+        ((errno<NUM_ERRS)?(errno_names[errno]):("an unknown errno"))
+
+#define ERRTEST(EXPECTED, NAME, FUNCTION)                              \
+    if ((FUNCTION) < 0) {                                              \
+      if (errno == (EXPECTED)) {                                       \
+        if (Vflag)                                                     \
+         fprintf(stdout,"\treport on test for " #EXPECTED              \
+                          " in %s: test successful\n", (NAME));                \
+      }                                                                        \
+      else {                                                           \
+        fprintf(stdout, "\tERROR testing for " #EXPECTED               \
+                 " in %s: found %s.\n", (NAME), ERR_NAME);             \
+      }                                                                        \
+    }                                                                  \
+    else {                                                             \
+      fprintf(stdout, "\tERROR testing for " #EXPECTED                 \
+             " in %s: no error was produced!\n", (NAME));              \
+    }
+
+
+#define EXCLTEST(NAME, HANP, HLEN, TOKEN, FUNCTION)                      \
+if (dm_create_userevent(sid, 10, "DMAPI" NAME, &(TOKEN))) {            \
+  fprintf(stdout,                                                      \
+         "\tERROR: can't create token (%s); skipping EACCES test\n",   \
+         ERR_NAME);                                                    \
+}                                                                      \
+else {                                                                 \
+  ERRTEST(EACCES, "no-right " NAME, (FUNCTION))                                \
+                                                                       \
+  if (dm_request_right(sid, (HANP), (HLEN), (TOKEN), 0, DM_RIGHT_SHARED))      \
+    fprintf(stdout, "\t"NAME" ERROR: Couldn't upgrade to SHARED. %s\n",        \
+           ERR_NAME);                                                  \
+  else ERRTEST(EACCES, "SHARED " NAME, (FUNCTION))                     \
+                                                                       \
+  if (dm_request_right(sid, (HANP), (HLEN), (TOKEN), 0, DM_RIGHT_EXCL))        \
+    fprintf(stdout, "\t"NAME" ERROR: Couldn't upgrade to EXCL: %s\n",  \
+           ERR_NAME);                                                  \
+  else if ((FUNCTION) < 0)                                             \
+    fprintf(stdout, "\t"NAME" ERROR: token with DM_RIGHT_EXCL was "    \
+           "denied access: %s\n", ERR_NAME);                           \
+  else if (Vflag)                                                      \
+    fprintf(stdout, "\treport on test for success in EXCL "NAME": "    \
+           "test successful.\n");                                      \
+                                                                       \
+  if (dm_respond_event(sid, (TOKEN), DM_RESP_CONTINUE, 0, 0, 0))       \
+    fprintf(stdout, "\tERROR in responding to token: %s\n", ERR_NAME); \
+}
+
+
+
+#define SHAREDTEST(NAME, HANP, HLEN,  TOKEN, FUNCTION)                 \
+if (dm_create_userevent(sid, 10, "DMAPI" NAME, &(TOKEN))) {            \
+     fprintf(stdout,                                                   \
+            "\tCannot create_userevent (%s); skipping EACCES test\n",  \
+            ERR_NAME);                                                 \
+}                                                                      \
+else {                                                                 \
+  ERRTEST(EACCES, "no-right " NAME, (FUNCTION))                                \
+                                                                       \
+  if (dm_request_right(sid, (HANP), (HLEN), (TOKEN),                   \
+                      0, DM_RIGHT_SHARED))                             \
+    fprintf(stdout, "\t"NAME" ERROR: Couldn't upgrade to EXCL. %s\n",  \
+           ERR_NAME);                                                  \
+  else if ((FUNCTION) < 0)                                             \
+    fprintf(stdout, "\t" NAME" ERROR: token with DM_RIGHT_SHARED "     \
+           "was denied access. %s\n", ERR_NAME);                       \
+  else if (Vflag)                                                      \
+    fprintf(stdout, "\treport on test for success in SHARED "NAME": "  \
+           "test successful.\n");                                      \
+                                                                       \
+  if (dm_request_right(sid, (HANP), (HLEN), (TOKEN), 0, DM_RIGHT_EXCL))        \
+    fprintf(stdout, "\t"NAME" ERROR: Couldn't upgrade to EXCL. %s\n",  \
+           ERR_NAME);                                                  \
+  else if ((FUNCTION) < 0)                                             \
+      fprintf(stdout, "\t" NAME" ERROR: token with DM_RIGHT_EXCL was " \
+             "denied access. %s\n", ERR_NAME);                         \
+  else if (Vflag)                                                      \
+    fprintf(stdout, "\treport on test for success in EXCL "NAME": "    \
+           "test successful.\n");                                      \
+                                                                       \
+  if (dm_respond_event(sid, (TOKEN), DM_RESP_CONTINUE, 0, 0, 0))       \
+    fprintf(stderr, "\tERROR in responding to token: %s\n", ERR_NAME); \
+}
+
+
+
+void* 
+handle_clone(void* src_hanp, u_int hlen )
+{
+  void* dest_hanp;
+
+  if ((dest_hanp = malloc(hlen)) == NULL) return(NULL);
+  bcopy(src_hanp, dest_hanp, hlen);
+  return(dest_hanp);
+}
+
+#endif
+
diff --git a/dmapi/src/suite2/menu_test b/dmapi/src/suite2/menu_test
new file mode 100755 (executable)
index 0000000..f364504
--- /dev/null
@@ -0,0 +1,358 @@
+#!/bin/ksh
+
+#
+# Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+# 
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# 
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like.  Any license provided herein, whether implied or
+# otherwise, applies only to this software file.  Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+# 
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA  94043, or:
+# 
+# http://www.sgi.com 
+# 
+# For further information regarding this notice, see: 
+# 
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+
+#---------------------------------------------------------------------------
+# CONFIGURATION SECTION:  
+#    Configure this script by changing the variables in this section.
+#    Please change ONLY this section!
+#---------------------------------------------------------------------------
+
+# Base directory:
+base_dir="/home/poplar45/kfr/dmapi/test/laguna/jaytest"
+
+# Primary username:
+p_user="kfr"
+
+# Path to the mountpoint of the test filesystem:
+m_main="/dmapi"
+
+# m_main concatenated with d_name == the full test directory path
+#
+# EXAMPLE:  If m_main is "/dmitest", and the test directory
+# is "/dmitest/test", set this to "/test"
+#
+d_name="/kfr/test_dir"
+
+# Path to the mountpoint of the nfs2 test filesystem:
+m_nfs2="/dmapi/kfr/nfs2"
+
+# Path to the mountpoint of the nfs3 test filesystem:
+m_nfs3="/dmapi/kfr/nfs3"
+
+# Path to the mountpoint of the realtime test filesystem:
+m_rt="/dmf"
+# Path to the realtime test directory:
+d_rt="$m_rt/kcm"
+
+#--------------------------------------------------------------------
+# END OF CONFIGURATION SECTION:
+#    No changes should be made past this point!  Please change only   
+#    the above shell variables to configure this script.
+#--------------------------------------------------------------------
+
+# Path to the "bindir" directory:
+bin="$base_dir/bindir"
+
+# Path to the "generic file" (a copy of ls): 
+ls_path="$bin/ls_to_copy"
+
+# Path to the main test directory:
+d_main="$m_main$d_name"
+
+# Path to the nfs2 test directory:
+d_nfs2="$m_nfs2$d_name"
+
+# Path to the nfs3 test directory:
+d_nfs3="$m_nfs2$d_name"
+
+PS3="> "
+unset Vflag
+unset Pflag
+
+while true
+do 
+clear
+print "+-------------------------+"
+print "| DMAPI tests:  main menu |"
+print "+-------------------------+\n"
+select menu1 in 'DMAPI function tests, which run without a daemon' \
+               'DMAPI event tests, which invoke and monitor a daemon' \
+                'Basic DMAPI existence/version test' \
+               'quit'
+do case $menu1 in
+    'DMAPI function tests, which run without a daemon')
+    while true 
+    do
+    if [[ $Vflag = -v ]] 
+    then Vstr='turn off verbose mode'
+    else Vstr='turn on verbose mode'
+    fi
+    clear
+    print "+----------------------+"
+    print "| DMAPI function tests |"
+    print "+----------------------+\n"
+    select menu2 in  'ALL of the following function tests:' \
+                   '    get/set_dmattr' \
+                   '    get/set_eventlist' \
+                   '    get/set_fileattr, get_bulkattr, get_dirattrs' \
+                   '    probe/punch_hole' \
+                   '    read/write_invis' \
+                   '    get/set_region' \
+                   '    get_allocinfo vs. xfs_bmap' \
+                   '    get_allocinfo with various buffer sizes' \
+                   '    EFAULT errno' \
+                   '    EACCES errno and access rights' \
+                   "$Vstr" \
+                   'previous menu' \
+                   'quit'
+     do case $menu2 in
+       'ALL of the following function tests:')
+           for run_me in \
+               "$bin/test_dmattr $Vflag $ls_path $d_main" \
+               "$bin/test_eventlist $Vflag $ls_path $d_main" \
+               "$bin/test_fileattr $Vflag $ls_path $d_main" \
+               "$bin/test_hole $Vflag $ls_path $d_main" \
+               "$bin/test_invis $Vflag $ls_path $d_main" \
+               "$bin/test_region $Vflag $ls_path $d_main" \
+               "$bin/test_efault $Vflag $ls_path $d_main" \
+               "$bin/test_rights $Vflag $ls_path $d_main" \
+               "$bin/test_allocinfo_1 $bin $d_main" \
+               "$bin/test_allocinfo_2  $bin $d_main" 
+           do
+           eval $run_me
+           print "Press enter to continue..."; read go
+           done
+           break;;     
+       '    get/set_dmattr')
+           eval "$bin/test_dmattr $Vflag $ls_path $d_main"
+           print "Press enter to continue..."; read go
+           break;;
+       '    get/set_eventlist')
+           eval "$bin/test_eventlist $Vflag $ls_path $d_main"
+           print "Press enter to continue..."; read go
+           break;;
+       '    get/set_fileattr, get_bulkattr, get_dirattrs')
+           eval "$bin/test_fileattr $Vflag $ls_path $d_main"
+           print "Press enter to continue..."; read go
+           break;;
+       '    probe/punch_hole')
+           eval "$bin/test_hole $Vflag $ls_path $d_main"
+           print "Press enter to continue..."; read go
+           break;;
+       '    read/write_invis')
+           eval "$bin/test_invis $Vflag $ls_path $d_main"
+           print "Press enter to continue..."; read go
+           break;;
+       '    get/set_region')
+           eval "$bin/test_region $Vflag $ls_path $d_main"
+           print "Press enter to continue..."; read go
+           break;; 
+       '    EFAULT errno') 
+           eval "$bin/test_efault $Vflag $ls_path $d_main"
+           print "Press enter to continue..."; read go
+           break;;
+       '    EACCES errno and access rights')
+           eval "$bin/test_rights $Vflag $ls_path $d_main"
+           break;;
+       '    get_allocinfo vs. xfs_bmap')
+           eval "$bin/test_allocinfo_1 $bin $d_main" 
+           print "Press enter to continue..."; read go
+           break;;
+       '    get_allocinfo with various buffer sizes')
+           eval "$bin/test_allocinfo_2  $bin $d_main"
+           print "Press enter to continue..."; read go
+           break;;
+       "$Vstr")
+           if [[ $Vflag = -v ]] 
+           then unset Vflag 
+           else Vflag=-v
+           fi
+           break;;
+       'previous menu')
+           break 2;;
+       'quit')
+           exit 0;;
+       *) break;;
+       esac
+    done
+    done
+    break;;
+
+    'DMAPI event tests, which invoke and monitor a daemon' )
+    while true
+    do
+    if [[ $Pflag = -p ]] 
+    then Pstr='turn off pausing after each command'
+    else Pstr='turn on pausing after each command'
+    fi
+    clear
+    print "+--------------------------+"
+    print "| DMAPI daemon/event tests |"
+    print "+--------------------------+\n"
+    select menu2 in 'ALL of the following four:' \
+                   '    standard i/o' \
+                   '    abort responses to events, and other i/o' \
+                   '    unsuccessful commands (bad file permissions)' \
+                   '    dm_pending' \
+                   'realtime filesystem' \
+                   'small event queue' \
+                   'nfs2 tests' \
+                   'nfs3 tests' \
+                   "$Pstr" \
+                   'previous menu' \
+                   'quit'
+    do case $menu2 in
+       'ALL of the following four:')
+       for run_me in \
+           "$bin/run_test $Pflag -u $p_user -f standard.dat $bin $d_main $m_main" \
+           "$bin/run_test $Pflag -u $p_user $bin $d_main $m_main" \
+           "$bin/run_test $Pflag -u $p_user -f fail.dat $bin $d_main $m_main" \
+           "$bin/run_test $Pflag -u $p_user -f pending.dat $bin $d_main $m_main" 
+       do
+           eval $run_me
+       done
+       break;;
+       '    standard i/o')
+           eval "$bin/run_test $Pflag -u $p_user -f standard.dat $bin $d_main $m_main"
+           break;;
+       '    abort responses to events, and other i/o')
+           eval "$bin/run_test $Pflag -u $p_user $bin $d_main $m_main"
+           break;;
+       '    unsuccessful commands (bad file permissions)')
+           eval "$bin/run_test $Pflag -u $p_user -f fail.dat $bin $d_main $m_main"
+           break;;
+       '    dm_pending')
+           eval "$bin/run_test $Pflag -u $p_user -f pending.dat $bin $d_main $m_main"
+           break;;
+       'nfs2 tests')
+           while true
+           do
+           clear
+           print "+--------------------------------+"
+           print "| DMAPI daemon/event tests: nfs2 |"
+           print "+--------------------------------+\n"
+           select menu3 in 'ALL of the following four:' \
+                            '    nfs2: standard i/o' \
+                           '    nfs2: abort responses to events, and other i/o' \
+                           '    nfs2: unsuccessful commands (bad file permissions)' \
+                           '    nfs2: dm_pending' \
+                           'previous menu' \
+                           'quit'
+           do case $menu3 in
+               'ALL of the following four:')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f standard_nfs.dat $bin $d_nfs2 $m_main"
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f nfs.dat $bin $d_nfs2 $m_main"
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f fail.dat $bin $d_nfs2 $m_main"
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f pending_nfs.dat $bin $d_nfs2 $m_main"
+                   break;;
+                '    nfs2: standard i/o')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f standard_nfs.dat $bin $d_nfs2 $m_main"
+                   break;;
+               '    nfs2: abort responses to events, and other i/o')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f nfs.dat $bin $d_nfs2 $m_main"
+                   break;;
+               '    nfs2: unsuccessful commands (bad file permissions)')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f fail.dat $bin $d_nfs2 $m_main"
+                   break;;
+               '    nfs2: dm_pending')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs2 -M $m_nfs2 -R $d_main -f pending_nfs.dat $bin $d_nfs2 $m_main"
+                   break;;
+               'previous menu')
+                   break 2;;
+               'quit')
+                   exit 0;;
+              esac
+           done
+           done
+           break;;
+       'nfs3 tests')
+           while true 
+           do
+           clear
+           print "+--------------------------------+"
+           print "| DMAPI daemon/event tests: nfs3 |"
+           print "+--------------------------------+"
+           select menu3 in 'ALL of the following four:' \
+                            '    nfs3: standard i/o' \
+                            '    nfs3: abort responses to events, and other i/o' \
+                           '    nfs3: unsuccessful commands (bad file permissions)' \
+                           '    nfs3: dm_pending' \
+                           'previous menu' \
+                           'quit'
+           do case $menu3 in
+               'ALL of the following four:')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f standard_nfs.dat $bin $d_nfs3 $m_main"
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f nfs.dat $bin $d_nfs3 $m_main"
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f fail.dat $bin $d_nfs3 $m_main"
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f pending_nfs.dat $bin $d_nfs3 $m_main"
+                   break;;
+               '    nfs3: standard i/o')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f standard_nfs.dat $bin $d_nfs3 $m_main"
+                   break;;
+               '    nfs3: abort responses to events, and other i/o')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f nfs.dat $bin $d_nfs3 $m_main"
+                   break;;
+               '    nfs3: unsuccessful commands (bad file permissions)')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f fail.dat $bin $d_nfs3 $m_main"
+                   break;;
+               '    nfs3: dm_pending')
+                   eval "$bin/run_test $Pflag -u $p_user -F nfs3 -M $m_nfs3 -R $d_main -f pending_nfs.dat $bin $d_nfs3 $m_main"
+                   break;;
+               'previous menu')
+                   break 2;;
+               'quit')
+                   exit 0;;
+              esac
+           done
+           done
+           break;;
+       'realtime filesystem')
+           eval "$bin/run_test $Pflag -u $p_user -f realtime.dat $bin $d_rt $m_rt"
+           break;;
+       'small event queue')
+           # Set dm_max_queued to about 5 or so before running!
+           eval "$bin/run_test $Pflag -u $p_user -s 2 -f smallq.dat $bin $d_main $m_main"
+           break;;
+       "$Pstr")
+           if [[ $Pflag = -p ]] 
+           then unset Pflag
+           else Pflag=-p
+           fi
+           break;;
+       'previous menu')
+           break 2;;
+       'quit')
+           exit 0;;
+       esac
+    done
+    done
+    break;;
+    'Basic DMAPI existence/version test')
+       eval "$bin/check_dmapi $Vflag"
+       print "Press enter to continue..."; read go
+       break;;
+    quit)
+       break 2;;
+    esac
+    done
+done
diff --git a/dmapi/src/suite2/src/check_dmapi.c b/dmapi/src/suite2/src/check_dmapi.c
new file mode 100644 (file)
index 0000000..ddd977d
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef linux
+#include <linux/dmapi_kern.h>
+#else
+#include <sys/dmi.h>
+#endif
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+
+#include <lib/hsm.h>
+#include <lib/dmport.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+Automated test of version of DMAPI libraries & kernels 
+
+The command line is: 
+
+     check_dmapi [-v] 
+
+where v is a verbose-output flag
+----------------------------------------------------------------------------*/
+#ifdef linux
+#define CREATE_DESTROY_OPCODE DM_DESTROY_SESSION
+#define SET_DISP_OPCODE DM_SET_DISP
+#else
+#define CREATE_DESTROY_OPCODE 5
+#define SET_DISP_OPCODE 46
+#endif
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+char   *Progname;
+
+int     dmi(int, ...);
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-v]\n"
+               "\t(use the v switch for verbose output)\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     old_sid = -1;
+       dm_sessid_t     sid;
+       void            *hanp;
+       size_t           hlen;
+       dm_token_t      token = DM_NO_TOKEN;
+       int             Vflag = 0;
+       char            *name = "old";
+       char            *junk = "test junk";
+       int             opt;
+       int             i;
+       int             kernel_status=-1;
+       int             library_status=-1L;
+       dm_size_t       retval;
+       struct stat     stat_buf;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "v")) != EOF) {
+         switch (opt) {
+         case 'v':
+           Vflag++;
+           break;
+         case '?':
+           usage();
+         }
+       }
+       if (optind != argc)
+         usage();
+       
+
+       if (geteuid()!=0) {
+         printf("You are running as user #%d.  "
+                "You must be root to run this diagnostic.\n", geteuid());
+         exit(1);
+       }
+
+       /*--------------------------------
+        * EXAMINE /usr/include/sys/dmi.h:
+        *--------------------------------
+        */
+#ifdef linux
+#define DMAPI_HDR "/usr/include/linux/dmapi.h"
+#else
+#define DMAPI_HDR "/usr/include/sys/dmi.h"
+#endif
+       if (stat(DMAPI_HDR, &stat_buf)==-1){
+         if (errno==ENOENT) { 
+           printf( "You are missing a vital DMAPI file: %s\n", DMAPI_HDR);
+         }
+         else {
+           printf( "ERROR: could not stat %s (%s)\n", DMAPI_HDR, strerror(errno));
+         }
+       }
+       else {
+         if (stat_buf.st_size <= 15000) {
+           printf("You appear to have an old version of a vital DMAPI file: %s\n", DMAPI_HDR);
+         }
+         else if (Vflag) {
+           printf("(You appear to have the correct version of %s\n", DMAPI_HDR);
+         }
+       }
+       
+       /*--------------------------
+        * RESOLVE KERNEL PRESENCE:
+        *--------------------------
+        */
+       if (dmi(CREATE_DESTROY_OPCODE, old_sid, junk, &sid) >= 0) {
+         printf("ERROR: invalid kernel create/destroy_session call "
+                "succeeded!\n");
+         exit(1);
+       }
+       else if (errno==ENOPKG) {
+         kernel_status=0;
+       }
+       else if (errno==EINVAL){
+         if (Vflag) printf("(create/destroy_session call verifies "
+                           "that you have DMAPI in kernel)\n");
+       }
+       else {
+         printf("ERROR: kernel create/destroy_session call produced "
+                "unexpected errno, (%d) %s\n", errno, strerror(errno));
+       }
+       
+       /*----------------------------------
+        * RESOLVE KERNEL STATUS IF PRESENT:
+        *----------------------------------
+        */
+       if (kernel_status==-1 &&
+           dmi(SET_DISP_OPCODE, 
+               (dm_sessid_t) 0, 
+               (void*) 0,
+               (size_t) 0,
+               (dm_token_t) 0,
+               (dm_eventset_t) 0,
+               (u_int) 0) >= 0) { 
+         printf("ERROR: invalid kernel set_disp call suceeded!\n");
+       }
+       else {
+         if (errno==ENOSYS) {
+           if (Vflag) 
+             printf("(kernel set_disp call indicates old kernel)\n");
+           kernel_status=1;
+         }
+         else if (errno==ENOPKG) {
+           if (Vflag) 
+             printf("(kernel set_disp call indicates no kernel)\n");
+           kernel_status=0;
+         }
+         else if (errno==EINVAL) {
+           if (Vflag)
+             printf("(kernel set_disp call indicates new kernel)\n");
+           kernel_status=2;
+         }
+         else {
+           printf("ERROR: kernel set_disp call failed: (%d) %s\n", 
+                  errno, strerror(errno));
+/* XXX */
+/*         exit(1);*/
+         }
+       }
+
+       /*-------------------------
+        * RESOLVE LIBRARY STATUS:
+        *-------------------------
+        */
+       if (dm_init_service(&name) == -1)  {
+         fprintf(stderr, "ERROR: can't inititalize the DMAPI (%s).\n",
+                 strerror(errno));
+         library_status=0;
+       }
+       else if (strcmp(name, DM_VER_STR_CONTENTS)) {
+         if (Vflag) 
+           printf("(dm_init_service suggests that "
+                  "you have an old library)\n");
+         library_status=1;
+       }
+       else {
+         if (Vflag) 
+           printf("(dm_init_service suggests that "
+                  "you have a new library)\n");
+         library_status=2;
+       }
+       
+       if (Vflag) printf("(dm_init_service returned %s)\n", name);
+       
+       /*-------------------------
+        * MAKE A DIAGNOSIS:
+        *-------------------------
+        */
+
+       if (library_status==2 && kernel_status==2){
+         printf("DIAGNOSIS: Tests show a current version of "
+                "DMAPI is installed.\n");
+       } 
+       else if (library_status==1 && kernel_status==1) {
+         printf("DIAGNOSIS: Tests show that you have an outdated "
+                "installation of DMAPI.\nUpgrades to both kernel and "
+                "library routines will be necessary.\n");
+       }
+       else if (library_status==0 && kernel_status==0) {
+         printf("DIAGNOSIS: Tests show that NO components of the DMAPI "
+                "are installed!\nUpgrades to both kernel and "
+                "library routines will be necessary.\n");
+       }
+       else {
+         printf("DIAGNOSIS: Tests show that:\n"
+                "Your DMAPI kernel routines are ");
+         switch (kernel_status) {
+         case 0: printf ("missing (not installed).\n");
+            break;
+         case 1: printf ("outdated.\n");
+            break;
+         case 2: printf ("current.\n ");
+            break;
+         default: printf("[ERROR!].\n");
+         }
+         printf("Your DMAPI library is ");
+         switch (library_status) {
+         case 0: printf ("missing (not installed).\n");
+            break;
+         case 1: printf ("outdated.\n");
+            break;
+         case 2: printf ("current.\n");
+            break;
+         default: printf("[ERROR!].\n");
+         }
+       }
+#ifndef linux
+       if (library_status!=2 || kernel_status!=2){
+         printf("Please install XFS patch 1907 (for IRIX 6.2) or "
+                "patch 2287 (for IRIX 6.4).\n");
+       }
+#endif
+}
+
+
diff --git a/dmapi/src/suite2/src/dm_test_daemon.c b/dmapi/src/suite2/src/dm_test_daemon.c
new file mode 100644 (file)
index 0000000..d26be9f
--- /dev/null
@@ -0,0 +1,1328 @@
+
+
+/*
+ * dm_test_daemon.c
+ *
+ * Joseph Jackson
+ * 25-Jun-1996
+ *
+ * Additions:
+ * Jay Woodward
+ * 6-Aug-1997
+ * 
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/errno.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <lib/dmport.h>
+#include <lib/hsm.h>
+
+#ifdef linux
+#define MAXNAMELEN 256
+#endif
+
+  /*
+   * Define some standard formats for the printf statements below.
+   */
+
+#define HDR  "%s\ntoken          :%d\nsequence       :%d\n"
+#define VALS "%-15s:%s\n"
+#define VALD "%-15s:%d\n"
+#ifdef __sgi
+#define VALLLD "%-15s:%lld\n"
+#else
+#define VALLLD "%-15s:%ld\n"
+#endif
+
+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_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   (void);
+
+/*
+ * 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              friendly=1;
+int              unfriendly_errno=EBADMSG;
+int              unfriendly_count=0;
+int              pending_count=0;
+int             token_arr[10];
+int              arr_top=0;
+
+void
+usage(
+      char *prog)
+{
+  fprintf(stderr, "Usage: %s ", prog);
+  fprintf(stderr, "<-s sleeptime> <-S oldsid> <-v verbose> ");
+  fprintf(stderr, "filesystem \n");
+}
+
+
+int
+main(
+     int       argc,
+     char      *argv[])
+{
+
+  int           c;
+  int           error;
+  void         *fs_hanp;
+  size_t                fs_hlen;
+  char           buf[BUFSIZ + 8];
+
+  Progname  = argv[0];
+  fsname  = NULL;
+
+  while ((c = getopt(argc, argv, "vs:S:")) != EOF) {
+    switch (c) {
+    case 's':
+      Sleep = atoi(optarg);
+      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_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;
+
+  /*
+   * Set line buffering!!
+   */
+  error = setvbuf(stdout, buf, _IOLBF, BUFSIZ);
+  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();
+  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");
+                       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;
+                       }
+                       printf("end_of_message\n");
+                       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[MAXNAMELEN], nams2[MAXNAMELEN];
+       mode_t          mode;
+
+#if    VERITAS
+       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);
+       rootp  = NULL;
+       rlen   = 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 */
+
+       if (hanp1 && hlen1) {
+               hantoa(hanp1, hlen1, hans1);
+       } else {
+               sprintf(hans1, "<BAD_HANDLE_hlen_%d>", hlen1);
+       }
+       if (hanp2 && hlen2) {
+               hantoa(hanp2, hlen2, hans2);
+       } else {
+               sprintf(hans2, "<BAD_HANDLE_hlen_%d>", hlen2);
+       }
+       if (hanp3 && hlen3) {
+               hantoa(hanp3, hlen3, hans3);
+       } else {
+               sprintf(hans3, "<BAD_HANDLE_hlen_%d>", hlen3);
+       }
+       if (namp1 && nlen1) {
+               strncpy(nams1, namp1, nlen1);
+               if (nlen1 != sizeof(nams1))
+                       nams1[nlen1] = '\0';
+       } else {
+               sprintf(nams1, "<BAD STRING_nlen_%d>", nlen1);
+       }
+       if (namp2 && nlen2) {
+               strncpy(nams2, namp2, nlen2);
+               if (nlen2 != sizeof(nams2))
+                       nams2[nlen2] = '\0';
+       } else {
+               sprintf(nams2, "<BAD_STRING_nlen_%d>", 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;
+  int                  respond, response, respcode;
+  dm_namesp_event_t    *msg_ne;
+#if    !VERITAS
+    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], hans3[HANDLE_STR];
+  char                 nams1[MAXNAMELEN], nams2[MAXNAMELEN];
+  void                 *fs_hanp;
+  size_t               fs_hlen;
+  dm_timestruct_t       *pending_time;
+
+  /*
+   * Set the defaults for responding to events
+   */
+
+  /*****************************************************
+   *     If the daemon is feeling unfriendly, it will
+   *  respond (when necessary) with DM_RESP_ABORT, rather
+   *  than the standard DM_RESP_CONTINUE.
+   *
+   *     While unfriendly, the daemon normally returns
+   *  a respcode of "unfriendly_errno".  This defaults to 
+   *  EBADMSG but can be set when unfriendly mode is
+   *  activated.
+   *****************************************************/
+
+  respond = 1;
+  if (unfriendly_count==0) {
+    response = friendly ? DM_RESP_CONTINUE : DM_RESP_ABORT;
+    respcode = friendly ? 0 : unfriendly_errno;
+  }
+  else if (unfriendly_count > 0) {
+    if (unfriendly_count-- == 0) {
+      response = DM_RESP_CONTINUE;
+      respcode = 0;
+    }
+    else {
+      response = DM_RESP_ABORT;
+      respcode = unfriendly_errno;
+    }    
+  }
+  
+  if (pending_count >= 0) {
+    if (msg->ev_type != DM_EVENT_USER) {
+      if (pending_count-- == 0) {
+       int i;
+       for (i=arr_top; i>=0; --i) {
+         dm_respond_event(sid, token_arr[i], 
+                          DM_RESP_CONTINUE, 0, 0, 0);
+       }
+       response = DM_RESP_CONTINUE;
+       respcode = 0;
+      }
+      else {
+        if (pending_count<10) {
+         token_arr[pending_count]=msg->ev_token;
+       }
+       pending_time = malloc(sizeof(dm_timestruct_t));
+       pending_time->dm_tv_sec=0;
+       pending_time->dm_tv_nsec=0;
+       dm_pending(sid, msg->ev_token, pending_time);
+       printf("pending\ntries left\t:%d\n",pending_count);
+       return 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') {
+         /*****************************************************
+          *  Here, we check the messages from send_message.
+          *  Some of them have special meanings.
+          *****************************************************/
+         if (strncmp(privp, "over", 4)==0) {
+           response = DM_RESP_CONTINUE;
+           respcode = 0;
+         }
+         else if (strncmp(privp, "pending", 7)==0){
+           if (strlen(privp)>8) {
+             sscanf(privp, "pending%*c%d", &pending_count);
+           }     
+           else {
+             pending_count=1;
+           }
+           arr_top=pending_count-1;
+         }
+         else if (strncmp(privp, "reset_fs", 8)==0){
+           if (get_fs_handle(fsname, &fs_hanp, &fs_hlen)){
+             strcpy(privp, "error");
+           }
+           else if (set_disposition(sid, fs_hanp, fs_hlen)){
+             strcpy(privp, "error");
+           }
+           else if (set_events(sid, fs_hanp, fs_hlen)){
+             strcpy(privp, "error");
+           }
+         }
+         else if (strncmp(privp, "friendly", 8)==0) {
+           friendly = 1;
+           response = DM_RESP_CONTINUE;
+           respcode = 0;
+         }
+         else if (strncmp(privp, "unfriendly", 10)==0) {
+           friendly = 0;
+           response = DM_RESP_CONTINUE;
+           respcode = 0;
+           if (strlen(privp)>11) {
+             sscanf(privp, "unfriendly%*c%d", &unfriendly_errno);
+           }
+           else {
+             unfriendly_errno=EBADMSG;
+           }
+         }
+         else if (strncmp(privp, "countdown", 9)==0) {
+           response = DM_RESP_CONTINUE;
+           respcode = 0;
+           
+           if (strlen(privp)>10) {
+             sscanf(privp, "countdown%*c%d%*c%d",
+                    &unfriendly_count, &unfriendly_errno); 
+           }
+           else {
+             unfriendly_count=5;
+             unfriendly_errno=EAGAIN;
+           }
+         }
+
+
+         printf(VALS,
+                       "privdata", privp);
+
+       } else {
+          printf("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);
+    } 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",          msg_de->de_offset,
+            "length",          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",          msg_de->de_offset,
+            "length",          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",          msg_de->de_offset,
+            "length",          msg_de->de_length);
+      break;
+    }
+  }
+
+  /***** 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));
+    } 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("attrcopy :");
+      for (i = 0; i < clen; i++) {
+       /* Old version: printf("%.2x", copy[i]); */
+       printf("%c", 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
+               msg_me = DM_GET_VALUE(msg, ev_data, dm_mount_event_t *);
+               print_one_mount_event(msg_me);
+#else  /* VERITAS */
+               msg_ne = DM_GET_VALUE(msg, ev_data, dm_namesp_event_t *);
+               print_one_mount_event(msg_ne);
+#endif /* VERITAS */
+  }
+
+  /***** NAMESPACE EVENTS *****/
+
+  else {
+    char       *type;
+
+    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
+      } 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;
+      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) {
+    if (Sleep) sleep(Sleep); /* Slow things down here */
+
+    error = dm_respond_event(sid, msg->ev_token, response, respcode, 0, 0);
+    if (error) {
+      errno_msg("Can't respond to event");
+      return error;
+    }
+  }
+
+  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_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");
+       }
+
+       /* 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);
+       }
+
+       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 ( __sgi ) && ! defined ( VERITAS )
+       DMEV_SET(DM_EVENT_CANCEL, eventlist);   /* not supported on SGI */
+#endif
+#ifndef __sgi
+       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) {
+               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 ( __sgi ) && ! defined ( VERITAS )
+       DMEV_SET(DM_EVENT_CANCEL, eventlist);   /* not supported on SGI */
+#endif
+#ifndef __sgi
+       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_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);
+}
+
+
+/*
+ * 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;
+  size_t       buflen, 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 {
+    ntokens = (ntokens != ret_ntokens) ? ret_ntokens : ntokens*2;
+    nbytes = ntokens * (sizeof(dm_token_t) + sizeof(dm_vardata_t));
+    tokenbuf = malloc(nbytes);
+    if (tokenbuf == NULL) {
+      err_msg("Can't malloc %d bytes for tokenbuf\n", nbytes);
+      error = 1;
+      goto out;
+    }
+    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;
+  }
+
+  for (i = 0; i < ret_ntokens; i++) {
+    if (Verbose)
+      err_msg("Responding to outstanding event for token %d\n",(int)*tokenbuf);
+
+    /*
+     * The E2BIG dance reprise...
+     */
+    do {
+      buflen = (buflen != ret_buflen) ? ret_buflen : buflen * 2;
+      msgbuf = malloc(buflen);
+      if (msgbuf == NULL) {
+       err_msg("Can't malloc %d bytes for msgbuf\n", buflen);
+       error = 1;
+       goto out;
+      }
+      error = dm_find_eventmsg(sid, *tokenbuf, buflen, msgbuf, &ret_buflen);
+    } while (error && errno == E2BIG);
+    if (error) {
+      errno_msg("Can't find the event message for token %d", (int)*tokenbuf);
+      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 *);
+    }
+
+    tokenbuf++;
+  }
+
+ 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(void)
+{
+  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);
+}
diff --git a/dmapi/src/suite2/src/dump_allocinfo.c b/dmapi/src/suite2/src/dump_allocinfo.c
new file mode 100644 (file)
index 0000000..529c5d4
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <lib/dmport.h>
+#include <lib/hsm.h>
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_get_allocinfo().  The
+command line is:
+
+       dump_allocinfo [-D] [-n nelem] [-o offp] [-s sid] pathname
+
+where pathname is the name of a file, 'offp' is a byte offset from the
+beginning of the file where you want to start dumping, and 'nelem' allows
+you to specify how many extent structures to use in each dm_get_allocinfo
+call.
+
+The code checks the returned extents as much as possible for errors.
+It detects bad ex_type values, verifies that there is always a trailing
+hole at the end of the file, that the ex_offset of each extent matches the
+ex_offset+ex_length of the previous extent, and that ex_offset+ex_length
+is always an even multiple of 512.  It verifies that all ex_offset values
+after the first fall on a 512-byte boundary.  It verifies that the '*offp'
+value returned by dm_get_allocinfo() is 0 at the end of the file, and
+equals ex_offset+ex_length of the last extent if not at the end of the file.
+Any error is reported to stderr, and the program then terminates with a
+non-zero exit status.
+
+The program produces output similar to xfs_bmap in order to make comparison
+easier.  Here is some sample output.
+
+f1: offset 1
+        rc 0, nelemp 17
+        0: [0..127]: resv       [1..511]
+
+Line 1 gives the name of the file and the byte offset within the file where
+the dump started.  Line 2 appears once for each dm_get_allocinfo() call,
+giving the return value (rc) and the number of extents which were returned.
+Line 3 is repeated once for each extent.  The first field "0:" is the extent
+number.  The second field "[0..127]:" give the starting and ending block for
+the extent in 512-byte units.  The third field is either "resv" to indicate
+allocated space or "hole" if the extent is a hole.  The fourth field
+"[1..511]" only appears if the dump did not start with byte zero of the
+first block.  In that case, the first number shows the actual byte offset
+within the block (1 in this case).  The second number should always be
+511 since we always dump to the end of a block.
+
+Possible tests
+--------------
+
+Run the test scripts "test_allocinfo_1" and "test_allocinfo_2". 
+(The former compares dump_allocinfo output with xfs_bmap output. The latter
+compares various dump_allocinfo outputs, from trials with many different
+buffer sizes).
+
+Produce a file with holes, and perform the following tests using just one
+extent (-e 1).
+        Dump extents from beginning of the file.
+        Dump from byte 1 of the file.
+        Dump from the last byte of the first extent.
+        Dump from the first byte of the second extent.
+        Dump from the middle of the second extent.
+        Dump the first byte of the last extent.
+        Dump the last byte of the last extent.
+        Dump the first byte after the last extent.
+        Dump starting at an offset way past the end of the file.
+
+Produce a fragmented file with many adjacent DM_EXTENT_RES extents.
+        Repeat the above tests.
+
+Produce a GRIO file with holes.
+        Repeat the above tests.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+static int print_alloc(dm_sessid_t sid, void* hanp, size_t hlen,
+       char *pathname, dm_off_t startoff, u_int nelem);
+
+char   *Progname;
+int    Dflag = 0;
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\t%s [-D] [-n nelem] [-o off] [-s sid] "
+               "pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t      sid = DM_NO_SESSION;
+       dm_off_t        startoff = 0;           /* starting offset */
+       u_int           nelem = 100;
+       char            *pathname;
+       void            *hanp;
+       size_t           hlen;
+       dm_stat_t       sbuf;
+       char            *name;
+       int             opt;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Dn:o:s:")) != EOF) {
+               switch(opt) {
+               case 'D':
+                       Dflag++;
+                       break;
+               case 'n':
+                       nelem = atol(optarg);
+                       break;
+               case 'o':
+                       startoff = atoll(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       pathname = argv[optind];
+
+       if (dm_init_service(&name)) {
+               fprintf(stderr, "dm_init_service failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the file's handle and verify that it is a regular file. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for %s\n", pathname);
+               exit(1);
+       }
+       if (dm_get_fileattr(sid, hanp, hlen, DM_NO_TOKEN, DM_AT_STAT, &sbuf)) {
+               fprintf(stderr, "dm_get_fileattr failed\n");
+               exit(1);
+       }
+       if (!S_ISREG(sbuf.dt_mode)) {
+               fprintf(stderr, "%s is not a regular file\n", pathname);
+               exit(1);
+       }
+
+       /* Print the allocation. */
+
+       if (print_alloc(sid, hanp, hlen, pathname, startoff, nelem))
+               exit(1);
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
+
+
+static int
+print_alloc(
+       dm_sessid_t     sid,
+       void            *hanp,
+       size_t          hlen,
+       char            *pathname,
+       dm_off_t        startoff,
+       u_int           nelem)
+{
+       dm_off_t        endoff;
+       dm_extent_t     *extent;
+       u_int           nelemp;
+       u_int           num = 0;
+       u_int           i;
+       char            *type = NULL;
+       int             rc;
+       
+       if (Dflag) fprintf(stdout, "%s: starting offset %lld\n", pathname, startoff);
+
+       /* Allocate space for the number of extents requested by the user. */
+
+       if ((extent = malloc(nelem * sizeof(*extent))) == NULL) {
+               fprintf(stderr, "can't malloc extent structures\n");
+               return(1);
+       }
+
+       rc = 1;
+       endoff = startoff;
+
+       while (rc != 0) {
+         rc = dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN, &startoff,
+                               nelem, extent, &nelemp);
+         if (rc < 0) {
+           fprintf(stderr, "dm_get_allocinfo failed, %s\n",
+                   strerror(errno));
+           return(1);
+         }
+         
+         if (Dflag) fprintf(stdout, "\treturned %d, nelemp %d\n", rc, nelemp);
+         
+         if (Dflag && nelemp)
+           fprintf(stdout, " ex_type    ex_offset       ex_length\n");
+               
+         /* Note: it is possible for nelemp to be zero! */
+         
+         for (i = 0; i < nelemp; i++) {
+           /* The extent must either be reserved space or a hole. */
+           switch (extent[i].ex_type) {
+           case DM_EXTENT_RES:
+             type = "resv";
+             break;
+           case DM_EXTENT_HOLE:
+             type = "hole";
+             break;
+           default:
+             fprintf(stderr, "invalid extent type %d\n",
+                     extent[i].ex_type);
+             return(1);
+           }
+           
+           if (i!=nelemp-1 || rc!=0) {
+             if (!Dflag) {
+               fprintf(stdout, "\t%d: [%lld..%lld]: %s", num,
+                       extent[i].ex_offset / 512,
+                       (extent[i].ex_offset +
+                        extent[i].ex_length - 1) / 512, type);
+               if ((extent[i].ex_offset % 512 != 0) ||
+                                   (endoff % 512 != 0)) {
+                 fprintf(stdout, "\t[%lld..%lld]\n",
+                         extent[i].ex_offset % 512,
+                         (endoff-1) % 512);
+               } else {
+                 fprintf(stdout, "\n");
+               }
+             } else {
+               fprintf(stdout, "%5s    %13lld  %13lld\n",
+                       type, extent[i].ex_offset,
+                       extent[i].ex_length);
+             }
+           }
+           /* The ex_offset of the first extent should match the
+              'startoff' specified by the caller.  The ex_offset
+              in subsequent extents should always match
+              (ex_offset + ex_length) of the previous extent,
+              and should always start on a 512 byte boundary.
+              */
+           
+           if (extent[i].ex_offset != endoff) {
+             fprintf(stderr, "new extent (%lld)is not "
+                     "adjacent to previous one (%lld)\n",
+                     extent[i].ex_offset, endoff);
+             return(1);
+           }
+           if (num && (extent[i].ex_offset % 512) != 0) {
+             fprintf(stderr, "non-initial ex_offset (%lld) "
+                     "is not a 512-byte multiple\n",
+                     extent[i].ex_offset);
+             return(1);
+           }
+           
+           /* Non-initial extents should have ex_length values
+              that are an even multiple of 512.  The initial
+              extent should be a multiple of 512 less the offset
+              into the starting 512-byte block.
+              */
+           
+           if (((extent[i].ex_offset % 512) + extent[i].ex_length) % 512 != 0) { 
+             fprintf(stderr, "ex_length is incorrect based "
+                     "upon the ex_offset\n");
+             return(1);
+           }
+           
+           endoff = extent[i].ex_offset + extent[i].ex_length;
+           num++;              /* count of extents printed */
+         }
+         
+         /* If not yet at end of file, the startoff parameter should
+            match the ex_offset plus ex_length of the last extent
+            retrieved.
+            */
+         
+         if (rc && startoff != endoff) {
+           fprintf(stderr, "startoff is %lld, should be %lld\n",
+                   startoff, endoff);
+           return(1);
+         }
+         
+         /* If we are at end of file, the last extent should be a
+            hole.
+            */
+         
+         if (!rc && type && strcmp(type, "hole")) {
+           fprintf(stderr, "file didn't end with a hole\n");
+           return(1);
+         }
+       }
+
+       /* At end of file, startoff should always equal zero. */
+       
+       if (startoff != 0) {
+         fprintf(stderr, "startoff was not zero at end of file\n");
+         return(1);
+       }
+       return(0);
+}
diff --git a/dmapi/src/suite2/src/invis_test.c b/dmapi/src/suite2/src/invis_test.c
new file mode 100644 (file)
index 0000000..b422194
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits.h>
+
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+For manually testing DMAPI functions dm_write_invis() and dm_read_invis()
+
+The command line is:
+
+       invis_test [-Rrv] [-l len] [-o offset] [-s sid] ls_path pathname
+
+where:
+   -R
+       reuse existing test file
+   -r
+       use dm_invis_read, default is dm_invis_write.
+   len
+       length of read/write
+   offset
+       offset in file for read/write
+   sid
+      is the session ID whose events you you are interested in.
+   ls_path
+      is the path to a specific copy of ls, important only for its size
+   pathname
+      is the filesystem to use for the test.
+
+DM_WRITE_SYNC is is not supported.
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-Rrv] [-l len] [-o offset] [-s sid] ls_path pathname\n", 
+               Progname);
+       exit(1);
+}
+
+#define BUFSZ 100
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       int             Vflag=0;
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *dir_name = NULL;
+       char            *ls_path = NULL;
+       char            *name;
+       char            ch = 'A';
+       char            test_file[128];
+       char            command[1024];
+       void            *hanp;
+       size_t          hlen;
+       char            buf[BUFSZ];
+       dm_ssize_t      rc;
+       dm_off_t        offset = 0;
+       dm_size_t       length = BUFSZ;
+       int             opt;
+       int             reading = 0; /* writing is the default */
+       int             exitstat=0;
+       dm_size_t       errblockstart, errblockend;
+       int             in_err_block;
+       int             i;
+       int             reuse_file = 0;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "Rvs:rl:o:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                       Vflag++;
+                       break;
+               case 'r':
+                       reading++;
+                       break;
+               case 'R':
+                       reuse_file++;
+                       break;
+               case 'l':
+                       length = atoi(optarg);
+                       break;
+               case 'o':
+                       offset = atoi(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       ls_path = argv[optind];
+       dir_name = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       sprintf(test_file, "%s/DMAPI_test_file", dir_name);
+       if( (!reading) && (!reuse_file) ){
+               sprintf(command, "cp %s %s\n", ls_path, test_file); 
+               system(command);
+       }
+
+       if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for %s; bypassing test\n",
+                     test_file);
+               exit(1);
+       }
+
+       if( Vflag )
+               printf("using length = %lld\n", length );
+       if( length > BUFSZ ){
+               fprintf(stderr, "length(%lld) > BUFSZ(%lld)\n", length, BUFSZ);
+               exit(1);
+       }
+
+       if( reading ){
+               memset(buf, '\0', BUFSZ);
+
+               rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                                  offset, length, buf);
+               if( rc < 0 ){
+                       fprintf(stderr, "dm_read_invis failed, (err=%d)\n", errno);
+                       dm_handle_free(hanp, hlen);
+                       exit(1);
+               }
+               if( rc != length ){
+                       fprintf(stderr, "dm_read_invis read %lld bytes, wanted to write %lld bytes\n",
+                               rc, length );
+                       dm_handle_free(hanp, hlen);
+                       exitstat++;
+               }
+               else {
+                       printf("dm_read_invis read %lld bytes\n", rc);
+               }
+               
+               in_err_block = 0;
+               errblockstart = errblockend = 0;
+               for( i=0; i < length; ++i ){
+                       if( in_err_block ){
+                               if( buf[i] != ch ){
+                                       /* still in the err block */
+                                       errblockend = i;
+                               }
+                               else {
+                                       /* end of bad block */
+                                       fprintf(stderr, "read err block: byte %lld to %lld\n", errblockstart, errblockend);
+                                       in_err_block = 0;
+                               }
+                       }
+                       else if( buf[i] != ch ){
+                               /* enter err block */
+                               errblockstart = i;
+                               in_err_block = 1;
+                       }
+               }
+               if( in_err_block ){
+                       /* end of bad block */
+                       fprintf(stderr, "read err block: byte %lld to %lld\n", errblockstart, errblockend);
+                       in_err_block = 0;
+               }
+       }
+       else {
+
+               memset(buf, ch, BUFSZ);
+
+               rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                                   0, offset, length, buf);
+               if( rc < 0 ){
+                       fprintf(stderr, "dm_write_invis failed, (err=%d)\n", errno);
+                       dm_handle_free(hanp, hlen);
+                       exit(1);
+               }
+               if( rc != length ){
+                       fprintf(stderr, "dm_write_invis wrote %lld bytes, wanted to write %lld bytes\n",
+                               rc, length );
+                       dm_handle_free(hanp, hlen);
+                       exit(1);
+               }
+               printf("dm_write_invis wrote %lld bytes\n", rc);
+       }
+
+       dm_handle_free(hanp, hlen);
+       exit(exitstat);
+}
diff --git a/dmapi/src/suite2/src/mm_fill.c b/dmapi/src/suite2/src/mm_fill.c
new file mode 100644 (file)
index 0000000..25879fe
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+/*
+ *      mmap_fill
+ * 
+ *      use memory mapping to fill a filesystem! :)
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include <errno.h>
+
+
+char * progname;
+int    fd;                     /* file descriptor */
+addr_t ptr;                    /* mapped pointers */
+off_t   off;
+long long  junk[512] = { -1 };
+long long counter;
+
+main(int argc, char * argv[])
+{ 
+  int i;
+  for (i=0; i<512; i++) junk[i]=-1;
+  
+
+  if ((progname = strrchr(argv[0], '/')) == NULL)
+    progname = argv[0];
+  else
+    progname++;
+  
+  if (argc < 2) {
+    fprintf(stderr,"Usage: %s filename\n", progname);
+    exit(1);
+  }
+  
+  fd = open(argv[1], O_RDWR|O_CREAT, 0644);
+  if (fd < 0) {
+    fprintf(stderr,"%s: cannot open %s\n", progname, argv[1]);
+    perror(argv[1]);
+    exit(3);
+  }
+
+  ptr = mmap64(NULL, (size_t)(0x10000000), PROT_WRITE, MAP_SHARED|MAP_AUTOGROW, fd, 0);
+  if (ptr == MAP_FAILED) {
+    fprintf(stderr,"%s: cannot mmap64 %s\n", progname, argv[1]);
+    perror(argv[1]);
+    exit(3);
+  }
+  
+  for(counter=0; ; counter++) {
+    junk[0] = counter;
+    bcopy(junk, ptr, sizeof(junk));
+    ptr+=sizeof(junk);
+  }
+  printf("%s complete.\n", progname);
+  return 0;
+}
diff --git a/dmapi/src/suite2/src/mmap.c b/dmapi/src/suite2/src/mmap.c
new file mode 100644 (file)
index 0000000..6dc571c
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+/*
+ *     This routine simulates
+ *     
+ *     cp      file1 file2
+ *
+ *
+ *     It is a demo program which does the copy by memory mapping each of the
+ *     files and then doing a byte at a time memory copy.
+ *
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include <errno.h>
+
+
+char * Progname;
+off_t  len;                    /* length of file 1 */
+off_t  offset = 0;
+int    print_flags_set = 1;
+
+typedef        struct  fflag {
+       int     arg;            /* != 0 if ars specified */
+       int     value;          /* flags value */
+} fflag_t;
+
+
+typedef enum ftype {   /* flag bit types */
+       FL_MAP, FL_PROT, FL_OPEN, FL_MAX
+} ftype_t;
+
+typedef struct mfile   {
+       fflag_t flags[FL_MAX];
+       char    *path;
+       int     fd;
+       struct  stat    st;
+       addr_t  p;
+} mfile_t;
+
+
+#define        FLAG(symbol,type) { # symbol , symbol, type }
+#define        MAP_NONE        0
+
+static struct  {
+       char    *name;
+       int     value;
+       ftype_t type;
+} Flags[] = {
+       FLAG(O_RDONLY, FL_OPEN),
+       FLAG(O_WRONLY, FL_OPEN),
+       FLAG(O_RDWR, FL_OPEN),
+       FLAG(O_NDELAY, FL_OPEN),
+       FLAG(O_NONBLOCK, FL_OPEN),
+       FLAG(O_APPEND, FL_OPEN),
+       FLAG(O_SYNC, FL_OPEN),
+       FLAG(O_TRUNC, FL_OPEN),
+       FLAG(O_CREAT, FL_OPEN),
+       FLAG(O_DIRECT, FL_OPEN),
+       FLAG(PROT_NONE, FL_PROT),
+       FLAG(PROT_READ, FL_PROT),
+       FLAG(PROT_WRITE, FL_PROT),
+       FLAG(PROT_EXEC, FL_PROT),
+       FLAG(PROT_EXECUTE, FL_PROT),
+       FLAG(MAP_SHARED, FL_MAP),
+       FLAG(MAP_PRIVATE, FL_MAP),
+       FLAG(MAP_FIXED, FL_MAP),
+       FLAG(MAP_RENAME, FL_MAP),
+       FLAG(MAP_AUTOGROW, FL_MAP),
+       FLAG(MAP_LOCAL, FL_MAP),
+       FLAG(MAP_AUTORESRV, FL_MAP),
+       FLAG(MAP_NONE, FL_MAP),
+};
+
+int    num_Flags = sizeof(Flags)/sizeof(Flags[0]);
+
+
+mfile_t        *ifile, *ofile;
+mfile_t        *hfile; /* Hack job */
+static int     hack = 0;
+       
+static mfile_t *new_mfile(void);
+static int mfile_opt(char * s, mfile_t * f);
+static void print_flags(char *s, mfile_t *f);
+static void Usage(void);
+
+main(int argc, char * argv[])
+{
+       int     opt;
+
+       if ((Progname = strrchr(argv[0], '/')) == NULL)
+               Progname = argv[0];
+       else
+               Progname++;
+
+       ifile = new_mfile();
+       ofile = new_mfile();
+       hfile = new_mfile();
+       if (ifile == NULL || ofile == NULL || hfile == NULL) {
+               fprintf(stderr,"%s: malloc failure.\n", Progname);
+               exit (1);
+       }
+
+       /* Set default flags */
+       ifile->flags[FL_MAP].value = MAP_PRIVATE;
+       ifile->flags[FL_PROT].value = PROT_READ;
+       ifile->flags[FL_OPEN].value = O_RDONLY;
+       ofile->flags[FL_MAP].value = MAP_SHARED|MAP_AUTOGROW;
+       ofile->flags[FL_PROT].value = PROT_WRITE;
+       ofile->flags[FL_OPEN].value = O_RDWR|O_CREAT;
+
+       while ((opt = getopt(argc, argv, "i:o:h:d")) != EOF) {
+               switch(opt) {
+               case 'i':
+                       if (mfile_opt(optarg, ifile) != 0) {
+                               fprintf(stderr, "%s: Invalid -i option %s\n",
+                                       Progname, optarg);
+                               Usage();
+                       }
+                       break;
+
+               case 'o':
+                       if (mfile_opt(optarg, ofile) != 0) {
+                               fprintf(stderr, "%s: Invalid -o option %s\n",
+                                       Progname, optarg);
+                               Usage();
+                       }
+                       break;
+
+               case 'h':
+                       if (mfile_opt(optarg, hfile) != 0) {
+                               fprintf(stderr, "%s: Invalid -h option %s\n",
+                                       Progname, optarg);
+                               Usage();
+                       }
+                       hack = 1;
+                       break;
+
+               case 'd':
+                       print_flags_set ^= 1;
+                       break;
+               case '?':
+                       Usage();
+               }
+       }
+
+       if (optind+1 > argc)
+               Usage();
+
+       ifile->path = argv[optind++];
+       ofile->path = argv[optind++];
+
+       if (optind != argc)     /* Extra args on command line */
+               Usage();
+
+       if (stat(ifile->path, &(ifile->st)) < 0) {
+               fprintf(stderr,"%s: stat of %s failed.\n",
+                                               Progname, ifile->path);
+               perror(ifile->path);
+               exit(2);
+       }
+
+       len = ifile->st.st_size;
+
+       ifile->fd = open(ifile->path, ifile->flags[FL_OPEN].value);
+       if (ifile->fd < 0) {
+               fprintf(stderr,"%s: cannot open %s\n", Progname, ifile->path);
+                perror(ifile->path);
+                exit(2);
+       }
+
+
+       ofile->fd = open(ofile->path, ofile->flags[FL_OPEN].value, 0644);
+        if (ofile->fd < 0) {
+                fprintf(stderr,"%s: cannot open %s\n", Progname, ofile->path);
+                perror(ofile->path);
+                exit(3);
+        }
+
+       if (print_flags_set) {
+               print_flags("Input ", ifile);
+               print_flags("Output", ofile);
+               if (hack)
+                       print_flags("Hack  ", hfile);
+       }
+
+
+       ifile->p = mmap(NULL, len, ifile->flags[FL_PROT].value,
+                               ifile->flags[FL_MAP].value, ifile->fd, 0);
+       if (ifile->p == MAP_FAILED) {
+               fprintf(stderr,"%s: cannot mmap %s\n", Progname, ifile->path);
+                perror(ifile->path);
+                exit(2);
+        }
+
+       ofile->p = mmap(NULL, len, ofile->flags[FL_PROT].value,
+                               ofile->flags[FL_MAP].value , ofile->fd, 0);
+               if (ofile->p == MAP_FAILED) {
+                fprintf(stderr,"%s: cannot mmap %s\n", Progname, ofile->path);
+                perror(ofile->path);
+                exit(3);
+        }
+
+       if (hack) {
+               int     error;
+
+               error = mprotect(ofile->p, len, hfile->flags[FL_PROT].value);
+               if (error) {
+                       fprintf(stderr,"%s: mprotect call failed.\n", Progname);
+                       perror("mprotect");
+                       exit(3);
+               }
+       }
+       
+       bcopy(ifile->p, ofile->p, len);
+
+       printf("%s complete.\n", Progname);
+       return 0;
+}
+
+static mfile_t *
+new_mfile(void)
+{
+       mfile_t *ptr = (mfile_t *)malloc(sizeof(*ptr));
+       if (ptr)
+               bzero(ptr, sizeof *ptr);
+
+       return  ptr;
+}
+
+
+static int
+mfile_opt(char * s, mfile_t *f)
+{
+       int     i;
+       ftype_t type;
+
+       for (i = 0; i < num_Flags; i++) {
+               if(!strcasecmp(Flags[i].name, s)) {
+
+                       /* Zero value if this is 1st arg of this type */
+
+                       type = Flags[i].type;
+                       if (f->flags[type].arg++ == 0) 
+                               f->flags[type].value = 0;
+                       f->flags[type].value |= Flags[i].value;
+                       return 0;
+               }
+       }
+       return -1;      /* error - string not found */
+}
+
+static void
+Usage(void)
+{
+       int     i;
+
+       fprintf(stderr, 
+               "Usage: %s [-d] [-i flag] [-i flag] [-o flag] ... file1 file2\n",
+               Progname);
+       fprintf(stderr, "Valid flag values are:\n");
+
+       for (i = 0; i < num_Flags; i++) {
+               fprintf(stderr,"%15s",Flags[i].name);
+               if ((i+1)%4 == 0 || i == num_Flags-1)
+                       fprintf(stderr,"\n");
+               else
+                       fprintf(stderr,",");
+       }
+       exit(1);
+}
+
+static void
+print_flags(char *s, mfile_t *f)
+{
+       int             i;
+       ftype_t         type;
+
+       printf("DEBUG - %s flags:\n", s);
+       for (i = 0; i < num_Flags; i++) {
+               type = Flags[i].type;
+               if (type == FL_OPEN && Flags[i].value == O_RDONLY && 
+                       ((f->flags[type].value) & 3) == 0) 
+                               /* Hack to print out O_RDONLY */
+                               printf("\t%s\n", Flags[i].name);
+               else if ((Flags[i].value & (f->flags[type].value)) != 0)
+                       printf("\t%s\n", Flags[i].name);
+       }
+}
diff --git a/dmapi/src/suite2/src/mmap_cp.c b/dmapi/src/suite2/src/mmap_cp.c
new file mode 100644 (file)
index 0000000..e695301
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+/*
+ *      mmap_fill
+ * 
+ *      use memory mapping to fill a filesystem! :)
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include <errno.h>
+
+
+char * progname;
+int    fd;                     /* file descriptor */
+addr_t ptr;                    /* mapped pointers */
+long long  junk[512];
+
+main(int argc, char * argv[])
+{
+  printf("Sizeof junk = %d \n", junk);
+  exit(0);
+
+  if ((progname = strrchr(argv[0], '/')) == NULL)
+    progname = argv[0];
+  else
+    progname++;
+  
+  if (argc < 2) {
+    fprintf(stderr,"Usage: %s filename\n", progname);
+    exit(1);
+  }
+  
+  fd = open(argv[1], O_RDWR|O_CREAT, 0644);
+  if (fd < 0) {
+    fprintf(stderr,"%s: cannot open %s\n", progname, argv[1]);
+    perror(argv[1]);
+    exit(3);
+  }
+  
+  ptr = mmap(NULL, len, PROT_WRITE, MAP_SHARED|MAP_AUTOGROW , fd, 0);
+  if (ptr == MAP_FAILED) {
+    fprintf(stderr,"%s: cannot mmap %s\n", progname, argv[1]);
+    perror(argv[1]);
+    exit(3);
+  }
+  
+  while (1) {
+    bcopy(junk, ptr, size_of(junk));
+    ptr+=size_of(junk);
+  }
+  printf("%s complete.\n", progname);
+  return 0;
+}
diff --git a/dmapi/src/suite2/src/region_test.c b/dmapi/src/suite2/src/region_test.c
new file mode 100644 (file)
index 0000000..e88c2b4
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Manual test for the DMAPI functions dm_set_region() and dm_get_region().
+
+The command line is:
+
+        region_test [-Rv] [-s sid] [-l len] [-o offset] ls_path directory 
+
+where 
+   -R
+       reuse the existing test file
+   pathname
+      is the name of a file
+   ls_path
+      is the path to a specific copy of ls, important only for its size
+   sid
+      is the session ID whose events you you are interested in.
+----------------------------------------------------------------------------*/
+
+#define NELEM   1
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-Rv] [-s sid] [-l len] [-o offset] ls_path pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *dir_name = NULL;
+       char            *ls_path = NULL;
+       char            command[1024];
+       char            test_file[128];
+       int             opt;
+       int             Vflag = 0;
+       dm_region_t     region = { 0, 0, 0 };
+       char            *name;
+       int             reuse_file = 0;
+       void            *hanp;
+       size_t           hlen;
+       dm_boolean_t    exactflag;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "vo:l:s:R")) != EOF) {
+               switch (opt) {
+               case 'v':
+                       Vflag++;
+                       break;
+               case 'R':
+                       reuse_file++;
+                       break;
+               case 'o':
+                       region.rg_offset = atol(optarg);
+                       break;
+               case 'l':
+                       region.rg_size = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 > argc)
+               usage();
+       ls_path = argv[optind];
+       dir_name = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       sprintf(test_file, "%s/DMAPI_test_file", dir_name);
+       if( !reuse_file ){
+               sprintf(command, "cp %s %s\n", ls_path, test_file); 
+               system(command);
+       }
+
+       if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", test_file);
+               exit(1);
+       }
+
+       region.rg_flags = DM_REGION_READ | DM_REGION_WRITE | DM_REGION_TRUNCATE;
+       if( dm_set_region( sid, hanp, hlen, DM_NO_TOKEN, NELEM,
+                         &region, &exactflag ) ){
+               fprintf(stderr, "dm_set_region failed, err=%d\n", errno);
+               dm_handle_free(hanp,hlen);
+               exit(1);
+       }
+       if( exactflag == DM_FALSE )
+               fprintf(stderr, "exact flag was false\n");
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite2/src/send_msg.c b/dmapi/src/suite2/src/send_msg.c
new file mode 100644 (file)
index 0000000..3c39247
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <lib/dmport.h>
+#include <lib/hsm.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function send_msg().  
+The command line is:
+
+       send_msg [-a] [-s sid] string
+
+where string is the msgdata to be stored in the event.
+sid is the session ID to use for the event.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-a] [-s sid] string\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *string;
+       dm_token_t      token;
+       char            *name;
+       int             opt;
+       int             i;
+       dm_msgtype_t    msgtype = DM_MSGTYPE_SYNC;
+       
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "as:")) != EOF) {
+               switch (opt) {
+               case 'a':
+                       msgtype = DM_MSGTYPE_ASYNC;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 1 != argc)
+               usage();
+       string = argv[optind++];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       if (dm_send_msg(sid, msgtype, strlen(string)+ 1, string)) {
+               fprintf(stderr, "dm_send_msg failed, %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       exit(0);
+}
+
diff --git a/dmapi/src/suite2/src/test_dmattr.c b/dmapi/src/suite2/src/test_dmattr.c
new file mode 100644 (file)
index 0000000..f927e19
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits.h>
+
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+Automated test of the DMAPI functions: 
+     dm_set_dmattr()
+     dm_get_dmattr()
+     dm_remove_dmattr()
+
+The command line is:
+
+       test_dmattr [-v] [-n num] [-l length] [-s sid] directory 
+
+where 
+   ls_path 
+     is the path to a specific copy of ls, important only for its size
+   directory 
+     is the pathname to a DMAPI filesystem
+   num
+     is the number of files to create for the test.
+   length
+     is the length of the attribute value for the test.
+   sid 
+     is the session ID whose attributes you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#define VALUE_LENGTH 22
+#define NUM_ITERATIONS 50
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-v] [-n number] [-l length] "
+               "[-s sid] ls_path pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *dir_name;
+       char            *ls_path;
+       dm_attrname_t   *attrnamep;
+       size_t          buflen=VALUE_LENGTH;
+       char            *bufp;
+       int             setdtime = 0;
+       size_t          rlenp;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       int             opt;
+       int             i=0;
+       int             j=0;
+       int             Vflag=0;
+       int             num_iter = NUM_ITERATIONS;
+        char            test_file[128];
+       char            command[128];
+        char            **test_array;
+       dm_size_t       config_retval;
+       dm_token_t      test_token;
+       struct stat    *statbuf;
+       struct stat    *checkbuf;
+
+        if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "vn:l:s:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                       Vflag++;
+                       break;
+               case 'n':
+                       num_iter = atoi(optarg);
+                       break;
+               case 'l':
+                       buflen = atoi(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       ls_path = argv[optind];
+       dir_name = argv[optind+1];
+
+       bufp =
+         (char *)(malloc (buflen * sizeof(char)));  
+       statbuf = 
+         (struct stat *)(malloc (num_iter * sizeof(struct stat)));
+       checkbuf = 
+         (struct stat *)(malloc (num_iter * sizeof(struct stat)));
+       test_array = 
+         (char **)(malloc (num_iter * sizeof(char *)));
+       if (bufp==NULL || test_array==NULL || 
+           statbuf==NULL || checkbuf==NULL) {
+         printf("Malloc failed\n");
+         exit(1);
+       }
+       for (i=0; i<num_iter; i++) {
+         test_array[i] =
+           (char*)(malloc (buflen * sizeof(char)));
+         if (test_array[i] == NULL) {
+           printf("Malloc failed\n");
+           exit(1);
+         }
+       }
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       printf("Attribute tests beginning...\n");
+       
+       attrnamep = (dm_attrname_t *)("DMATTR");
+
+       /* File creation loop*/
+       for (i=0; i < num_iter; i++) {
+         sprintf(test_file, "%s/DMAPI_attribute_test_file.%d", 
+                 dir_name, i);
+         sprintf(command, "cp %s %s \n", ls_path, test_file); 
+         system(command);
+       }
+
+       /* SET loop */
+       for (i=0; i < num_iter; i++) {
+         sprintf(test_file, "%s/DMAPI_attribute_test_file.%d", 
+                 dir_name, i);
+
+         if (stat(test_file, &(statbuf[i]))){
+           fprintf(stdout, 
+                   "Error: unable to stat the test file; %s (before set)\n", 
+                   test_file);
+         }
+         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+           fprintf(stderr, "can't get handle for %s; bypassing test\n",
+                   test_file);
+         }
+         else {
+           for (j=0; j < VALUE_LENGTH; j++) {
+             test_array[i][j]=(char)(rand()/128);;
+           } 
+           /* buflen is already set (to VALUE_LENGTH) */
+           if (dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN, attrnamep, 
+                             (i<num_iter/2)?0:1, buflen, test_array[i])) {
+             fprintf(stderr, "dm_set_dmattr failed on test %d, %s\n",
+                     i, ERR_NAME);
+           }
+           else { 
+             if (Vflag){
+               printf("Report: success with set #%d.\n", i);
+             }
+           }
+         }
+       }
+               
+       /* GET loop */
+       for (i=0; i < num_iter; i++) {
+         sprintf(test_file, "%s/DMAPI_attribute_test_file.%d", 
+                 dir_name, i);
+
+         if (stat(test_file, &(checkbuf[i]))){
+           fprintf(stdout, 
+                   "Error: unable to stat the test file; %s (before get)\n", 
+                   test_file);
+         }
+         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+           fprintf(stderr, "can't get handle for %s; bypassing test\n",
+                   test_file);
+         }
+         else {
+           if (dm_get_dmattr(sid, hanp, hlen, DM_NO_TOKEN, attrnamep, buflen,
+                             bufp, &rlenp)) {
+             if (errno == E2BIG) {
+               fprintf(stderr, "dm_get_dmattr buffer too small, "
+                       "should be %d bytes\n", rlenp);
+             } else {
+               fprintf(stderr, "dm_get_dmattr failed (%s) for test file %d\n",
+                       ERR_NAME, i);
+             }
+           }
+           else {
+             /* Compare bufp with test_array[i]: */
+             if (strncmp(test_array[i], bufp, buflen)){
+               printf("ERROR: failure on get test #%d.\n", i);
+             }
+             else if (Vflag) {
+               printf("Report: success with get #%d. "
+                      "(output matches expectation)\n",i);
+             }
+           }
+         }
+       }
+       
+       /* It's time for timestamp checking! */
+       for (i=0; i < num_iter; i++) {
+#ifdef linux
+         if ((statbuf[i].st_atime == checkbuf[i].st_atime) &&
+             (statbuf[i].st_mtime == checkbuf[i].st_mtime) &&
+             (statbuf[i].st_ctime == checkbuf[i].st_ctime))
+#else
+         if ((statbuf[i].st_atim.tv_sec == checkbuf[i].st_atim.tv_sec) &&
+             (statbuf[i].st_atim.tv_nsec == checkbuf[i].st_atim.tv_nsec) &&
+             (statbuf[i].st_mtim.tv_sec == checkbuf[i].st_mtim.tv_sec) &&
+             (statbuf[i].st_mtim.tv_nsec == checkbuf[i].st_mtim.tv_nsec) &&
+             (statbuf[i].st_ctim.tv_sec == checkbuf[i].st_ctim.tv_sec) &&
+             (statbuf[i].st_ctim.tv_nsec == checkbuf[i].st_ctim.tv_nsec))
+#endif
+         {
+           if (i < num_iter/2) {
+             /* Time stamp did not change, correctly */
+               if (Vflag) {
+               fprintf(stdout, "Report: Time stamp was correctly "
+                       "unchanged by test %d.\n", i);
+               }
+           }
+           else {
+             /* Time stamp did not change, but should have */
+             fprintf(stdout, "Error: the time stamp should have "
+                     "changed in test file %d\n", i);
+           }
+         }
+         else {
+           /* Time stamp changed, but should not have. */
+           if (i < num_iter/2) {
+             fprintf(stdout, "Error: the time stamp should not"
+                     "change in test file %d\n", i);
+           }
+           else {
+           /* Time stamp changed, and should  have. */
+             if (Vflag) {
+               fprintf(stdout, "Report: Time stamp was correctly "
+                       "changed by test %d.\n", i);
+             }
+           }
+         }
+       }
+
+       
+       /* REMOVE loop */
+       for (i=0; i < num_iter; i++) {
+         sprintf(test_file, "%s/DMAPI_attribute_test_file.%d", 
+                 dir_name, i);
+
+         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+           fprintf(stderr, "can't get handle for %s; bypassing test\n",
+                   test_file);
+         }
+         else {
+           if (dm_remove_dmattr(sid, hanp, hlen, DM_NO_TOKEN, setdtime,
+                                attrnamep)) {
+             fprintf(stderr, "dm_remove_dmattr failed (%s) on test #%d\n",
+                     ERR_NAME, i);
+           }
+           else {
+             if (Vflag) {
+               printf("Report: success with remove test #%d.\n",i);
+             }
+           }
+         }
+       }
+
+       for (i=0; i < num_iter; i++) {
+         sprintf(test_file, "%s/DMAPI_attribute_test_file.%d", 
+                 dir_name, i);
+         sprintf(command, "rm %s \n", test_file); 
+         system(command);
+       }
+
+       /*************************************\
+       |* Correct-input testing complete.   *|
+       |* Beginning improper-input testing. *|
+       \*************************************/
+       sprintf(test_file, "%s/DMAPI_attribute_test_file.ERRNO", 
+               dir_name, i);
+       sprintf(command, "cp %s %s\n", ls_path, test_file); 
+       system(command);
+       
+       if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+         fprintf(stderr, "can't get handle for %s; bypassing errno tests\n",
+                 test_file);
+       }
+       else {
+         
+         printf("\t(errno subtests beginning...)\n");
+         /**** SET tests ****/
+         /*---------------------------------------------------------*/
+         dm_get_config(hanp, hlen, DM_CONFIG_MAX_ATTRIBUTE_SIZE, 
+                       &config_retval);
+         
+         ERRTEST(E2BIG,
+                 "set", 
+                 dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                                attrnamep, setdtime, (config_retval+1), 
+                               "foofoofoo"))
+         /*---------------------------------------------------------*/
+         EXCLTEST("set", hanp, hlen, test_token, 
+                  dm_set_dmattr(sid, hanp, hlen, test_token,
+                                attrnamep, 0, buflen, "no right"))
+         /*---------------------------------------------------------*/
+         { void* test_vp;
+           if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+             fprintf(stderr, "Cannot create a test handle (%s); "
+                     "skipping EBADF test\n", ERR_NAME);
+           }
+           else {
+             ((char *) test_vp)[hlen/2]++;
+             ERRTEST(EBADF,
+                     "set",
+                     dm_set_dmattr(sid, test_vp, hlen, DM_NO_TOKEN,
+                                   attrnamep, 0, buflen, "EBADF"))
+               dm_handle_free(test_vp, hlen);
+           }
+         }
+         /*---------------------------------------------------------*/
+         ERRTEST(EBADF,
+                 "set",
+                 dm_set_dmattr(sid, hanp, hlen-1, DM_NO_TOKEN,
+                               attrnamep, 0, buflen, "EBADF"))
+         /*---------------------------------------------------------*/
+         ERRTEST(EFAULT,
+                 "set",
+                 dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                               (dm_attrname_t*)(-1000), 0,
+                               buflen, "EFAULT_test" ))
+         ERRTEST(EFAULT,
+                 "set",
+                 dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                               attrnamep, 0, buflen, (void*)(-1000)))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "set (bad token)",
+                 dm_set_dmattr(sid, hanp, hlen, (dm_token_t)(-1000), 
+                               attrnamep, 0, buflen, 
+                               "EINVAL_bad_token"))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "set (bad session id)",
+                 dm_set_dmattr((dm_sessid_t)(-1000), hanp, hlen, 
+                               DM_NO_TOKEN, attrnamep, 0, buflen, 
+                               "EINVAL_bad_session_id"))
+           
+         /**** GET tests ****/
+         /*---------------------------------------------------------*/
+         dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                       attrnamep, 0, buflen,
+                       "ERRNO for GET_DMATTR");
+         /*---------------------------------------------------------*/
+         ERRTEST(E2BIG,
+                 "get",
+                 dm_get_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                               attrnamep, 0, bufp, &rlenp))
+         /*---------------------------------------------------------*/
+         SHAREDTEST("get", hanp, hlen, test_token, 
+                    dm_get_dmattr(sid, hanp, hlen, test_token,
+                                  attrnamep, buflen, bufp, &rlenp))
+         /*---------------------------------------------------------*/
+         { void* test_vp;
+           if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+             fprintf(stderr, "Cannot create a test handle (%s); "
+                     "skipping EBADF test\n", ERR_NAME);
+           }
+           else {
+             ((char *) test_vp)[hlen/2]++;
+             ERRTEST(EBADF,
+                     "get",
+                     dm_get_dmattr(sid, test_vp, hlen, DM_NO_TOKEN,
+                                   attrnamep, buflen, bufp, &rlenp))
+               dm_handle_free(test_vp, hlen);
+           }
+         }
+         /*---------------------------------------------------------*/
+         ERRTEST(EBADF,
+                 "get",
+                 dm_get_dmattr(sid, hanp, hlen-1, DM_NO_TOKEN,
+                               attrnamep, buflen, bufp, &rlenp))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "get (invalid session)",
+                 dm_get_dmattr((dm_sessid_t)(-1000), hanp, hlen, DM_NO_TOKEN,
+                               attrnamep, buflen, bufp, &rlenp))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "get (invalid token)",
+                 dm_get_dmattr(sid, hanp, hlen, (dm_token_t)(-1000),
+                               attrnamep, buflen, bufp, &rlenp))
+         /*---------------------------------------------------------*/
+         ERRTEST(ENOENT,
+                 "get",
+                 dm_get_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                               (dm_attrname_t *)("NO_SUCH_ENTRY"),
+                               buflen, bufp, &rlenp))
+         /*---------------------------------------------------------*/
+       
+         /**** REMOVE tests ****/
+         /*---------------------------------------------------------*/
+         dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                       attrnamep, 0, buflen,
+                       "ERRNO for DMATTR");
+         EXCLTEST("remove", hanp, hlen, test_token,
+                  dm_remove_dmattr(sid, hanp, hlen, test_token, 
+                                   0, attrnamep))
+         /*---------------------------------------------------------*/
+         { void* test_vp;
+           if (dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN, attrnamep, 
+                             0, buflen, "ERRNO for DMATTR")) {
+             printf("ERROR in setting dmattr for remove_dmattr test. (%s)\n",
+                    ERR_NAME);
+           } 
+           else if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+             fprintf(stderr, "Cannot create a test handle (%s); "
+                     "skipping EBADF test\n", ERR_NAME);
+           }
+           else {
+             ((char *) test_vp)[hlen/2]++;
+             ERRTEST(EBADF,
+                     "remove",
+                     dm_remove_dmattr(sid, test_vp, hlen, DM_NO_TOKEN,
+                                      0, attrnamep))
+               dm_handle_free(test_vp, hlen);
+           }
+         }
+         /*---------------------------------------------------------*/
+         if (dm_set_dmattr(sid, hanp, hlen, DM_NO_TOKEN, attrnamep, 0, 
+                           buflen, "ERRNO for DMATTR")) {
+           printf("ERROR in setting dmattr for remove_dmattr test. (%s)\n",
+                  ERR_NAME);
+         } 
+         else {
+           ERRTEST(EBADF,
+                   "remove",
+                   dm_remove_dmattr(sid, hanp, hlen-1, DM_NO_TOKEN,
+                                    0, attrnamep))
+         }
+         /*---------------------------------------------------------*/
+         ERRTEST(EFAULT,
+                 "remove",
+                 dm_remove_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                                0, (void*)(-1000)))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "remove (bad token)",
+                 dm_remove_dmattr(sid, hanp, hlen, (dm_token_t)(-1000),
+                                0, attrnamep))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "remove (bad session)",
+                 dm_remove_dmattr(-1, hanp, hlen, DM_NO_TOKEN,
+                                0, attrnamep))
+         /*---------------------------------------------------------*/
+
+
+        sprintf(test_file, "%s/DMAPI_attribute_test_file.ERRNO", 
+                dir_name, i);
+        sprintf(command, "rm %s\n", test_file); 
+        system(command);
+        printf("\t(errno subtests complete)\n");
+       }
+       /**********************************\
+       |* End of improper-input testing. *|
+       \**********************************/
+
+
+       printf("Attribute tests complete!\n");
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite2/src/test_efault.c b/dmapi/src/suite2/src/test_efault.c
new file mode 100644 (file)
index 0000000..803da88
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <lib/dmport.h>
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+Automated search for EFAULT in the following DMAPI commands:
+   dm_get_allocinfo
+   dm_get_config
+   dm_get_config_events
+   dm_getall_dmattr
+   dm_init_attrloc
+
+There are other EFAULT tests, in the programs that test individual 
+DMAPI functions.  Those other tests are referenced in comments in this source.
+
+The command line is:
+   test_efault [-s sid] [-v] ls_path pathname
+
+where:
+   sid
+      is the session ID whose events you you are interested in.
+   ls_path
+      is the path to a copy of ls, which will be copied as a test file.
+   pathname
+      is the filesystem to use for the test.
+----------------------------------------------------------------------------*/
+
+extern int     optind;
+extern int     opterr;
+extern char    *optarg;
+
+char   *Progname;
+int     Vflag=0;
+
+static void
+usage(void)
+{
+       fprintf(stderr, 
+               "Usage: %s [-v] [-s sid] ls_path pathname\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(int argc, char **argv) {
+     
+        dm_sessid_t    sid = DM_NO_SESSION;
+       dm_token_t      test_token = DM_NO_TOKEN;
+       void            *hanp;
+       size_t          hlen;
+       char            *name;
+       char            *ls_path;
+       char            *pathname;
+       char            test_file[100];
+       char            command[100];
+       int             opt;
+       int             i=0;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       opterr = 0;
+       while ((opt = getopt(argc, argv, "vn:s:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                        Vflag++;
+                        break;
+               case 's': 
+                        sid = atol(optarg);
+                        break;
+               case '?':
+                        usage();
+               }
+       }
+       if (optind + 2 != argc) {
+               usage();
+       }
+       ls_path = argv[optind];
+       pathname = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       printf("Beginning EFAULT testing...\n");
+
+       /*----------------------------------*\
+       |*  ## Traditional errno tests  ##  *|
+       \*----------------------------------*/
+       sprintf(test_file, "%s/DMAPI_EFAULT_test_file", pathname);
+       sprintf(command, "cp %s %s\n", ls_path, test_file); 
+       system(command);
+       
+       if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 test_file, ERR_NAME);
+         goto abort_test;
+       }
+
+
+       /*---------------------------------------------------------
+        * get_allocinfo
+        *---------------------------------------------------------
+        */
+       { dm_off_t     off=0;
+         u_int        nelem=1;
+         dm_extent_t  extent;
+         dm_extent_t  *extentp;
+         u_int        nelem_ret;
+         
+         ERRTEST(EFAULT, "get_allocinfo (bad offp)",
+                 dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
+                                  (dm_off_t*)(-1000), 
+                                  nelem, &extent, &nelem_ret))
+         ERRTEST(EFAULT, "get_allocinfo (bad extentp)",
+                 dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
+                                  &off, nelem, (dm_extent_t*)(-1000),
+                                  &nelem_ret))
+         ERRTEST(EFAULT, "get_allocinfo (bad nelemp)",
+                 dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
+                                  &off, nelem, &extent,
+                                  (u_int*)(-1000)))
+       }
+   
+       /*------------------------------------------------------
+        * get_bulkattr: see test_fileattr.c
+        *------------------------------------------------------
+        * get_config
+        *------------------------------------------------------
+        */
+         ERRTEST(EFAULT, "get_config", 
+                 dm_get_config(hanp, hlen, DM_CONFIG_BULKALL,
+                               (dm_size_t*)(-1000)))
+       /*---------------------------------------------------------
+        * get_config_events
+        *---------------------------------------------------------
+        */
+       { 
+         u_int         nelem=5;
+         u_int         *nelemp;
+         dm_eventset_t *eventsetp;
+         eventsetp = (dm_eventset_t *)malloc(nelem*sizeof(dm_eventset_t));
+         if (eventsetp == NULL) {
+           printf("Couldn't malloc for config_events tests: %s\n", ERR_NAME);
+         }
+         else {
+         ERRTEST(EFAULT, "get_config_events (bad eventsetp)",
+               dm_get_config_events(hanp, hlen, nelem, 
+                                    (dm_eventset_t*)(-1000), nelemp))
+         ERRTEST(EFAULT, "get_config_events (bad nelemp)",
+                 dm_get_config_events(hanp, hlen, nelem, eventsetp, 
+                                      (u_int*)(-1000)))
+         }
+       }
+       /*---------------------------------------------------------
+        * get_dirattrs: see test_fileattr.c
+        *---------------------------------------------------------
+        * get_fileattr: see test_fileattr.c
+        *---------------------------------------------------------
+        * get_region: see test_region.c
+        *---------------------------------------------------------
+        * getall_dmattr
+        *---------------------------------------------------------
+        */
+       { 
+         size_t buflen = 5;
+         void   *bufp  = (void *)malloc(buflen*sizeof(dm_attrlist_t));
+         size_t *rlenp;
+         ERRTEST(EFAULT, "getall_dmattr (NULL handle)", 
+                 dm_getall_dmattr(sid, NULL, hlen, DM_NO_TOKEN,
+                                  buflen, bufp, rlenp))
+         ERRTEST(EFAULT, "getall_dmattr (incremented  bufp)", 
+                 dm_getall_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                                  buflen, (void*)((char*)(bufp)+1), rlenp))
+         ERRTEST(EFAULT, "getall_dmattr (bad bufp)", 
+                 dm_getall_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                                  buflen, (void*)(-1000), rlenp))
+         ERRTEST(EFAULT, "getall_dmattr (bad rlenp)", 
+                 dm_getall_dmattr(sid, hanp, hlen, DM_NO_TOKEN,
+                                  buflen, bufp, (size_t*)(-1000)))
+       }
+       /*---------------------------------------------------------
+        * init_attrloc
+        *---------------------------------------------------------
+        */
+       ERRTEST(ENOTSUP, "init_attrloc", 
+               dm_init_attrloc(sid, hanp, hlen, DM_NO_TOKEN,
+                               (dm_attrloc_t*)(-1000)))
+       /*---------------------------------------------------------
+        * probe_hole: see test_hole.c
+        *---------------------------------------------------------
+        * remove_dmattr: see test_dmattr.c
+        *---------------------------------------------------------
+        * set_dmattr: see test_dmattr.c
+        *---------------------------------------------------------
+        * set_eventlist: see test_eventlist.c
+        *---------------------------------------------------------
+        * set_region: see test_region.c
+        *---------------------------------------------------------
+        */
+
+abort_test:
+       sprintf(command, "rm %s\n", test_file); 
+       system(command);
+
+       printf("EFAULT testing complete.\n");
+
+}
+
diff --git a/dmapi/src/suite2/src/test_eventlist.c b/dmapi/src/suite2/src/test_eventlist.c
new file mode 100644 (file)
index 0000000..56039ae
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_set_eventlist().  The
+command line is:
+
+       test_eventlist [-v] [-s sid] [-t token] directory
+
+where:
+ls_path
+        is the path to a specific copy of ls, important only for its size
+directory
+       is the pathname to a DMAPI filesystem.
+sid
+       is the dm_sessid_t value to use.
+token
+       is the dm_token_t value to use (DM_NO_TOKEN is the default).
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+int check_one_event (dm_sessid_t, void*, size_t, dm_token_t, 
+                    dm_eventtype_t, int);
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-v] [-s sid] [-t token]"
+               "ls_path directory \n", Progname);
+       /* fprintf(stderr, "possible events are:\n");
+          for (i = 0; i < ev_namecnt; i++) {
+               fprintf(stderr, "%s (%d)\n", ev_names[i].name,
+                       ev_names[i].value);
+        }
+        */
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      token = DM_NO_TOKEN;
+       char            object[128];
+       void            *hanp;
+       size_t          hlen;
+       int             Fflag = 0;
+       int             Vflag = 0;
+       char            *name;
+       int             opt;
+       dm_eventtype_t  event;
+       int             error;
+        void           *fshanp;
+        size_t          fshlen;
+       int             i;
+       char            command[128];
+       char           *ls_path;
+       char           *dir_name;
+       dm_token_t      test_token = DM_NO_TOKEN;
+       dm_eventset_t   eventset;
+       void           *test_vp;
+       u_int           nelemp;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "s:t:uv")) != EOF) {
+               switch (opt) {
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case 't':
+                       token = atol(optarg);
+                       break;
+               case 'u':
+                       Vflag=2;
+                       break;
+               case 'v':
+                       if (Vflag==0) Vflag=1;
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+
+       if (optind + 2 != argc)
+               usage();
+       ls_path = argv[optind];
+       dir_name = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't initialize the DMAPI\n");
+               exit(1);
+       }
+
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       /* Get the directory handle */
+       if (dm_path_to_handle(dir_name, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for %s\n", dir_name);
+               exit(1);
+       }
+
+       /***********************************************\
+       |* Test to run on a FILE...                    *|
+       \***********************************************/
+       
+       printf("File test beginning...\n");
+       sprintf(object, "%s/VeryLongUnlikelyFilename.DMAPIFOO", dir_name);
+       sprintf(command, "cp %s %s \n", ls_path, object); 
+       system(command);
+
+       if (dm_path_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for %s\n; aborting test",
+                       object);
+       }
+       else {
+         for (i = 0; i < ev_namecnt; i++) {
+           error = check_one_event(sid, hanp, hlen, token,
+                                   ev_names[i].value, Vflag);  
+           switch (ev_names[i].value){
+           case DM_EVENT_ATTRIBUTE: case DM_EVENT_DESTROY:
+             if (error) {
+               fprintf(stderr, "ERROR: %s failed on a file!\n",
+                       ev_names[i].name);  
+             }
+             break;
+           default: 
+             if (!error) {
+               fprintf(stderr, "ERROR: %s succeeded on a file!\n",
+                       ev_names[i].name);  
+             }
+           }
+         }
+         /*------------------------*\
+         |*  ## Errno subtests ##  *|
+         \*------------------------*/
+         printf("\t(errno subtests beginning...)\n");
+         DMEV_ZERO(eventset);
+         DMEV_SET(DM_EVENT_ATTRIBUTE, eventset);
+         /*---------------------------------------------------------*/
+         EXCLTEST("set", hanp, hlen, test_token, 
+                  dm_set_eventlist(sid, hanp, hlen, test_token, 
+                                   &eventset, DM_EVENT_MAX))
+         /*---------------------------------------------------------*/
+         if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+           fprintf(stderr, 
+                   "Cannot create a test handle (%s); skipping EBADF test\n",
+                   ERR_NAME);
+         }
+         else {
+           /* Alter the handle copy to make it (presumably) invalid */
+           ((char *) test_vp)[hlen/2]++;
+           ERRTEST(EBADF,
+                   "set",
+                   dm_set_eventlist(sid, test_vp, hlen, token,
+                                    &eventset, DM_EVENT_MAX))
+           dm_handle_free(test_vp, hlen);
+         }
+         /*---------------------------------------------------------*/
+#ifdef VERITAS_21
+       /* Veritas gets a segmentation fault if hanp is NULL or if the
+          &eventset is out of range.
+       */
+       fprintf(stderr, "\tERROR testing for EFAULT in set (bad hanp): "
+               "Veritas gets a segmentation fault.\n");
+       fprintf(stderr, "\tERROR testing for EFAULT in set (bad eventset): "
+               "Veritas gets a segmentation fault.\n");
+#else
+         ERRTEST(EFAULT, 
+                 "set",
+                 dm_set_eventlist(sid, NULL, hlen, token, 
+                               &eventset, DM_EVENT_MAX))
+         ERRTEST(EFAULT, 
+                 "set",
+                 dm_set_eventlist(sid, hanp, hlen, token, 
+                               (dm_eventset_t*)(-1000), DM_EVENT_MAX))
+#endif
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "set (bad session)",
+                 dm_set_eventlist(-100, hanp, hlen, token,
+                                  &eventset, DM_EVENT_MAX))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "set (bad token)",
+                 dm_set_eventlist(sid, hanp, hlen, 0, 
+                               &eventset, DM_EVENT_MAX))
+         /*---------------------------------------------------------*/
+         /* PROBLEM: too-small buffer doesn't produce E2BIG 
+         { 
+           dm_eventset_t  *small_evsp = malloc(0);
+           if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+             fprintf(stderr, 
+                     "can't get filesystem handle from %s; aborting test\n",
+                     dir_name);
+           } 
+           else {
+             check_one_event(sid, fshanp, fshlen, token, 
+                             DM_EVENT_CREATE, Vflag);
+             ERRTEST(E2BIG,
+                     "(broken) get",
+                     dm_get_eventlist(sid, fshanp, fshlen, token, 
+                                      DM_EVENT_MAX, small_evsp, &nelemp))
+             check_one_event(sid, fshanp, fshlen, token, 
+                             DM_EVENT_INVALID, Vflag);
+           }
+         }
+         /*---------------------------------------------------------*/
+         SHAREDTEST("get", hanp, hlen, test_token, 
+                    dm_get_eventlist(sid, hanp, hlen, test_token,
+                                     DM_EVENT_MAX, &eventset, &nelemp))
+         /*---------------------------------------------------------*/
+         ERRTEST(EBADF,
+                 "get",
+                 dm_get_eventlist(sid, test_vp, hlen, token, DM_EVENT_MAX,
+                                  &eventset, &nelemp))
+         /*---------------------------------------------------------*/
+#ifdef VERITAS_21
+       /* Veritas gets a segmentation fault if hanp is NULL. */
+
+       fprintf(stderr, "\tERROR testing for EFAULT in get (bad hanp): "
+               "Veritas gets a segmentation fault.\n");
+#else
+         ERRTEST(EFAULT, 
+                 "get",
+                 dm_get_eventlist(sid, NULL, hlen, token, DM_EVENT_MAX,
+                                  &eventset, &nelemp ))
+#endif
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "get (bad session)",
+                 dm_get_eventlist(-100, hanp, hlen, token, DM_EVENT_MAX,
+                                  &eventset, &nelemp))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "get (bad token)",
+                 dm_get_eventlist(sid, hanp, hlen, 0, DM_EVENT_MAX,
+                               &eventset, &nelemp))
+         /*---------------------------------------------------------*/
+         printf("\t(errno subtests complete)\n");
+         /*---------------------*\
+         |* End of errno tests  *|
+         \*---------------------*/
+
+       /* Finally, use DM_EVENT_INVALID to delete events... */
+       check_one_event(sid, hanp, hlen, token, DM_EVENT_INVALID, Vflag);
+       }
+       sprintf(command, "rm %s \n", object); 
+       system(command);
+       printf("\tFile test complete.\n");
+       if (Vflag) printf("\n");
+       
+       /***********************************************\
+       |* Test to run on a DIRECTORY...               *|
+       \***********************************************/
+       
+               printf("Directory test beginning...\n");
+       sprintf(object, "%s/VeryLongUnlikelyDirectoryName.DMAPIFOO",
+               dir_name);
+       sprintf(command, "mkdir %s \n", object); 
+        system(command);       
+       
+       if (opaque_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for %s\n; aborting test",
+                       object);
+       }
+       else {
+         for (i = 0; i < ev_namecnt; i++) {
+           error = check_one_event(sid, hanp, hlen, token,
+                                   ev_names[i].value, Vflag);
+           switch (ev_names[i].value){
+           case DM_EVENT_CREATE:    case DM_EVENT_POSTCREATE:
+           case DM_EVENT_REMOVE:    case DM_EVENT_POSTREMOVE:
+           case DM_EVENT_RENAME:    case DM_EVENT_POSTRENAME:
+           case DM_EVENT_LINK:      case DM_EVENT_POSTLINK:
+           case DM_EVENT_SYMLINK:   case DM_EVENT_POSTSYMLINK:
+           case DM_EVENT_ATTRIBUTE: case DM_EVENT_DESTROY:
+             if (error) {
+               fprintf(stderr, "ERROR: %s failed on a directory!\n",
+                       ev_names[i].name);  
+             }
+             break;
+           default: 
+             if (!error) {
+               fprintf(stderr, "ERROR: %s succeeded on a directory!\n",
+                       ev_names[i].name);  
+             }
+           }
+         }
+       /* Use DM_EVENT_INVALID to delete events... */
+       check_one_event(sid, hanp, hlen, token, DM_EVENT_INVALID, Vflag);
+       }
+       sprintf(object, "%s/VeryLongUnlikelyDirectoryName.DMAPIFOO", dir_name);
+       sprintf(command, "rmdir %s\n", object); 
+       system(command);
+               printf("\tDirectory test complete.\n");
+       if (Vflag) printf("\n");
+
+       /***********************************************\
+       |* Test to run on a FILESYSTEM...              *|
+       \***********************************************/
+       
+               printf("Filesystem test beginning...\n");
+       
+       if (dm_handle_to_fshandle(hanp, hlen, &fshanp, &fshlen)) {
+         fprintf(stderr, 
+                 "can't get filesystem handle from %s; aborting test\n",
+                 dir_name);
+       }
+       else {
+         for (i = 0; i < ev_namecnt; i++) {
+           error = check_one_event(sid, fshanp, fshlen, token, 
+                                   ev_names[i].value, Vflag);
+           switch (ev_names[i].value){
+           case DM_EVENT_PREUNMOUNT: case DM_EVENT_UNMOUNT:
+           case DM_EVENT_NOSPACE:    case DM_EVENT_DEBUT:
+           case DM_EVENT_CREATE:     case DM_EVENT_POSTCREATE:
+           case DM_EVENT_REMOVE:     case DM_EVENT_POSTREMOVE:
+           case DM_EVENT_RENAME:     case DM_EVENT_POSTRENAME:
+           case DM_EVENT_LINK:       case DM_EVENT_POSTLINK:
+           case DM_EVENT_SYMLINK:    case DM_EVENT_POSTSYMLINK:
+           case DM_EVENT_ATTRIBUTE:  case DM_EVENT_DESTROY:
+             if (error) {
+               fprintf(stderr, "ERROR: %s failed on a filesystem!\n",
+                       ev_names[i].name);  
+             }
+             break;
+           default: 
+             if (!error) {
+               fprintf(stderr, "ERROR: %s succeeded on a filesystem!\n",
+                       ev_names[i].name);  
+             }
+           }
+         }
+       /* Use DM_EVENT_INVALID to delete events... */
+       check_one_event(sid, fshanp, fshlen, token, DM_EVENT_INVALID, Vflag);
+       }
+               printf("\tFilesystem test complete.\n");
+
+       /***********************************************\
+       |* End of tests!                               *|
+       \***********************************************/
+
+       dm_handle_free(fshanp, fshlen);
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
+
+/*-------------------------------------------------------------------
+  check_one_event: 
+   
+  Using dm_set_eventlist, set a single event on the object
+  indicated by the handle.
+
+  Using dm_get_eventlist, check to see that the single event
+  was set correctly.
+  -------------------------------------------------------------------*/
+
+int 
+check_one_event (
+                dm_sessid_t       sid,
+                void              *hanp,
+                size_t            hlen,
+                dm_token_t        token,
+                dm_eventtype_t    event,
+                int               Vflag )
+{
+       dm_eventset_t   eventset;
+       dm_eventset_t   check_eventset;
+       u_int           nelemp;
+       int             set_count = 0;
+       int             i;
+
+       DMEV_ZERO(eventset);
+       DMEV_ZERO(check_eventset);
+               
+       if (event != DM_EVENT_INVALID) {
+         DMEV_SET(event, eventset);
+       }
+
+       if (dm_set_eventlist(sid, hanp, hlen, token, 
+                                     &eventset, DM_EVENT_MAX)) {
+               if (Vflag){
+                 fprintf(stdout, " note: %s could not be set (%s)\n",
+                         ev_value_to_name(event), errno_names[errno]);
+               }
+               return (-1);
+       }
+
+       if (dm_get_eventlist(sid, hanp, hlen, token,
+                            DM_EVENT_MAX, &check_eventset, &nelemp)) {
+               if (Vflag){
+               fprintf(stdout, "dm_get_eventlist failed, %s\n",
+                       errno_names[errno]);
+               }
+               return (-2);
+       }
+       
+       /*  For each element, see that get_eventlist agrees 
+        *  with set_eventlist; if not, make noise.
+        */  
+       for (i = 0; i < ev_namecnt; i++) {
+         int set = DMEV_ISSET(ev_names[i].value, eventset);
+         int found = DMEV_ISSET(ev_names[i].value, check_eventset);
+         if (set && !found) {
+           fprintf(stderr, "ERROR: event %s was set but not found.\n",
+                   ev_names[i].name);
+           return (-3);
+         } 
+         else if (!set && found) {
+           fprintf(stderr, "ERROR: Found unexpected event %s \n",
+                   ev_names[i].name);
+           return (-4);
+         }
+         else if ((Vflag == 2) && !set && !found) {
+           fprintf(stderr, "clear: %s\n",
+                  ev_names[i].name);
+         }
+         else if (Vflag && set && found) {
+           fprintf(stderr, "  SET: %s\n", ev_names[i].name);
+           set_count++;
+         }
+       }
+       if (Vflag && set_count == 0) {
+         fprintf(stderr, "\t(All events cleared)\n");
+       }
+        return 0;
+}
diff --git a/dmapi/src/suite2/src/test_fileattr.c b/dmapi/src/suite2/src/test_fileattr.c
new file mode 100644 (file)
index 0000000..8ba0fd5
--- /dev/null
@@ -0,0 +1,713 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <lib/dmport.h>
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#include <unistd.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+Automated test of the DMAPI functions:
+   dm_set_fileattr()
+   dm_get_fileattr()
+   dm_get_bulkattr()
+   dm_get_dirattrs()
+
+The command line is:
+   test_fileattr [-s sid] [-n num_files] [-v] ls_path pathname
+
+where:
+   sid
+      is the session ID whose events you you are interested in.
+   num_files
+      is the number of test files to create.
+   ls_path
+      is the path to a copy of ls, which will be copied as a test file.
+   pathname
+      is the filesystem to use for the test.
+----------------------------------------------------------------------------*/
+
+#define SET_MASK  DM_AT_ATIME|DM_AT_MTIME|DM_AT_CTIME|DM_AT_DTIME|\
+                  DM_AT_UID|DM_AT_GID|DM_AT_MODE|DM_AT_SIZE 
+
+#define GET_MASK DM_AT_EMASK|DM_AT_PMANR|DM_AT_PATTR|\
+                 DM_AT_DTIME|DM_AT_CFLAG|DM_AT_STAT
+
+extern int     optind;
+extern int     opterr;
+extern char    *optarg;
+
+char   *Progname;
+int     Vflag=0;
+
+
+int
+comp_stat ( dm_stat_t expected,
+           dm_stat_t found,
+           int       i)
+{
+   int good=0;
+   if (found.dt_mode != expected.dt_mode) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected mode %ld, but found %ld\n",
+            i, expected.dt_mode, found.dt_mode);
+   }
+   else good++;
+   if (found.dt_uid != expected.dt_uid) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected uid %ld, but found %ld\n",
+            i, expected.dt_uid, found.dt_uid);
+   }
+   else good++;
+   if (found.dt_gid != expected.dt_gid) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected gid %ld, but found %ld\n",
+            i, expected.dt_gid, found.dt_gid);
+   }
+   else good++;
+   if (found.dt_atime != expected.dt_atime) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected atime %ld, but found %ld\n",
+            i, expected.dt_atime, found.dt_atime);
+   }
+   else good++;
+   if (found.dt_mtime != expected.dt_mtime) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected mtime %ld, but found %ld\n",
+            i, expected.dt_mtime, found.dt_mtime);
+   }
+   else good++;
+   if (found.dt_ctime != expected.dt_ctime) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected ctime %ld, but found %ld\n",
+            i, expected.dt_ctime, found.dt_ctime);
+   }
+   else good++;
+   
+   /* NOTE: dtime gets set to ctime */
+   
+   if (found.dt_dtime != expected.dt_ctime) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected dtime %ld, but found %ld\n",
+            i, expected.dt_ctime, found.dt_dtime);
+   }
+   else good++;
+   if (found.dt_size != expected.dt_size) {
+     fprintf(stderr, 
+            "ERROR: get #%d, expected size %ld, but found %ld\n",
+            i, expected.dt_size, found.dt_size);
+   }
+   else good++;
+   if (Vflag){
+     if (good==8) {
+       fprintf(stderr, "report: get #%d had no errors.\n",i);
+     } else {
+       fprintf(stderr, "report: %d tests correct for get #%d.\n", 
+              good, i);
+     }
+   }
+   return(good);
+}
+
+
+static void
+usage(void)
+{
+       fprintf(stderr, 
+               "Usage: %s [-v] [-s sid] [-n num_files] ls_path pathname\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc,
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       dm_token_t      test_token = DM_NO_TOKEN;
+       void            *hanp;
+       size_t          hlen;
+       char            *ls_path;
+       char            *pathname;
+       char            test_file[100];
+       char            command[100];
+       int             fs_num_files;
+       int             num_files=50;
+       dm_stat_t       *stat_arr;
+       dm_stat_t       dmstat;
+       dm_fileattr_t   fileattr;
+       char            *name;
+       int             opt;
+       int             oops=1;
+       int             i=0;
+       dm_attrloc_t    loc;
+       size_t          buflen = 16*sizeof(dm_stat_t);
+       size_t          rlen;
+       void            *bufp;
+       dm_stat_t       *statbuf;
+       int             loops=0;
+       int             all_file_count=0;
+       void            *fs_hanp;
+       size_t          fs_hlen;
+       void            *targhanp;
+       size_t          targhlen;
+       char            check_name[100];
+       char            *chk_name_p;
+       int             chk_num;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       opterr = 0;
+       while ((opt = getopt(argc, argv, "vn:s:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                        Vflag++;
+                        break;
+               case 'n':
+                        num_files = atoi(optarg);
+                        break;
+               case 's': 
+                        sid = atol(optarg);
+                        break;
+               case '?':
+                        usage();
+               }
+       }
+       if (optind + 2 != argc) {
+               usage();
+       }
+       ls_path = argv[optind];
+       pathname = argv[optind+1];
+
+       /* Seed the random number generator */
+       srand((unsigned int)time(NULL)); 
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       /* Dynamically allocate stat_arr; */
+       stat_arr = 
+         (dm_stat_t *)malloc(num_files * sizeof(dm_stat_t));
+       
+       printf("Beginning file attribute tests...\n");
+
+       /* Fill in the dm_stat blocks with lots of junk...
+        */
+       for (i=0; i<num_files; i++) {
+         stat_arr[i].dt_atime=(time_t)(rand()+rand()*0x10000);
+         stat_arr[i].dt_mtime=(time_t)(rand()+rand()*0x10000);
+         stat_arr[i].dt_ctime=(time_t)(rand()+rand()*0x10000);
+         stat_arr[i].dt_dtime=(time_t)(rand()+rand()*0x10000);
+         stat_arr[i].dt_uid=(uid_t)(rand()+rand()*0x10000);
+         stat_arr[i].dt_gid=(gid_t)(rand()+rand()*0x10000);
+         stat_arr[i].dt_mode=(mode_t)((rand()%4096)+32768);
+         stat_arr[i].dt_size=(dm_off_t)(rand()+rand()*0x10000);
+       }       
+
+       /*-----------------------------------------------------*\
+       |* File creation and set_fileattr loop                 *|
+       \*-----------------------------------------------------*/
+       if (Vflag) fprintf(stderr, "\nCreating/setting up test files.\n");
+       for (i=0; i < num_files; i++) {
+         sprintf(test_file, "%s/DMAPI_fileattr_test.%d", 
+                 pathname, i);
+         sprintf(command, "cp %s %s \n", ls_path, test_file); 
+         system(command);
+
+         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+           fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                   test_file, ERR_NAME);
+         }
+         else {
+           fileattr.fa_mode  = stat_arr[i].dt_mode;
+           fileattr.fa_uid   = stat_arr[i].dt_uid;
+           fileattr.fa_gid   = stat_arr[i].dt_gid;
+           fileattr.FA_ATIME = stat_arr[i].dt_atime;
+           fileattr.FA_MTIME = stat_arr[i].dt_mtime;
+           fileattr.FA_CTIME = stat_arr[i].dt_ctime;
+           fileattr.FA_DTIME = stat_arr[i].dt_dtime;
+           fileattr.fa_size  = stat_arr[i].dt_size;
+           if (dm_set_fileattr(sid, hanp, hlen, DM_NO_TOKEN,
+                               SET_MASK, &fileattr)) {
+             fprintf(stderr, "ERROR: set_fileattr failed on pass #%d; %s.\n",
+                     i, ERR_NAME);
+           }
+           else if (Vflag) {
+             fprintf(stderr, "report: set #%d was successful.\n", i);
+           }
+         }
+       }
+       
+       /*-----------------------------------------------------*\
+       |* Get_fileattr loop                                   *|
+       \*-----------------------------------------------------*/
+       if (Vflag) fprintf(stderr, "\nRunning get_fileattr test\n");
+       for (i=0; i < num_files; i++) {
+         sprintf(test_file, "%s/DMAPI_fileattr_test.%d", 
+                 pathname, i);
+         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+           fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                   test_file, ERR_NAME);
+         }
+         if (dm_get_fileattr(sid, hanp, hlen, DM_NO_TOKEN,
+                             GET_MASK, &dmstat)) {
+           fprintf(stderr,
+                   "ERROR: dm_get_fileattr failed on pass #%d, %s\n",
+                   ERR_NAME);
+         }
+         else {
+           comp_stat(stat_arr[i], dmstat, i); 
+         }
+       }
+         
+#if 0
+       /*-----------------------------------------------------*\
+       |* Get_dirattrs loop                                   *|
+       \*-----------------------------------------------------*/
+       if (Vflag) fprintf(stderr, "\nRunning get_dirattrs test\n");
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 pathname, ERR_NAME);
+         goto abort_test;
+       }
+       if ((bufp = (void*)malloc(buflen)) == NULL) {
+         fprintf(stderr, "Can't allocate memory for buffer.\n");
+           goto abort_test;
+       }
+       if (dm_init_attrloc(sid, hanp, hlen, DM_NO_TOKEN, &loc)){
+         fprintf(stderr, 
+                 "ERROR: dm_init_attrloc failed with %s.\n",
+                 ERR_NAME);
+         goto abort_test;
+       }
+       i=0; 
+       loops=0;
+       do {
+         /* printf("About to call get_dirattrs;\tloops=%d\n", loops);
+          * fflush(stdout);
+          * sleep(1);
+          */
+         oops=dm_get_dirattrs(sid, hanp, hlen, DM_NO_TOKEN,
+                              GET_MASK, &loc, buflen,
+                              bufp, &rlen);
+         if (rlen==0) break;
+         for (statbuf = bufp; statbuf != NULL; 
+              statbuf = DM_STEP_TO_NEXT(statbuf, dm_stat_t *)) {
+           chk_name_p = DM_GET_VALUE(statbuf, dt_compname, void *);
+           if (strncmp(chk_name_p, "DMAPI_fileattr_test.", 20)==0) {
+             sscanf(chk_name_p, "DMAPI_fileattr_test.%d", &chk_num);
+             if (comp_stat(stat_arr[chk_num], *statbuf, chk_num)==8) i++;
+           }
+         }
+         loops++;
+       } while (oops==1);
+       
+       if (oops==-1) {
+         fprintf(stderr, 
+                 "ERROR: dm_get_dirattrs failed with %s.\n",
+                 ERR_NAME);
+       }
+       if (i!=num_files) {
+         fprintf(stderr,
+                 "ERROR: get_dirattrs found %d matching file%s "
+                 "(expected %d).\n", i, (i==1)?"":"s", num_files);
+       }
+       else if (Vflag) {
+         fprintf(stderr, "report: get_dirattrs successfully "
+                 "found %d files in %d loops.\n", i, loops);
+       }
+#endif
+
+       /*-----------------------------------------------------*\
+       |* Get_bulkattr loop                                   *|
+       \*-----------------------------------------------------*/
+       if (Vflag) fprintf(stderr, "\nRunning get_bulkattr test\n");
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 pathname, ERR_NAME);
+         goto abort_test;
+       }
+        if (dm_path_to_fshandle(pathname, &fs_hanp, &fs_hlen)) {
+         fprintf(stderr, "ERROR: can't get filesystem handle for %s; %s\n",
+                 pathname, ERR_NAME);
+         goto abort_test;
+       }
+       
+       buflen = 16*sizeof(dm_stat_t); /* 100000000; */  
+       if ((bufp = (void*)malloc(buflen)) == NULL) {
+         fprintf(stderr, "Can't allocate memory for buffer.\n");
+         goto abort_test;
+       }
+       if (dm_init_attrloc(sid, fs_hanp, fs_hlen,
+                           DM_NO_TOKEN, &loc)){
+         fprintf(stderr, 
+                 "ERROR: dm_init_attrloc failed with %s.\n",
+                 ERR_NAME);
+         goto abort_test;
+       }
+       
+       i=0;
+       loops=0;
+       do {
+         oops=dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
+                              GET_MASK, &loc, buflen, bufp, &rlen); 
+         if (rlen==0) break;
+         for( statbuf = bufp; statbuf != NULL;  
+              statbuf = DM_STEP_TO_NEXT(statbuf, dm_stat_t *) ) {
+           targhanp = DM_GET_VALUE(statbuf, dt_handle, void *);
+           targhlen = DM_GET_LEN(statbuf, dt_handle);
+           if (dm_handle_to_path(hanp, hlen, targhanp, targhlen,
+                                 (size_t)100, check_name, &rlen)){
+             fprintf(stderr, 
+                     "Warning: Couldn't get name from handle. (%s)\n",
+                         ERR_NAME);
+           }
+           else {
+             /* Put JUST name (not path) from check_name into chk_name_p */
+             if (chk_name_p = strrchr(check_name, '/')) chk_name_p++;
+             else chk_name_p = check_name;
+             /* Verify that check_name_p holds a testfile name */
+             if (strncmp(chk_name_p, "DMAPI_fileattr_test.",20)==0) {
+               /* Get the test file's number and compare. */
+               sscanf(chk_name_p, "DMAPI_fileattr_test.%d", &chk_num);
+               if (comp_stat(stat_arr[chk_num], *statbuf, chk_num)==8)i++;
+             }
+           }            
+         }
+         loops++;
+       } while (oops==1);
+       
+       if (oops) {
+         fprintf(stderr, 
+                 "ERROR: dm_get_bulkattr failed with %s.\n",
+                 ERR_NAME);
+       }
+       /* printf("All_file_count: %d.  BUFLEN: %d\n",
+        * all_file_count, buflen);
+        */ 
+       if (i!=num_files) {
+         fprintf(stderr,
+                 "ERROR: get_bulkattr found %d matching file%s "
+                 "(expected %d) in %d loops.\n", i, (i==1)?"":"s",
+                 num_files, loops);
+       }
+       else if (Vflag) {
+         fprintf(stderr, "report: get_bulkattr successfully "
+                 "found %d files in %d loops.\n", i, loops);
+       }
+
+         /*------------------------*\
+         |*  ## Errno subtests ##  *|
+         \*------------------------*/
+         printf("\t(errno subtests beginning...)\n");
+         sprintf(test_file, "%s/DMAPI_fileattr_test.ERRNO", 
+                 pathname);
+         sprintf(command, "cp %s %s\n", ls_path, test_file); 
+         system(command);
+
+         if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+           fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                   test_file, ERR_NAME);
+           goto abort_test;
+         }
+         /*------------------------------------*\
+         |*  ## dm_set_fileattr() subtests ##  *|
+         \*------------------------------------*/
+         /*---------------------------------------------------------*/
+         EXCLTEST("set", hanp, hlen, test_token, 
+                  dm_set_fileattr(sid, hanp, hlen, test_token,
+                                  SET_MASK, &fileattr))
+         /*---------------------------------------------------------*/
+         { void *test_vp;
+         if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+           fprintf(stderr, 
+                   "Cannot create a test handle (%s); skipping EBADF test\n",
+                   ERR_NAME);
+         }
+         else {
+           ((char *) test_vp)[hlen/2]++;
+           ERRTEST(EBADF,
+                   "set",
+                   dm_set_fileattr(sid, test_vp, hlen, DM_NO_TOKEN,
+                                   SET_MASK, &fileattr))
+             dm_handle_free(test_vp, hlen);
+         }
+         }
+         /*---------------------------------------------------------*/
+         ERRTEST(EFAULT, 
+                 "set",
+                 dm_set_fileattr(sid, NULL, hlen, DM_NO_TOKEN, 
+                                 SET_MASK, &fileattr))
+         /*---------------------------------------------------------*/
+         /* PROBLEM: 32 ones as a mask does not produce a "bad mask" 
+         /* EINVAL.  If it doesn't, I suspect nothing will.
+         ERRTEST(EINVAL, 
+                 "set (bad mask) [BROKEN]",
+                 dm_set_fileattr(sid, hanp, hlen, DM_NO_TOKEN, 
+                                 0xFFFFFFFF, &fileattr))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "set (bad token)",
+                 dm_set_fileattr(sid, hanp, hlen, 0, 
+                                 SET_MASK, &fileattr))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "set (bad session)",
+                 dm_set_fileattr(-100, hanp, hlen, DM_NO_TOKEN, 
+                                 SET_MASK, &fileattr))
+         /*---------------------------------------------------------*/
+
+
+         /*------------------------------------*\
+         |*  ## dm_get_fileattr() subtests ##  *|
+         \*------------------------------------*/
+         /*---------------------------------------------------------*/
+         SHAREDTEST("get", hanp, hlen, test_token,
+                    dm_get_fileattr(sid, hanp, hlen, test_token,
+                                    GET_MASK, &dmstat))
+         /*---------------------------------------------------------*/
+         { void *test_vp;
+         if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+           fprintf(stderr, 
+                   "Cannot create a test handle (%s); skipping EBADF test\n",
+                   ERR_NAME);
+         }
+         else {
+           ((char *) test_vp)[hlen/2]++;
+           ERRTEST(EBADF,
+                   "get",
+                   dm_get_fileattr(sid, test_vp, hlen, DM_NO_TOKEN,
+                                   GET_MASK, &dmstat))
+             dm_handle_free(test_vp, hlen);
+         }
+         }
+         /*---------------------------------------------------------*/
+         ERRTEST(EFAULT, 
+                 "get",
+                 dm_get_fileattr(sid, NULL, hlen, DM_NO_TOKEN, 
+                                 GET_MASK, &dmstat))
+         ERRTEST(EFAULT, 
+                 "get",
+                 dm_get_fileattr(sid, hanp, hlen, DM_NO_TOKEN, 
+                                 GET_MASK, (dm_stat_t *)(-1000)))
+         /*---------------------------------------------------------*/
+         /* PROBLEM: 32 ones as a mask does not produce a "bad mask" 
+         /* EINVAL.  If it doesn't, I suspect nothing will.
+         ERRTEST(EINVAL, 
+                 "get (bad mask) [BROKEN]",
+                 dm_get_fileattr(sid, hanp, hlen, DM_NO_TOKEN, 
+                                 0xFFFFFFFF, &dmstat))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "get (bad token)",
+                 dm_get_fileattr(sid, hanp, hlen, 0, 
+                                 GET_MASK, &dmstat))
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL, 
+                 "get (bad session)",
+                 dm_get_fileattr(-100, hanp, hlen, DM_NO_TOKEN, 
+                                 GET_MASK, &dmstat))
+         /*---------------------------------------------------------*/
+           
+
+         dm_handle_free(hanp, hlen);
+#if 0
+         /*------------------------------------*\
+         |*  ## dm_get_dirattrs() subtests ##  *|
+         \*------------------------------------*/
+         if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+           fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                   pathname, ERR_NAME);
+         }
+         else if ((bufp = (void*)malloc(buflen)) == NULL) {
+           fprintf(stderr, "Can't allocate memory for buffer.\n");
+         }
+         else {
+           /*---------------------------------------------------------*/
+           if (dm_init_attrloc(sid, hanp, hlen, DM_NO_TOKEN, &loc)){
+             fprintf(stderr, 
+                     "ERROR: dm_init_attrloc failed with %s.\n",
+                     ERR_NAME);
+           } else {
+             SHAREDTEST("get_dir", hanp, hlen, test_token, 
+                        dm_get_dirattrs(sid, hanp, hlen, test_token,
+                                        GET_MASK, &loc, buflen, bufp, &rlen))
+           }
+           /*---------------------------------------------------------*/
+           { void* test_vp;
+             if (dm_init_attrloc(sid, hanp, hlen, DM_NO_TOKEN, &loc)){
+               fprintf(stderr,  "ERROR: dm_init_attrloc failed with %s.\n",
+                       ERR_NAME);
+             } 
+             else if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+               fprintf(stderr, "Cannot create a test handle (%s); "
+                       "skipping EBADF test\n", ERR_NAME);
+             }
+             else {
+               ((char *) test_vp)[hlen/2]++;
+               ERRTEST(EBADF,
+                       "get",
+                       dm_get_dirattrs(sid, test_vp, hlen, DM_NO_TOKEN,
+                                       GET_MASK, &loc, buflen, bufp, &rlen))
+               dm_handle_free(test_vp, hlen);
+             }
+           }
+           /*---------------------------------------------------------*/
+           { void *p = (void *)(((char *)bufp)+1);
+              if (dm_init_attrloc(sid, hanp, hlen, DM_NO_TOKEN, &loc)){
+               fprintf(stderr, 
+                       "ERROR: dm_init_attrloc failed with %s.\n",
+                       ERR_NAME);
+             } 
+             else {
+               /* PROBLEM:
+                   This would test alignment.  Right now, no error occurs
+                  when the buffer is "out of sync" with struct size.
+                  It makes it tough to read from the buffer, tho!
+                 ERRTEST(EFAULT,
+                       "get_dir (bad bufp)",
+                       dm_get_dirattrs(sid, hanp, hlen, DM_NO_TOKEN,
+                                       GET_MASK, &loc, buflen, p, &rlen))
+                       */
+               ERRTEST(EFAULT,
+                       "get_dir (bad locp)",
+                       dm_get_dirattrs(sid, hanp, hlen, DM_NO_TOKEN,
+                                       GET_MASK, (dm_attrloc_t*)(-1000),
+                                       buflen, bufp, &rlen))
+               ERRTEST(EFAULT,
+                       "get_dir (bad bufp)",
+                       dm_get_dirattrs(sid, hanp, hlen, DM_NO_TOKEN,
+                                       GET_MASK, &loc, buflen, 
+                                       (void*)(-1000), &rlen))
+               ERRTEST(EFAULT,
+                       "get_dir (bad rlenp)",
+                       dm_get_dirattrs(sid, hanp, hlen, DM_NO_TOKEN,
+                                       GET_MASK, &loc, buflen, bufp,
+                                       (size_t*)(-1000)))
+             }
+           }
+           /*---------------------------------------------------------*/
+           /*---------------------------------------------------------*/
+         }
+#endif
+           
+        /*------------------------------------*\
+        |*  ## dm_get_bulkattr() subtests ##  *|
+        \*------------------------------------*/
+        if (dm_path_to_fshandle(pathname, &fs_hanp, &fs_hlen)) {
+          fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                  pathname, ERR_NAME);
+        }
+        else if ((bufp = (void*)malloc(buflen)) == NULL) {
+          fprintf(stderr, "Can't allocate memory for buffer.\n");
+        }
+        else {
+          /*---------------------------------------------------------*/
+          if (dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &loc)){
+            fprintf(stderr, 
+                    "ERROR: dm_init_attrloc failed with %s.\n",
+                    ERR_NAME);
+          } 
+          else {
+            SHAREDTEST("get_bulk", fs_hanp, fs_hlen, test_token, 
+                       dm_get_bulkattr(sid, fs_hanp, fs_hlen, test_token,
+                                       GET_MASK, &loc, buflen, bufp, &rlen))
+          }
+          /*---------------------------------------------------------*/
+          if (dm_init_attrloc(sid, fs_hanp, fs_hlen, DM_NO_TOKEN, &loc)){
+            fprintf(stderr, 
+                    "ERROR: dm_init_attrloc failed with %s.\n",
+                    ERR_NAME);
+          }
+          else {
+            void *p = (void *)(((char *)bufp)+1);
+            ERRTEST(EFAULT, "get_bulk (bad bufp)",
+                    dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
+                                    GET_MASK, &loc, buflen, 
+                                    (void *)(-1000), &rlen))
+            ERRTEST(EFAULT, "get_bulk (bad locp)",
+                    dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
+                                    GET_MASK, (dm_attrloc_t *)(-1000),
+                                    buflen, bufp, &rlen))
+            ERRTEST(EFAULT, "get_bulk (bad rlenp)", 
+                    dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
+                                    GET_MASK, &loc, buflen, bufp,
+                                    (u_int*)(-1000)))
+            ERRTEST(EFAULT, "get_bulk (bad bufp)",
+                    dm_get_bulkattr(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
+                                    GET_MASK, &loc, buflen, p, &rlen))
+          }
+          /*---------------------------------------------------------*/
+        }
+        
+         sprintf(command, "rm %s/DMAPI_fileattr_test.ERRNO\n", pathname); 
+         system(command);
+         printf("\t(errno subtests complete)\n");
+         /*---------------------*\
+         |* End of errno tests  *|
+         \*---------------------*/
+
+abort_test:
+       /* File deletion loop */
+       if (Vflag) printf("(Deleting test files...)\n"); 
+        for (i=0; i < num_files; i++) {
+         sprintf(test_file, "%s/DMAPI_fileattr_test.%d", 
+                 pathname, i);
+         sprintf(command, "rm %s\n", test_file); 
+         system(command);
+       }
+       printf("File attribute tests complete.\n");
+}
diff --git a/dmapi/src/suite2/src/test_hole.c b/dmapi/src/suite2/src/test_hole.c
new file mode 100644 (file)
index 0000000..c3d18f9
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Test program used to test the DMAPI function dm_punch_hole().  The
+command line is:
+
+       test_hole [-v] [-s sid] pathname
+
+where 
+   ls_path
+      is the path to a specific copy of ls, important only for its size
+   pathname 
+      is the path to the test filesystem
+   sid
+      is the session ID whose events you you are interested in.
+
+----------------------------------------------------------------------------*/
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path directoryname\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *pathname = NULL;
+       char            *ls_path = NULL;
+       dm_off_t        offset = 0;
+       dm_off_t        ex_off = 0;
+       dm_extent_t     extent[20];
+       u_int           nelem;
+       dm_size_t       length = 0;
+       void            *hanp;
+       size_t          hlen;
+       dm_token_t      test_token;
+       char            *name;
+       int             opt;
+       int             i;
+       int             Vflag = 0;
+       char            filename[128];
+       char            command[128];
+       dm_off_t        roff;
+       dm_size_t       rlen;
+       dm_off_t        blocksize = 5; 
+       void            *test_vp;
+       struct stat    buf;
+       struct stat    checkbuf;
+
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "vs:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                       Vflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       ls_path = argv[optind];
+       pathname = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stdout, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /* Get the directory handle. */
+
+       if (dm_path_to_handle(pathname, &hanp, &hlen)) {
+               fprintf(stdout, 
+                    "ERROR: can't get handle for directory %s\n", pathname);
+               exit(1);
+       }
+       
+       printf("Hole test beginning...\n");
+       sprintf(filename, "%s/VeryLongUnlikelyFilename.HOLETEST", pathname);
+       sprintf(command, "cp %s %s \n", ls_path, filename); 
+       system(command);
+
+       if (dm_path_to_handle(filename, &hanp, &hlen)) {
+         fprintf(stdout, "can't get handle for %s\n; aborting test",
+                 filename);
+         
+         sprintf(command, "rm %s \n", filename); 
+         system(command);
+         fprintf(stdout, "\tHole test aborted.\n");
+         
+         dm_handle_free(hanp, hlen);
+         exit(1);
+       }
+   
+       /*   ## Get the block size using a length-1 probe. ##   */
+       dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 1, 0,
+                     &blocksize, &rlen);
+       
+       if (blocksize==0) {
+         fprintf(stdout, "Error: block size appears to be 0!\n");
+         
+         sprintf(command, "rm %s \n", filename); 
+         system(command);
+         fprintf(stdout, "\tHole test aborted.\n");
+         
+         dm_handle_free(hanp, hlen);
+         exit(1);
+       }
+
+       /* Check that dm_probe_hole returns an extent from the next
+        * highest multiple of the block size, to the end of the file
+        */
+       i = 0;
+       for (offset = 0; offset < 29604; offset++) { 
+         if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
+                           &roff, &rlen)) {
+           fprintf(stdout, "dm_probe_hole failed on pass %lld (%s)\n",
+                   (long long)offset, ERR_NAME);
+         }
+         else {
+           if (rlen != 0) {
+               fprintf(stdout, 
+                       "Error: hole did not extend to end of file!\n");
+           }
+           if (blocksize*(roff/blocksize) != roff) {
+               fprintf(stdout,
+                       "Error: offset not a multiple of block size!\n");
+           }
+         }
+       }
+       
+       /* Be sure dm_punch_hole doesn't change the time stamp, 
+        * and verify that dm_get_allocinfo shows a hole
+        * followed by an extent to the end of the file.
+        */
+       for(offset = 28672; offset > 0; offset-=blocksize) {
+         if (stat(filename, &buf)){
+           fprintf(stdout, 
+                   "Error: unable to stat the test file; %s (1st)\n", 
+                   filename);
+           continue;
+         }
+         if (dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
+                           &roff, &rlen)) {
+           fprintf(stdout, "dm_probe_hole failed, %s\n",
+                   ERR_NAME);
+           continue;
+         }
+         if (roff != offset) {
+           fprintf(stdout, 
+                   "Error: presumed offset was not %lld.\n",
+                   (long long)(roff));
+         }
+         if (dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
+                           roff, length)) {
+           fprintf(stdout, "dm_punch_hole failed, %s\n",
+                   ERR_NAME);
+           continue;
+         }
+         if (stat(filename, &checkbuf)){
+           fprintf(stdout, 
+                   "Error: unable to stat the test file. (2nd)\n");
+           continue;
+         }
+         else {
+           /* COMPARE BUF AND CHECKBUF! */
+#ifdef linux
+           if ((buf.st_atime == checkbuf.st_atime) &&
+               (buf.st_mtime == checkbuf.st_mtime) &&
+               (buf.st_ctime == checkbuf.st_ctime))
+#else
+           if ((buf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
+               (buf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
+               (buf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
+               (buf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
+               (buf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
+               (buf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
+#endif
+          {
+             if (Vflag) {
+               fprintf(stdout, 
+                       "\tTime stamp unchanged by hole from offset %lld.\n",
+                       (long long)(offset));
+             }
+           }
+           else {
+             fprintf(stdout,
+                     "Error: punch_hole changed file's time stamp.\n");
+           }
+           ex_off=0;
+           if ((dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN, 
+                                 &ex_off, 1, extent, &nelem) == 1) &&
+               (extent->ex_type == DM_EXTENT_RES) &&
+               (dm_get_allocinfo(sid, hanp, hlen, DM_NO_TOKEN,
+                                 &ex_off, 1, extent, &nelem) == 0) &&
+               (extent->ex_type == DM_EXTENT_HOLE)) {
+             if (extent->ex_offset == roff){
+               if (Vflag) {
+                 fprintf(stdout, "\tVerified hole at %lld\n", 
+                         (long long)(extent->ex_offset));
+               }
+             }
+             else {
+               fprintf(stdout, "\tError: get_allocinfo found hole at %lld\n",
+                       (long long)(extent->ex_offset));
+             }
+           }
+           else {
+               fprintf(stdout, "\tError: get_allocinfo did not find an "
+                       "extent followed by a hole!\n");
+           }
+         }
+       }
+       /*------------------------*\
+       |*  ## Errno subtests ##  *|
+       \*------------------------*/
+       fprintf(stdout, "\t(beginning errno subtests...)\n");
+       /*---------------------------------------------------------*/
+       ERRTEST(E2BIG,
+               "probe (from past EOF)",
+               dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 30000, length,
+                             &roff, &rlen))
+       /*---------------------------------------------------------*/
+       /* PROBLEM: No error is produced.  
+       /* off+len >= filesize should produce E2BIG...
+       ERRTEST(E2BIG,
+               "probe (to past EOF)",
+               dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, 15000, 150000,
+                             &roff, &rlen))
+        /*---------------------------------------------------------*/
+       SHAREDTEST("probe", hanp, hlen, test_token, 
+                dm_probe_hole(sid, hanp, hlen, test_token, 
+                              0, 0, &roff, &rlen)) 
+       /*---------------------------------------------------------*/
+       EXCLTEST("punch", hanp, hlen, test_token, 
+                  dm_punch_hole(sid, hanp, hlen, test_token, 0, 0)) 
+       /*---------------------------------------------------------*/
+       ERRTEST(EAGAIN,
+               "punch",
+               dm_punch_hole(sid, hanp, hlen, DM_NO_TOKEN,
+                             1, length))       
+       /*---------------------------------------------------------*/
+       if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+         fprintf(stderr, 
+                 "Cannot create a test handle (%s); skipping EBADF test\n",
+                 ERR_NAME);
+       }
+       else {
+        ((char *) test_vp)[hlen/2]++;
+         ERRTEST(EBADF,
+                 "probe",
+                 dm_probe_hole(sid, test_vp, hlen, DM_NO_TOKEN,
+                               offset, length,
+                               &roff, &rlen))
+         ERRTEST(EBADF,
+                 "punch",
+                 dm_punch_hole(sid, test_vp, hlen, DM_NO_TOKEN,
+                               offset, length))
+       }
+       dm_handle_free(test_vp, hlen);
+        /*---------------------------------------------------------*/
+        ERRTEST(EFAULT,
+               "probe (null handle)",
+               dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
+                               &roff, &rlen))
+        ERRTEST(EFAULT,
+               "probe (bad rlen)",
+               dm_probe_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length,
+                               &roff, (dm_size_t*)(-1000)))
+        ERRTEST(EFAULT,
+               "probe (bad roff)",
+               dm_probe_hole(sid, hanp, hlen, DM_NO_TOKEN, offset, length,
+                               (dm_off_t*)(-1000), &rlen))
+        /*---------------------------------------------------------*/
+        ERRTEST(EFAULT,
+               "punch",
+               dm_punch_hole(sid, 0, hlen, DM_NO_TOKEN, offset, length))
+        /*---------------------------------------------------------*/
+        ERRTEST(EINVAL,
+               "probe (bad session)",
+               dm_probe_hole(-100, hanp, hlen, DM_NO_TOKEN, offset, length,
+                               &roff, &rlen))
+        /*---------------------------------------------------------*/
+        ERRTEST(EINVAL, 
+               "probe (bad token)",
+               dm_probe_hole(sid, hanp, hlen, 0, offset, length,
+                               &roff, &rlen))
+        /*---------------------------------------------------------*/
+        ERRTEST(EINVAL, 
+               "probe (bad token 2)",
+               dm_probe_hole(sid, hanp, hlen, 0, offset, length,
+                               &roff, &rlen))
+        /*---------------------------------------------------------*/
+       fprintf(stdout, "\t(errno subtests complete)\n");
+               
+
+       sprintf(command, "rm %s \n", filename); 
+       system(command);
+       printf("Hole test complete.\n");
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
+
diff --git a/dmapi/src/suite2/src/test_invis.c b/dmapi/src/suite2/src/test_invis.c
new file mode 100644 (file)
index 0000000..57d4473
--- /dev/null
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits.h>
+
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Automated test of the DMAPI functions dm_write_invis() and dm_read_invis()
+
+The command line is:
+
+       test_invis [-s sid] [-v] ls_path pathname
+
+where:
+   sid
+      is the session ID whose events you you are interested in.
+   ls_path
+      is the path to a specific copy of ls, important only for its size
+   pathname
+      is the filesystem to use for the test.
+
+DM_WRITE_SYNC is is not supported.
+----------------------------------------------------------------------------*/
+
+#define OFF_MAX  50
+#define OFF_STEP 5
+#define LEN_MAX  50
+#define LEN_STEP 5
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-v] [-s sid] ls_path pathname\n", 
+               Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *dir_name = NULL;
+       char            *ls_path = NULL;
+       dm_off_t        offset = 0;
+       dm_size_t       length = 1;
+       dm_size_t       curlength = 0;
+       u_char          ch;
+       void            *bufp = NULL;
+       void            *hanp;
+       size_t          hlen;
+       dm_ssize_t      rc;
+       char            *name;
+       char            test_file[128];
+       char            command[128];
+       int             opt;
+       int             i;
+       int             j;
+       int             k;
+       int             Vflag=0;
+       struct stat     statbuf;
+       struct stat     checkbuf;
+       dm_token_t      test_token;
+       void*           test_vp;
+       int             cont;
+       int             error_reported;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "vs:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                       Vflag++;
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 != argc)
+               usage();
+       ls_path = argv[optind];
+       dir_name = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       /* Get a random character for read/write tests */
+       srand((unsigned int)time(NULL));
+       ch = (char)rand(); 
+
+       printf("Invisible read/write tests beginning...\n");
+       
+       /* File creation loop*/
+       for(i=0; i<LEN_MAX; i+=LEN_STEP) {
+         for (j=0; j<OFF_MAX; j+=OFF_STEP) {
+           sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
+                   dir_name, i, j);
+           sprintf(command, "cp %s %s\n", ls_path, test_file); 
+           system(command);
+         }
+       }
+       
+       /* Write to files, then read them to check for correct results. 
+          Do timestamp checking along the way. */
+
+       for(i=0; i<LEN_MAX; i+=LEN_STEP) {
+         for (j=0; j<OFF_MAX; j+=OFF_STEP) {
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+           length = max((dm_size_t)(i), length);
+           offset = (dm_off_t)(j);
+
+           sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
+                   dir_name, i, j);
+           
+           if (stat(test_file, &statbuf)){
+             fprintf(stdout, 
+                     "Error: unable to stat test file; %s (before test)\n", 
+                     test_file);
+             continue;
+           }
+           
+           if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+             fprintf(stderr, "can't get handle for %s; bypassing test\n",
+                     test_file);
+             continue;
+           }
+           
+printf("test_invis/%d: checking length(%d)>0\n", __LINE__, length);
+           if (length > curlength) {
+printf("test_invis/%d: bufp malloc(%d)\n", __LINE__, length);
+             if(curlength>0)
+               free(bufp);
+             if ((bufp = malloc(length)) == NULL) {
+               fprintf(stderr, "malloc of %d bytes failed\n", length);
+               continue;
+             }
+             curlength = length;
+             memset(bufp, ch, length);
+           }
+
+           rc = dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                               0, offset, length, bufp);
+           cont = 0;
+           if (rc < 0) {
+             fprintf(stderr, "dm_write_invis failed, %s\n", ERR_NAME);
+             cont=1;
+           } else if (rc != length) {
+             fprintf(stderr, "expected to write %lld bytes, actually "
+                     "wrote %lld\n", length, rc);
+             cont=1;
+           }
+           if(cont)
+               continue;
+           
+           /* Timestamp checking, part 1 */
+           if (stat(test_file, &checkbuf)){
+             fprintf(stdout, 
+                     "Error: unable to stat the test file; %s (after write)\n", 
+                     test_file);
+           }
+           else {
+#if 0
+             if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
+             (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
+             (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
+             (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
+             (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
+             (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
+#else
+             if ((statbuf.st_atime == checkbuf.st_atime) &&
+             (statbuf.st_mtime == checkbuf.st_mtime) &&
+             (statbuf.st_ctime == checkbuf.st_ctime))
+#endif
+               {
+               if (Vflag) {
+                 printf("Report: time stamp unchanged by write\n");
+               }
+             }
+             else {
+               printf("Error: time stamp changed by write\n");
+             }
+           }
+           
+           rc = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                               offset, length, bufp);
+           if (rc < 0) {
+             fprintf(stderr, "dm_read_invis failed, %s\n", ERR_NAME);
+             continue;
+           } 
+           else if (rc != length) {
+             fprintf(stderr, "expected to read %lld bytes, actually "
+                     "wrote %lld\n", length, rc);
+             continue;
+           }
+           else {
+             /* Be sure the buffer is filled with the test char */
+             error_reported = 0;
+printf("%s/%d: i=%d\n", __FILE__, __LINE__, i);
+             for (k=0; k<i; k++){
+               if (((char *)bufp)[k] == ch) {
+                 if (Vflag) printf(".");
+               }
+               else {
+                 if(!error_reported){
+                       printf("Error!(line=%d)\n", __LINE__);
+                       error_reported++;
+                 }
+               }
+             }
+             if (Vflag) printf("\n");
+           }
+
+           /* Timestamp checking, part 2 */
+           if (stat(test_file, &statbuf)){
+             fprintf(stdout, 
+                     "Error: unable to stat the test file; %s (after write)\n", 
+                     test_file);
+           }
+           else {
+#if 0
+             if ((statbuf.st_atim.tv_sec == checkbuf.st_atim.tv_sec) &&
+             (statbuf.st_atim.tv_nsec == checkbuf.st_atim.tv_nsec) &&
+             (statbuf.st_mtim.tv_sec == checkbuf.st_mtim.tv_sec) &&
+             (statbuf.st_mtim.tv_nsec == checkbuf.st_mtim.tv_nsec) &&
+             (statbuf.st_ctim.tv_sec == checkbuf.st_ctim.tv_sec) &&
+             (statbuf.st_ctim.tv_nsec == checkbuf.st_ctim.tv_nsec))
+#else
+             if ((statbuf.st_atime == checkbuf.st_atime) &&
+             (statbuf.st_mtime == checkbuf.st_mtime) &&
+             (statbuf.st_ctime == checkbuf.st_ctime))
+#endif
+               {
+               if (Vflag) {
+                 printf("Report: time stamp unchanged by read\n");
+               }
+             }
+             else {
+               printf("Error: time stamp changed by read\n");
+             }
+           }
+         } /* for (j=0; j<OFF_MAX; j+=OFF_STEP) */
+       } /* for(i=0; i<LEN_MAX; i+=LEN_STEP) */
+       
+       /* File deletion loop*/
+       for(i=0; i<LEN_MAX; i+=LEN_STEP) {
+         for(j=0; j<OFF_MAX; j+=OFF_STEP) {
+           sprintf(test_file, "%s/DMAPI_invis_test_file.%02d%02d", 
+                   dir_name, i, j);
+           sprintf(command, "rm %s\n", test_file); 
+           system(command);
+         }
+       }
+       
+       /*************************************\
+       |* Correct-input testing complete.   *|
+       |* Beginning improper-input testing. *|
+       \*************************************/
+       sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
+               dir_name, i);
+       sprintf(command, "cp %s %s\n", ls_path, test_file); 
+       system(command);
+
+       if (dm_path_to_handle(test_file, &hanp, &hlen)) {
+         fprintf(stderr, "can't get handle for %s; bypassing errno tests\n",
+                 test_file);
+       }
+       else {
+
+         /* Try writing a character waaaaaay up in the millions range */
+         sprintf(bufp, "%c", ch);
+         if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
+                            (1000000*(unsigned int)(ch)), 1, bufp)==-1){
+           printf("Error invis-writing %s at byte %d million: %s\n", 
+                  (char*)bufp, (unsigned int)ch, ERR_NAME);
+         }
+         else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                                (1000000*(unsigned int)(ch)), 1, bufp)==-1){
+           printf("Error invis-reading at byte %d million: %s\n", ch,
+                  (unsigned int)ch, ERR_NAME);
+         }
+         else if (((char*)bufp)[0]!=ch) {
+           printf("Error: wanted to read %c and instead got %s.\n",
+                  ch, (char*)bufp);
+         }
+         else if (Vflag) {
+           printf("Report: \"%c\" was written and \"%s\" was read "
+                  "at byte %d million.\n", ch, (char*)bufp, ch);
+         }
+
+#if 0
+         /* Try writing a character in the 2 gigabyte (2^31) range */
+         sprintf(bufp, "%c", ch);
+         if (dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN, 0, 
+                            2147840000, 1, bufp)==-1){
+           printf("Error invis-writing %s at 2 gigabytes: %s\n", 
+                  (char*)bufp, (unsigned int)ch, ERR_NAME);
+         }
+         else if (dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                                2147840000, 1, bufp)==-1){
+           printf("Error invis-reading at 2 gigabytes: %s\n", ch,
+                  (unsigned int)ch, ERR_NAME);
+         }
+         else if (((char*)bufp)[0]!=ch) {
+           printf("Error: wanted to read %c and instead got %s.\n",
+                  ch, (char*)bufp);
+         }
+         else if (Vflag) {
+           printf("Report: \"%c\" was written and \"%s\" was read "
+                  "at 2147840000 bytes\n\t(a bit over 2 gigabytes).\n", 
+                  ch, (char*)bufp);
+         }
+#endif
+
+         printf("\t(errno subtests beginning...)\n");
+         /**** WRITE tests ****/
+         /*---------------------------------------------------------*/
+         EXCLTEST("write", hanp, hlen, test_token, 
+                  dm_write_invis(sid, hanp, hlen, test_token,
+                                 0, 0, 13, "write test 1"))
+         /*---------------------------------------------------------*/
+            if ((test_vp = handle_clone(hanp, hlen)) == NULL) {
+           fprintf(stderr, 
+                   "Cannot create a test handle (%s); skipping EBADF test\n",
+                   ERR_NAME);
+         }
+         else {
+           ((char *) test_vp)[hlen/2]++;
+           ERRTEST(EBADF,
+                   "write",
+                   dm_write_invis(sid, test_vp, hlen, DM_NO_TOKEN,
+                                  0, 0, 0, bufp))
+           ERRTEST(EBADF,
+                   "read",
+                   dm_read_invis(sid, test_vp, hlen, DM_NO_TOKEN,
+                                 0, 0, bufp))
+           dm_handle_free(test_vp, hlen);
+         }
+
+         /*---------------------------------------------------------*/
+         ERRTEST(EBADF,
+                 "write",
+                 dm_write_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
+                                0, 0, 0, NULL))
+         /*---------------------------------------------------------*/
+         ERRTEST(EFAULT,
+                 "write",
+                 dm_write_invis(sid, NULL, hlen, DM_NO_TOKEN,
+                                0, 0, 0, NULL))
+         /*---------------------------------------------------------*/
+         /* PROBLEM: write_invis refuses to produce EINVAL for 
+         /* lengths that will not fit in a dm_size_t.
+         ERRTEST(EINVAL,
+                 "(bad length) write",
+                 dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                                0, 4096, (long long)0xFFFFFFFFFFFFFFFFLL,
+                                "write invalid length test"))
+         /*---------------------------------------------------------*/
+         /* PROBLEM (somewhat fixed): A signal is sent, rather than EFBIG.
+         /* Presumably, this signal is needed to comply with...something.
+         /* If this is uncommented, the program will abort here, with the 
+         /* error message "exceeded file size limit". 
+         ERRTEST(EFBIG,
+                 "write",
+                 dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                                0, (long long)0xFFFFFFFFFFLL, 
+                                (long long)0xFFFFFFFFFFLL,
+                                "foo foo foo"))
+         /*---------------------------------------------------------*/
+#if 0
+         ERRTEST(EINVAL,
+                 "(bad offset) write",
+                 dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
+#ifdef VERITAS_21
+                                0, (dm_size_t) ULONG_MAX, 5,
+#else
+                                0, (dm_size_t) ULONGLONG_MAX, 5,
+#endif
+                                "write invalid offset test"))
+#else
+         ERRTEST(EINVAL,
+                 "(bad offset) write",
+                 dm_write_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                                0, (dm_size_t) ULONG_MAX, 5,
+                                "write invalid offset test"))
+#endif
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "(bad sid) write",
+                 dm_write_invis(-100, hanp, hlen, DM_NO_TOKEN,
+                                0, 0, 26, "write invalid offset test"))
+
+
+         /**** READ tests ****/
+         /*---------------------------------------------------------*/
+         SHAREDTEST("read", hanp, hlen, test_token,
+                    dm_read_invis(sid, hanp, hlen, test_token, 
+                                  0, 13, bufp))
+         /*---------------------------------------------------------*/
+         ERRTEST(EBADF,
+                 "read",
+                 dm_read_invis(sid, hanp, hlen-1, DM_NO_TOKEN,
+                                0, 0, bufp))
+         /*---------------------------------------------------------*/
+         ERRTEST(EFAULT,
+                 "read",
+                 dm_read_invis(sid, NULL, hlen, DM_NO_TOKEN,
+                                0, 0, bufp))
+         /*---------------------------------------------------------*/
+#if 0
+         ERRTEST(EINVAL,
+                 "(bad offset) read",
+                 dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
+#ifdef VERITAS_21
+                               ULONG_MAX, 5, bufp))
+#else
+                               ULONGLONG_MAX, 5, bufp))
+#endif
+#else
+         ERRTEST(EINVAL,
+                 "(bad offset) read",
+                 dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN,
+                               ULONG_MAX, 5, bufp))
+#endif
+         /*---------------------------------------------------------*/
+         ERRTEST(EINVAL,
+                 "(bad sid) read",
+                 dm_read_invis(-100, hanp, hlen, DM_NO_TOKEN,
+                               0, 5, bufp))
+         /*---------------------------------------------------------*/
+         printf("\t(errno subtests complete!)\n");
+       }
+       sprintf(test_file, "%s/DMAPI_invis_test_file.ERRNO", 
+               dir_name, i);
+       sprintf(command, "rm %s \n", test_file); 
+       system(command);
+
+       printf("Invisible read/write tests complete.\n");
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite2/src/test_region.c b/dmapi/src/suite2/src/test_region.c
new file mode 100644 (file)
index 0000000..e4f76ee
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/types.h>
+
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+
+Automated test of the DMAPI functions dm_set_region() and dm_get_region().
+
+The command line is:
+
+        test_region [-s sid] ls_path directory 
+
+where 
+   pathname
+      is the name of a file
+   ls_path
+      is the path to a specific copy of ls, important only for its size
+   sid
+      is the session ID whose events you you are interested in.
+----------------------------------------------------------------------------*/
+
+#define NELEM   1
+
+#ifndef linux
+extern char    *sys_errlist[];
+#endif
+extern  int     optind;
+extern  char    *optarg;
+
+
+char   *Progname;
+
+static struct  {
+       char    *name;
+       int     value;
+} rg_events[3] = {
+       { "DM_REGION_READ", DM_REGION_READ },
+       { "DM_REGION_WRITE", DM_REGION_WRITE },
+       { "DM_REGION_TRUNCATE", DM_REGION_TRUNCATE }
+};
+
+u_int reg_flags[8] = {DM_REGION_NOEVENT,
+                     DM_REGION_READ,
+                     DM_REGION_WRITE,
+                     DM_REGION_TRUNCATE,
+                     DM_REGION_READ | DM_REGION_WRITE,
+                     DM_REGION_READ | DM_REGION_TRUNCATE,
+                     DM_REGION_WRITE | DM_REGION_TRUNCATE,
+                     DM_REGION_READ | DM_REGION_WRITE | DM_REGION_TRUNCATE};
+
+
+static int     nevents = sizeof(rg_events)/sizeof(rg_events[0]);
+
+
+static void
+usage(void)
+{
+       int     i;
+
+       fprintf(stderr, "usage:\t%s [-s sid] ls_path pathname\n", Progname);
+       exit(1);
+}
+
+
+int
+main(
+       int     argc, 
+       char    **argv)
+{
+       dm_region_t     region = { 0, 0, 0 };
+       dm_region_t     checkregion = { 0, 0, 0 };
+       dm_sessid_t     sid = DM_NO_SESSION;
+       char            *dir_name = NULL;
+       char            *ls_path = NULL;
+       char            object[128];
+       char            command[128];
+       u_int           exactflag;
+       u_int           nelem_read = 0;
+       void            *hanp;
+       size_t           hlen;
+       char            *name;
+       int             opt;
+       int             i;
+       int             Vflag = 0;
+       dm_token_t      test_token = DM_NO_TOKEN;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       /* Crack and validate the command line options. */
+
+       while ((opt = getopt(argc, argv, "vo:l:s:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                       Vflag++;
+                       break;
+               case 'o':
+                       region.rg_offset = atol(optarg);
+                       break;
+               case 'l':
+                       region.rg_size = atol(optarg);
+                       break;
+               case 's':
+                       sid = atol(optarg);
+                       break;
+               case '?':
+                       usage();
+               }
+       }
+       if (optind + 2 > argc)
+               usage();
+       ls_path = argv[optind];
+       dir_name = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+
+       /***********************************************\
+       |* Beginning the testing of set/get_region...  *|
+       \***********************************************/
+
+       printf("Region test beginning...\n");
+       sprintf(object, "%s/VeryLongUnlikelyFilename.REGIONTEST", dir_name);
+       sprintf(command, "cp %s %s \n", ls_path, object); 
+       system(command);
+       
+       /* Get the test file's handle. */
+       if (dm_path_to_handle(object, &hanp, &hlen)) {
+               fprintf(stderr, "can't get handle for file %s\n", object);
+               exit(1);
+       }
+       /* Loop over all possible region flag combinations, 
+        * setting and getting. See what works!  
+        */
+       for (i = 0; i < 8; i++) {
+               region.rg_flags = reg_flags[i];
+               if (dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, NELEM, 
+                                 &region, &exactflag)) {
+                 fprintf(stderr, "dm_set_region failed, %s\n",
+                         ERR_NAME);
+                 continue;
+               }
+               if (exactflag != DM_TRUE){
+                 fprintf(stdout, "oops...exactflag was false!\n");
+               }
+               if (dm_get_region(sid, hanp, hlen, DM_NO_TOKEN, NELEM,
+                                 &checkregion, &nelem_read)) {
+                 fprintf(stderr, "dm_get_region failed, %s\n",
+                         ERR_NAME);
+                 continue;
+               }
+               if (region.rg_flags != checkregion.rg_flags) {
+                 fprintf(stdout, "set region flags %d, but found %d\n", 
+                         region.rg_flags, checkregion.rg_flags);
+               }
+               else if (Vflag) {
+                 fprintf(stdout, "Test #%d okay\n", i);
+               }
+       }
+
+       /*************************************\
+       |* Correct-input testing complete.   *|
+       |* Beginning improper-input testing. *|
+       \*************************************/
+       printf("\t(errno subtests beginning...)\n");
+       region.rg_flags = 7;
+       
+       /**** SET tests ****/
+       /*---------------------------------------------------------*/
+       ERRTEST(E2BIG,
+               "set", 
+               dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, 
+                             2, &region, &exactflag))
+       ERRTEST(E2BIG,
+               "set", 
+               dm_set_region(sid, hanp, hlen, DM_NO_TOKEN, 
+                             -1, &region, &exactflag))
+       /*---------------------------------------------------------*/
+       EXCLTEST("set", hanp, hlen, test_token, 
+                dm_set_region(sid, hanp, hlen, test_token,
+                              NELEM, &region, &exactflag)) 
+       /*---------------------------------------------------------*/
+       ERRTEST(EFAULT,
+               "set",
+               dm_set_region(sid, hanp, hlen, DM_NO_TOKEN,
+                            NELEM, (dm_region_t*)(-1000), &exactflag))
+       ERRTEST(EFAULT,
+               "set",
+               dm_set_region(sid, hanp, hlen, DM_NO_TOKEN,
+                            NELEM, &region, (dm_boolean_t*)(-1000)))
+               /*---------------------------------------------------------*/
+       ERRTEST(EINVAL, 
+               "set (bad session id)",
+               dm_set_region(-100, hanp, hlen, DM_NO_TOKEN, 
+                             NELEM, &region, &exactflag))
+               /*---------------------------------------------------------*/
+       
+       /**** GET tests ****/
+               /*---------------------------------------------------------*/
+         ERRTEST (E2BIG,
+                "get", 
+                dm_get_region(sid, hanp, hlen, DM_NO_TOKEN,
+                              0, &checkregion, &nelem_read))
+       /*---------------------------------------------------------*/
+       ERRTEST(EFAULT,
+               "get (bad handle)",
+               dm_get_region(sid, NULL, hlen, DM_NO_TOKEN,
+                             NELEM, &checkregion, &nelem_read)) 
+       /*---------------------------------------------------------*/
+       ERRTEST(EFAULT,
+               "get (bad regbufp)",
+               dm_get_region(sid, hanp, hlen, DM_NO_TOKEN,
+                             NELEM, (dm_region_t *)(-1000), &nelem_read)) 
+       /*---------------------------------------------------------*/
+       ERRTEST(EFAULT,
+               "get (bad nelemp)",
+               dm_get_region(sid, hanp, hlen, DM_NO_TOKEN,
+                             NELEM, &checkregion, (u_int *)(-1000))) 
+       /*---------------------------------------------------------*/
+       SHAREDTEST("get", hanp, hlen, test_token, 
+                  dm_get_region(sid, hanp, hlen, test_token,
+                                NELEM, &checkregion, &nelem_read))
+       /*---------------------------------------------------------*/
+       ERRTEST(EINVAL, 
+               "get", 
+               dm_get_region(-100, hanp, hlen, DM_NO_TOKEN,
+                             NELEM, &checkregion, &nelem_read))
+       /*---------------------------------------------------------*/
+         printf("\t(errno subtests complete)\n");
+       /**********************************\
+       |* End of improper-input testing. *|
+       \**********************************/
+
+       sprintf(command, "rm %s \n", object); 
+       system(command);
+       printf("Region test complete.\n");
+       
+       /***********************************\
+       |* End of set/get_region testing.  *|
+       \***********************************/
+
+       dm_handle_free(hanp, hlen);
+       exit(0);
+}
diff --git a/dmapi/src/suite2/src/test_rights.c b/dmapi/src/suite2/src/test_rights.c
new file mode 100644 (file)
index 0000000..53be869
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <lib/dmport.h>
+#include <lib/hsm.h>
+#include <lib/errtest.h>
+
+#ifdef linux
+#include <string.h>
+#endif
+
+/*---------------------------------------------------------------------------
+Automated test of access rights, involving many DMAPI functions
+
+The command line is:
+   test_rights [-s sid] [-v] ls_path pathname
+
+where:
+   sid
+      is the session ID whose events you you are interested in.
+   ls_path
+      is the path to a copy of ls, which will be copied as a test file.
+   pathname
+      is the filesystem to use for the test.
+----------------------------------------------------------------------------*/
+
+#define NUM_TOKENS 4
+
+extern int     optind;
+extern int     opterr;
+extern char    *optarg;
+
+char   *Progname;
+int     Vflag=0;
+
+static void
+usage(void)
+{
+       fprintf(stderr, 
+               "Usage: %s [-v] [-s sid] ls_path pathname\n",
+               Progname);
+       exit(1);
+}
+
+
+int
+main(int argc, char **argv) {
+     
+        dm_sessid_t    sid = DM_NO_SESSION;
+       dm_token_t      token[NUM_TOKENS];
+       dm_token_t      test_token;
+       void            *fs_hanp;
+       size_t          fs_hlen;
+       void            *dir_hanp;
+       size_t          dir_hlen;
+       void            *ap;
+       size_t          alen;
+       void            *bp;
+       size_t          blen;
+       void            *cp;
+       size_t          clen;
+       char            *name;
+       char            *ls_path;
+       char            *pathname;
+       char            fname_a[100];
+       char            fname_b[100];
+       char            fname_c[100];
+       char            command[150];
+       int             opt;
+       int             i=0;
+       int             error_count=0;
+
+       if (Progname = strrchr(argv[0], '/')) {
+               Progname++;
+       } else {
+               Progname = argv[0];
+       }
+
+       opterr = 0;
+       while ((opt = getopt(argc, argv, "vn:s:")) != EOF) {
+               switch (opt) {
+               case 'v':
+                        Vflag++;
+                        break;
+               case 's': 
+                        sid = atol(optarg);
+                        break;
+               case '?':
+                        usage();
+               }
+       }
+       if (optind + 2 != argc) {
+               usage();
+       }
+       ls_path = argv[optind];
+       pathname = argv[optind+1];
+
+       if (dm_init_service(&name) == -1)  {
+               fprintf(stderr, "Can't inititalize the DMAPI\n");
+               exit(1);
+       }
+       if (sid == DM_NO_SESSION)
+               find_test_session(&sid);
+       
+       printf("Beginning access rights testing...\n");
+
+       sprintf(fname_a, "%s/DMAPI_rights_test_file_a", pathname);
+       sprintf(command, "cp %s %s\n", ls_path, fname_a); 
+       system(command);
+
+       if (dm_path_to_handle(fname_a, &ap, &alen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 fname_a, ERR_NAME);
+         goto abort_test;
+       }
+
+       sprintf(fname_b, "%s/DMAPI_rights_test_file_b", pathname);
+       sprintf(command, "cp %s %s\n", ls_path, fname_b); 
+       system(command);
+       
+       if (dm_path_to_handle(fname_b, &bp, &blen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 fname_b, ERR_NAME);
+         goto abort_test;
+       }
+
+       sprintf(fname_c, "%s/DMAPI_rights_test_file_c", pathname);
+       sprintf(command, "cp %s %s\n", ls_path, fname_c); 
+       system(command);
+       
+       if (dm_path_to_handle(fname_c, &cp, &clen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 fname_c, ERR_NAME);
+         goto abort_test;
+       }
+
+       if (dm_path_to_fshandle(pathname, &fs_hanp, &fs_hlen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 pathname, ERR_NAME);
+         goto abort_test;
+       }
+
+       sprintf(pathname, "%s/DMAPI_rights_test_dir", pathname); 
+       sprintf(command, "mkdir %s\n", pathname); 
+       system(command);
+
+       if (dm_path_to_handle(pathname, &dir_hanp, &dir_hlen)) {
+         fprintf(stderr, "ERROR: can't get handle for %s; %s\n",
+                 pathname, ERR_NAME);
+         goto abort_test;
+       }
+
+       /* Test remaining functions for appropriate 
+        * right requirements...
+        *------------------------------------------------------------*/
+       { 
+         dm_off_t off = (dm_off_t)0;
+         dm_extent_t extent;
+         u_int nelem_ret;
+         SHAREDTEST("get_allocinfo", ap, alen, test_token,
+                  dm_get_allocinfo(sid, ap, alen, test_token, 
+                                   &off, 1, &extent, &nelem_ret))
+       }
+       /*------------------------------------------------------------*/
+       { 
+         void *bufp=(void*)malloc(5*sizeof(dm_attrlist_t));
+         size_t rlen;
+         SHAREDTEST("getall_dmattr", ap, alen, test_token,
+                  dm_getall_dmattr(sid, ap, alen, test_token, 
+                                   5, bufp, &rlen))
+       }
+       /*------------------------------------------------------------*/
+       { 
+         dm_attrloc_t loc;
+         SHAREDTEST("init_attrloc", dir_hanp, dir_hlen, test_token,
+                    dm_init_attrloc(sid, dir_hanp, dir_hlen, test_token,
+                                    &loc))
+       }
+       /*------------------------------------------------------------*/
+       /* mkdir_by_handle is NOT SUPPORTED in current SGI DMAPI 
+       { 
+         SHAREDTEST("mkdir_by_handle", fs_hanp, fs_hlen, test_token,
+                    dm_mkdir_by_handle(sid, fs_hanp, fs_hlen, test_token,
+                                       dir_hanp, dir_hlen, "FUBAR_DIR"))
+       }
+       /*------------------------------------------------------------*/
+       { dm_eventset_t eventset;
+         DMEV_ZERO(eventset);
+         EXCLTEST("set_disp", fs_hanp, fs_hlen, test_token,
+                  dm_set_disp(sid, fs_hanp, fs_hlen, test_token,
+                              &eventset, DM_EVENT_MAX))
+       }
+       /*------------------------------------------------------------*/
+       { dm_attrname_t attrname={"TEST"};
+         EXCLTEST("set_return...", fs_hanp, fs_hlen, test_token,
+                  dm_set_return_on_destroy(sid, fs_hanp, fs_hlen, test_token,
+                              &attrname, DM_TRUE))
+       }
+       /*------------------------------------------------------------*/
+
+       /* Create the tokens */
+       for (i=1; i<NUM_TOKENS; i++){
+         if (dm_create_userevent(sid, 0, 0, &token[i])==-1) {
+           fprintf(stderr, "Couldn't create token %d.\n", i);
+           goto abort_test;
+         }
+       }
+
+       ERRTEST(EINVAL,
+               "rights-on-NO_TOKEN",
+               dm_request_right(sid, ap, alen, DM_NO_TOKEN,
+                                0, DM_RIGHT_SHARED))
+       ERRTEST(EINVAL,
+               "rights-on-NO_TOKEN",
+               dm_request_right(sid, ap, alen, DM_NO_TOKEN,
+                                0, DM_RIGHT_EXCL))
+
+       if (dm_request_right(sid, ap, alen, token[1], 0, DM_RIGHT_SHARED))
+         printf("ERROR: Request for SHARED failed on handle a, token 1");
+       if (dm_request_right(sid, ap, alen, token[2], 0, DM_RIGHT_SHARED))
+         printf("ERROR: Request for SHARED failed on handle a, token 2");
+       
+       /* ---  These WOULD be correct tests, 
+           ---  if rights were fully implemented.
+
+       ERRTEST(EAGAIN, "EXCL request",
+               dm_request_right(sid, ap, alen, token[1], 0, DM_RIGHT_EXCL))
+       ERRTEST(EAGAIN, "EXCL request",
+               dm_request_right(sid, ap, alen, token[2], 0, DM_RIGHT_EXCL))
+       ERRTEST(EAGAIN, "upgrade",
+               dm_upgrade_right(sid, ap, alen, token[1]))
+       */
+       
+abort_test:    
+       
+       for (i=1; i<NUM_TOKENS; i++)
+         dm_respond_event(sid, token[i], DM_RESP_CONTINUE, 0, 0, 0); 
+
+       sprintf(command, "rm %s\n", fname_a); 
+       system(command);
+
+       sprintf(command, "rm %s\n", fname_b); 
+       system(command);
+       
+       sprintf(command, "rm %s\n", fname_c); 
+       system(command);
+
+       sprintf(command, "rmdir %s\n", pathname); 
+       system(command);
+
+       dm_handle_free(ap, alen);
+       dm_handle_free(bp, blen);
+       dm_handle_free(cp, clen);
+
+       printf("Access rights testing complete.\n");
+
+}
+
+
+
+
+
+
+