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 cur_char[0] = *handle_str;
185 cur_char[1] = *(handle_str + 1);
187 num = strtol(cur_char, (char **)0, 16);
188 handle[i++] = num & 0xff;
195 if ((*hanpp = malloc(*hlenp)) == NULL)
197 memcpy(*hanpp, handle, *hlenp);
208 if (atohan(name, hanpp, hlenp)) {
210 } else if (dm_handle_is_valid(*hanpp, *hlenp) == DM_FALSE) {
211 dm_handle_free(*hanpp, *hlenp);
217 /* Perhaps it is a pathname */
219 if (dm_path_to_handle(name, hanpp, hlenp)) {
231 char handle_str[HANDLE_STR];
233 if (hlen > HANDLE_LEN) {
234 printf("-- invalid hlen length %d --\n", hlen);
238 printf("print_handle: ");
239 printf("%d\t", hlen);
240 hantoa(hanp, hlen, handle_str);
241 printf("%s\n ", handle_str);
250 char handle_str[HANDLE_STR];
252 if (hlen > HANDLE_LEN) {
253 printf("-- invalid length --\n");
257 printf("%d\t", hlen);
258 hantoa(hanp, hlen, handle_str);
259 printf("%s ", handle_str);
260 printf("\t%lld \n", fsize);
265 * Print out a simple error message, and include the errno
269 errno_msg(char *fmt, ...)
275 fprintf(stderr, "%s: ", Progname);
278 vfprintf(stderr, fmt, ap);
286 * Print out a simple error message
289 err_msg(char *fmt, ...)
293 fprintf(stderr, "%s: ", Progname);
296 vfprintf(stderr, fmt, ap);
303 * Initialize the interface to the DMAPI
306 setup_dmapi(dm_sessid_t *sidp)
310 if (dm_init_service(&cp) == -1) {
311 err_msg("%s/%d: Can't init dmapi", __FILE__, __LINE__);
314 if (strcmp(cp, DM_VER_STR_CONTENTS)) {
315 err_msg("%s/%d: Compiled for a different version", __FILE__, __LINE__);
319 find_test_session(sidp);
324 * Get the file's change indicator
338 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_CFLAG, &statbuf);
340 errno_msg("%s/%d: Can't stat file (%d)", __FILE__, __LINE__, errno);
343 *change_start = statbuf.dt_change;
349 * Write a file's data to the staging file. We write the file out
363 dm_ssize_t nread, lastbuf;
367 nbufs = fsize / CHUNKSIZE;
370 filebuf = malloc(CHUNKSIZE);
371 if (filebuf == NULL) {
372 err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
376 for (i = 0; i<nbufs; i++) {
377 nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
378 (dm_ssize_t)CHUNKSIZE, filebuf);
379 if (nread != CHUNKSIZE) {
381 errno_msg("%s/%d: invis read err: got %lld, expected %lld, buf %d",
383 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) {
407 errno_msg("%s/%d: invis read error- got %lld, expected %lld, last buf",
409 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
417 nwrite = write(stg_fd, filebuf, (int)lastbuf);
418 if (nwrite != lastbuf) {
420 errno_msg("%s/%d: write error %d, expected %lld, last buffer",
422 errno_msg("%s/%d: write error %d, expected %d, last buffer",
439 * Read a file's data from the staging file.
440 * Since we only have the staging file handle (not a file descriptor)
441 * we use dm_read_invis() to read the data.
443 * We stage the entire file in, regardless of how much was asked for,
444 * starting at the faulting offset.
459 dm_ssize_t nread, nwrite, lastbuf;
461 dm_stat_t dm_statbuf;
463 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_STAT,
466 errno_msg("%s/%d: Can't get dm stats of file (%d)", __FILE__, __LINE__, errno);
470 fsize = dm_statbuf.dt_size;
471 nbufs = fsize / CHUNKSIZE;
474 filebuf = malloc(CHUNKSIZE);
475 if (filebuf == NULL) {
476 err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
480 for (i = 0; i<nbufs; i++) {
481 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN,
482 off, (dm_ssize_t)CHUNKSIZE, filebuf);
483 if (nread != CHUNKSIZE) {
484 errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
486 nread, CHUNKSIZE, i);
491 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, nread,
493 if (nwrite != nread) {
494 errno_msg("%s/%d: write error -got %d, expected %d, buf %d",
503 lastbuf = fsize % CHUNKSIZE;
504 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN, off,
505 (dm_ssize_t)lastbuf, filebuf);
506 if (nread != lastbuf) {
507 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
514 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, lastbuf, filebuf);
515 if (nwrite != lastbuf) {
516 errno_msg("%s/%d: write error - got %d, expected %d, last buffer",
532 switch (mode & S_IFMT) {
570 /* Get the stat block for the file. */
572 if (lstat(pathname, &statb)) {
573 perror("stat failed");
577 /* Compare its fields against the dm_stat_t structure. */
579 if (dmstat->dt_dev != statb.st_dev) {
581 fprintf(stdout, "ERROR:dmstat->dt_dev 0x%llx, "
582 "statb.st_dev 0x%llx\n",
583 (uint64_t)dmstat->dt_dev,
584 (uint64_t)statb.st_dev);
588 if (dmstat->dt_ino != statb.st_ino) {
590 fprintf(stdout, "ERROR:dmstat->dt_ino %llx, "
591 #if defined(linux) || (defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32))
592 "statb.st_ino %llx\n",
596 dmstat->dt_ino, 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 %d, "
621 "statb.st_nlink %d\n", dmstat->dt_nlink,
626 if (dmstat->dt_uid != statb.st_uid) {
628 fprintf(stdout, "ERROR:dmstat->dt_uid %d, "
629 "statb.st_uid %d\n", dmstat->dt_uid,
634 if (dmstat->dt_gid != statb.st_gid) {
636 fprintf(stdout, "ERROR:dmstat->dt_gid %d, "
637 "statb.st_gid %d\n", dmstat->dt_gid,
642 if (dmstat->dt_rdev != statb.st_rdev) {
644 fprintf(stdout, "ERROR:dmstat->dt_rdev 0x%llx, "
645 "statb.st_rdev 0x%llx\n",
646 (uint64_t)dmstat->dt_rdev,
647 (uint64_t)statb.st_rdev);
651 if (dmstat->dt_size != statb.st_size) {
653 fprintf(stdout, "ERROR:dmstat->dt_size %lld, "
654 #if defined(linux) || (defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32))
655 "statb.st_size %lld\n",
657 "statb.st_size %d\n",
659 dmstat->dt_size, statb.st_size);
663 if (dmstat->dt_atime != statb.st_atime) {
665 fprintf(stdout, "ERROR:dmstat->dt_atime %ld, "
666 "statb.st_atime %ld\n", dmstat->dt_atime,
671 if (dmstat->dt_mtime != statb.st_mtime) {
673 fprintf(stdout, "ERROR:dmstat->dt_mtime %ld, "
674 "statb.st_mtime %ld\n", dmstat->dt_mtime,
679 if (dmstat->dt_ctime != statb.st_ctime) {
681 fprintf(stdout, "ERROR:dmstat->dt_ctime %ld, "
682 "statb.st_ctime %ld\n", dmstat->dt_ctime,
687 if (dmstat->dt_dtime != statb.st_ctime) {
689 fprintf(stdout, "ERROR:dmstat->dt_dtime %ld, "
690 "statb.st_ctime %ld\n", dmstat->dt_dtime,
695 if (dmstat->dt_blksize != statb.st_blksize) {
697 fprintf(stdout, "ERROR:dmstat->dt_blksize %d, "
698 "statb.st_blksize %ld\n", dmstat->dt_blksize,
703 if (dmstat->dt_blocks != statb.st_blocks) {
705 fprintf(stdout, "ERROR:dmstat->dt_blocks %lld, "
706 #if defined(linux) || (defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32))
707 "statb.st_blocks %lld\n",
709 "statb.st_blocks %d\n",
711 dmstat->dt_blocks, statb.st_blocks);
716 if (errors && report_errors)
717 fprintf(stdout, "There were %d differences\n", errors);
726 static char buffer[21];
729 if (timeval == (time_t)0) {
732 tmstr = asctime(localtime(&timeval));
734 strncpy(buffer, tmstr, 20);
745 static char buffer[256];
747 switch (mode & S_IFMT) {
771 sprintf(buffer, "Invalid mode 0%o", mode & S_IFMT);
781 static char buffer[256];
786 for (i = 0; i < 32; i++) {
787 if (!DMEV_ISSET(i, emask))
791 case DM_EVENT_CREATE:
792 name = "DM_EVENT_CREATE";
794 case DM_EVENT_POSTCREATE:
795 name = "DM_EVENT_POSTCREATE";
797 case DM_EVENT_REMOVE:
798 name = "DM_EVENT_REMOVE";
800 case DM_EVENT_POSTREMOVE:
801 name = "DM_EVENT_POSTREMOVE";
803 case DM_EVENT_RENAME:
804 name = "DM_EVENT_RENAME";
806 case DM_EVENT_POSTRENAME:
807 name = "DM_EVENT_POSTRENAME";
810 name = "DM_EVENT_LINK";
812 case DM_EVENT_POSTLINK:
813 name = "DM_EVENT_POSTLINK";
815 case DM_EVENT_SYMLINK:
816 name = "DM_EVENT_SYMLINK";
818 case DM_EVENT_POSTSYMLINK:
819 name = "DM_EVENT_POSTSYMLINK";
822 name = "DM_EVENT_READ";
825 name = "DM_EVENT_WRITE";
827 case DM_EVENT_TRUNCATE:
828 name = "DM_EVENT_TRUNCATE";
830 case DM_EVENT_ATTRIBUTE:
831 name = "DM_EVENT_ATTRIBUTE";
833 case DM_EVENT_DESTROY:
834 name = "DM_EVENT_DESTROY";
837 fprintf(stderr, "Unknown event type %d\n", i);
840 sprintf(buffer + len, "%c%s", (len ? '|' : '('), name);
841 len = strlen(buffer);
845 sprintf(buffer, "(none)");
847 sprintf(buffer + len, ")");
853 #if defined(__sgi) || defined(linux)
859 static char buffer[256];
862 if (xflags & ~(DM_XFLAG_REALTIME|DM_XFLAG_PREALLOC|DM_XFLAG_HASATTR)) {
863 sprintf(buffer, "Invalid xflags 0%o", xflags);
867 if (xflags & DM_XFLAG_REALTIME) {
868 sprintf(buffer + len, "%cREALTIME", (len ? '|' : '('));
869 len = strlen(buffer);
871 if (xflags & DM_XFLAG_PREALLOC) {
872 sprintf(buffer + len, "%cPREALLOC", (len ? '|' : '('));
873 len = strlen(buffer);
875 if (xflags & DM_XFLAG_HASATTR) {
876 sprintf(buffer + len, "%cHASATTR", (len ? '|' : '('));
877 len = strlen(buffer);
880 sprintf(buffer, "(none)");
882 sprintf(buffer + len, ")");
894 /* Print all the stat block fields. */
896 fprintf(stdout, "dt_dev 0x%llx\n", (uint64_t)dmstat->dt_dev);
897 fprintf(stdout, "dt_ino %llx\n", dmstat->dt_ino);
898 fprintf(stdout, "dt_mode (type) %s\n",
899 mode_to_string(dmstat->dt_mode));
900 fprintf(stdout, "dt_mode (perm) 0%o\n", dmstat->dt_mode & S_MASK);
901 fprintf(stdout, "dt_nlink %d\n", dmstat->dt_nlink);
902 fprintf(stdout, "dt_uid %d\n", dmstat->dt_uid);
903 fprintf(stdout, "dt_gid %d\n", dmstat->dt_gid);
904 fprintf(stdout, "dt_rdev 0x%llx\n", (uint64_t)dmstat->dt_rdev);
905 fprintf(stdout, "dt_size %lld\n", dmstat->dt_size);
907 fprintf(stdout, "dt_atime %s\n",
908 date_to_string(dmstat->dt_atime));
909 fprintf(stdout, "dt_mtime %s\n",
910 date_to_string(dmstat->dt_mtime));
911 fprintf(stdout, "dt_ctime %s\n",
912 date_to_string(dmstat->dt_ctime));
914 fprintf(stdout, "dt_blksize %d\n", dmstat->dt_blksize);
915 fprintf(stdout, "dt_blocks %lld\n", dmstat->dt_blocks);
917 #if defined(__sgi) || defined(linux)
918 fprintf(stdout, "dt_xfs_igen %d\n", dmstat->dt_xfs_igen);
919 fprintf(stdout, "dt_xfs_xflags %s\n",
920 xflags_to_string(dmstat->dt_xfs_xflags));
921 fprintf(stdout, "dt_xfs_extsize %d\n", dmstat->dt_xfs_extsize);
922 fprintf(stdout, "dt_xfs_extents %d\n", dmstat->dt_xfs_extents);
923 fprintf(stdout, "dt_xfs_aextents %d\n", dmstat->dt_xfs_aextents);
928 /* Print all other fields. */
930 fprintf(stdout, "emask %s\n",
931 emask_to_string(dmstat->dt_emask));
932 fprintf(stdout, "nevents %d\n", dmstat->dt_nevents);
933 fprintf(stdout, "pmanreg %d\n", dmstat->dt_pmanreg);
934 fprintf(stdout, "pers %d\n", dmstat->dt_pers);
935 fprintf(stdout, "dt_dtime %s\n",
936 date_to_string(dmstat->dt_dtime));
937 fprintf(stdout, "change %d\n", dmstat->dt_change);
945 fprintf(stdout, "0x%llx|", (uint64_t)dmstat->dt_dev);
946 fprintf(stdout, "%llx|", dmstat->dt_ino);
947 fprintf(stdout, "%s|", mode_to_string(dmstat->dt_mode));
948 fprintf(stdout, "0%o|", dmstat->dt_mode & S_MASK);
949 fprintf(stdout, "%d|", dmstat->dt_nlink);
950 fprintf(stdout, "%d|", dmstat->dt_uid);
951 fprintf(stdout, "%d|", dmstat->dt_gid);
952 fprintf(stdout, "0x%llx|", (uint64_t)dmstat->dt_rdev);
953 fprintf(stdout, "%lld|", dmstat->dt_size);
955 fprintf(stdout, "%s|", date_to_string(dmstat->dt_atime));
956 fprintf(stdout, "%s|", date_to_string(dmstat->dt_mtime));
957 fprintf(stdout, "%s|", date_to_string(dmstat->dt_ctime));
959 fprintf(stdout, "%d|", dmstat->dt_blksize);
960 fprintf(stdout, "%lld|", dmstat->dt_blocks);
962 fprintf(stdout, "%d|", dmstat->dt_xfs_igen);
963 fprintf(stdout, "%s|", xflags_to_string(dmstat->dt_xfs_xflags));
964 fprintf(stdout, "%d|", dmstat->dt_xfs_extsize);
965 fprintf(stdout, "%d|", dmstat->dt_xfs_extents);
966 fprintf(stdout, "%d|", dmstat->dt_xfs_aextents);
968 /* Print all other fields. */
970 fprintf(stdout, "%s|", emask_to_string(dmstat->dt_emask));
971 fprintf(stdout, "%d|", dmstat->dt_nevents);
972 fprintf(stdout, "%d|", dmstat->dt_pmanreg);
973 fprintf(stdout, "%d|", dmstat->dt_pers);
974 fprintf(stdout, "%s|", date_to_string(dmstat->dt_dtime));
975 fprintf(stdout, "%d", dmstat->dt_change);