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