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>
33 #define S_IAMB (S_IRWXU|S_IRWXG|S_IRWXO)
36 #define S_MASK (S_ISUID|S_ISGID|S_ISVTX|S_IAMB)
38 extern char *Progname;
41 void err_msg(char *, ...);
42 void errno_msg(char *, ...);
44 struct ev_name_to_value ev_names[] = {
45 { "DM_EVENT_CANCEL", DM_EVENT_CANCEL },
46 { "DM_EVENT_MOUNT", DM_EVENT_MOUNT },
47 { "DM_EVENT_PREUNMOUNT", DM_EVENT_PREUNMOUNT },
48 { "DM_EVENT_UNMOUNT", DM_EVENT_UNMOUNT },
49 { "DM_EVENT_DEBUT", DM_EVENT_DEBUT },
50 { "DM_EVENT_CREATE", DM_EVENT_CREATE },
51 { "DM_EVENT_CLOSE", DM_EVENT_CLOSE },
52 { "DM_EVENT_POSTCREATE", DM_EVENT_POSTCREATE },
53 { "DM_EVENT_REMOVE", DM_EVENT_REMOVE },
54 { "DM_EVENT_POSTREMOVE", DM_EVENT_POSTREMOVE },
55 { "DM_EVENT_RENAME", DM_EVENT_RENAME },
56 { "DM_EVENT_POSTRENAME", DM_EVENT_POSTRENAME },
57 { "DM_EVENT_LINK", DM_EVENT_LINK },
58 { "DM_EVENT_POSTLINK", DM_EVENT_POSTLINK },
59 { "DM_EVENT_SYMLINK", DM_EVENT_SYMLINK },
60 { "DM_EVENT_POSTSYMLINK", DM_EVENT_POSTSYMLINK },
61 { "DM_EVENT_READ", DM_EVENT_READ },
62 { "DM_EVENT_WRITE", DM_EVENT_WRITE },
63 { "DM_EVENT_TRUNCATE", DM_EVENT_TRUNCATE },
64 { "DM_EVENT_ATTRIBUTE", DM_EVENT_ATTRIBUTE },
65 { "DM_EVENT_DESTROY", DM_EVENT_DESTROY },
66 { "DM_EVENT_NOSPACE", DM_EVENT_NOSPACE },
67 { "DM_EVENT_USER", DM_EVENT_USER }
70 int ev_namecnt = sizeof(ev_names) / sizeof(ev_names[0]);
78 for (i = 0; i < ev_namecnt; i++) {
79 if (!strcmp(name, ev_names[i].name))
80 return(ev_names[i].value);
82 return(DM_EVENT_INVALID);
89 static char buffer[100];
92 for (i = 0; i < ev_namecnt; i++) {
93 if (event == ev_names[i].value)
94 return(ev_names[i].name);
96 sprintf(buffer, "Unknown Event Number %d\n", event);
102 struct rt_name_to_value rt_names[] = {
103 { "DM_RIGHT_NULL", DM_RIGHT_NULL },
104 { "DM_RIGHT_SHARED", DM_RIGHT_SHARED },
105 { "DM_RIGHT_EXCL", DM_RIGHT_EXCL }
108 int rt_namecnt = sizeof(rt_names) / sizeof(rt_names[0]);
117 for (i = 0; i < rt_namecnt; i++) {
118 if (!strcmp(name, rt_names[i].name)) {
119 *rightp = rt_names[i].value;
133 for (i = 0; i < rt_namecnt; i++) {
134 if (right == rt_names[i].value)
135 return(rt_names[i].name);
142 * Convert a handle from (possibly) binary to ascii.
154 for (i=0;i<hlen; i++) {
155 sprintf(handle_str, "%.2x", *cp++);
158 *handle_str = '\0'; /* Null-terminate to make it printable */
162 * Convert a handle from ascii back to it's native binary representation
171 u_char handle[HANDLE_LEN];
176 if (strlen(handle_str) > HANDLE_LEN * 2){
180 while (*handle_str && *(handle_str + 1)) {
181 if (i == HANDLE_LEN){
184 if( ! (isxdigit(*handle_str) && (isxdigit(*(handle_str +1))))) {
187 cur_char[0] = *handle_str;
188 cur_char[1] = *(handle_str + 1);
190 num = strtol(cur_char, (char **)0, 16);
191 handle[i++] = num & 0xff;
198 if ((*hanpp = malloc(*hlenp)) == NULL)
200 memcpy(*hanpp, handle, *hlenp);
211 if (atohan(name, hanpp, hlenp)) {
213 } else if (dm_handle_is_valid(*hanpp, *hlenp) == DM_FALSE) {
214 dm_handle_free(*hanpp, *hlenp);
220 /* Perhaps it is a pathname */
222 if (dm_path_to_handle(name, hanpp, hlenp)) {
234 char handle_str[HANDLE_STR];
236 if (hlen > HANDLE_LEN) {
237 printf("-- invalid hlen length %zd --\n", hlen);
241 printf("print_handle: ");
242 printf("%zd\t", hlen);
243 hantoa(hanp, hlen, handle_str);
244 printf("%s\n ", handle_str);
253 char handle_str[HANDLE_STR];
255 if (hlen > HANDLE_LEN) {
256 printf("-- invalid length --\n");
260 printf("%zd\t", hlen);
261 hantoa(hanp, hlen, handle_str);
262 printf("%s ", handle_str);
263 printf("\t%lld \n", (long long) fsize);
268 * Print out a simple error message, and include the errno
272 errno_msg(char *fmt, ...)
278 fprintf(stderr, "%s: ", Progname);
281 vfprintf(stderr, fmt, ap);
289 * Print out a simple error message
292 err_msg(char *fmt, ...)
296 fprintf(stderr, "%s: ", Progname);
299 vfprintf(stderr, fmt, ap);
306 * Initialize the interface to the DMAPI
309 setup_dmapi(dm_sessid_t *sidp)
313 if (dm_init_service(&cp) == -1) {
314 err_msg("%s/%d: Can't init dmapi\n", __FILE__, __LINE__);
317 if (strcmp(cp, DM_VER_STR_CONTENTS)) {
318 err_msg("%s/%d: Compiled for a different version\n", __FILE__, __LINE__);
322 find_test_session(sidp);
327 * Get the file's change indicator
341 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_CFLAG, &statbuf);
343 errno_msg("%s/%d: Can't stat file (%d)", __FILE__, __LINE__, errno);
346 *change_start = statbuf.dt_change;
352 * Write a file's data to the staging file. We write the file out
366 dm_ssize_t nread, lastbuf;
370 nbufs = fsize / CHUNKSIZE;
373 filebuf = malloc(CHUNKSIZE);
374 if (filebuf == NULL) {
375 err_msg("%s/%d: Can't alloc memory for file buffer\n", __FILE__, __LINE__);
379 for (i = 0; i<nbufs; i++) {
380 nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
381 (dm_ssize_t)CHUNKSIZE, filebuf);
382 if (nread != CHUNKSIZE) {
384 errno_msg("%s/%d: invis read err: got %lld, expected %lld, buf %d",
386 errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
389 nread, (dm_ssize_t)CHUNKSIZE, i);
395 nwrite = write(stg_fd, filebuf, CHUNKSIZE);
396 if (nwrite != CHUNKSIZE) {
397 errno_msg("%s/%d: write err %d, expected %d, buf %d",
399 nwrite, CHUNKSIZE, i);
405 lastbuf = fsize % CHUNKSIZE;
406 nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
407 (dm_ssize_t)lastbuf, filebuf);
408 if (nread != lastbuf) {
410 errno_msg("%s/%d: invis read error- got %lld, expected %lld, last buf",
412 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
420 nwrite = write(stg_fd, filebuf, (int)lastbuf);
421 if (nwrite != lastbuf) {
423 errno_msg("%s/%d: write error %d, expected %lld, last buffer",
425 errno_msg("%s/%d: write error %d, expected %d, last buffer",
442 * Read a file's data from the staging file.
443 * Since we only have the staging file handle (not a file descriptor)
444 * we use dm_read_invis() to read the data.
446 * We stage the entire file in, regardless of how much was asked for,
447 * starting at the faulting offset.
462 dm_ssize_t nread, nwrite, lastbuf;
464 dm_stat_t dm_statbuf;
466 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_STAT,
469 errno_msg("%s/%d: Can't get dm stats of file (%d)", __FILE__, __LINE__, errno);
473 fsize = dm_statbuf.dt_size;
474 nbufs = fsize / CHUNKSIZE;
477 filebuf = malloc(CHUNKSIZE);
478 if (filebuf == NULL) {
479 err_msg("%s/%d: Can't alloc memory for file buffer\n", __FILE__, __LINE__);
483 for (i = 0; i<nbufs; i++) {
484 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN,
485 off, (dm_ssize_t)CHUNKSIZE, filebuf);
486 if (nread != CHUNKSIZE) {
487 errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
489 nread, CHUNKSIZE, i);
494 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, nread,
496 if (nwrite != nread) {
497 errno_msg("%s/%d: write error -got %d, expected %d, buf %d",
506 lastbuf = fsize % CHUNKSIZE;
507 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN, off,
508 (dm_ssize_t)lastbuf, filebuf);
509 if (nread != lastbuf) {
510 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
517 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, lastbuf, filebuf);
518 if (nwrite != lastbuf) {
519 errno_msg("%s/%d: write error - got %d, expected %d, last buffer",
535 switch (mode & S_IFMT) {
573 /* Get the stat block for the file. */
575 if (lstat(pathname, &statb)) {
576 perror("stat failed");
580 /* Compare its fields against the dm_stat_t structure. */
582 if (dmstat->dt_dev != statb.st_dev) {
584 fprintf(stdout, "ERROR:dmstat->dt_dev 0x%llx, "
585 "statb.st_dev 0x%llx\n",
586 (unsigned long long) dmstat->dt_dev,
587 (unsigned long long) statb.st_dev);
591 if (dmstat->dt_ino != statb.st_ino) {
593 fprintf(stdout, "ERROR:dmstat->dt_ino %llx, "
594 "statb.st_ino %llx\n",
595 (unsigned long long) dmstat->dt_ino,
596 (unsigned long long) statb.st_ino);
600 if ((dmstat->dt_mode & S_IFMT) != field_to_mode(statb.st_mode)) {
602 fprintf(stdout, "ERROR:dmstat->dt_mode (mode) %s, "
603 "statb.st_mode (mode) %s\n",
604 mode_to_string(dmstat->dt_mode),
605 mode_to_string(field_to_mode(statb.st_mode)));
609 if ((dmstat->dt_mode & S_MASK) != (statb.st_mode & S_MASK)) {
611 fprintf(stdout, "ERROR:dmstat->dt_mode (perm) 0%o, "
612 "statb.st_mode (perm) 0%o\n",
613 dmstat->dt_mode & S_MASK,
614 statb.st_mode & S_MASK);
618 if (dmstat->dt_nlink != statb.st_nlink) {
620 fprintf(stdout, "ERROR:dmstat->dt_nlink %u, "
621 "statb.st_nlink %u\n",
622 (unsigned int) dmstat->dt_nlink,
623 (unsigned int) statb.st_nlink);
627 if (dmstat->dt_uid != statb.st_uid) {
629 fprintf(stdout, "ERROR:dmstat->dt_uid %d, "
630 "statb.st_uid %d\n", dmstat->dt_uid,
635 if (dmstat->dt_gid != statb.st_gid) {
637 fprintf(stdout, "ERROR:dmstat->dt_gid %d, "
638 "statb.st_gid %d\n", dmstat->dt_gid,
643 if (dmstat->dt_rdev != statb.st_rdev) {
645 fprintf(stdout, "ERROR:dmstat->dt_rdev 0x%llx, "
646 "statb.st_rdev 0x%llx\n",
647 (unsigned long long) dmstat->dt_rdev,
648 (unsigned long long) statb.st_rdev);
652 if (dmstat->dt_size != statb.st_size) {
654 fprintf(stdout, "ERROR:dmstat->dt_size %lld, "
655 "statb.st_size %lld\n",
656 (long long) dmstat->dt_size,
657 (long long) statb.st_size);
661 if (dmstat->dt_atime != statb.st_atime) {
663 fprintf(stdout, "ERROR:dmstat->dt_atime %ld, "
664 "statb.st_atime %ld\n", dmstat->dt_atime,
669 if (dmstat->dt_mtime != statb.st_mtime) {
671 fprintf(stdout, "ERROR:dmstat->dt_mtime %ld, "
672 "statb.st_mtime %ld\n", dmstat->dt_mtime,
677 if (dmstat->dt_ctime != statb.st_ctime) {
679 fprintf(stdout, "ERROR:dmstat->dt_ctime %ld, "
680 "statb.st_ctime %ld\n", dmstat->dt_ctime,
685 if (dmstat->dt_dtime != statb.st_ctime) {
687 fprintf(stdout, "ERROR:dmstat->dt_dtime %ld, "
688 "statb.st_ctime %ld\n", dmstat->dt_dtime,
693 if (dmstat->dt_blksize != statb.st_blksize) {
695 fprintf(stdout, "ERROR:dmstat->dt_blksize %d, "
696 "statb.st_blksize %ld\n", dmstat->dt_blksize,
701 if (dmstat->dt_blocks != statb.st_blocks) {
703 fprintf(stdout, "ERROR:dmstat->dt_blocks %lld, "
704 "statb.st_blocks %lld\n",
705 (long long) dmstat->dt_blocks,
706 (long long) statb.st_blocks);
711 if (errors && report_errors)
712 fprintf(stdout, "There were %d differences\n", errors);
721 static char buffer[21];
724 if (timeval == (time_t)0) {
727 tmstr = asctime(localtime(&timeval));
729 strncpy(buffer, tmstr, 20);
740 static char buffer[256];
742 switch (mode & S_IFMT) {
766 sprintf(buffer, "Invalid mode 0%o", mode & S_IFMT);
776 static char buffer[256];
781 for (i = 0; i < 32; i++) {
782 if (!DMEV_ISSET(i, emask))
786 case DM_EVENT_CREATE:
787 name = "DM_EVENT_CREATE";
789 case DM_EVENT_POSTCREATE:
790 name = "DM_EVENT_POSTCREATE";
792 case DM_EVENT_REMOVE:
793 name = "DM_EVENT_REMOVE";
795 case DM_EVENT_POSTREMOVE:
796 name = "DM_EVENT_POSTREMOVE";
798 case DM_EVENT_RENAME:
799 name = "DM_EVENT_RENAME";
801 case DM_EVENT_POSTRENAME:
802 name = "DM_EVENT_POSTRENAME";
805 name = "DM_EVENT_LINK";
807 case DM_EVENT_POSTLINK:
808 name = "DM_EVENT_POSTLINK";
810 case DM_EVENT_SYMLINK:
811 name = "DM_EVENT_SYMLINK";
813 case DM_EVENT_POSTSYMLINK:
814 name = "DM_EVENT_POSTSYMLINK";
817 name = "DM_EVENT_READ";
820 name = "DM_EVENT_WRITE";
822 case DM_EVENT_TRUNCATE:
823 name = "DM_EVENT_TRUNCATE";
825 case DM_EVENT_ATTRIBUTE:
826 name = "DM_EVENT_ATTRIBUTE";
828 case DM_EVENT_DESTROY:
829 name = "DM_EVENT_DESTROY";
832 fprintf(stderr, "Unknown event type %d\n", i);
835 sprintf(buffer + len, "%c%s", (len ? '|' : '('), name);
836 len = strlen(buffer);
840 sprintf(buffer, "(none)");
842 sprintf(buffer + len, ")");
848 #if defined(__sgi) || defined(linux)
854 static char buffer[256];
857 if (xflags & ~(DM_XFLAG_REALTIME|DM_XFLAG_PREALLOC|DM_XFLAG_HASATTR)) {
858 sprintf(buffer, "Invalid xflags 0%o", xflags);
862 if (xflags & DM_XFLAG_REALTIME) {
863 sprintf(buffer + len, "%cREALTIME", (len ? '|' : '('));
864 len = strlen(buffer);
866 if (xflags & DM_XFLAG_PREALLOC) {
867 sprintf(buffer + len, "%cPREALLOC", (len ? '|' : '('));
868 len = strlen(buffer);
870 if (xflags & DM_XFLAG_HASATTR) {
871 sprintf(buffer + len, "%cHASATTR", (len ? '|' : '('));
872 len = strlen(buffer);
875 sprintf(buffer, "(none)");
877 sprintf(buffer + len, ")");
889 /* Print all the stat block fields. */
891 fprintf(stdout, "dt_dev 0x%llx\n",
892 (unsigned long long) dmstat->dt_dev);
893 fprintf(stdout, "dt_ino %llx\n",
894 (unsigned long long) dmstat->dt_ino);
895 fprintf(stdout, "dt_mode (type) %s\n",
896 mode_to_string(dmstat->dt_mode));
897 fprintf(stdout, "dt_mode (perm) 0%o\n", dmstat->dt_mode & S_MASK);
898 fprintf(stdout, "dt_nlink %d\n", dmstat->dt_nlink);
899 fprintf(stdout, "dt_uid %d\n", dmstat->dt_uid);
900 fprintf(stdout, "dt_gid %d\n", dmstat->dt_gid);
901 fprintf(stdout, "dt_rdev 0x%llx\n",
902 (unsigned long long) dmstat->dt_rdev);
903 fprintf(stdout, "dt_size %lld\n",
904 (unsigned long long) dmstat->dt_size);
906 fprintf(stdout, "dt_atime %s\n",
907 date_to_string(dmstat->dt_atime));
908 fprintf(stdout, "dt_mtime %s\n",
909 date_to_string(dmstat->dt_mtime));
910 fprintf(stdout, "dt_ctime %s\n",
911 date_to_string(dmstat->dt_ctime));
913 fprintf(stdout, "dt_blksize %d\n", dmstat->dt_blksize);
914 fprintf(stdout, "dt_blocks %lld\n", (long long) dmstat->dt_blocks);
916 #if defined(__sgi) || defined(linux)
917 fprintf(stdout, "dt_xfs_igen %d\n", dmstat->dt_xfs_igen);
918 fprintf(stdout, "dt_xfs_xflags %s\n",
919 xflags_to_string(dmstat->dt_xfs_xflags));
920 fprintf(stdout, "dt_xfs_extsize %d\n", dmstat->dt_xfs_extsize);
921 fprintf(stdout, "dt_xfs_extents %d\n", dmstat->dt_xfs_extents);
922 fprintf(stdout, "dt_xfs_aextents %d\n", dmstat->dt_xfs_aextents);
927 /* Print all other fields. */
929 fprintf(stdout, "emask %s\n",
930 emask_to_string(dmstat->dt_emask));
931 fprintf(stdout, "nevents %d\n", dmstat->dt_nevents);
932 fprintf(stdout, "pmanreg %d\n", dmstat->dt_pmanreg);
933 fprintf(stdout, "pers %d\n", dmstat->dt_pers);
934 fprintf(stdout, "dt_dtime %s\n",
935 date_to_string(dmstat->dt_dtime));
936 fprintf(stdout, "change %d\n", dmstat->dt_change);
944 fprintf(stdout, "0x%llx|", (unsigned long long) dmstat->dt_dev);
945 fprintf(stdout, "%llx|", (unsigned long long) dmstat->dt_ino);
946 fprintf(stdout, "%s|", mode_to_string(dmstat->dt_mode));
947 fprintf(stdout, "0%o|", dmstat->dt_mode & S_MASK);
948 fprintf(stdout, "%d|", dmstat->dt_nlink);
949 fprintf(stdout, "%d|", dmstat->dt_uid);
950 fprintf(stdout, "%d|", dmstat->dt_gid);
951 fprintf(stdout, "0x%llx|", (unsigned long long) dmstat->dt_rdev);
952 fprintf(stdout, "%lld|", (long long) dmstat->dt_size);
954 fprintf(stdout, "%s|", date_to_string(dmstat->dt_atime));
955 fprintf(stdout, "%s|", date_to_string(dmstat->dt_mtime));
956 fprintf(stdout, "%s|", date_to_string(dmstat->dt_ctime));
958 fprintf(stdout, "%d|", dmstat->dt_blksize);
959 fprintf(stdout, "%lld|", (long long) dmstat->dt_blocks);
961 fprintf(stdout, "%d|", dmstat->dt_xfs_igen);
962 fprintf(stdout, "%s|", xflags_to_string(dmstat->dt_xfs_xflags));
963 fprintf(stdout, "%d|", dmstat->dt_xfs_extsize);
964 fprintf(stdout, "%d|", dmstat->dt_xfs_extents);
965 fprintf(stdout, "%d|", dmstat->dt_xfs_aextents);
967 /* Print all other fields. */
969 fprintf(stdout, "%s|", emask_to_string(dmstat->dt_emask));
970 fprintf(stdout, "%d|", dmstat->dt_nevents);
971 fprintf(stdout, "%d|", dmstat->dt_pmanreg);
972 fprintf(stdout, "%d|", dmstat->dt_pers);
973 fprintf(stdout, "%s|", date_to_string(dmstat->dt_dtime));
974 fprintf(stdout, "%d", dmstat->dt_change);