4 * This code was written by Peter Lawthers, and placed in the public
5 * domain for use by DMAPI implementors and app writers.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
11 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
12 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
16 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
17 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
21 #include <sys/types.h>
34 #define S_IAMB (S_IRWXU|S_IRWXG|S_IRWXO)
37 #define S_MASK (S_ISUID|S_ISGID|S_ISVTX|S_IAMB)
39 extern char *Progname;
42 void err_msg(char *, ...);
43 void errno_msg(char *, ...);
45 struct ev_name_to_value ev_names[] = {
46 { "DM_EVENT_CANCEL", DM_EVENT_CANCEL },
47 { "DM_EVENT_MOUNT", DM_EVENT_MOUNT },
48 { "DM_EVENT_PREUNMOUNT", DM_EVENT_PREUNMOUNT },
49 { "DM_EVENT_UNMOUNT", DM_EVENT_UNMOUNT },
50 { "DM_EVENT_DEBUT", DM_EVENT_DEBUT },
51 { "DM_EVENT_CREATE", DM_EVENT_CREATE },
52 { "DM_EVENT_CLOSE", DM_EVENT_CLOSE },
53 { "DM_EVENT_POSTCREATE", DM_EVENT_POSTCREATE },
54 { "DM_EVENT_REMOVE", DM_EVENT_REMOVE },
55 { "DM_EVENT_POSTREMOVE", DM_EVENT_POSTREMOVE },
56 { "DM_EVENT_RENAME", DM_EVENT_RENAME },
57 { "DM_EVENT_POSTRENAME", DM_EVENT_POSTRENAME },
58 { "DM_EVENT_LINK", DM_EVENT_LINK },
59 { "DM_EVENT_POSTLINK", DM_EVENT_POSTLINK },
60 { "DM_EVENT_SYMLINK", DM_EVENT_SYMLINK },
61 { "DM_EVENT_POSTSYMLINK", DM_EVENT_POSTSYMLINK },
62 { "DM_EVENT_READ", DM_EVENT_READ },
63 { "DM_EVENT_WRITE", DM_EVENT_WRITE },
64 { "DM_EVENT_TRUNCATE", DM_EVENT_TRUNCATE },
65 { "DM_EVENT_ATTRIBUTE", DM_EVENT_ATTRIBUTE },
66 { "DM_EVENT_DESTROY", DM_EVENT_DESTROY },
67 { "DM_EVENT_NOSPACE", DM_EVENT_NOSPACE },
68 { "DM_EVENT_USER", DM_EVENT_USER }
71 int ev_namecnt = sizeof(ev_names) / sizeof(ev_names[0]);
79 for (i = 0; i < ev_namecnt; i++) {
80 if (!strcmp(name, ev_names[i].name))
81 return(ev_names[i].value);
83 return(DM_EVENT_INVALID);
90 static char buffer[100];
93 for (i = 0; i < ev_namecnt; i++) {
94 if (event == ev_names[i].value)
95 return(ev_names[i].name);
97 sprintf(buffer, "Unknown Event Number %d\n", event);
103 struct rt_name_to_value rt_names[] = {
104 { "DM_RIGHT_NULL", DM_RIGHT_NULL },
105 { "DM_RIGHT_SHARED", DM_RIGHT_SHARED },
106 { "DM_RIGHT_EXCL", DM_RIGHT_EXCL }
109 int rt_namecnt = sizeof(rt_names) / sizeof(rt_names[0]);
118 for (i = 0; i < rt_namecnt; i++) {
119 if (!strcmp(name, rt_names[i].name)) {
120 *rightp = rt_names[i].value;
134 for (i = 0; i < rt_namecnt; i++) {
135 if (right == rt_names[i].value)
136 return(rt_names[i].name);
143 * Convert a handle from (possibly) binary to ascii.
155 for (i=0;i<hlen; i++) {
156 sprintf(handle_str, "%.2x", *cp++);
159 *handle_str = '\0'; /* Null-terminate to make it printable */
163 * Convert a handle from ascii back to it's native binary representation
172 u_char handle[HANDLE_LEN];
177 if (strlen(handle_str) > HANDLE_LEN * 2){
181 while (*handle_str && *(handle_str + 1)) {
182 if (i == HANDLE_LEN){
185 if( ! (isxdigit(*handle_str) && (isxdigit(*(handle_str +1))))) {
188 cur_char[0] = *handle_str;
189 cur_char[1] = *(handle_str + 1);
191 num = strtol(cur_char, (char **)0, 16);
192 handle[i++] = num & 0xff;
199 if ((*hanpp = malloc(*hlenp)) == NULL)
201 memcpy(*hanpp, handle, *hlenp);
212 if (atohan(name, hanpp, hlenp)) {
214 } else if (dm_handle_is_valid(*hanpp, *hlenp) == DM_FALSE) {
215 dm_handle_free(*hanpp, *hlenp);
221 /* Perhaps it is a pathname */
223 if (dm_path_to_handle(name, hanpp, hlenp)) {
235 char handle_str[HANDLE_STR];
237 if (hlen > HANDLE_LEN) {
238 printf("-- invalid hlen length %zd --\n", hlen);
242 printf("print_handle: ");
243 printf("%zd\t", hlen);
244 hantoa(hanp, hlen, handle_str);
245 printf("%s\n ", handle_str);
254 char handle_str[HANDLE_STR];
256 if (hlen > HANDLE_LEN) {
257 printf("-- invalid length --\n");
261 printf("%zd\t", hlen);
262 hantoa(hanp, hlen, handle_str);
263 printf("%s ", handle_str);
264 printf("\t%lld \n", (long long) fsize);
269 * Print out a simple error message, and include the errno
273 errno_msg(char *fmt, ...)
279 fprintf(stderr, "%s: ", Progname);
282 vfprintf(stderr, fmt, ap);
290 * Print out a simple error message
293 err_msg(char *fmt, ...)
297 fprintf(stderr, "%s: ", Progname);
300 vfprintf(stderr, fmt, ap);
307 * Initialize the interface to the DMAPI
310 setup_dmapi(dm_sessid_t *sidp)
314 if (dm_init_service(&cp) == -1) {
315 err_msg("%s/%d: Can't init dmapi\n", __FILE__, __LINE__);
318 if (strcmp(cp, DM_VER_STR_CONTENTS)) {
319 err_msg("%s/%d: Compiled for a different version\n", __FILE__, __LINE__);
323 find_test_session(sidp);
328 * Get the file's change indicator
342 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_CFLAG, &statbuf);
344 errno_msg("%s/%d: Can't stat file (%d)", __FILE__, __LINE__, errno);
347 *change_start = statbuf.dt_change;
353 * Write a file's data to the staging file. We write the file out
367 dm_ssize_t nread, lastbuf;
371 nbufs = fsize / CHUNKSIZE;
374 filebuf = malloc(CHUNKSIZE);
375 if (filebuf == NULL) {
376 err_msg("%s/%d: Can't alloc memory for file buffer\n", __FILE__, __LINE__);
380 for (i = 0; i<nbufs; i++) {
381 nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
382 (dm_ssize_t)CHUNKSIZE, filebuf);
383 if (nread != CHUNKSIZE) {
384 errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
386 nread, (dm_ssize_t)CHUNKSIZE, i);
392 nwrite = write(stg_fd, filebuf, CHUNKSIZE);
393 if (nwrite != CHUNKSIZE) {
394 errno_msg("%s/%d: write err %d, expected %d, buf %d",
396 nwrite, CHUNKSIZE, i);
402 lastbuf = fsize % CHUNKSIZE;
403 nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
404 (dm_ssize_t)lastbuf, filebuf);
405 if (nread != lastbuf) {
406 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
413 nwrite = write(stg_fd, filebuf, (int)lastbuf);
414 if (nwrite != lastbuf) {
415 errno_msg("%s/%d: write error %d, expected %d, last buffer",
431 * Read a file's data from the staging file.
432 * Since we only have the staging file handle (not a file descriptor)
433 * we use dm_read_invis() to read the data.
435 * We stage the entire file in, regardless of how much was asked for,
436 * starting at the faulting offset.
451 dm_ssize_t nread, nwrite, lastbuf;
453 dm_stat_t dm_statbuf;
455 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_STAT,
458 errno_msg("%s/%d: Can't get dm stats of file (%d)", __FILE__, __LINE__, errno);
462 fsize = dm_statbuf.dt_size;
463 nbufs = fsize / CHUNKSIZE;
466 filebuf = malloc(CHUNKSIZE);
467 if (filebuf == NULL) {
468 err_msg("%s/%d: Can't alloc memory for file buffer\n", __FILE__, __LINE__);
472 for (i = 0; i<nbufs; i++) {
473 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN,
474 off, (dm_ssize_t)CHUNKSIZE, filebuf);
475 if (nread != CHUNKSIZE) {
476 errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
478 nread, CHUNKSIZE, i);
483 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, nread,
485 if (nwrite != nread) {
486 errno_msg("%s/%d: write error -got %d, expected %d, buf %d",
495 lastbuf = fsize % CHUNKSIZE;
496 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN, off,
497 (dm_ssize_t)lastbuf, filebuf);
498 if (nread != lastbuf) {
499 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
506 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, lastbuf, filebuf);
507 if (nwrite != lastbuf) {
508 errno_msg("%s/%d: write error - got %d, expected %d, last buffer",
524 switch (mode & S_IFMT) {
562 /* Get the stat block for the file. */
564 if (lstat(pathname, &statb)) {
565 perror("stat failed");
569 /* Compare its fields against the dm_stat_t structure. */
571 if (dmstat->dt_dev != statb.st_dev) {
573 fprintf(stdout, "ERROR:dmstat->dt_dev 0x%llx, "
574 "statb.st_dev 0x%llx\n",
575 (unsigned long long) dmstat->dt_dev,
576 (unsigned long long) statb.st_dev);
580 if (dmstat->dt_ino != statb.st_ino) {
582 fprintf(stdout, "ERROR:dmstat->dt_ino %llx, "
583 "statb.st_ino %llx\n",
584 (unsigned long long) dmstat->dt_ino,
585 (unsigned long long) statb.st_ino);
589 if ((dmstat->dt_mode & S_IFMT) != field_to_mode(statb.st_mode)) {
591 fprintf(stdout, "ERROR:dmstat->dt_mode (mode) %s, "
592 "statb.st_mode (mode) %s\n",
593 mode_to_string(dmstat->dt_mode),
594 mode_to_string(field_to_mode(statb.st_mode)));
598 if ((dmstat->dt_mode & S_MASK) != (statb.st_mode & S_MASK)) {
600 fprintf(stdout, "ERROR:dmstat->dt_mode (perm) 0%o, "
601 "statb.st_mode (perm) 0%o\n",
602 dmstat->dt_mode & S_MASK,
603 statb.st_mode & S_MASK);
607 if (dmstat->dt_nlink != statb.st_nlink) {
609 fprintf(stdout, "ERROR:dmstat->dt_nlink %u, "
610 "statb.st_nlink %u\n",
611 (unsigned int) dmstat->dt_nlink,
612 (unsigned int) statb.st_nlink);
616 if (dmstat->dt_uid != statb.st_uid) {
618 fprintf(stdout, "ERROR:dmstat->dt_uid %d, "
619 "statb.st_uid %d\n", dmstat->dt_uid,
624 if (dmstat->dt_gid != statb.st_gid) {
626 fprintf(stdout, "ERROR:dmstat->dt_gid %d, "
627 "statb.st_gid %d\n", dmstat->dt_gid,
632 if (dmstat->dt_rdev != statb.st_rdev) {
634 fprintf(stdout, "ERROR:dmstat->dt_rdev 0x%llx, "
635 "statb.st_rdev 0x%llx\n",
636 (unsigned long long) dmstat->dt_rdev,
637 (unsigned long long) statb.st_rdev);
641 if (dmstat->dt_size != statb.st_size) {
643 fprintf(stdout, "ERROR:dmstat->dt_size %lld, "
644 "statb.st_size %lld\n",
645 (long long) dmstat->dt_size,
646 (long long) statb.st_size);
650 if (dmstat->dt_atime != statb.st_atime) {
652 fprintf(stdout, "ERROR:dmstat->dt_atime %ld, "
653 "statb.st_atime %ld\n", dmstat->dt_atime,
658 if (dmstat->dt_mtime != statb.st_mtime) {
660 fprintf(stdout, "ERROR:dmstat->dt_mtime %ld, "
661 "statb.st_mtime %ld\n", dmstat->dt_mtime,
666 if (dmstat->dt_ctime != statb.st_ctime) {
668 fprintf(stdout, "ERROR:dmstat->dt_ctime %ld, "
669 "statb.st_ctime %ld\n", dmstat->dt_ctime,
674 if (dmstat->dt_dtime != statb.st_ctime) {
676 fprintf(stdout, "ERROR:dmstat->dt_dtime %ld, "
677 "statb.st_ctime %ld\n", dmstat->dt_dtime,
682 if (dmstat->dt_blksize != statb.st_blksize) {
684 fprintf(stdout, "ERROR:dmstat->dt_blksize %d, "
685 "statb.st_blksize %ld\n", dmstat->dt_blksize,
690 if (dmstat->dt_blocks != statb.st_blocks) {
692 fprintf(stdout, "ERROR:dmstat->dt_blocks %lld, "
693 "statb.st_blocks %lld\n",
694 (long long) dmstat->dt_blocks,
695 (long long) statb.st_blocks);
700 if (errors && report_errors)
701 fprintf(stdout, "There were %d differences\n", errors);
710 static char buffer[21];
713 if (timeval == (time_t)0) {
716 tmstr = asctime(localtime(&timeval));
718 strncpy(buffer, tmstr, 20);
729 static char buffer[256];
731 switch (mode & S_IFMT) {
755 sprintf(buffer, "Invalid mode 0%o", mode & S_IFMT);
765 static char buffer[256];
770 for (i = 0; i < 32; i++) {
771 if (!DMEV_ISSET(i, emask))
775 case DM_EVENT_CREATE:
776 name = "DM_EVENT_CREATE";
778 case DM_EVENT_POSTCREATE:
779 name = "DM_EVENT_POSTCREATE";
781 case DM_EVENT_REMOVE:
782 name = "DM_EVENT_REMOVE";
784 case DM_EVENT_POSTREMOVE:
785 name = "DM_EVENT_POSTREMOVE";
787 case DM_EVENT_RENAME:
788 name = "DM_EVENT_RENAME";
790 case DM_EVENT_POSTRENAME:
791 name = "DM_EVENT_POSTRENAME";
794 name = "DM_EVENT_LINK";
796 case DM_EVENT_POSTLINK:
797 name = "DM_EVENT_POSTLINK";
799 case DM_EVENT_SYMLINK:
800 name = "DM_EVENT_SYMLINK";
802 case DM_EVENT_POSTSYMLINK:
803 name = "DM_EVENT_POSTSYMLINK";
806 name = "DM_EVENT_READ";
809 name = "DM_EVENT_WRITE";
811 case DM_EVENT_TRUNCATE:
812 name = "DM_EVENT_TRUNCATE";
814 case DM_EVENT_ATTRIBUTE:
815 name = "DM_EVENT_ATTRIBUTE";
817 case DM_EVENT_DESTROY:
818 name = "DM_EVENT_DESTROY";
821 fprintf(stderr, "Unknown event type %d\n", i);
824 sprintf(buffer + len, "%c%s", (len ? '|' : '('), name);
825 len = strlen(buffer);
829 sprintf(buffer, "(none)");
831 sprintf(buffer + len, ")");
843 static char buffer[256];
846 if (xflags & ~(DM_XFLAG_REALTIME|DM_XFLAG_PREALLOC|DM_XFLAG_HASATTR)) {
847 sprintf(buffer, "Invalid xflags 0%o", xflags);
851 if (xflags & DM_XFLAG_REALTIME) {
852 sprintf(buffer + len, "%cREALTIME", (len ? '|' : '('));
853 len = strlen(buffer);
855 if (xflags & DM_XFLAG_PREALLOC) {
856 sprintf(buffer + len, "%cPREALLOC", (len ? '|' : '('));
857 len = strlen(buffer);
859 if (xflags & DM_XFLAG_HASATTR) {
860 sprintf(buffer + len, "%cHASATTR", (len ? '|' : '('));
861 len = strlen(buffer);
864 sprintf(buffer, "(none)");
866 sprintf(buffer + len, ")");
878 /* Print all the stat block fields. */
880 fprintf(stdout, "dt_dev 0x%llx\n",
881 (unsigned long long) dmstat->dt_dev);
882 fprintf(stdout, "dt_ino %llx\n",
883 (unsigned long long) dmstat->dt_ino);
884 fprintf(stdout, "dt_mode (type) %s\n",
885 mode_to_string(dmstat->dt_mode));
886 fprintf(stdout, "dt_mode (perm) 0%o\n", dmstat->dt_mode & S_MASK);
887 fprintf(stdout, "dt_nlink %d\n", dmstat->dt_nlink);
888 fprintf(stdout, "dt_uid %d\n", dmstat->dt_uid);
889 fprintf(stdout, "dt_gid %d\n", dmstat->dt_gid);
890 fprintf(stdout, "dt_rdev 0x%llx\n",
891 (unsigned long long) dmstat->dt_rdev);
892 fprintf(stdout, "dt_size %lld\n",
893 (unsigned long long) dmstat->dt_size);
895 fprintf(stdout, "dt_atime %s\n",
896 date_to_string(dmstat->dt_atime));
897 fprintf(stdout, "dt_mtime %s\n",
898 date_to_string(dmstat->dt_mtime));
899 fprintf(stdout, "dt_ctime %s\n",
900 date_to_string(dmstat->dt_ctime));
902 fprintf(stdout, "dt_blksize %d\n", dmstat->dt_blksize);
903 fprintf(stdout, "dt_blocks %lld\n", (long long) dmstat->dt_blocks);
906 fprintf(stdout, "dt_xfs_igen %d\n", dmstat->dt_xfs_igen);
907 fprintf(stdout, "dt_xfs_xflags %s\n",
908 xflags_to_string(dmstat->dt_xfs_xflags));
909 fprintf(stdout, "dt_xfs_extsize %d\n", dmstat->dt_xfs_extsize);
910 fprintf(stdout, "dt_xfs_extents %d\n", dmstat->dt_xfs_extents);
911 fprintf(stdout, "dt_xfs_aextents %d\n", dmstat->dt_xfs_aextents);
916 /* Print all other fields. */
918 fprintf(stdout, "emask %s\n",
919 emask_to_string(dmstat->dt_emask));
920 fprintf(stdout, "nevents %d\n", dmstat->dt_nevents);
921 fprintf(stdout, "pmanreg %d\n", dmstat->dt_pmanreg);
922 fprintf(stdout, "pers %d\n", dmstat->dt_pers);
923 fprintf(stdout, "dt_dtime %s\n",
924 date_to_string(dmstat->dt_dtime));
925 fprintf(stdout, "change %d\n", dmstat->dt_change);
933 fprintf(stdout, "0x%llx|", (unsigned long long) dmstat->dt_dev);
934 fprintf(stdout, "%llx|", (unsigned long long) dmstat->dt_ino);
935 fprintf(stdout, "%s|", mode_to_string(dmstat->dt_mode));
936 fprintf(stdout, "0%o|", dmstat->dt_mode & S_MASK);
937 fprintf(stdout, "%d|", dmstat->dt_nlink);
938 fprintf(stdout, "%d|", dmstat->dt_uid);
939 fprintf(stdout, "%d|", dmstat->dt_gid);
940 fprintf(stdout, "0x%llx|", (unsigned long long) dmstat->dt_rdev);
941 fprintf(stdout, "%lld|", (long long) dmstat->dt_size);
943 fprintf(stdout, "%s|", date_to_string(dmstat->dt_atime));
944 fprintf(stdout, "%s|", date_to_string(dmstat->dt_mtime));
945 fprintf(stdout, "%s|", date_to_string(dmstat->dt_ctime));
947 fprintf(stdout, "%d|", dmstat->dt_blksize);
948 fprintf(stdout, "%lld|", (long long) dmstat->dt_blocks);
950 fprintf(stdout, "%d|", dmstat->dt_xfs_igen);
951 fprintf(stdout, "%s|", xflags_to_string(dmstat->dt_xfs_xflags));
952 fprintf(stdout, "%d|", dmstat->dt_xfs_extsize);
953 fprintf(stdout, "%d|", dmstat->dt_xfs_extents);
954 fprintf(stdout, "%d|", dmstat->dt_xfs_aextents);
956 /* Print all other fields. */
958 fprintf(stdout, "%s|", emask_to_string(dmstat->dt_emask));
959 fprintf(stdout, "%d|", dmstat->dt_nevents);
960 fprintf(stdout, "%d|", dmstat->dt_pmanreg);
961 fprintf(stdout, "%d|", dmstat->dt_pers);
962 fprintf(stdout, "%s|", date_to_string(dmstat->dt_dtime));
963 fprintf(stdout, "%d", dmstat->dt_change);