--- /dev/null
+/*
+ * 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.
+ *
+ * October 1, 2003: Dean Roehrich
+ * - Adapted to test dm_get_bulkall, from migfind.c.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include <lib/hsm.h>
+
+#include <getopt.h>
+
+
+extern char *optarg;
+extern int optind, optopt, opterr;
+char *Progname;
+
+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_attrname_t*, size_t,
+ int, int);
+void usage(char *);
+
+void
+usage(
+ char *prog)
+{
+ fprintf(stderr, "Usage: %s ", prog);
+ fprintf(stderr, " <-a attrname> [-b bufsz] [-v] [-q]");
+ fprintf(stderr, " filesystem\n");
+}
+
+#define V_PRINT 0x01
+#define V_VERBOSE 0x02
+
+int
+main(
+ int argc,
+ char *argv[])
+{
+
+ int c;
+ int error;
+ char *fsname;
+ dm_sessid_t sid;
+ void *fs_hanp;
+ size_t fs_hlen;
+ dm_attrname_t dmattr;
+ size_t bufsz = 65536;
+ dm_size_t ret;
+ int extras = 0;
+ int verbose = V_PRINT;
+
+ Progname = argv[0];
+ memset(&dmattr, 0, sizeof(dmattr));
+
+ while ((c = getopt(argc, argv, "a:b:evq")) != EOF) {
+ switch (c) {
+ case 'a':
+ if (strlen(optarg) > (DM_ATTR_NAME_SIZE-1)){
+ printf("Arg for -a too long\n");
+ exit(1);
+ }
+ strcpy((char*)dmattr.an_chars, optarg);
+ break;
+ case 'b':
+ bufsz = atoi(optarg);
+ break;
+ case 'e':
+ extras++;
+ break;
+ case 'v':
+ verbose |= V_VERBOSE;
+ break;
+ case 'q':
+ verbose &= ~V_PRINT;
+ break;
+ case '?':
+ default:
+ usage(Progname);
+ exit(1);
+ }
+ }
+ if (optind >= argc) {
+ usage(Progname);
+ exit(1);
+ }
+ if (dmattr.an_chars[0] == '\0') {
+ usage(Progname);
+ 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);
+ }
+
+
+ if( dm_get_config(fs_hanp, fs_hlen, DM_CONFIG_BULKALL, &ret) ||
+ (ret != DM_TRUE)) {
+ printf("Kernel does not have dm_get_bulkall\n");
+ exit(1);
+ }
+
+ /*
+ * Get the attributes of all files in the filesystem
+ */
+ error = scan_fs(sid, fs_hanp, fs_hlen, &dmattr, bufsz, extras, verbose);
+ 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);
+
+}
+
+void
+my_print_victim(
+ void *hanp,
+ size_t hlen,
+ dm_xstat_t *xbuf,
+ dm_stat_t *sbuf,
+ int extras,
+ int verbose)
+{
+ u_int attrlen;
+ char *attrval;
+
+ if (hlen > HANDLE_LEN) {
+ if (verbose & V_PRINT)
+ printf("-- invalid length --\n");
+ }
+ else {
+ char handle_str[HANDLE_STR];
+ if (verbose & V_PRINT) {
+ printf("%d\t", hlen);
+ hantoa(hanp, hlen, handle_str);
+ printf("%s ", handle_str);
+ if (extras) {
+ printf("size=%lld ",
+ (int64_t)sbuf->dt_size);
+ printf("ino=%lld ",
+ (int64_t)sbuf->dt_ino);
+ }
+ }
+
+ attrval = DM_GET_VALUE(xbuf,
+ dx_attrdata, char*);
+ attrlen = DM_GET_LEN(xbuf,
+ dx_attrdata);
+ /* Hmmm, a hole in the dmapi spec.
+ * No way to have a null pointer
+ * for the value. No way to
+ * distinguish between a zero-length
+ * attribute value and not finding
+ * the attribute in the first place.
+ *
+ * Punt. Since I cannot get a null
+ * pointer for the value, let's look
+ * at the length. If it's zero,
+ * we'll say the attribute was
+ * not found.
+ */
+ if (verbose & V_PRINT) {
+ if (attrlen) {
+ printf("%d (%s)\n",
+ attrlen,
+ isalpha(attrval[0]) ? attrval : "");
+ }
+ else {
+ printf("<none>\n");
+ }
+ }
+ }
+}
+
+/*
+ * Get the attributes for all the files in a filesystem in bulk,
+ * including the specified dmattr,
+ * and print out the handles and dmattr values.
+ */
+int
+scan_fs(
+ dm_sessid_t sid,
+ void *fs_hanp,
+ size_t fs_hlen,
+ dm_attrname_t *dmattr,
+ size_t buflen,
+ int extras,
+ int verbose)
+{
+ u_int mask; /* attributes to scan for */
+ dm_xstat_t *dm_xstatbuf, *xbuf; /* attributes buffer */
+ dm_stat_t *sbuf;
+ dm_attrloc_t locp; /* opaque location in fs */
+ size_t rlenp; /* ret length of stat info */
+ void *hanp; /* file handle */
+ size_t hlen; /* file handle */
+ int more; /* loop terminator */
+ int error;
+
+#ifdef VERITAS_21
+ if (buflen > 65536)
+ buflen= 65536;
+#endif
+ dm_xstatbuf = (dm_xstat_t *)calloc(1, buflen);
+ if (dm_xstatbuf == 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_xstatbuf);
+ 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_bulkall(sid, fs_hanp, fs_hlen, DM_NO_TOKEN,
+ mask, dmattr, &locp, buflen,
+ dm_xstatbuf, &rlenp);
+ if (verbose & V_VERBOSE)
+ fprintf(stderr, "BULKALL more=%d, rlen=%d\n", more, rlenp);
+ if (more == -1) {
+ errno_msg("%s/%d: Can't get bulkall 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_xstat_t structure in the returned buffer.
+ */
+ xbuf = dm_xstatbuf;
+ while (xbuf != NULL) {
+ sbuf = &xbuf->dx_statinfo;
+ if (S_ISREG(sbuf->dt_mode)) {
+ hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
+ hlen = DM_GET_LEN(sbuf, dt_handle);
+
+ my_print_victim(hanp, hlen, xbuf, sbuf,
+ extras, verbose);
+ }
+ /* The sbuf has the offset to the next xbuf */
+ xbuf = DM_STEP_TO_NEXT(sbuf, dm_xstat_t *);
+ }
+ } while (more == 1);
+
+ free(dm_xstatbuf);
+ if (more == -1)
+ return(1);
+
+ return(0);
+}
+
--- /dev/null
+/*
+ * 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.
+ *
+ * October 2, 2003: Dean Roehrich
+ * - Adapted to test dm_get_bulkattr + dm_get_dmattr, from migfind.c.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+#include <lib/hsm.h>
+
+#include <getopt.h>
+
+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_attrname_t*,
+ size_t, int);
+void usage(char *);
+
+void
+usage(
+ char *prog)
+{
+ fprintf(stderr, "Usage: %s ", prog);
+ fprintf(stderr, " [-a attrname] [-b bufsz] [-v]");
+ fprintf(stderr, " [-q] filesystem\n");
+}
+
+#define V_PRINT 0x01
+#define V_VERBOSE 0x02
+
+
+int
+main(
+ int argc,
+ char *argv[])
+{
+
+ int c;
+ int error;
+ char *fsname;
+ dm_sessid_t sid;
+ void *fs_hanp;
+ size_t fs_hlen;
+ dm_attrname_t dmattr;
+ size_t bufsz = 65536;
+ dm_attrname_t *dmattrp = NULL;
+ int verbose = V_PRINT;
+
+ Progname = argv[0];
+ memset(&dmattr, 0, sizeof(dmattr));
+
+ while ((c = getopt(argc, argv, "a:b:vq")) != EOF) {
+ switch (c) {
+ case 'a':
+ if (strlen(optarg) > (DM_ATTR_NAME_SIZE-1)){
+ printf("Arg for -a too long\n");
+ exit(1);
+ }
+ strcpy((char*)dmattr.an_chars, optarg);
+ dmattrp = &dmattr;
+ break;
+ case 'b':
+ bufsz = atoi(optarg);
+ break;
+ case 'v':
+ verbose |= V_VERBOSE;
+ break;
+
+ case 'q':
+ verbose &= ~V_PRINT;
+ break;
+
+ case '?':
+ default:
+ usage(Progname);
+ exit(1);
+ }
+ }
+ if (optind >= argc) {
+ usage(Progname);
+ 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, dmattrp, bufsz, verbose);
+ 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);
+
+}
+
+void
+my_print_victim(
+ dm_sessid_t sid,
+ void *hanp,
+ size_t hlen,
+ dm_attrname_t *dm_attrp,
+ int verbose)
+{
+ size_t rlen;
+ size_t buflen = 10000;
+ char buf[buflen];
+
+ if (hlen > HANDLE_LEN) {
+ if (verbose & V_PRINT)
+ printf("-- invalid length --\n");
+ }
+ else {
+ char handle_str[HANDLE_STR];
+ if (verbose & V_PRINT) {
+ printf("%d\t", hlen);
+ hantoa(hanp, hlen, handle_str);
+ printf("%s ", handle_str);
+ }
+
+ if (dm_get_dmattr(sid, hanp, hlen, DM_NO_TOKEN, dm_attrp,
+ buflen, (char*)buf, &rlen)) {
+ if (verbose & V_PRINT) {
+ if( errno == E2BIG ){
+ printf("E2BIG\n");
+ }
+ else if (errno == ENOMEM){
+ printf("ENOMEM\n");
+ }
+ else {
+ printf("<none>\n");
+ }
+ }
+ }
+ else if (verbose & V_PRINT) {
+ if( isalpha(buf[0]) )
+ printf("(%s)\n", buf);
+ else
+ printf("<len=%d>\n",rlen);
+ }
+ }
+}
+
+/*
+ * 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_attrname_t *dmattrp,
+ size_t buflen,
+ int verbose)
+{
+ 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 */
+ void *hanp; /* file handle */
+ size_t hlen; /* file handle */
+ int more; /* loop terminator */
+ int error;
+
+
+#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 (verbose & V_VERBOSE)
+ fprintf(stderr, "BULKATTR more=%d, rlen=%d\n", more, 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)) {
+ hanp = DM_GET_VALUE(sbuf, dt_handle, void *);
+ hlen = DM_GET_LEN(sbuf, dt_handle);
+
+ if (dmattrp) {
+ my_print_victim(sid, hanp, hlen,
+ dmattrp, verbose);
+ }
+ else if (verbose & V_PRINT){
+ 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);
+}
+