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>
31 #define S_IAMB (S_IRWXU|S_IRWXG|S_IRWXO)
34 #define S_MASK (S_ISUID|S_ISGID|S_ISVTX|S_IAMB)
36 extern char *Progname;
39 void err_msg(char *, ...);
40 void errno_msg(char *, ...);
42 struct ev_name_to_value ev_names[] = {
43 { "DM_EVENT_CANCEL", DM_EVENT_CANCEL },
44 { "DM_EVENT_MOUNT", DM_EVENT_MOUNT },
45 { "DM_EVENT_PREUNMOUNT", DM_EVENT_PREUNMOUNT },
46 { "DM_EVENT_UNMOUNT", DM_EVENT_UNMOUNT },
47 { "DM_EVENT_DEBUT", DM_EVENT_DEBUT },
48 { "DM_EVENT_CREATE", DM_EVENT_CREATE },
49 { "DM_EVENT_CLOSE", DM_EVENT_CLOSE },
50 { "DM_EVENT_POSTCREATE", DM_EVENT_POSTCREATE },
51 { "DM_EVENT_REMOVE", DM_EVENT_REMOVE },
52 { "DM_EVENT_POSTREMOVE", DM_EVENT_POSTREMOVE },
53 { "DM_EVENT_RENAME", DM_EVENT_RENAME },
54 { "DM_EVENT_POSTRENAME", DM_EVENT_POSTRENAME },
55 { "DM_EVENT_LINK", DM_EVENT_LINK },
56 { "DM_EVENT_POSTLINK", DM_EVENT_POSTLINK },
57 { "DM_EVENT_SYMLINK", DM_EVENT_SYMLINK },
58 { "DM_EVENT_POSTSYMLINK", DM_EVENT_POSTSYMLINK },
59 { "DM_EVENT_READ", DM_EVENT_READ },
60 { "DM_EVENT_WRITE", DM_EVENT_WRITE },
61 { "DM_EVENT_TRUNCATE", DM_EVENT_TRUNCATE },
62 { "DM_EVENT_ATTRIBUTE", DM_EVENT_ATTRIBUTE },
63 { "DM_EVENT_DESTROY", DM_EVENT_DESTROY },
64 { "DM_EVENT_NOSPACE", DM_EVENT_NOSPACE },
65 { "DM_EVENT_USER", DM_EVENT_USER }
68 int ev_namecnt = sizeof(ev_names) / sizeof(ev_names[0]);
76 for (i = 0; i < ev_namecnt; i++) {
77 if (!strcmp(name, ev_names[i].name))
78 return(ev_names[i].value);
80 return(DM_EVENT_INVALID);
87 static char buffer[100];
90 for (i = 0; i < ev_namecnt; i++) {
91 if (event == ev_names[i].value)
92 return(ev_names[i].name);
94 sprintf(buffer, "Unknown Event Number %d\n", event);
100 struct rt_name_to_value rt_names[] = {
101 { "DM_RIGHT_NULL", DM_RIGHT_NULL },
102 { "DM_RIGHT_SHARED", DM_RIGHT_SHARED },
103 { "DM_RIGHT_EXCL", DM_RIGHT_EXCL }
106 int rt_namecnt = sizeof(rt_names) / sizeof(rt_names[0]);
115 for (i = 0; i < rt_namecnt; i++) {
116 if (!strcmp(name, rt_names[i].name)) {
117 *rightp = rt_names[i].value;
131 for (i = 0; i < rt_namecnt; i++) {
132 if (right == rt_names[i].value)
133 return(rt_names[i].name);
140 * Convert a handle from (possibly) binary to ascii.
152 for (i=0;i<hlen; i++) {
153 sprintf(handle_str, "%.2x", *cp++);
156 *handle_str = '\0'; /* Null-terminate to make it printable */
160 * Convert a handle from ascii back to it's native binary representation
169 u_char handle[HANDLE_LEN];
174 if (strlen(handle_str) > HANDLE_LEN * 2){
178 while (*handle_str && *(handle_str + 1)) {
179 if (i == HANDLE_LEN){
182 cur_char[0] = *handle_str;
183 cur_char[1] = *(handle_str + 1);
185 num = strtol(cur_char, (char **)0, 16);
186 handle[i++] = num & 0xff;
193 if ((*hanpp = malloc(*hlenp)) == NULL)
195 memcpy(*hanpp, handle, *hlenp);
206 if (atohan(name, hanpp, hlenp)) {
208 } else if (dm_handle_is_valid(*hanpp, *hlenp) == DM_FALSE) {
209 dm_handle_free(*hanpp, *hlenp);
215 /* Perhaps it is a pathname */
217 if (dm_path_to_handle(name, hanpp, hlenp)) {
229 char handle_str[HANDLE_STR];
231 if (hlen > HANDLE_LEN) {
232 printf("-- invalid hlen length %d --\n", hlen);
236 printf("print_handle: ");
237 printf("%d\t", hlen);
238 hantoa(hanp, hlen, handle_str);
239 printf("%s\n ", handle_str);
248 char handle_str[HANDLE_STR];
250 if (hlen > HANDLE_LEN) {
251 printf("-- invalid length --\n");
255 printf("%d\t", hlen);
256 hantoa(hanp, hlen, handle_str);
257 printf("%s ", handle_str);
259 printf("\t%lld \n", fsize);
261 printf("\t%ld \n", fsize);
267 * Print out a simple error message, and include the errno
271 errno_msg(char *fmt, ...)
277 fprintf(stderr, "%s: ", Progname);
280 vfprintf(stderr, fmt, ap);
288 * Print out a simple error message
291 err_msg(char *fmt, ...)
295 fprintf(stderr, "%s: ", Progname);
298 vfprintf(stderr, fmt, ap);
305 * Initialize the interface to the DMAPI
308 setup_dmapi(dm_sessid_t *sidp)
312 if (dm_init_service(&cp) == -1) {
313 err_msg("%s/%d: Can't init dmapi", __FILE__, __LINE__);
316 if (strcmp(cp, DM_VER_STR_CONTENTS)) {
317 err_msg("%s/%d: Compiled for a different version", __FILE__, __LINE__);
321 find_test_session(sidp);
326 * Get the file's change indicator
340 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_CFLAG, &statbuf);
342 errno_msg("%s/%d: Can't stat file (%d)", __FILE__, __LINE__, errno);
345 *change_start = statbuf.dt_change;
351 * Write a file's data to the staging file. We write the file out
365 dm_ssize_t nread, lastbuf;
369 nbufs = fsize / CHUNKSIZE;
372 filebuf = malloc(CHUNKSIZE);
373 if (filebuf == NULL) {
374 err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
378 for (i = 0; i<nbufs; i++) {
379 nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
380 (dm_ssize_t)CHUNKSIZE, filebuf);
381 if (nread != CHUNKSIZE) {
383 errno_msg("%s/%d: invis read err: got %lld, expected %lld, buf %d",
385 errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
388 nread, (dm_ssize_t)CHUNKSIZE, i);
394 nwrite = write(stg_fd, filebuf, CHUNKSIZE);
395 if (nwrite != CHUNKSIZE) {
396 errno_msg("%s/%d: write err %d, expected %d, buf %d",
398 nwrite, CHUNKSIZE, i);
404 lastbuf = fsize % CHUNKSIZE;
405 nread = dm_read_invis(sid, hanp, hlen, DM_NO_TOKEN, off,
406 (dm_ssize_t)lastbuf, filebuf);
407 if (nread != lastbuf) {
409 errno_msg("%s/%d: invis read error- got %lld, expected %lld, last buf",
411 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
419 nwrite = write(stg_fd, filebuf, (int)lastbuf);
420 if (nwrite != lastbuf) {
422 errno_msg("%s/%d: write error %d, expected %lld, last buffer",
424 errno_msg("%s/%d: write error %d, expected %d, last buffer",
441 * Read a file's data from the staging file.
442 * Since we only have the staging file handle (not a file descriptor)
443 * we use dm_read_invis() to read the data.
445 * We stage the entire file in, regardless of how much was asked for,
446 * starting at the faulting offset.
461 dm_ssize_t nread, nwrite, lastbuf;
463 dm_stat_t dm_statbuf;
465 error = dm_get_fileattr(sid, hanp, hlen, token, DM_AT_STAT,
468 errno_msg("%s/%d: Can't get dm stats of file (%d)", __FILE__, __LINE__, errno);
472 fsize = dm_statbuf.dt_size;
473 nbufs = fsize / CHUNKSIZE;
476 filebuf = malloc(CHUNKSIZE);
477 if (filebuf == NULL) {
478 err_msg("%s/%d: Can't alloc memory for file buffer", __FILE__, __LINE__);
482 for (i = 0; i<nbufs; i++) {
483 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN,
484 off, (dm_ssize_t)CHUNKSIZE, filebuf);
485 if (nread != CHUNKSIZE) {
486 errno_msg("%s/%d: invis read err: got %d, expected %d, buf %d",
488 nread, CHUNKSIZE, i);
493 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, nread,
495 if (nwrite != nread) {
496 errno_msg("%s/%d: write error -got %d, expected %d, buf %d",
505 lastbuf = fsize % CHUNKSIZE;
506 nread = dm_read_invis(sid, stg_hanp, stg_hlen, DM_NO_TOKEN, off,
507 (dm_ssize_t)lastbuf, filebuf);
508 if (nread != lastbuf) {
509 errno_msg("%s/%d: invis read error- got %d, expected %d, last buf",
516 nwrite = dm_write_invis(sid, hanp, hlen, token, 0, off, lastbuf, filebuf);
517 if (nwrite != lastbuf) {
518 errno_msg("%s/%d: write error - got %d, expected %d, last buffer",
534 switch (mode & S_IFMT) {
572 /* Get the stat block for the file. */
574 if (lstat(pathname, &statb)) {
575 perror("stat failed");
579 /* Compare its fields against the dm_stat_t structure. */
581 if (dmstat->dt_dev != statb.st_dev) {
583 fprintf(stdout, "ERROR:dmstat->dt_dev 0x%x, "
584 "statb.st_dev 0x%x\n", dmstat->dt_dev,
589 if (dmstat->dt_ino != statb.st_ino) {
591 fprintf(stdout, "ERROR:dmstat->dt_ino %llx, "
592 #if defined(__sgi) && (_MIPS_SIM != _MIPS_SIM_ABI32)
593 "statb.st_ino %llx\n",
597 dmstat->dt_ino, statb.st_ino);
601 if ((dmstat->dt_mode & S_IFMT) != field_to_mode(statb.st_mode)) {
603 fprintf(stdout, "ERROR:dmstat->dt_mode (mode) %s, "
604 "statb.st_mode (mode) %s\n",
605 mode_to_string(dmstat->dt_mode),
606 mode_to_string(field_to_mode(statb.st_mode)));
610 if ((dmstat->dt_mode & S_MASK) != (statb.st_mode & S_MASK)) {
612 fprintf(stdout, "ERROR:dmstat->dt_mode (perm) 0%o, "
613 "statb.st_mode (perm) 0%o\n",
614 dmstat->dt_mode & S_MASK,
615 statb.st_mode & S_MASK);
619 if (dmstat->dt_nlink != statb.st_nlink) {
621 fprintf(stdout, "ERROR:dmstat->dt_nlink %d, "
622 "statb.st_nlink %d\n", dmstat->dt_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%x, "
646 "statb.st_rdev 0x%x\n", dmstat->dt_rdev,
651 if (dmstat->dt_size != statb.st_size) {
653 fprintf(stdout, "ERROR:dmstat->dt_size %lld, "
654 #if 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 %d, "
666 "statb.st_atime %d\n", dmstat->dt_atime,
671 if (dmstat->dt_mtime != statb.st_mtime) {
673 fprintf(stdout, "ERROR:dmstat->dt_mtime %d, "
674 "statb.st_mtime %d\n", dmstat->dt_mtime,
679 if (dmstat->dt_ctime != statb.st_ctime) {
681 fprintf(stdout, "ERROR:dmstat->dt_ctime %d, "
682 "statb.st_ctime %d\n", dmstat->dt_ctime,
687 if (dmstat->dt_dtime != statb.st_ctime) {
689 fprintf(stdout, "ERROR:dmstat->dt_dtime %d, "
690 "statb.st_ctime %d\n", dmstat->dt_dtime,
695 if (dmstat->dt_blksize != statb.st_blksize) {
697 fprintf(stdout, "ERROR:dmstat->dt_blksize %d, "
698 "statb.st_blksize %d\n", dmstat->dt_blksize,
703 if (dmstat->dt_blocks != statb.st_blocks) {
705 fprintf(stdout, "ERROR:dmstat->dt_blocks %lld, "
706 #if 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%x\n", dmstat->dt_dev);
898 fprintf(stdout, "dt_ino %llx\n", dmstat->dt_ino);
900 fprintf(stdout, "dt_ino %x\n", dmstat->dt_ino);
902 fprintf(stdout, "dt_mode (type) %s\n",
903 mode_to_string(dmstat->dt_mode));
904 fprintf(stdout, "dt_mode (perm) 0%o\n", dmstat->dt_mode & S_MASK);
905 fprintf(stdout, "dt_nlink %d\n", dmstat->dt_nlink);
906 fprintf(stdout, "dt_uid %d\n", dmstat->dt_uid);
907 fprintf(stdout, "dt_gid %d\n", dmstat->dt_gid);
908 fprintf(stdout, "dt_rdev 0x%x\n", dmstat->dt_rdev);
910 fprintf(stdout, "dt_size %lld\n", dmstat->dt_size);
912 fprintf(stdout, "dt_size %d\n", dmstat->dt_size);
915 fprintf(stdout, "dt_atime %s\n",
916 date_to_string(dmstat->dt_atime));
917 fprintf(stdout, "dt_mtime %s\n",
918 date_to_string(dmstat->dt_mtime));
919 fprintf(stdout, "dt_ctime %s\n",
920 date_to_string(dmstat->dt_ctime));
922 fprintf(stdout, "dt_blksize %d\n", dmstat->dt_blksize);
924 fprintf(stdout, "dt_blocks %lld\n", dmstat->dt_blocks);
926 fprintf(stdout, "dt_blocks %d\n", dmstat->dt_blocks);
929 #if defined(__sgi) || defined(linux)
930 fprintf(stdout, "dt_xfs_igen %d\n", dmstat->dt_xfs_igen);
931 fprintf(stdout, "dt_xfs_xflags %s\n",
932 xflags_to_string(dmstat->dt_xfs_xflags));
933 fprintf(stdout, "dt_xfs_extsize %d\n", dmstat->dt_xfs_extsize);
934 fprintf(stdout, "dt_xfs_extents %d\n", dmstat->dt_xfs_extents);
935 fprintf(stdout, "dt_xfs_aextents %d\n", dmstat->dt_xfs_aextents);
940 /* Print all other fields. */
942 fprintf(stdout, "emask %s\n",
943 emask_to_string(dmstat->dt_emask));
944 fprintf(stdout, "nevents %d\n", dmstat->dt_nevents);
945 fprintf(stdout, "pmanreg %d\n", dmstat->dt_pmanreg);
946 fprintf(stdout, "pers %d\n", dmstat->dt_pers);
947 fprintf(stdout, "dt_dtime %s\n",
948 date_to_string(dmstat->dt_dtime));
949 fprintf(stdout, "change %d\n", dmstat->dt_change);
957 fprintf(stdout, "0x%x|", dmstat->dt_dev);
959 fprintf(stdout, "%llx|", dmstat->dt_ino);
961 fprintf(stdout, "%x|", dmstat->dt_ino);
963 fprintf(stdout, "%s|", mode_to_string(dmstat->dt_mode));
964 fprintf(stdout, "0%o|", dmstat->dt_mode & S_MASK);
965 fprintf(stdout, "%d|", dmstat->dt_nlink);
966 fprintf(stdout, "%d|", dmstat->dt_uid);
967 fprintf(stdout, "%d|", dmstat->dt_gid);
968 fprintf(stdout, "0x%x|", dmstat->dt_rdev);
970 fprintf(stdout, "%lld|", dmstat->dt_size);
972 fprintf(stdout, "%d|", dmstat->dt_size);
975 fprintf(stdout, "%s|", date_to_string(dmstat->dt_atime));
976 fprintf(stdout, "%s|", date_to_string(dmstat->dt_mtime));
977 fprintf(stdout, "%s|", date_to_string(dmstat->dt_ctime));
979 fprintf(stdout, "%d|", dmstat->dt_blksize);
981 fprintf(stdout, "%lld|", dmstat->dt_blocks);
983 fprintf(stdout, "%d|", dmstat->dt_blocks);
987 fprintf(stdout, "%d|", dmstat->dt_xfs_igen);
988 fprintf(stdout, "%s|", xflags_to_string(dmstat->dt_xfs_xflags));
989 fprintf(stdout, "%d|", dmstat->dt_xfs_extsize);
990 fprintf(stdout, "%d|", dmstat->dt_xfs_extents);
991 fprintf(stdout, "%d|", dmstat->dt_xfs_aextents);
994 /* Print all other fields. */
996 fprintf(stdout, "%s|", emask_to_string(dmstat->dt_emask));
997 fprintf(stdout, "%d|", dmstat->dt_nevents);
998 fprintf(stdout, "%d|", dmstat->dt_pmanreg);
999 fprintf(stdout, "%d|", dmstat->dt_pers);
1000 fprintf(stdout, "%s|", date_to_string(dmstat->dt_dtime));
1001 fprintf(stdout, "%d", dmstat->dt_change);
1003 fputc('\n', stdout);