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 
 
 |