19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
25 * permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39 #include <sys/errno.h>
40 #include <ctype.h>
41 #include <stdlib.h>
42 #include <time.h>
43 #include <sys/types.h>
44 #include <unistd.h>
45 #include <libzfs.h>
46 #include <pthread.h>
47 #include "tlm.h"
48 #include "tlm_proto.h"
49 #include <ndmpd_prop.h>
50 #include <sys/mtio.h>
51 #include <sys/mnttab.h>
52 #include <sys/mntent.h>
53 #include <sys/statvfs.h>
54 #include <sys/scsi/impl/uscsi.h>
55 #include <sys/scsi/scsi.h>
56 #include <sys/mtio.h>
57 #include <thread.h>
58 #include <synch.h>
59 #include <sys/mutex.h>
301
302 /*
303 * verify the tar header checksum
304 */
305 int
306 tlm_vfy_tar_checksum(tlm_tar_hdr_t *tar_hdr)
307 {
308 int chksum = oct_atoi(tar_hdr->th_chksum);
309 uchar_t *p = (uchar_t *)tar_hdr;
310 int sum = 0; /* initial value of checksum */
311 int i; /* loop counter */
312
313 /*
314 * compute the checksum
315 */
316 for (i = 0; i < RECORDSIZE; i++) {
317 sum += p[i] & 0xFF;
318 }
319
320 if (sum == 0) {
321 NDMP_LOG(LOG_DEBUG,
322 "should be %d, is 0", chksum);
323 /* a zero record ==> end of tar file */
324 return (0);
325 }
326
327 /*
328 * subtract out the label's checksum values
329 * this lets us undo the old checksum "in-
330 * place", no need to swap blanks in and out
331 */
332 for (i = 0; i < 8; i++) {
333 sum -= 0xFF & tar_hdr->th_chksum[i];
334 }
335
336 /*
337 * replace the old checksum field with blanks
338 */
339 sum += ' ' * 8;
340
341 if (sum != chksum)
342 NDMP_LOG(LOG_DEBUG,
343 "should be %d, is %d", chksum, sum);
344
345 return ((sum == chksum) ? 1 : -1);
346 }
347
348 /*
349 * get internal scsi_sasd entry for this tape drive
350 */
351 int
352 tlm_get_scsi_sasd_entry(int lib, int drv)
353 {
354 int entry;
355 int i, n;
356 scsi_link_t *sl;
357 tlm_drive_t *dp;
358
359 entry = -1;
360 dp = tlm_drive(lib, drv);
361 if (!dp) {
362 NDMP_LOG(LOG_DEBUG, "NULL dp for (%d.%d)", lib, drv);
363 } else if (!dp->td_slink) {
364 NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink for (%d.%d)", lib, drv);
365 } else if (!dp->td_slink->sl_sa) {
366 NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink->sl_sa for (%d.%d)",
367 lib, drv);
368 } else {
369 /* search through the SASD table */
370 n = sasd_dev_count();
371 for (i = 0; i < n; i++) {
372 sl = sasd_dev_slink(i);
373 if (!sl)
374 continue;
375
376 if (dp->td_slink->sl_sa == sl->sl_sa &&
377 dp->td_scsi_id == sl->sl_sid &&
378 dp->td_lun == sl->sl_lun) {
379 /* all 3 variables match */
380 entry = i;
381 break;
382 }
383 }
384 }
385
386 return (entry);
479 */
480 void
481 lbrlog_callbacks_done(lbr_fhlog_call_backs_t *p)
482 {
483 if (p != NULL)
484 (void) free((char *)p);
485 }
486
487 /*
488 * Call back for file history directory info
489 */
490 int
491 tlm_log_fhdir(tlm_job_stats_t *job_stats, char *dir, struct stat64 *stp,
492 fs_fhandle_t *fhp)
493 {
494 int rv;
495 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
496
497 rv = 0;
498 if (job_stats == NULL) {
499 NDMP_LOG(LOG_DEBUG, "log_fhdir: jstat is NULL");
500 } else if (dir == NULL) {
501 NDMP_LOG(LOG_DEBUG, "log_fhdir: dir is NULL");
502 } else if (stp == NULL) {
503 NDMP_LOG(LOG_DEBUG, "log_fhdir: stp is NULL");
504 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
505 == NULL) {
506 NDMP_LOG(LOG_DEBUG, "log_fhdir: cbp is NULL");
507 } else if (cbp->fh_log_dir == NULL) {
508 NDMP_LOG(LOG_DEBUG, "log_fhdir: callback is NULL");
509 } else
510 rv = (*cbp->fh_log_dir)(cbp, dir, stp, fhp);
511
512 return (rv);
513 }
514
515 /*
516 * Call back for file history node info
517 */
518 int
519 tlm_log_fhnode(tlm_job_stats_t *job_stats, char *dir, char *file,
520 struct stat64 *stp, u_longlong_t off)
521 {
522 int rv;
523 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
524
525 rv = 0;
526 if (job_stats == NULL) {
527 NDMP_LOG(LOG_DEBUG, "log_fhnode: jstat is NULL");
528 } else if (dir == NULL) {
529 NDMP_LOG(LOG_DEBUG, "log_fhnode: dir is NULL");
530 } else if (file == NULL) {
531 NDMP_LOG(LOG_DEBUG, "log_fhnode: file is NULL");
532 } else if (stp == NULL) {
533 NDMP_LOG(LOG_DEBUG, "log_fhnode: stp is NULL");
534 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
535 == NULL) {
536 NDMP_LOG(LOG_DEBUG, "log_fhnode: cbp is NULL");
537 } else if (cbp->fh_log_node == NULL) {
538 NDMP_LOG(LOG_DEBUG, "log_fhnode: callback is NULL");
539 } else
540 rv = (*cbp->fh_log_node)(cbp, dir, file, stp, off);
541
542 return (rv);
543 }
544
545 /*
546 * Call back for file history path info
547 */
548 int
549 tlm_log_fhpath_name(tlm_job_stats_t *job_stats, char *pathname,
550 struct stat64 *stp, u_longlong_t off)
551 {
552 int rv;
553 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
554
555 rv = 0;
556 if (!job_stats) {
557 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: jstat is NULL");
558 } else if (!pathname) {
559 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: pathname is NULL");
560 } else if (!stp) {
561 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: stp is NULL");
562 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
563 == 0) {
564 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: cbp is NULL");
565 } else if (!cbp->fh_logpname) {
566 NDMP_LOG(LOG_DEBUG, "log_fhpath_name: callback is NULL");
567 } else
568 rv = (*cbp->fh_logpname)(cbp, pathname, stp, off);
569
570 return (rv);
571 }
572
573
574 /*
575 * Log call back to report the entry recovery
576 */
577 int
578 tlm_entry_restored(tlm_job_stats_t *job_stats, char *name, int pos)
579 {
580 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
581
582 NDMP_LOG(LOG_DEBUG, "name: \"%s\", pos: %d", name, pos);
583
584 if (job_stats == NULL) {
585 NDMP_LOG(LOG_DEBUG, "entry_restored: jstat is NULL");
586 return (0);
587 }
588 cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks;
589 if (cbp == NULL) {
590 NDMP_LOG(LOG_DEBUG, "entry_restored is NULL");
591 return (0);
592 }
593 return (*cbp->fh_logpname)(cbp, name, 0, (longlong_t)pos);
594 }
595 /*
596 * NDMP support ends here.
597 */
598
599 /*
600 * Function: tlm_cat_path
601 * Concatenates two path names
602 * or directory name and file name
603 * into a buffer passed by the caller. A slash
604 * is inserted if required. Buffer is assumed
605 * to hold PATH_MAX characters.
606 *
607 * Parameters:
608 * char *buf - buffer to write new dir/name string
609 * char *dir - directory name
610 * char *name - file name
629 fmt = "%s%s";
630 } else {
631 fmt = "%s/%s";
632 }
633
634 /* check for ".../" and "/...." */
635 if ((dirlen > 0) && (dir[dirlen - 1] == '/') && (*name == '/'))
636 name += strspn(name, "/");
637
638 /* LINTED variable format */
639 (void) snprintf(buf, TLM_MAX_PATH_NAME, fmt, dir, name);
640
641 return (TRUE);
642 }
643
644 /*
645 * Get the checkpoint (snapshot) creation time.
646 * This is necessary to check for checkpoints not being stale.
647 */
648 int
649 tlm_get_chkpnt_time(char *path, int auto_checkpoint, time_t *tp, char *jname)
650 {
651 char volname[TLM_VOLNAME_MAX_LENGTH];
652 char chk_name[PATH_MAX];
653 char *cp_nm;
654
655 NDMP_LOG(LOG_DEBUG, "path [%s] auto_checkpoint: %d",
656 path, auto_checkpoint);
657
658 if (path == NULL || *path == '\0' || tp == NULL)
659 return (-1);
660
661 if (get_zfsvolname(volname, TLM_VOLNAME_MAX_LENGTH,
662 path) == -1)
663 return (-1);
664
665 if (auto_checkpoint) {
666 NDMP_LOG(LOG_DEBUG, "volname [%s]", volname);
667 (void) snprintf(chk_name, PATH_MAX, "%s", jname);
668 return (chkpnt_creationtime_bypattern(volname, chk_name, tp));
669 }
670 cp_nm = strchr(volname, '@');
671 NDMP_LOG(LOG_DEBUG, "volname [%s] cp_nm [%s]", volname, cp_nm);
672
673 return (chkpnt_creationtime_bypattern(volname, cp_nm, tp));
674 }
675
676 /*
677 * Release an array of pointers and the pointers themselves.
678 */
679 void
680 tlm_release_list(char **lpp)
681 {
682 char **save;
683
684 if ((save = lpp) == 0)
685 return;
686
687 while (*lpp)
688 free(*lpp++);
689
690 free(save);
691 }
692
693 /*
694 * Print the list of array of strings in the backup log
695 */
696 void
697 tlm_log_list(char *title, char **lpp)
698 {
699 int i;
700
701 if (!lpp)
702 return;
703
704 NDMP_LOG(LOG_DEBUG, "%s:", title);
705
706 for (i = 0; *lpp; lpp++, i++)
707 NDMP_LOG(LOG_DEBUG, "%d: [%s]", i, *lpp);
708 }
709
710 /*
711 * Insert the backup snapshot name into the path.
712 *
713 * Input:
714 * name: Original path name.
715 *
716 * Output:
717 * name: Original name modified to include a snapshot.
718 *
719 * Returns:
720 * Original name modified to include a snapshot.
721 */
722 char *
723 tlm_build_snapshot_name(char *name, char *sname, char *jname)
724 {
725 zfs_handle_t *zhp;
726 char *rest;
727 char volname[ZFS_MAX_DATASET_NAME_LEN];
728 char mountpoint[PATH_MAX];
729
730 if (get_zfsvolname(volname, ZFS_MAX_DATASET_NAME_LEN, name) == -1)
731 goto notzfs;
732
733 (void) mutex_lock(&zlib_mtx);
734 if ((zlibh == NULL) ||
735 (zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == NULL) {
736 (void) mutex_unlock(&zlib_mtx);
737 goto notzfs;
738 }
739
740 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, PATH_MAX, NULL,
741 NULL, 0, B_FALSE) != 0) {
742 zfs_close(zhp);
743 (void) mutex_unlock(&zlib_mtx);
744 goto notzfs;
745 }
746
747 zfs_close(zhp);
748 (void) mutex_unlock(&zlib_mtx);
749
750 rest = name + strlen(mountpoint);
751 (void) snprintf(sname, TLM_MAX_PATH_NAME, "%s/%s/%s%s", mountpoint,
752 TLM_SNAPSHOT_DIR, jname, rest);
753
754 return (sname);
755
756 notzfs:
757 (void) strlcpy(sname, name, TLM_MAX_PATH_NAME);
758 return (sname);
759 }
760
761 /*
762 * Remove the checkpoint from a path name.
763 *
764 * Input:
765 * name: Full pathname with checkpoint embeded.
766 *
767 * Output:
768 * unchkp_name: real pathname with no checkpoint.
769 *
770 * Returns:
771 * Pointer to the un-checkpointed path.
772 */
809 unchkp_name[i] = name[i];
810 break;
811 }
812 }
813 return (name);
814 }
815
816 /*
817 * see if we should exclude this file.
818 */
819 boolean_t
820 tlm_is_excluded(char *dir, char *name, char **excl_files)
821 {
822 int i;
823 char full_name[TLM_MAX_PATH_NAME];
824
825 if (!dir || !name || !excl_files)
826 return (FALSE);
827
828 if (!tlm_cat_path(full_name, dir, name)) {
829 NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]",
830 dir, name);
831 return (FALSE);
832 }
833 for (i = 0; excl_files[i] != 0; i++) {
834 if (match(excl_files[i], full_name)) {
835 return (TRUE);
836 }
837 }
838 return (FALSE);
839 }
840
841 /*
842 * Check if the path is too long
843 */
844 boolean_t
845 tlm_is_too_long(int checkpointed, char *dir, char *nm)
846 {
847 int nlen, tot;
848
849 tot = 0;
863 */
864 longlong_t
865 tlm_get_data_offset(tlm_cmd_t *lcmds)
866 {
867 if (!lcmds)
868 return (0LL);
869
870 return (lcmds->tc_buffers->tbs_offset);
871 }
872
873 /*
874 * Enable the barcode capability on the library
875 */
876 void
877 tlm_enable_barcode(int l)
878 {
879 tlm_library_t *lp;
880
881 if ((lp = tlm_library(l))) {
882 lp->tl_capability_barcodes = TRUE;
883 NDMP_LOG(LOG_DEBUG,
884 "Barcode capability on library %d enabled.", l);
885 }
886 }
887
888 /*
889 * SASD SCSI support
890 */
891 static scsi_adapter_t my_sa;
892 static int sasd_drive_count = 0;
893 static scsi_sasd_drive_t *scsi_sasd_drives[128];
894
895 /*
896 * Count of SCSI devices
897 */
898 int
899 sasd_dev_count(void)
900 {
901 return (sasd_drive_count);
902 }
903
1008 * Go through the attached devices and detect the tape
1009 * and robot by checking the /dev entries
1010 */
1011 int
1012 probe_scsi(void)
1013 {
1014 DIR *dirp;
1015 struct dirent *dp;
1016 scsi_adapter_t *sa = &my_sa;
1017 char *p;
1018 int lun = 0;
1019 int sid = 0;
1020 char *drive_type;
1021
1022 /* Initialize the scsi adapter link */
1023 sa->sa_link_head.sl_next = &sa->sa_link_head;
1024
1025 /* Scan for the changer */
1026 dirp = opendir(SCSI_CHANGER_DIR);
1027 if (dirp == NULL) {
1028 NDMP_LOG(LOG_DEBUG,
1029 "Changer directory read error %s", SCSI_CHANGER_DIR);
1030 } else {
1031 while ((dp = readdir(dirp)) != NULL) {
1032 if ((strcmp(dp->d_name, ".") == 0) ||
1033 (strcmp(dp->d_name, "..") == 0))
1034 continue;
1035
1036 if ((p = strchr(dp->d_name, 'd')) != NULL) {
1037 lun = atoi(++p);
1038 p = strchr(dp->d_name, 't');
1039 sid = atoi(++p);
1040 }
1041 else
1042 sid = atoi(dp->d_name);
1043
1044 scsi_sasd_attach(sa, 0, lun, dp->d_name,
1045 DTYPE_CHANGER);
1046 }
1047 (void) closedir(dirp);
1048 }
1049
1050 /* Scan for tape drives */
1051 dirp = opendir(SCSI_TAPE_DIR);
1052 if (dirp == NULL) {
1053 NDMP_LOG(LOG_DEBUG,
1054 "Tape directory read error %s", SCSI_TAPE_DIR);
1055 } else {
1056 drive_type = ndmpd_get_prop(NDMP_DRIVE_TYPE);
1057
1058 if ((strcasecmp(drive_type, "sysv") != 0) &&
1059 (strcasecmp(drive_type, "bsd") != 0)) {
1060 NDMP_LOG(LOG_ERR, "Invalid ndmpd/drive-type value. "
1061 "Valid values are 'sysv' and 'bsd'.");
1062 return (-1);
1063 }
1064
1065 while ((dp = readdir(dirp)) != NULL) {
1066 if ((strcmp(dp->d_name, ".") == 0) ||
1067 (strcmp(dp->d_name, "..") == 0))
1068 continue;
1069
1070 /* Skip special modes */
1071 if (strpbrk(dp->d_name, "chlmu") != NULL)
1072 continue;
1073
1074 /* Pick the non-rewind device */
1075 if (strchr(dp->d_name, 'n') == NULL)
1076 continue;
1077
1078 if (strcasecmp(drive_type, "sysv") == 0) {
1079 if (strchr(dp->d_name, 'b') != NULL)
1080 continue;
1148 }
1149
1150 /*
1151 * Return the SCSI adapter structure
1152 */
1153 /*ARGSUSED*/
1154 scsi_adapter_t *
1155 scsi_get_adapter(int adapter)
1156 {
1157 return (&my_sa);
1158 }
1159
1160 /*
1161 * IOCTL wrapper with retries
1162 */
1163 int
1164 tlm_ioctl(int fd, int cmd, void *data)
1165 {
1166 int retries = 0;
1167
1168 NDMP_LOG(LOG_DEBUG, "tlm_ioctl fd %d cmd %d", fd, cmd);
1169 if (fd == 0 || data == NULL)
1170 return (EINVAL);
1171
1172 do {
1173 if (ioctl(fd, cmd, data) == 0)
1174 break;
1175
1176 if (errno != EIO && errno != 0) {
1177 NDMP_LOG(LOG_ERR,
1178 "Failed to send command to device: %m.");
1179 NDMP_LOG(LOG_DEBUG, "IOCTL error %d", errno);
1180 return (errno);
1181 }
1182 (void) sleep(1);
1183 } while (retries++ < MAXIORETRY);
1184
1185 return (0);
1186 }
1187
1188 /*
1189 * Checkpoint or snapshot calls
1190 */
1191
1192 /*
1193 * Get the snapshot creation time
1194 */
1195 int
1196 chkpnt_creationtime_bypattern(char *volname, char *pattern, time_t *tp)
1197 {
1198 char chk_name[PATH_MAX];
1199 zfs_handle_t *zhp;
1200 char *p;
1201
1202 if (!volname || !*volname)
1203 return (-1);
1204
1205 /* Should also return -1 if checkpoint not enabled */
1206
1207 /* Remove the leading slash */
1208 p = volname;
1209 while (*p == '/')
1210 p++;
1211
1212 (void) strlcpy(chk_name, p, PATH_MAX);
1213 (void) strlcat(chk_name, "@", PATH_MAX);
1214 (void) strlcat(chk_name, pattern, PATH_MAX);
1215
1216 (void) mutex_lock(&zlib_mtx);
1217 if ((zhp = zfs_open(zlibh, chk_name, ZFS_TYPE_DATASET)) == NULL) {
1218 NDMP_LOG(LOG_DEBUG, "chkpnt_creationtime: open %s failed",
1219 chk_name);
1220 (void) mutex_unlock(&zlib_mtx);
1221 return (-1);
1222 }
1223
1224 *tp = zfs_prop_get_int(zhp, ZFS_PROP_CREATION);
1225 zfs_close(zhp);
1226 (void) mutex_unlock(&zlib_mtx);
1227
1228 return (0);
1229 }
1230
1231
1232 /*
1233 * Get the ZFS volume name out of the given path
1234 */
1235 int
1236 get_zfsvolname(char *volname, int len, char *path)
1237 {
1238 struct stat64 stbuf;
1239 struct extmnttab ent;
1240 FILE *mntfp;
1241 int rv;
1242
1243 *volname = '\0';
1244 if (stat64(path, &stbuf) != 0) {
1245 return (-1);
1246 }
1247
1248 if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
1249 return (-1);
1250 }
1251 while ((rv = getextmntent(mntfp, &ent, 0)) == 0) {
1252 if (makedevice(ent.mnt_major, ent.mnt_minor) ==
1253 stbuf.st_dev)
1254 break;
1255 }
1256
1257 if (rv == 0 &&
1258 strcmp(ent.mnt_fstype, MNTTYPE_ZFS) == 0)
1259 (void) strlcpy(volname, ent.mnt_special, len);
1260 else
1261 rv = -1;
1262
1263 (void) fclose(mntfp);
1264 return (rv);
1265 }
1266
1267
1268 /*
1269 * Check if the volume type is snapshot volume
1270 */
1271 boolean_t
1272 fs_is_chkpntvol(char *path)
1273 {
1274 zfs_handle_t *zhp;
1275 char vol[ZFS_MAX_DATASET_NAME_LEN];
1276
1277 if (!path || !*path)
1278 return (FALSE);
1279
1280 if (get_zfsvolname(vol, sizeof (vol), path) == -1)
1281 return (FALSE);
1282
|
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
25 * permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39 /* Copyright 2017 Nexenta Systems, Inc. All rights reserved. */
40
41 #include <sys/errno.h>
42 #include <syslog.h>
43 #include <ctype.h>
44 #include <stdlib.h>
45 #include <time.h>
46 #include <sys/types.h>
47 #include <unistd.h>
48 #include <libzfs.h>
49 #include <pthread.h>
50 #include "tlm.h"
51 #include "tlm_proto.h"
52 #include <ndmpd_prop.h>
53 #include <sys/mtio.h>
54 #include <sys/mnttab.h>
55 #include <sys/mntent.h>
56 #include <sys/statvfs.h>
57 #include <sys/scsi/impl/uscsi.h>
58 #include <sys/scsi/scsi.h>
59 #include <sys/mtio.h>
60 #include <thread.h>
61 #include <synch.h>
62 #include <sys/mutex.h>
304
305 /*
306 * verify the tar header checksum
307 */
308 int
309 tlm_vfy_tar_checksum(tlm_tar_hdr_t *tar_hdr)
310 {
311 int chksum = oct_atoi(tar_hdr->th_chksum);
312 uchar_t *p = (uchar_t *)tar_hdr;
313 int sum = 0; /* initial value of checksum */
314 int i; /* loop counter */
315
316 /*
317 * compute the checksum
318 */
319 for (i = 0; i < RECORDSIZE; i++) {
320 sum += p[i] & 0xFF;
321 }
322
323 if (sum == 0) {
324 syslog(LOG_DEBUG,
325 "should be %d, is 0", chksum);
326 /* a zero record ==> end of tar file */
327 return (0);
328 }
329
330 /*
331 * subtract out the label's checksum values
332 * this lets us undo the old checksum "in-
333 * place", no need to swap blanks in and out
334 */
335 for (i = 0; i < 8; i++) {
336 sum -= 0xFF & tar_hdr->th_chksum[i];
337 }
338
339 /*
340 * replace the old checksum field with blanks
341 */
342 sum += ' ' * 8;
343
344 if (sum != chksum) {
345 syslog(LOG_DEBUG,
346 "should be %d, is %d", chksum, sum);
347 }
348
349 return ((sum == chksum) ? 1 : -1);
350 }
351
352 /*
353 * get internal scsi_sasd entry for this tape drive
354 */
355 int
356 tlm_get_scsi_sasd_entry(int lib, int drv)
357 {
358 int entry;
359 int i, n;
360 scsi_link_t *sl;
361 tlm_drive_t *dp;
362
363 entry = -1;
364 dp = tlm_drive(lib, drv);
365 if (!dp) {
366 syslog(LOG_DEBUG, "NULL dp for (%d.%d)", lib, drv);
367 } else if (!dp->td_slink) {
368 syslog(LOG_DEBUG, "NULL dp->td_slink for (%d.%d)", lib, drv);
369 } else if (!dp->td_slink->sl_sa) {
370 syslog(LOG_DEBUG, "NULL dp->td_slink->sl_sa for (%d.%d)",
371 lib, drv);
372 } else {
373 /* search through the SASD table */
374 n = sasd_dev_count();
375 for (i = 0; i < n; i++) {
376 sl = sasd_dev_slink(i);
377 if (!sl)
378 continue;
379
380 if (dp->td_slink->sl_sa == sl->sl_sa &&
381 dp->td_scsi_id == sl->sl_sid &&
382 dp->td_lun == sl->sl_lun) {
383 /* all 3 variables match */
384 entry = i;
385 break;
386 }
387 }
388 }
389
390 return (entry);
483 */
484 void
485 lbrlog_callbacks_done(lbr_fhlog_call_backs_t *p)
486 {
487 if (p != NULL)
488 (void) free((char *)p);
489 }
490
491 /*
492 * Call back for file history directory info
493 */
494 int
495 tlm_log_fhdir(tlm_job_stats_t *job_stats, char *dir, struct stat64 *stp,
496 fs_fhandle_t *fhp)
497 {
498 int rv;
499 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
500
501 rv = 0;
502 if (job_stats == NULL) {
503 syslog(LOG_DEBUG, "log_fhdir: jstat is NULL");
504 } else if (dir == NULL) {
505 syslog(LOG_DEBUG, "log_fhdir: dir is NULL");
506 } else if (stp == NULL) {
507 syslog(LOG_DEBUG, "log_fhdir: stp is NULL");
508 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
509 == NULL) {
510 syslog(LOG_DEBUG, "log_fhdir: cbp is NULL");
511 } else if (cbp->fh_log_dir == NULL) {
512 syslog(LOG_DEBUG, "log_fhdir: callback is NULL");
513 } else
514 rv = (*cbp->fh_log_dir)(cbp, dir, stp, fhp);
515
516 return (rv);
517 }
518
519 /*
520 * Call back for file history node info
521 */
522 int
523 tlm_log_fhnode(tlm_job_stats_t *job_stats, char *dir, char *file,
524 struct stat64 *stp, u_longlong_t off)
525 {
526 int rv;
527 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
528
529 rv = 0;
530 if (job_stats == NULL) {
531 syslog(LOG_DEBUG, "log_fhnode: jstat is NULL");
532 } else if (dir == NULL) {
533 syslog(LOG_DEBUG, "log_fhnode: dir is NULL");
534 } else if (file == NULL) {
535 syslog(LOG_DEBUG, "log_fhnode: file is NULL");
536 } else if (stp == NULL) {
537 syslog(LOG_DEBUG, "log_fhnode: stp is NULL");
538 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
539 == NULL) {
540 syslog(LOG_DEBUG, "log_fhnode: cbp is NULL");
541 } else if (cbp->fh_log_node == NULL) {
542 syslog(LOG_DEBUG, "log_fhnode: callback is NULL");
543 } else
544 rv = (*cbp->fh_log_node)(cbp, dir, file, stp, off);
545
546 return (rv);
547 }
548
549 /*
550 * Call back for file history path info
551 */
552 int
553 tlm_log_fhpath_name(tlm_job_stats_t *job_stats, char *pathname,
554 struct stat64 *stp, u_longlong_t off)
555 {
556 int rv;
557 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
558
559 rv = 0;
560 if (!job_stats) {
561 syslog(LOG_DEBUG, "log_fhpath_name: jstat is NULL");
562 } else if (!pathname) {
563 syslog(LOG_DEBUG, "log_fhpath_name: pathname is NULL");
564 } else if (!stp) {
565 syslog(LOG_DEBUG, "log_fhpath_name: stp is NULL");
566 } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
567 == 0) {
568 syslog(LOG_DEBUG, "log_fhpath_name: cbp is NULL");
569 } else if (!cbp->fh_logpname) {
570 syslog(LOG_DEBUG, "log_fhpath_name: callback is NULL");
571 } else
572 rv = (*cbp->fh_logpname)(cbp, pathname, stp, off);
573
574 return (rv);
575 }
576
577
578 /*
579 * Log call back to report the entry recovery
580 */
581 int
582 tlm_entry_restored(tlm_job_stats_t *job_stats, char *name, int pos)
583 {
584 lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
585
586 if (job_stats == NULL) {
587 syslog(LOG_DEBUG, "entry_restored: jstat is NULL");
588 return (0);
589 }
590 cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks;
591 if (cbp == NULL) {
592 syslog(LOG_DEBUG, "entry_restored is NULL");
593 return (0);
594 }
595 return (*cbp->fh_logpname)(cbp, name, 0, (longlong_t)pos);
596 }
597 /*
598 * NDMP support ends here.
599 */
600
601 /*
602 * Function: tlm_cat_path
603 * Concatenates two path names
604 * or directory name and file name
605 * into a buffer passed by the caller. A slash
606 * is inserted if required. Buffer is assumed
607 * to hold PATH_MAX characters.
608 *
609 * Parameters:
610 * char *buf - buffer to write new dir/name string
611 * char *dir - directory name
612 * char *name - file name
631 fmt = "%s%s";
632 } else {
633 fmt = "%s/%s";
634 }
635
636 /* check for ".../" and "/...." */
637 if ((dirlen > 0) && (dir[dirlen - 1] == '/') && (*name == '/'))
638 name += strspn(name, "/");
639
640 /* LINTED variable format */
641 (void) snprintf(buf, TLM_MAX_PATH_NAME, fmt, dir, name);
642
643 return (TRUE);
644 }
645
646 /*
647 * Get the checkpoint (snapshot) creation time.
648 * This is necessary to check for checkpoints not being stale.
649 */
650 int
651 tlm_get_chkpnt_time(char *path, time_t *tp)
652 {
653 zfs_handle_t *zhp;
654
655 if (path == NULL || *path == '\0' || tp == NULL) {
656 syslog(LOG_ERR, "tlm_get_chkpnt_time: bad params");
657 return (-1);
658 }
659
660 (void) mutex_lock(&zlib_mtx);
661 if ((zhp = zfs_open(zlibh, path, ZFS_TYPE_DATASET)) == NULL) {
662 syslog(LOG_DEBUG, "tlm_get_chkpnt_time: open %s failed",
663 path);
664 (void) mutex_unlock(&zlib_mtx);
665 return (-1);
666 }
667
668 *tp = zfs_prop_get_int(zhp, ZFS_PROP_CREATION);
669
670 zfs_close(zhp);
671 (void) mutex_unlock(&zlib_mtx);
672
673 return (0);
674 }
675
676 /*
677 * Release an array of pointers and the pointers themselves.
678 */
679 void
680 tlm_release_list(char **lpp)
681 {
682 char **save;
683
684 if ((save = lpp) == 0)
685 return;
686
687 while (*lpp)
688 free(*lpp++);
689
690 free(save);
691 }
692
693 /*
694 * Print the list of array of strings in the backup log
695 */
696 void
697 tlm_log_list(char *title, char **lpp)
698 {
699 int i;
700
701 if (!lpp)
702 return;
703
704 syslog(LOG_DEBUG, "%s:", title);
705
706 for (i = 0; *lpp; lpp++, i++)
707 syslog(LOG_DEBUG, "%d: [%s]", i, *lpp);
708 }
709
710 /*
711 * Insert the backup snapshot name into the path.
712 *
713 * Input:
714 * name: Original path name.
715 *
716 * Output:
717 * name: Original name modified to include a snapshot.
718 *
719 * Returns:
720 * Original name modified to include a snapshot.
721 */
722 char *
723 tlm_build_snapshot_name(char *name, char *sname, char *jname)
724 {
725 zfs_handle_t *zhp;
726 char volname[ZFS_MAX_DATASET_NAME_LEN] = {'\0'};
727 char mountpoint[PATH_MAX] = {'\0'};
728 char zpoolname[ZFS_MAX_DATASET_NAME_LEN] = {'\0'};
729 char *slash, *rest;
730
731 if (get_zfsvolname(volname, ZFS_MAX_DATASET_NAME_LEN, name) == -1)
732 goto notzfs;
733
734 (void) mutex_lock(&zlib_mtx);
735 if ((zlibh == NULL) ||
736 (zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == NULL) {
737 (void) mutex_unlock(&zlib_mtx);
738 goto notzfs;
739 }
740
741 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, PATH_MAX, NULL,
742 NULL, 0, B_FALSE) != 0) {
743 zfs_close(zhp);
744 (void) mutex_unlock(&zlib_mtx);
745 goto notzfs;
746 }
747
748 zfs_close(zhp);
749 (void) mutex_unlock(&zlib_mtx);
750
751 (void) strlcpy(zpoolname, volname, ZFS_MAX_DATASET_NAME_LEN);
752 slash = strchr(zpoolname, '/');
753 if (slash != 0) {
754 *slash = '\0';
755 }
756
757 rest = name + strlen(mountpoint);
758 (void) snprintf(sname,
759 TLM_MAX_PATH_NAME, "/%s/%s%s", zpoolname, jname, rest);
760
761 return (sname);
762
763 notzfs:
764 (void) strlcpy(sname, name, TLM_MAX_PATH_NAME);
765 return (sname);
766 }
767
768 /*
769 * Remove the checkpoint from a path name.
770 *
771 * Input:
772 * name: Full pathname with checkpoint embeded.
773 *
774 * Output:
775 * unchkp_name: real pathname with no checkpoint.
776 *
777 * Returns:
778 * Pointer to the un-checkpointed path.
779 */
816 unchkp_name[i] = name[i];
817 break;
818 }
819 }
820 return (name);
821 }
822
823 /*
824 * see if we should exclude this file.
825 */
826 boolean_t
827 tlm_is_excluded(char *dir, char *name, char **excl_files)
828 {
829 int i;
830 char full_name[TLM_MAX_PATH_NAME];
831
832 if (!dir || !name || !excl_files)
833 return (FALSE);
834
835 if (!tlm_cat_path(full_name, dir, name)) {
836 syslog(LOG_DEBUG, "Path too long [%s][%s]",
837 dir, name);
838 return (FALSE);
839 }
840 for (i = 0; excl_files[i] != 0; i++) {
841 if (match(excl_files[i], full_name)) {
842 return (TRUE);
843 }
844 }
845 return (FALSE);
846 }
847
848 /*
849 * Check if the path is too long
850 */
851 boolean_t
852 tlm_is_too_long(int checkpointed, char *dir, char *nm)
853 {
854 int nlen, tot;
855
856 tot = 0;
870 */
871 longlong_t
872 tlm_get_data_offset(tlm_cmd_t *lcmds)
873 {
874 if (!lcmds)
875 return (0LL);
876
877 return (lcmds->tc_buffers->tbs_offset);
878 }
879
880 /*
881 * Enable the barcode capability on the library
882 */
883 void
884 tlm_enable_barcode(int l)
885 {
886 tlm_library_t *lp;
887
888 if ((lp = tlm_library(l))) {
889 lp->tl_capability_barcodes = TRUE;
890 syslog(LOG_DEBUG,
891 "Barcode capability on library %d enabled.", l);
892 }
893 }
894
895 /*
896 * SASD SCSI support
897 */
898 static scsi_adapter_t my_sa;
899 static int sasd_drive_count = 0;
900 static scsi_sasd_drive_t *scsi_sasd_drives[128];
901
902 /*
903 * Count of SCSI devices
904 */
905 int
906 sasd_dev_count(void)
907 {
908 return (sasd_drive_count);
909 }
910
1015 * Go through the attached devices and detect the tape
1016 * and robot by checking the /dev entries
1017 */
1018 int
1019 probe_scsi(void)
1020 {
1021 DIR *dirp;
1022 struct dirent *dp;
1023 scsi_adapter_t *sa = &my_sa;
1024 char *p;
1025 int lun = 0;
1026 int sid = 0;
1027 char *drive_type;
1028
1029 /* Initialize the scsi adapter link */
1030 sa->sa_link_head.sl_next = &sa->sa_link_head;
1031
1032 /* Scan for the changer */
1033 dirp = opendir(SCSI_CHANGER_DIR);
1034 if (dirp == NULL) {
1035 syslog(LOG_DEBUG,
1036 "Changer directory read error %s", SCSI_CHANGER_DIR);
1037 } else {
1038 while ((dp = readdir(dirp)) != NULL) {
1039 if ((strcmp(dp->d_name, ".") == 0) ||
1040 (strcmp(dp->d_name, "..") == 0))
1041 continue;
1042
1043 if ((p = strchr(dp->d_name, 'd')) != NULL) {
1044 lun = atoi(++p);
1045 p = strchr(dp->d_name, 't');
1046 sid = atoi(++p);
1047 }
1048 else
1049 sid = atoi(dp->d_name);
1050
1051 scsi_sasd_attach(sa, 0, lun, dp->d_name,
1052 DTYPE_CHANGER);
1053 }
1054 (void) closedir(dirp);
1055 }
1056
1057 /* Scan for tape drives */
1058 dirp = opendir(SCSI_TAPE_DIR);
1059 if (dirp == NULL) {
1060 syslog(LOG_DEBUG,
1061 "Tape directory read error %s", SCSI_TAPE_DIR);
1062 } else {
1063 drive_type = ndmpd_get_prop(NDMP_DRIVE_TYPE);
1064
1065 if ((strcasecmp(drive_type, "sysv") != 0) &&
1066 (strcasecmp(drive_type, "bsd") != 0)) {
1067 syslog(LOG_ERR, "Invalid ndmpd/drive-type value. "
1068 "Valid values are 'sysv' and 'bsd'.");
1069 return (-1);
1070 }
1071
1072 while ((dp = readdir(dirp)) != NULL) {
1073 if ((strcmp(dp->d_name, ".") == 0) ||
1074 (strcmp(dp->d_name, "..") == 0))
1075 continue;
1076
1077 /* Skip special modes */
1078 if (strpbrk(dp->d_name, "chlmu") != NULL)
1079 continue;
1080
1081 /* Pick the non-rewind device */
1082 if (strchr(dp->d_name, 'n') == NULL)
1083 continue;
1084
1085 if (strcasecmp(drive_type, "sysv") == 0) {
1086 if (strchr(dp->d_name, 'b') != NULL)
1087 continue;
1155 }
1156
1157 /*
1158 * Return the SCSI adapter structure
1159 */
1160 /*ARGSUSED*/
1161 scsi_adapter_t *
1162 scsi_get_adapter(int adapter)
1163 {
1164 return (&my_sa);
1165 }
1166
1167 /*
1168 * IOCTL wrapper with retries
1169 */
1170 int
1171 tlm_ioctl(int fd, int cmd, void *data)
1172 {
1173 int retries = 0;
1174
1175 syslog(LOG_DEBUG, "tlm_ioctl fd %d cmd %d", fd, cmd);
1176 if (fd == 0 || data == NULL)
1177 return (EINVAL);
1178
1179 do {
1180 if (ioctl(fd, cmd, data) == 0)
1181 break;
1182
1183 if (errno != EIO && errno != 0) {
1184 syslog(LOG_ERR,
1185 "Failed to send command to device: %m.");
1186 syslog(LOG_DEBUG, "IOCTL error %d", errno);
1187 return (errno);
1188 }
1189 (void) sleep(1);
1190 } while (retries++ < MAXIORETRY);
1191
1192 return (0);
1193 }
1194
1195 /*
1196 * Checkpoint or snapshot calls
1197 */
1198
1199 /*
1200 * Get the snapshot creation time
1201 */
1202 int
1203 chkpnt_creationtime_bypattern(char *volname, char *pattern, time_t *tp)
1204 {
1205 char chk_name[PATH_MAX];
1206 zfs_handle_t *zhp;
1207 char *p;
1208
1209 if (!volname || !*volname)
1210 return (-1);
1211
1212 /* Should also return -1 if checkpoint not enabled */
1213
1214 /* Remove the leading slash */
1215 p = volname;
1216 while (*p == '/')
1217 p++;
1218
1219 (void) strlcpy(chk_name, p, PATH_MAX);
1220 (void) strlcat(chk_name, "@", PATH_MAX);
1221 (void) strlcat(chk_name, pattern, PATH_MAX);
1222
1223 (void) mutex_lock(&zlib_mtx);
1224 if ((zhp = zfs_open(zlibh, chk_name, ZFS_TYPE_DATASET)) == NULL) {
1225 syslog(LOG_DEBUG, "chkpnt_creationtime: open %s failed",
1226 chk_name);
1227 (void) mutex_unlock(&zlib_mtx);
1228 return (-1);
1229 }
1230
1231 *tp = zfs_prop_get_int(zhp, ZFS_PROP_CREATION);
1232 zfs_close(zhp);
1233 (void) mutex_unlock(&zlib_mtx);
1234
1235 return (0);
1236 }
1237
1238
1239 /*
1240 * Get the ZFS volume name out of the given path
1241 */
1242 int
1243 get_zfsvolname(char *volname, int len, char *path)
1244 {
1245 struct stat64 stbuf;
1246 struct extmnttab ent;
1247 FILE *mntfp;
1248 int rv = 0;
1249
1250 *volname = '\0';
1251 if (stat64(path, &stbuf) != 0) {
1252 syslog(LOG_DEBUG, "stat64 failed open %s - %s",
1253 volname, path);
1254 return (-1);
1255 }
1256
1257 if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
1258 syslog(LOG_DEBUG, "failed open mnttab");
1259 return (-1);
1260 }
1261 while ((rv = getextmntent(mntfp, &ent, 0)) == 0) {
1262 if (makedevice(ent.mnt_major, ent.mnt_minor) ==
1263 stbuf.st_dev)
1264 break;
1265 }
1266
1267 if (rv == 0 &&
1268 strcmp(ent.mnt_fstype, MNTTYPE_ZFS) == 0) {
1269 (void) strlcpy(volname, ent.mnt_special, len);
1270 } else {
1271 rv = -1;
1272 }
1273 (void) fclose(mntfp);
1274 return (rv);
1275 }
1276
1277
1278 /*
1279 * Check if the volume type is snapshot volume
1280 */
1281 boolean_t
1282 fs_is_chkpntvol(char *path)
1283 {
1284 zfs_handle_t *zhp;
1285 char vol[ZFS_MAX_DATASET_NAME_LEN];
1286
1287 if (!path || !*path)
1288 return (FALSE);
1289
1290 if (get_zfsvolname(vol, sizeof (vol), path) == -1)
1291 return (FALSE);
1292
|