1 /*
   2  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2015 by Delphix. All rights reserved.
   4  */
   5 
   6 /*
   7  * BSD 3 Clause License
   8  *
   9  * Copyright (c) 2007, The Storage Networking Industry Association.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  *      - Redistributions of source code must retain the above copyright
  15  *        notice, this list of conditions and the following disclaimer.
  16  *
  17  *      - Redistributions in binary form must reproduce the above copyright
  18  *        notice, this list of conditions and the following disclaimer in
  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>
  60 #include <sys/sysmacros.h>
  61 #include <sys/mkdev.h>
  62 
  63 /*
  64  * Tar archiving ops vector
  65  */
  66 tm_ops_t tm_tar_ops = {
  67         "tar",
  68         tar_putfile,
  69         tar_putdir,
  70         NULL,
  71         tar_getfile,
  72         tar_getdir,
  73         NULL
  74 };
  75 
  76 extern  libzfs_handle_t *zlibh;
  77 extern  mutex_t zlib_mtx;
  78 
  79 /*
  80  * get the next tape buffer from the drive's pool of buffers
  81  */
  82 /*ARGSUSED*/
  83 char *
  84 tlm_get_write_buffer(long want, long *actual_size,
  85     tlm_buffers_t *buffers, int zero)
  86 {
  87         int     buf = buffers->tbs_buffer_in;
  88         tlm_buffer_t *buffer = &buffers->tbs_buffer[buf];
  89         int     align_size = RECORDSIZE - 1;
  90         char    *rec;
  91 
  92         /*
  93          * make sure the allocation is in chunks of 512 bytes
  94          */
  95         want += align_size;
  96         want &= ~align_size;
  97 
  98         *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
  99         if (*actual_size <= 0) {
 100                 /*
 101                  * no room, send this one
 102                  * and wait for a free one
 103                  */
 104                 if (!buffer->tb_full) {
 105                         /*
 106                          * we are now ready to send a full buffer
 107                          * instead of trying to get a new buffer
 108                          *
 109                          * do not send if we failed to get a buffer
 110                          * on the previous call
 111                          */
 112                         buffer->tb_full = TRUE;
 113 
 114                         /*
 115                          * tell the writer that a buffer is available
 116                          */
 117                         tlm_buffer_release_in_buf(buffers);
 118 
 119                         buffer = tlm_buffer_advance_in_idx(buffers);
 120                 }
 121 
 122                 buffer = tlm_buffer_in_buf(buffers, NULL);
 123 
 124                 if (buffer->tb_full) {
 125                         /*
 126                          * wait for the writer to free up a buffer
 127                          */
 128                         tlm_buffer_out_buf_timed_wait(buffers, 500);
 129                 }
 130 
 131                 buffer = tlm_buffer_in_buf(buffers, NULL);
 132                 if (buffer->tb_full) {
 133                         /*
 134                          * the next buffer is still full
 135                          * of data from previous activity
 136                          *
 137                          * nothing has changed.
 138                          */
 139                         return (0);
 140                 }
 141 
 142                 buffer->tb_buffer_spot = 0;
 143                 *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
 144         }
 145 
 146         *actual_size = min(want, *actual_size);
 147         rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot];
 148         buffer->tb_buffer_spot += *actual_size;
 149         buffers->tbs_offset += *actual_size;
 150         if (zero) {
 151                 (void) memset(rec, 0, *actual_size);
 152         }
 153         return (rec);
 154 }
 155 
 156 /*
 157  * get a read record from the tape buffer,
 158  * and read a tape block if necessary
 159  */
 160 /*ARGSUSED*/
 161 char *
 162 tlm_get_read_buffer(int want, int *error,
 163     tlm_buffers_t *buffers, int *actual_size)
 164 {
 165         tlm_buffer_t *buffer;
 166         int     align_size = RECORDSIZE - 1;
 167         int     buf;
 168         int     current_size;
 169         char    *rec;
 170 
 171         buf = buffers->tbs_buffer_out;
 172         buffer = &buffers->tbs_buffer[buf];
 173 
 174         /*
 175          * make sure the allocation is in chunks of 512 bytes
 176          */
 177         want += align_size;
 178         want &= ~align_size;
 179 
 180         current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
 181         if (buffer->tb_full && current_size <= 0) {
 182                 /*
 183                  * no more data, release this
 184                  * one and go get another
 185                  */
 186 
 187                 /*
 188                  * tell the reader that a buffer is available
 189                  */
 190                 buffer->tb_full = FALSE;
 191                 tlm_buffer_release_out_buf(buffers);
 192 
 193                 buffer = tlm_buffer_advance_out_idx(buffers);
 194                 current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
 195         }
 196 
 197         if (!buffer->tb_full) {
 198                 /*
 199                  * next buffer is not full yet.
 200                  * wait for the reader.
 201                  */
 202                 tlm_buffer_in_buf_timed_wait(buffers, 500);
 203 
 204                 buffer = tlm_buffer_out_buf(buffers, NULL);
 205                 if (!buffer->tb_full) {
 206                         /*
 207                          * we do not have anything from the tape yet
 208                          */
 209                         return (0);
 210                 }
 211 
 212                 current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
 213         }
 214 
 215         /* Make sure we got something */
 216         if (current_size <= 0)
 217                 return (NULL);
 218 
 219         current_size = min(want, current_size);
 220         rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot];
 221         buffer->tb_buffer_spot += current_size;
 222         *actual_size = current_size;
 223 
 224         /*
 225          * the error flag is only sent back one time,
 226          * since the flag refers to a previous read
 227          * attempt, not the data in this buffer.
 228          */
 229         *error = buffer->tb_errno;
 230 
 231         return (rec);
 232 }
 233 
 234 
 235 /*
 236  * unread a previously read buffer back to the tape buffer
 237  */
 238 void
 239 tlm_unget_read_buffer(tlm_buffers_t *buffers, int size)
 240 {
 241         tlm_buffer_t *buffer;
 242         int     align_size = RECORDSIZE - 1;
 243         int     buf;
 244         int     current_size;
 245 
 246         buf = buffers->tbs_buffer_out;
 247         buffer = &buffers->tbs_buffer[buf];
 248 
 249         /*
 250          * make sure the allocation is in chunks of 512 bytes
 251          */
 252         size += align_size;
 253         size &= ~align_size;
 254 
 255         current_size = min(size, buffer->tb_buffer_spot);
 256         buffer->tb_buffer_spot -= current_size;
 257 }
 258 
 259 
 260 /*
 261  * unwrite a previously written buffer
 262  */
 263 void
 264 tlm_unget_write_buffer(tlm_buffers_t *buffers, int size)
 265 {
 266         tlm_buffer_t *buffer;
 267         int     align_size = RECORDSIZE - 1;
 268         int     buf;
 269         int     current_size;
 270 
 271         buf = buffers->tbs_buffer_in;
 272         buffer = &buffers->tbs_buffer[buf];
 273 
 274         /*
 275          * make sure the allocation is in chunks of 512 bytes
 276          */
 277         size += align_size;
 278         size &= ~align_size;
 279 
 280         current_size = min(size, buffer->tb_buffer_spot);
 281         buffer->tb_buffer_spot -= current_size;
 282 }
 283 
 284 
 285 /*
 286  * build a checksum for a TAR header record
 287  */
 288 void
 289 tlm_build_header_checksum(tlm_tar_hdr_t *r)
 290 {
 291         int     i;
 292         int     sum = 0;
 293         char *c = (char *)r;
 294 
 295         (void) memcpy(r->th_chksum, CHKBLANKS, strlen(CHKBLANKS));
 296         for (i = 0; i < RECORDSIZE; i++) {
 297                 sum += c[i] & 0xFF;
 298         }
 299         (void) snprintf(r->th_chksum, sizeof (r->th_chksum), "%6o", sum);
 300 }
 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);
 387 }
 388 
 389 /*
 390  * get the OS device name for this tape
 391  */
 392 char *
 393 tlm_get_tape_name(int lib, int drv)
 394 {
 395         int entry;
 396 
 397         entry = tlm_get_scsi_sasd_entry(lib, drv);
 398         if (entry >= 0) {
 399                 sasd_drive_t *sd;
 400 
 401                 if ((sd = sasd_drive(entry)) != 0)
 402                         return (sd->sd_name);
 403         }
 404 
 405         return ("");
 406 }
 407 
 408 /*
 409  * create the IPC area between the reader and writer
 410  */
 411 tlm_cmd_t *
 412 tlm_create_reader_writer_ipc(boolean_t write, long data_transfer_size)
 413 {
 414         tlm_cmd_t *cmd;
 415 
 416         cmd = ndmp_malloc(sizeof (tlm_cmd_t));
 417         if (cmd == NULL)
 418                 return (NULL);
 419 
 420         cmd->tc_reader = TLM_BACKUP_RUN;
 421         cmd->tc_writer = TLM_BACKUP_RUN;
 422         cmd->tc_ref = 1;
 423 
 424         cmd->tc_buffers = tlm_allocate_buffers(write, data_transfer_size);
 425         if (cmd->tc_buffers == NULL) {
 426                 free(cmd);
 427                 return (NULL);
 428         }
 429 
 430         (void) mutex_init(&cmd->tc_mtx, 0, NULL);
 431         (void) cond_init(&cmd->tc_cv, 0, NULL);
 432 
 433         return (cmd);
 434 }
 435 
 436 /*
 437  * release(destroy) the IPC between the reader and writer
 438  */
 439 void
 440 tlm_release_reader_writer_ipc(tlm_cmd_t *cmd)
 441 {
 442         if (--cmd->tc_ref <= 0) {
 443                 (void) mutex_lock(&cmd->tc_mtx);
 444                 tlm_release_buffers(cmd->tc_buffers);
 445                 (void) cond_destroy(&cmd->tc_cv);
 446                 (void) mutex_unlock(&cmd->tc_mtx);
 447                 (void) mutex_destroy(&cmd->tc_mtx);
 448                 free(cmd);
 449         }
 450 }
 451 
 452 
 453 /*
 454  * NDMP support begins here.
 455  */
 456 
 457 /*
 458  * Initialize the file history callback functions
 459  */
 460 lbr_fhlog_call_backs_t *
 461 lbrlog_callbacks_init(void *cookie, path_hist_func_t log_pname_func,
 462     dir_hist_func_t log_dir_func, node_hist_func_t log_node_func)
 463 {
 464         lbr_fhlog_call_backs_t *p;
 465 
 466         p = ndmp_malloc(sizeof (lbr_fhlog_call_backs_t));
 467         if (p == NULL)
 468                 return (NULL);
 469 
 470         p->fh_cookie = cookie;
 471         p->fh_logpname = (func_t)log_pname_func;
 472         p->fh_log_dir = (func_t)log_dir_func;
 473         p->fh_log_node = (func_t)log_node_func;
 474         return (p);
 475 }
 476 
 477 /*
 478  * Cleanup the callbacks
 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
 611  *
 612  * Returns:
 613  *      TRUE            - No errors. buf contains the dir/name string
 614  *      FALSE           - Error. buf is not modified.
 615  */
 616 boolean_t
 617 tlm_cat_path(char *buf, char *dir, char *name)
 618 {
 619         char *fmt;
 620         int dirlen = strlen(dir);
 621         int filelen = strlen(name);
 622 
 623         if ((dirlen + filelen + 1) >= PATH_MAX) {
 624                 return (FALSE);
 625         }
 626 
 627         if (*dir == '\0' || *name == '\0' || dir[dirlen - 1] == '/' ||
 628             *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  */
 773 char *
 774 tlm_remove_checkpoint(char *name, char *unchkp_name)
 775 {
 776         char *cp;
 777         int i;
 778         int plen;
 779 
 780         unchkp_name[0] = name[0];
 781         plen = strlen(TLM_SNAPSHOT_PREFIX);
 782         for (i = 1; i <= TLM_VOLNAME_MAX_LENGTH + 1; i++) {
 783                 switch (name[i]) {
 784                 case '.':
 785                         if (strncmp(&name[i], TLM_SNAPSHOT_PREFIX,
 786                             plen) == 0) {
 787                                 unchkp_name[i] = '\0';
 788                                 i += plen;
 789                                 if (name[i] == '\0') {
 790                                         /*
 791                                          * name == "/v1.chkpnt"
 792                                          */
 793                                         return (unchkp_name);
 794                                 }
 795                                 if ((cp = strchr(&name[++i], '/')) != NULL) {
 796                                         (void) strlcat(unchkp_name, cp,
 797                                             TLM_VOLNAME_MAX_LENGTH + 1);
 798                                 }
 799                                 return (unchkp_name);
 800                         } else {
 801                                 unchkp_name[i] = name[i];
 802                         }
 803                         break;
 804                 case '/':
 805                         return (name);
 806                 case 0:
 807                         return (name);
 808                 default:
 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;
 850         if (dir)
 851                 tot += strlen(dir);
 852         if (checkpointed)
 853                 tot += strlen(TLM_SNAPSHOT_DIR) + 1;
 854         if (nm) {
 855                 if ((nlen = strlen(nm)) > 0)
 856                         tot += nlen + 1;
 857         }
 858         return ((tot >= PATH_MAX) ? TRUE : FALSE);
 859 }
 860 
 861 /*
 862  * Get the data offset of inside the buffer
 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 
 904 /*
 905  * Return the SCSI device name
 906  */
 907 char *
 908 sasd_slink_name(scsi_link_t *slink)
 909 {
 910         int i;
 911 
 912         for (i = 0; i < sasd_drive_count; i++) {
 913                 if (&scsi_sasd_drives[i]->ss_slink == slink)
 914                         return (scsi_sasd_drives[i]->ss_sd.sd_name);
 915         }
 916         return (NULL);
 917 }
 918 
 919 /*
 920  * Return the SCSI drive structure
 921  */
 922 sasd_drive_t *
 923 sasd_slink_drive(scsi_link_t *slink)
 924 {
 925         int i;
 926 
 927         for (i = 0; i < sasd_drive_count; i++) {
 928                 if (&scsi_sasd_drives[i]->ss_slink == slink)
 929                         return (&scsi_sasd_drives[i]->ss_sd);
 930         }
 931         return (NULL);
 932 }
 933 
 934 /*
 935  * Return the SCSI link pointer for the given index
 936  */
 937 scsi_link_t *
 938 sasd_dev_slink(int entry)
 939 {
 940         scsi_link_t *rv;
 941 
 942         if (entry >= 0 && entry < sasd_drive_count)
 943                 rv = &scsi_sasd_drives[entry]->ss_slink;
 944         else
 945                 rv = NULL;
 946 
 947         return (rv);
 948 }
 949 
 950 /*
 951  * Return the SCSI drive for the given index
 952  */
 953 sasd_drive_t *
 954 sasd_drive(int entry)
 955 {
 956         sasd_drive_t *rv;
 957 
 958         if (entry >= 0 && entry < sasd_drive_count)
 959                 rv = &scsi_sasd_drives[entry]->ss_sd;
 960         else
 961                 rv = NULL;
 962 
 963         return (rv);
 964 }
 965 
 966 /*
 967  * Attach the SCSI device by updating the structures
 968  */
 969 void
 970 scsi_sasd_attach(scsi_adapter_t *sa, int sid, int lun, char *name,
 971     int type)
 972 {
 973         scsi_link_t *sl, *next;
 974         scsi_sasd_drive_t *ssd;
 975 
 976         ssd = ndmp_malloc(sizeof (scsi_sasd_drive_t));
 977         if (ssd == NULL)
 978                 return;
 979 
 980         scsi_sasd_drives[sasd_drive_count++] = ssd;
 981 
 982         switch (type) {
 983         case DTYPE_CHANGER:
 984                 (void) snprintf(ssd->ss_sd.sd_name,
 985                     sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_CHANGER_DIR,
 986                     name);
 987                 break;
 988         case DTYPE_SEQUENTIAL:
 989                 (void) snprintf(ssd->ss_sd.sd_name,
 990                     sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_TAPE_DIR, name);
 991                 break;
 992         }
 993 
 994         sl = &ssd->ss_slink;
 995         sl->sl_type = type;
 996         sl->sl_sa = sa;
 997         sl->sl_lun = lun;
 998         sl->sl_sid = sid;
 999         sl->sl_requested_max_active = 1;
1000 
1001         /* Insert slink */
1002         next = sa->sa_link_head.sl_next;
1003         sa->sa_link_head.sl_next = sl;
1004         sl->sl_next = next;
1005 }
1006 
1007 /*
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;
1081                         } else if (strcasecmp(drive_type, "bsd") == 0) {
1082                                 if (strchr(dp->d_name, 'b') == NULL)
1083                                         continue;
1084                         }
1085 
1086                         sid = atoi(dp->d_name);
1087 
1088                         /*
1089                          * SCSI ID should match with the ID of the device
1090                          * (will be checked by SCSI get elements page later)
1091                          */
1092                         scsi_sasd_attach(sa, sid, 0, dp->d_name,
1093                             DTYPE_SEQUENTIAL);
1094                 }
1095                 (void) closedir(dirp);
1096         }
1097 
1098         return (0);
1099 }
1100 
1101 /*
1102  * Get the SCSI device type (tape, robot)
1103  */
1104 /*ARGSUSED*/
1105 int
1106 scsi_get_devtype(char *adapter, int sid, int lun)
1107 {
1108         int rv;
1109         scsi_adapter_t *sa = &my_sa;
1110         scsi_link_t *sl, *sh;
1111 
1112         rv = -1;
1113         sh = &sa->sa_link_head;
1114         for (sl = sh->sl_next; sl != sh; sl = sl->sl_next)
1115                 if (sl->sl_sid == sid && sl->sl_lun == lun)
1116                         rv = sl->sl_type;
1117 
1118         return (rv);
1119 }
1120 
1121 
1122 /*
1123  * Check if the SCSI device exists
1124  */
1125 /*ARGSUSED*/
1126 int
1127 scsi_dev_exists(char *adapter, int sid, int lun)
1128 {
1129         scsi_adapter_t *sa = &my_sa;
1130         scsi_link_t *sl, *sh;
1131 
1132         sh = &sa->sa_link_head;
1133         for (sl = sh->sl_next; sl != sh; sl = sl->sl_next)
1134                 if (sl->sl_sid == sid && sl->sl_lun == lun)
1135                         return (1);
1136         return (0);
1137 }
1138 
1139 
1140 /*
1141  * Count of SCSI adapters
1142  */
1143 int
1144 scsi_get_adapter_count(void)
1145 {
1146         /* Currently support one adapter only */
1147         return (1);
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 
1283         (void) mutex_lock(&zlib_mtx);
1284         if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) {
1285                 (void) mutex_unlock(&zlib_mtx);
1286                 return (FALSE);
1287         }
1288 
1289         if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) {
1290                 zfs_close(zhp);
1291                 (void) mutex_unlock(&zlib_mtx);
1292                 return (FALSE);
1293         }
1294         zfs_close(zhp);
1295         (void) mutex_unlock(&zlib_mtx);
1296 
1297         return (TRUE);
1298 }
1299 
1300 /*
1301  * Check if the volume is capable of checkpoints
1302  */
1303 boolean_t
1304 fs_is_chkpnt_enabled(char *path)
1305 {
1306         zfs_handle_t *zhp;
1307         char vol[ZFS_MAX_DATASET_NAME_LEN];
1308 
1309         if (!path || !*path)
1310                 return (FALSE);
1311 
1312         (void) mutex_lock(&zlib_mtx);
1313         if (get_zfsvolname(vol, sizeof (vol), path) == -1) {
1314                 (void) mutex_unlock(&zlib_mtx);
1315                 return (FALSE);
1316         }
1317 
1318         if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) {
1319                 (void) mutex_unlock(&zlib_mtx);
1320                 return (FALSE);
1321         }
1322         zfs_close(zhp);
1323         (void) mutex_unlock(&zlib_mtx);
1324 
1325         return (TRUE);
1326 }
1327 
1328 /*
1329  * Check if the volume is read-only
1330  */
1331 boolean_t
1332 fs_is_rdonly(char *path)
1333 {
1334         return (fs_is_chkpntvol(path));
1335 }
1336 
1337 /*
1338  * Min/max functions
1339  */
1340 unsigned
1341 min(unsigned a, unsigned b)
1342 {
1343         return (a < b ? a : b);
1344 }
1345 
1346 unsigned
1347 max(unsigned a, unsigned b)
1348 {
1349         return (a > b ? a : b);
1350 }
1351 
1352 longlong_t
1353 llmin(longlong_t a, longlong_t b)
1354 {
1355         return (a < b ? a : b);
1356 }