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 %d --\n", hlen);
241 printf("print_handle: ");
242 printf("%d\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("%d\t", hlen);
261 hantoa(hanp, hlen, handle_str);
262 printf("%s ", handle_str);
263 printf("\t%lld \n", 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 (uint64_t)dmstat->dt_dev,
587 (uint64_t)statb.st_dev);
591 if (dmstat->dt_ino != statb.st_ino) {
593 fprintf(stdout, "ERROR:dmstat->dt_ino %llx, "
594 #if defined(linux) || (defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32))
595 "statb.st_ino %llx\n",
599 dmstat->dt_ino, statb.st_ino);
603 if ((dmstat->dt_mode & S_IFMT) != field_to_mode(statb.st_mode)) {
605 fprintf(stdout, "ERROR:dmstat->dt_mode (mode) %s, "
606 "statb.st_mode (mode) %s\n",
607 mode_to_string(dmstat->dt_mode),
608 mode_to_string(field_to_mode(statb.st_mode)));
612 if ((dmstat->dt_mode & S_MASK) != (statb.st_mode & S_MASK)) {
614 fprintf(stdout, "ERROR:dmstat->dt_mode (perm) 0%o, "
615 "statb.st_mode (perm) 0%o\n",
616 dmstat->dt_mode & S_MASK,
617 statb.st_mode & S_MASK);
621 if (dmstat->dt_nlink != statb.st_nlink) {
623 fprintf(stdout, "ERROR:dmstat->dt_nlink %d, "
624 "statb.st_nlink %d\n", dmstat->dt_nlink,
629 if (dmstat->dt_uid != statb.st_uid) {
631 fprintf(stdout, "ERROR:dmstat->dt_uid %d, "
632 "statb.st_uid %d\n", dmstat->dt_uid,
637 if (dmstat->dt_gid != statb.st_gid) {
639 fprintf(stdout, "ERROR:dmstat->dt_gid %d, "
640 "statb.st_gid %d\n", dmstat->dt_gid,
645 if (dmstat->dt_rdev != statb.st_rdev) {
647 fprintf(stdout, "ERROR:dmstat->dt_rdev 0x%llx, "
648 "statb.st_rdev 0x%llx\n",
649 (uint64_t)dmstat->dt_rdev,
650 (uint64_t)statb.st_rdev);
654 if (dmstat->dt_size != statb.st_size) {
656 fprintf(stdout, "ERROR:dmstat->dt_size %lld, "
657 #if defined(linux) || (defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32))
658 "statb.st_size %lld\n",
660 "statb.st_size %d\n",
662 dmstat->dt_size, statb.st_size);
666 if (dmstat->dt_atime != statb.st_atime) {
668 fprintf(stdout, "ERROR:dmstat->dt_atime %ld, "
669 "statb.st_atime %ld\n", dmstat->dt_atime,
674 if (dmstat->dt_mtime != statb.st_mtime) {
676 fprintf(stdout, "ERROR:dmstat->dt_mtime %ld, "
677 "statb.st_mtime %ld\n", dmstat->dt_mtime,
682 if (dmstat->dt_ctime != statb.st_ctime) {
684 fprintf(stdout, "ERROR:dmstat->dt_ctime %ld, "
685 "statb.st_ctime %ld\n", dmstat->dt_ctime,
690 if (dmstat->dt_dtime != statb.st_ctime) {
692 fprintf(stdout, "ERROR:dmstat->dt_dtime %ld, "
693 "statb.st_ctime %ld\n", dmstat->dt_dtime,
698 if (dmstat->dt_blksize != statb.st_blksize) {
700 fprintf(stdout, "ERROR:dmstat->dt_blksize %d, "
701 "statb.st_blksize %ld\n", dmstat->dt_blksize,
706 if (dmstat->dt_blocks != statb.st_blocks) {
708 fprintf(stdout, "ERROR:dmstat->dt_blocks %lld, "
709 #if defined(linux) || (defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32))
710 "statb.st_blocks %lld\n",
712 "statb.st_blocks %d\n",
714 dmstat->dt_blocks, statb.st_blocks);
719 if (errors && report_errors)
720 fprintf(stdout, "There were %d differences\n", errors);
729 static char buffer[21];
732 if (timeval == (time_t)0) {
735 tmstr = asctime(localtime(&timeval));
737 strncpy(buffer, tmstr, 20);
748 static char buffer[256];
750 switch (mode & S_IFMT) {
774 sprintf(buffer, "Invalid mode 0%o", mode & S_IFMT);
784 static char buffer[256];
789 for (i = 0; i < 32; i++) {
790 if (!DMEV_ISSET(i, emask))
794 case DM_EVENT_CREATE:
795 name = "DM_EVENT_CREATE";
797 case DM_EVENT_POSTCREATE:
798 name = "DM_EVENT_POSTCREATE";
800 case DM_EVENT_REMOVE:
801 name = "DM_EVENT_REMOVE";
803 case DM_EVENT_POSTREMOVE:
804 name = "DM_EVENT_POSTREMOVE";
806 case DM_EVENT_RENAME:
807 name = "DM_EVENT_RENAME";
809 case DM_EVENT_POSTRENAME:
810 name = "DM_EVENT_POSTRENAME";
813 name = "DM_EVENT_LINK";
815 case DM_EVENT_POSTLINK:
816 name = "DM_EVENT_POSTLINK";
818 case DM_EVENT_SYMLINK:
819 name = "DM_EVENT_SYMLINK";
821 case DM_EVENT_POSTSYMLINK:
822 name = "DM_EVENT_POSTSYMLINK";
825 name = "DM_EVENT_READ";
828 name = "DM_EVENT_WRITE";
830 case DM_EVENT_TRUNCATE:
831 name = "DM_EVENT_TRUNCATE";
833 case DM_EVENT_ATTRIBUTE:
834 name = "DM_EVENT_ATTRIBUTE";
836 case DM_EVENT_DESTROY:
837 name = "DM_EVENT_DESTROY";
840 fprintf(stderr, "Unknown event type %d\n", i);
843 sprintf(buffer + len, "%c%s", (len ? '|' : '('), name);
844 len = strlen(buffer);
848 sprintf(buffer, "(none)");
850 sprintf(buffer + len, ")");
856 #if defined(__sgi) || defined(linux)
862 static char buffer[256];
865 if (xflags & ~(DM_XFLAG_REALTIME|DM_XFLAG_PREALLOC|DM_XFLAG_HASATTR)) {
866 sprintf(buffer, "Invalid xflags 0%o", xflags);
870 if (xflags & DM_XFLAG_REALTIME) {
871 sprintf(buffer + len, "%cREALTIME", (len ? '|' : '('));
872 len = strlen(buffer);
874 if (xflags & DM_XFLAG_PREALLOC) {
875 sprintf(buffer + len, "%cPREALLOC", (len ? '|' : '('));
876 len = strlen(buffer);
878 if (xflags & DM_XFLAG_HASATTR) {
879 sprintf(buffer + len, "%cHASATTR", (len ? '|' : '('));
880 len = strlen(buffer);
883 sprintf(buffer, "(none)");
885 sprintf(buffer + len, ")");
897 /* Print all the stat block fields. */
899 fprintf(stdout, "dt_dev 0x%llx\n", (uint64_t)dmstat->dt_dev);
900 fprintf(stdout, "dt_ino %llx\n", dmstat->dt_ino);
901 fprintf(stdout, "dt_mode (type) %s\n",
902 mode_to_string(dmstat->dt_mode));
903 fprintf(stdout, "dt_mode (perm) 0%o\n", dmstat->dt_mode & S_MASK);
904 fprintf(stdout, "dt_nlink %d\n", dmstat->dt_nlink);
905 fprintf(stdout, "dt_uid %d\n", dmstat->dt_uid);
906 fprintf(stdout, "dt_gid %d\n", dmstat->dt_gid);
907 fprintf(stdout, "dt_rdev 0x%llx\n", (uint64_t)dmstat->dt_rdev);
908 fprintf(stdout, "dt_size %lld\n", dmstat->dt_size);
910 fprintf(stdout, "dt_atime %s\n",
911 date_to_string(dmstat->dt_atime));
912 fprintf(stdout, "dt_mtime %s\n",
913 date_to_string(dmstat->dt_mtime));
914 fprintf(stdout, "dt_ctime %s\n",
915 date_to_string(dmstat->dt_ctime));
917 fprintf(stdout, "dt_blksize %d\n", dmstat->dt_blksize);
918 fprintf(stdout, "dt_blocks %lld\n", dmstat->dt_blocks);
920 #if defined(__sgi) || defined(linux)
921 fprintf(stdout, "dt_xfs_igen %d\n", dmstat->dt_xfs_igen);
922 fprintf(stdout, "dt_xfs_xflags %s\n",
923 xflags_to_string(dmstat->dt_xfs_xflags));
924 fprintf(stdout, "dt_xfs_extsize %d\n", dmstat->dt_xfs_extsize);
925 fprintf(stdout, "dt_xfs_extents %d\n", dmstat->dt_xfs_extents);
926 fprintf(stdout, "dt_xfs_aextents %d\n", dmstat->dt_xfs_aextents);
931 /* Print all other fields. */
933 fprintf(stdout, "emask %s\n",
934 emask_to_string(dmstat->dt_emask));
935 fprintf(stdout, "nevents %d\n", dmstat->dt_nevents);
936 fprintf(stdout, "pmanreg %d\n", dmstat->dt_pmanreg);
937 fprintf(stdout, "pers %d\n", dmstat->dt_pers);
938 fprintf(stdout, "dt_dtime %s\n",
939 date_to_string(dmstat->dt_dtime));
940 fprintf(stdout, "change %d\n", dmstat->dt_change);
948 fprintf(stdout, "0x%llx|", (uint64_t)dmstat->dt_dev);
949 fprintf(stdout, "%llx|", dmstat->dt_ino);
950 fprintf(stdout, "%s|", mode_to_string(dmstat->dt_mode));
951 fprintf(stdout, "0%o|", dmstat->dt_mode & S_MASK);
952 fprintf(stdout, "%d|", dmstat->dt_nlink);
953 fprintf(stdout, "%d|", dmstat->dt_uid);
954 fprintf(stdout, "%d|", dmstat->dt_gid);
955 fprintf(stdout, "0x%llx|", (uint64_t)dmstat->dt_rdev);
956 fprintf(stdout, "%lld|", dmstat->dt_size);
958 fprintf(stdout, "%s|", date_to_string(dmstat->dt_atime));
959 fprintf(stdout, "%s|", date_to_string(dmstat->dt_mtime));
960 fprintf(stdout, "%s|", date_to_string(dmstat->dt_ctime));
962 fprintf(stdout, "%d|", dmstat->dt_blksize);
963 fprintf(stdout, "%lld|", dmstat->dt_blocks);
965 fprintf(stdout, "%d|", dmstat->dt_xfs_igen);
966 fprintf(stdout, "%s|", xflags_to_string(dmstat->dt_xfs_xflags));
967 fprintf(stdout, "%d|", dmstat->dt_xfs_extsize);
968 fprintf(stdout, "%d|", dmstat->dt_xfs_extents);
969 fprintf(stdout, "%d|", dmstat->dt_xfs_aextents);
971 /* Print all other fields. */
973 fprintf(stdout, "%s|", emask_to_string(dmstat->dt_emask));
974 fprintf(stdout, "%d|", dmstat->dt_nevents);
975 fprintf(stdout, "%d|", dmstat->dt_pmanreg);
976 fprintf(stdout, "%d|", dmstat->dt_pers);
977 fprintf(stdout, "%s|", date_to_string(dmstat->dt_dtime));
978 fprintf(stdout, "%d", dmstat->dt_change);