17917SReza.Sabdar@Sun.COM /*
212186SJanice.Chang@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
37917SReza.Sabdar@Sun.COM */
47917SReza.Sabdar@Sun.COM
57917SReza.Sabdar@Sun.COM /*
67917SReza.Sabdar@Sun.COM * BSD 3 Clause License
77917SReza.Sabdar@Sun.COM *
87917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association.
97917SReza.Sabdar@Sun.COM *
107917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without
117917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions
127917SReza.Sabdar@Sun.COM * are met:
137917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright
147917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer.
157917SReza.Sabdar@Sun.COM *
167917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright
177917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in
187917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the
197917SReza.Sabdar@Sun.COM * distribution.
207917SReza.Sabdar@Sun.COM *
217917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA)
227917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote
237917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written
247917SReza.Sabdar@Sun.COM * permission.
257917SReza.Sabdar@Sun.COM *
267917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
277917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
307917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
327917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
337917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
347917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
357917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
367917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE.
377917SReza.Sabdar@Sun.COM */
387917SReza.Sabdar@Sun.COM #include <sys/errno.h>
397917SReza.Sabdar@Sun.COM #include <ctype.h>
407917SReza.Sabdar@Sun.COM #include <stdlib.h>
417917SReza.Sabdar@Sun.COM #include <time.h>
427917SReza.Sabdar@Sun.COM #include <sys/types.h>
437917SReza.Sabdar@Sun.COM #include <unistd.h>
447917SReza.Sabdar@Sun.COM #include <libzfs.h>
457917SReza.Sabdar@Sun.COM #include <pthread.h>
467917SReza.Sabdar@Sun.COM #include "tlm.h"
477917SReza.Sabdar@Sun.COM #include "tlm_proto.h"
48*13051SJanice.Chang@Sun.COM #include <ndmpd_prop.h>
497917SReza.Sabdar@Sun.COM #include <sys/mtio.h>
507917SReza.Sabdar@Sun.COM #include <sys/mnttab.h>
517917SReza.Sabdar@Sun.COM #include <sys/mntent.h>
527917SReza.Sabdar@Sun.COM #include <sys/statvfs.h>
537917SReza.Sabdar@Sun.COM #include <sys/scsi/impl/uscsi.h>
547917SReza.Sabdar@Sun.COM #include <sys/scsi/scsi.h>
557917SReza.Sabdar@Sun.COM #include <sys/mtio.h>
567917SReza.Sabdar@Sun.COM #include <thread.h>
577917SReza.Sabdar@Sun.COM #include <synch.h>
587917SReza.Sabdar@Sun.COM #include <sys/mutex.h>
597917SReza.Sabdar@Sun.COM #include <sys/sysmacros.h>
607917SReza.Sabdar@Sun.COM #include <sys/mkdev.h>
617917SReza.Sabdar@Sun.COM
627917SReza.Sabdar@Sun.COM /*
637917SReza.Sabdar@Sun.COM * Tar archiving ops vector
647917SReza.Sabdar@Sun.COM */
657917SReza.Sabdar@Sun.COM tm_ops_t tm_tar_ops = {
667917SReza.Sabdar@Sun.COM "tar",
677917SReza.Sabdar@Sun.COM tar_putfile,
687917SReza.Sabdar@Sun.COM tar_putdir,
697917SReza.Sabdar@Sun.COM NULL,
707917SReza.Sabdar@Sun.COM tar_getfile,
717917SReza.Sabdar@Sun.COM tar_getdir,
727917SReza.Sabdar@Sun.COM NULL
737917SReza.Sabdar@Sun.COM };
747917SReza.Sabdar@Sun.COM
757917SReza.Sabdar@Sun.COM extern libzfs_handle_t *zlibh;
767917SReza.Sabdar@Sun.COM extern mutex_t zlib_mtx;
777917SReza.Sabdar@Sun.COM
787917SReza.Sabdar@Sun.COM /*
797917SReza.Sabdar@Sun.COM * get the next tape buffer from the drive's pool of buffers
807917SReza.Sabdar@Sun.COM */
817917SReza.Sabdar@Sun.COM /*ARGSUSED*/
827917SReza.Sabdar@Sun.COM char *
tlm_get_write_buffer(long want,long * actual_size,tlm_buffers_t * buffers,int zero)837917SReza.Sabdar@Sun.COM tlm_get_write_buffer(long want, long *actual_size,
847917SReza.Sabdar@Sun.COM tlm_buffers_t *buffers, int zero)
857917SReza.Sabdar@Sun.COM {
867917SReza.Sabdar@Sun.COM int buf = buffers->tbs_buffer_in;
877917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer = &buffers->tbs_buffer[buf];
887917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1;
897917SReza.Sabdar@Sun.COM char *rec;
907917SReza.Sabdar@Sun.COM
917917SReza.Sabdar@Sun.COM /*
927917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes
937917SReza.Sabdar@Sun.COM */
947917SReza.Sabdar@Sun.COM want += align_size;
957917SReza.Sabdar@Sun.COM want &= ~align_size;
967917SReza.Sabdar@Sun.COM
977917SReza.Sabdar@Sun.COM *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
987917SReza.Sabdar@Sun.COM if (*actual_size <= 0) {
997917SReza.Sabdar@Sun.COM /*
1007917SReza.Sabdar@Sun.COM * no room, send this one
1017917SReza.Sabdar@Sun.COM * and wait for a free one
1027917SReza.Sabdar@Sun.COM */
1037917SReza.Sabdar@Sun.COM if (!buffer->tb_full) {
1047917SReza.Sabdar@Sun.COM /*
1057917SReza.Sabdar@Sun.COM * we are now ready to send a full buffer
1067917SReza.Sabdar@Sun.COM * instead of trying to get a new buffer
1077917SReza.Sabdar@Sun.COM *
1087917SReza.Sabdar@Sun.COM * do not send if we failed to get a buffer
1097917SReza.Sabdar@Sun.COM * on the previous call
1107917SReza.Sabdar@Sun.COM */
1117917SReza.Sabdar@Sun.COM buffer->tb_full = TRUE;
1127917SReza.Sabdar@Sun.COM
1137917SReza.Sabdar@Sun.COM /*
1147917SReza.Sabdar@Sun.COM * tell the writer that a buffer is available
1157917SReza.Sabdar@Sun.COM */
1167917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(buffers);
1177917SReza.Sabdar@Sun.COM
1187917SReza.Sabdar@Sun.COM buffer = tlm_buffer_advance_in_idx(buffers);
1197917SReza.Sabdar@Sun.COM }
1207917SReza.Sabdar@Sun.COM
1217917SReza.Sabdar@Sun.COM buffer = tlm_buffer_in_buf(buffers, NULL);
1227917SReza.Sabdar@Sun.COM
1237917SReza.Sabdar@Sun.COM if (buffer->tb_full) {
1247917SReza.Sabdar@Sun.COM /*
1257917SReza.Sabdar@Sun.COM * wait for the writer to free up a buffer
1267917SReza.Sabdar@Sun.COM */
1277917SReza.Sabdar@Sun.COM tlm_buffer_out_buf_timed_wait(buffers, 500);
1287917SReza.Sabdar@Sun.COM }
1297917SReza.Sabdar@Sun.COM
1307917SReza.Sabdar@Sun.COM buffer = tlm_buffer_in_buf(buffers, NULL);
1317917SReza.Sabdar@Sun.COM if (buffer->tb_full) {
1327917SReza.Sabdar@Sun.COM /*
1337917SReza.Sabdar@Sun.COM * the next buffer is still full
1347917SReza.Sabdar@Sun.COM * of data from previous activity
1357917SReza.Sabdar@Sun.COM *
1367917SReza.Sabdar@Sun.COM * nothing has changed.
1377917SReza.Sabdar@Sun.COM */
1387917SReza.Sabdar@Sun.COM return (0);
1397917SReza.Sabdar@Sun.COM }
1407917SReza.Sabdar@Sun.COM
1417917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot = 0;
1427917SReza.Sabdar@Sun.COM *actual_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
1437917SReza.Sabdar@Sun.COM }
1447917SReza.Sabdar@Sun.COM
1457917SReza.Sabdar@Sun.COM *actual_size = min(want, *actual_size);
1467917SReza.Sabdar@Sun.COM rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot];
1477917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot += *actual_size;
1487917SReza.Sabdar@Sun.COM buffers->tbs_offset += *actual_size;
1497917SReza.Sabdar@Sun.COM if (zero) {
1507917SReza.Sabdar@Sun.COM (void) memset(rec, 0, *actual_size);
1517917SReza.Sabdar@Sun.COM }
1527917SReza.Sabdar@Sun.COM return (rec);
1537917SReza.Sabdar@Sun.COM }
1547917SReza.Sabdar@Sun.COM
1557917SReza.Sabdar@Sun.COM /*
1567917SReza.Sabdar@Sun.COM * get a read record from the tape buffer,
1577917SReza.Sabdar@Sun.COM * and read a tape block if necessary
1587917SReza.Sabdar@Sun.COM */
1597917SReza.Sabdar@Sun.COM /*ARGSUSED*/
1607917SReza.Sabdar@Sun.COM char *
tlm_get_read_buffer(int want,int * error,tlm_buffers_t * buffers,int * actual_size)1617917SReza.Sabdar@Sun.COM tlm_get_read_buffer(int want, int *error,
1627917SReza.Sabdar@Sun.COM tlm_buffers_t *buffers, int *actual_size)
1637917SReza.Sabdar@Sun.COM {
1647917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer;
1657917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1;
1667917SReza.Sabdar@Sun.COM int buf;
1677917SReza.Sabdar@Sun.COM int current_size;
1687917SReza.Sabdar@Sun.COM char *rec;
1697917SReza.Sabdar@Sun.COM
1707917SReza.Sabdar@Sun.COM buf = buffers->tbs_buffer_out;
1717917SReza.Sabdar@Sun.COM buffer = &buffers->tbs_buffer[buf];
1727917SReza.Sabdar@Sun.COM
1737917SReza.Sabdar@Sun.COM /*
1747917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes
1757917SReza.Sabdar@Sun.COM */
1767917SReza.Sabdar@Sun.COM want += align_size;
1777917SReza.Sabdar@Sun.COM want &= ~align_size;
1787917SReza.Sabdar@Sun.COM
1797917SReza.Sabdar@Sun.COM current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
1807917SReza.Sabdar@Sun.COM if (buffer->tb_full && current_size <= 0) {
1817917SReza.Sabdar@Sun.COM /*
1827917SReza.Sabdar@Sun.COM * no more data, release this
1837917SReza.Sabdar@Sun.COM * one and go get another
1847917SReza.Sabdar@Sun.COM */
1857917SReza.Sabdar@Sun.COM
1867917SReza.Sabdar@Sun.COM /*
1877917SReza.Sabdar@Sun.COM * tell the reader that a buffer is available
1887917SReza.Sabdar@Sun.COM */
1897917SReza.Sabdar@Sun.COM buffer->tb_full = FALSE;
1907917SReza.Sabdar@Sun.COM tlm_buffer_release_out_buf(buffers);
1917917SReza.Sabdar@Sun.COM
1927917SReza.Sabdar@Sun.COM buffer = tlm_buffer_advance_out_idx(buffers);
1937917SReza.Sabdar@Sun.COM current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
1947917SReza.Sabdar@Sun.COM }
1957917SReza.Sabdar@Sun.COM
1967917SReza.Sabdar@Sun.COM if (!buffer->tb_full) {
1977917SReza.Sabdar@Sun.COM /*
1987917SReza.Sabdar@Sun.COM * next buffer is not full yet.
1997917SReza.Sabdar@Sun.COM * wait for the reader.
2007917SReza.Sabdar@Sun.COM */
2017917SReza.Sabdar@Sun.COM tlm_buffer_in_buf_timed_wait(buffers, 500);
2027917SReza.Sabdar@Sun.COM
2037917SReza.Sabdar@Sun.COM buffer = tlm_buffer_out_buf(buffers, NULL);
2047917SReza.Sabdar@Sun.COM if (!buffer->tb_full) {
2057917SReza.Sabdar@Sun.COM /*
2067917SReza.Sabdar@Sun.COM * we do not have anything from the tape yet
2077917SReza.Sabdar@Sun.COM */
2087917SReza.Sabdar@Sun.COM return (0);
2097917SReza.Sabdar@Sun.COM }
2107917SReza.Sabdar@Sun.COM
2117917SReza.Sabdar@Sun.COM current_size = buffer->tb_buffer_size - buffer->tb_buffer_spot;
2127917SReza.Sabdar@Sun.COM }
2137917SReza.Sabdar@Sun.COM
2147917SReza.Sabdar@Sun.COM /* Make sure we got something */
2157917SReza.Sabdar@Sun.COM if (current_size <= 0)
2167917SReza.Sabdar@Sun.COM return (NULL);
2177917SReza.Sabdar@Sun.COM
2187917SReza.Sabdar@Sun.COM current_size = min(want, current_size);
2197917SReza.Sabdar@Sun.COM rec = &buffer->tb_buffer_data[buffer->tb_buffer_spot];
2207917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot += current_size;
2217917SReza.Sabdar@Sun.COM *actual_size = current_size;
2227917SReza.Sabdar@Sun.COM
2237917SReza.Sabdar@Sun.COM /*
2247917SReza.Sabdar@Sun.COM * the error flag is only sent back one time,
2257917SReza.Sabdar@Sun.COM * since the flag refers to a previous read
2267917SReza.Sabdar@Sun.COM * attempt, not the data in this buffer.
2277917SReza.Sabdar@Sun.COM */
2287917SReza.Sabdar@Sun.COM *error = buffer->tb_errno;
2297917SReza.Sabdar@Sun.COM
2307917SReza.Sabdar@Sun.COM return (rec);
2317917SReza.Sabdar@Sun.COM }
2327917SReza.Sabdar@Sun.COM
2337917SReza.Sabdar@Sun.COM
2347917SReza.Sabdar@Sun.COM /*
2357917SReza.Sabdar@Sun.COM * unread a previously read buffer back to the tape buffer
2367917SReza.Sabdar@Sun.COM */
2377917SReza.Sabdar@Sun.COM void
tlm_unget_read_buffer(tlm_buffers_t * buffers,int size)2387917SReza.Sabdar@Sun.COM tlm_unget_read_buffer(tlm_buffers_t *buffers, int size)
2397917SReza.Sabdar@Sun.COM {
2407917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer;
2417917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1;
2427917SReza.Sabdar@Sun.COM int buf;
2437917SReza.Sabdar@Sun.COM int current_size;
2447917SReza.Sabdar@Sun.COM
2457917SReza.Sabdar@Sun.COM buf = buffers->tbs_buffer_out;
2467917SReza.Sabdar@Sun.COM buffer = &buffers->tbs_buffer[buf];
2477917SReza.Sabdar@Sun.COM
2487917SReza.Sabdar@Sun.COM /*
2497917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes
2507917SReza.Sabdar@Sun.COM */
2517917SReza.Sabdar@Sun.COM size += align_size;
2527917SReza.Sabdar@Sun.COM size &= ~align_size;
2537917SReza.Sabdar@Sun.COM
2547917SReza.Sabdar@Sun.COM current_size = min(size, buffer->tb_buffer_spot);
2557917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot -= current_size;
2567917SReza.Sabdar@Sun.COM }
2577917SReza.Sabdar@Sun.COM
2587917SReza.Sabdar@Sun.COM
2597917SReza.Sabdar@Sun.COM /*
2607917SReza.Sabdar@Sun.COM * unwrite a previously written buffer
2617917SReza.Sabdar@Sun.COM */
2627917SReza.Sabdar@Sun.COM void
tlm_unget_write_buffer(tlm_buffers_t * buffers,int size)2637917SReza.Sabdar@Sun.COM tlm_unget_write_buffer(tlm_buffers_t *buffers, int size)
2647917SReza.Sabdar@Sun.COM {
2657917SReza.Sabdar@Sun.COM tlm_buffer_t *buffer;
2667917SReza.Sabdar@Sun.COM int align_size = RECORDSIZE - 1;
2677917SReza.Sabdar@Sun.COM int buf;
2687917SReza.Sabdar@Sun.COM int current_size;
2697917SReza.Sabdar@Sun.COM
2707917SReza.Sabdar@Sun.COM buf = buffers->tbs_buffer_in;
2717917SReza.Sabdar@Sun.COM buffer = &buffers->tbs_buffer[buf];
2727917SReza.Sabdar@Sun.COM
2737917SReza.Sabdar@Sun.COM /*
2747917SReza.Sabdar@Sun.COM * make sure the allocation is in chunks of 512 bytes
2757917SReza.Sabdar@Sun.COM */
2767917SReza.Sabdar@Sun.COM size += align_size;
2777917SReza.Sabdar@Sun.COM size &= ~align_size;
2787917SReza.Sabdar@Sun.COM
2797917SReza.Sabdar@Sun.COM current_size = min(size, buffer->tb_buffer_spot);
2807917SReza.Sabdar@Sun.COM buffer->tb_buffer_spot -= current_size;
2817917SReza.Sabdar@Sun.COM }
2827917SReza.Sabdar@Sun.COM
2837917SReza.Sabdar@Sun.COM
2847917SReza.Sabdar@Sun.COM /*
2857917SReza.Sabdar@Sun.COM * build a checksum for a TAR header record
2867917SReza.Sabdar@Sun.COM */
2877917SReza.Sabdar@Sun.COM void
tlm_build_header_checksum(tlm_tar_hdr_t * r)2887917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tlm_tar_hdr_t *r)
2897917SReza.Sabdar@Sun.COM {
2907917SReza.Sabdar@Sun.COM int i;
2917917SReza.Sabdar@Sun.COM int sum = 0;
2927917SReza.Sabdar@Sun.COM char *c = (char *)r;
2937917SReza.Sabdar@Sun.COM
2947917SReza.Sabdar@Sun.COM (void) memcpy(r->th_chksum, CHKBLANKS, strlen(CHKBLANKS));
2957917SReza.Sabdar@Sun.COM for (i = 0; i < RECORDSIZE; i++) {
2967917SReza.Sabdar@Sun.COM sum += c[i] & 0xFF;
2977917SReza.Sabdar@Sun.COM }
2987917SReza.Sabdar@Sun.COM (void) snprintf(r->th_chksum, sizeof (r->th_chksum), "%6o", sum);
2997917SReza.Sabdar@Sun.COM }
3007917SReza.Sabdar@Sun.COM
3017917SReza.Sabdar@Sun.COM /*
3027917SReza.Sabdar@Sun.COM * verify the tar header checksum
3037917SReza.Sabdar@Sun.COM */
3047917SReza.Sabdar@Sun.COM int
tlm_vfy_tar_checksum(tlm_tar_hdr_t * tar_hdr)3057917SReza.Sabdar@Sun.COM tlm_vfy_tar_checksum(tlm_tar_hdr_t *tar_hdr)
3067917SReza.Sabdar@Sun.COM {
3077917SReza.Sabdar@Sun.COM int chksum = oct_atoi(tar_hdr->th_chksum);
3087917SReza.Sabdar@Sun.COM uchar_t *p = (uchar_t *)tar_hdr;
3097917SReza.Sabdar@Sun.COM int sum = 0; /* initial value of checksum */
3107917SReza.Sabdar@Sun.COM int i; /* loop counter */
3117917SReza.Sabdar@Sun.COM
3127917SReza.Sabdar@Sun.COM /*
3137917SReza.Sabdar@Sun.COM * compute the checksum
3147917SReza.Sabdar@Sun.COM */
3157917SReza.Sabdar@Sun.COM for (i = 0; i < RECORDSIZE; i++) {
3167917SReza.Sabdar@Sun.COM sum += p[i] & 0xFF;
3177917SReza.Sabdar@Sun.COM }
3187917SReza.Sabdar@Sun.COM
3197917SReza.Sabdar@Sun.COM if (sum == 0) {
3207917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
3217917SReza.Sabdar@Sun.COM "should be %d, is 0", chksum);
3227917SReza.Sabdar@Sun.COM /* a zero record ==> end of tar file */
3237917SReza.Sabdar@Sun.COM return (0);
3247917SReza.Sabdar@Sun.COM }
3257917SReza.Sabdar@Sun.COM
3267917SReza.Sabdar@Sun.COM /*
3277917SReza.Sabdar@Sun.COM * subtract out the label's checksum values
3287917SReza.Sabdar@Sun.COM * this lets us undo the old checksum "in-
3297917SReza.Sabdar@Sun.COM * place", no need to swap blanks in and out
3307917SReza.Sabdar@Sun.COM */
3317917SReza.Sabdar@Sun.COM for (i = 0; i < 8; i++) {
3327917SReza.Sabdar@Sun.COM sum -= 0xFF & tar_hdr->th_chksum[i];
3337917SReza.Sabdar@Sun.COM }
3347917SReza.Sabdar@Sun.COM
3357917SReza.Sabdar@Sun.COM /*
3367917SReza.Sabdar@Sun.COM * replace the old checksum field with blanks
3377917SReza.Sabdar@Sun.COM */
3387917SReza.Sabdar@Sun.COM sum += ' ' * 8;
3397917SReza.Sabdar@Sun.COM
3407917SReza.Sabdar@Sun.COM if (sum != chksum)
3417917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
3427917SReza.Sabdar@Sun.COM "should be %d, is %d", chksum, sum);
3437917SReza.Sabdar@Sun.COM
3447917SReza.Sabdar@Sun.COM return ((sum == chksum) ? 1 : -1);
3457917SReza.Sabdar@Sun.COM }
3467917SReza.Sabdar@Sun.COM
3477917SReza.Sabdar@Sun.COM /*
3487917SReza.Sabdar@Sun.COM * get internal scsi_sasd entry for this tape drive
3497917SReza.Sabdar@Sun.COM */
3507917SReza.Sabdar@Sun.COM int
tlm_get_scsi_sasd_entry(int lib,int drv)3517917SReza.Sabdar@Sun.COM tlm_get_scsi_sasd_entry(int lib, int drv)
3527917SReza.Sabdar@Sun.COM {
3537917SReza.Sabdar@Sun.COM int entry;
3547917SReza.Sabdar@Sun.COM int i, n;
3557917SReza.Sabdar@Sun.COM scsi_link_t *sl;
3567917SReza.Sabdar@Sun.COM tlm_drive_t *dp;
3577917SReza.Sabdar@Sun.COM
3587917SReza.Sabdar@Sun.COM entry = -1;
3597917SReza.Sabdar@Sun.COM dp = tlm_drive(lib, drv);
3607917SReza.Sabdar@Sun.COM if (!dp) {
3617917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NULL dp for (%d.%d)", lib, drv);
3627917SReza.Sabdar@Sun.COM } else if (!dp->td_slink) {
3637917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink for (%d.%d)", lib, drv);
3647917SReza.Sabdar@Sun.COM } else if (!dp->td_slink->sl_sa) {
3657917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NULL dp->td_slink->sl_sa for (%d.%d)",
3667917SReza.Sabdar@Sun.COM lib, drv);
3677917SReza.Sabdar@Sun.COM } else {
3687917SReza.Sabdar@Sun.COM /* search through the SASD table */
3697917SReza.Sabdar@Sun.COM n = sasd_dev_count();
3707917SReza.Sabdar@Sun.COM for (i = 0; i < n; i++) {
3717917SReza.Sabdar@Sun.COM sl = sasd_dev_slink(i);
3727917SReza.Sabdar@Sun.COM if (!sl)
3737917SReza.Sabdar@Sun.COM continue;
3747917SReza.Sabdar@Sun.COM
3757917SReza.Sabdar@Sun.COM if (dp->td_slink->sl_sa == sl->sl_sa &&
3767917SReza.Sabdar@Sun.COM dp->td_scsi_id == sl->sl_sid &&
3777917SReza.Sabdar@Sun.COM dp->td_lun == sl->sl_lun) {
3787917SReza.Sabdar@Sun.COM /* all 3 variables match */
3797917SReza.Sabdar@Sun.COM entry = i;
3807917SReza.Sabdar@Sun.COM break;
3817917SReza.Sabdar@Sun.COM }
3827917SReza.Sabdar@Sun.COM }
3837917SReza.Sabdar@Sun.COM }
3847917SReza.Sabdar@Sun.COM
3857917SReza.Sabdar@Sun.COM return (entry);
3867917SReza.Sabdar@Sun.COM }
3877917SReza.Sabdar@Sun.COM
3887917SReza.Sabdar@Sun.COM /*
3897917SReza.Sabdar@Sun.COM * get the OS device name for this tape
3907917SReza.Sabdar@Sun.COM */
3917917SReza.Sabdar@Sun.COM char *
tlm_get_tape_name(int lib,int drv)3927917SReza.Sabdar@Sun.COM tlm_get_tape_name(int lib, int drv)
3937917SReza.Sabdar@Sun.COM {
3947917SReza.Sabdar@Sun.COM int entry;
3957917SReza.Sabdar@Sun.COM
3967917SReza.Sabdar@Sun.COM entry = tlm_get_scsi_sasd_entry(lib, drv);
3977917SReza.Sabdar@Sun.COM if (entry >= 0) {
3987917SReza.Sabdar@Sun.COM sasd_drive_t *sd;
3997917SReza.Sabdar@Sun.COM
4007917SReza.Sabdar@Sun.COM if ((sd = sasd_drive(entry)) != 0)
4017917SReza.Sabdar@Sun.COM return (sd->sd_name);
4027917SReza.Sabdar@Sun.COM }
4037917SReza.Sabdar@Sun.COM
4047917SReza.Sabdar@Sun.COM return ("");
4057917SReza.Sabdar@Sun.COM }
4067917SReza.Sabdar@Sun.COM
4077917SReza.Sabdar@Sun.COM /*
4087917SReza.Sabdar@Sun.COM * create the IPC area between the reader and writer
4097917SReza.Sabdar@Sun.COM */
4107917SReza.Sabdar@Sun.COM tlm_cmd_t *
tlm_create_reader_writer_ipc(boolean_t write,long data_transfer_size)4117917SReza.Sabdar@Sun.COM tlm_create_reader_writer_ipc(boolean_t write, long data_transfer_size)
4127917SReza.Sabdar@Sun.COM {
4137917SReza.Sabdar@Sun.COM tlm_cmd_t *cmd;
4147917SReza.Sabdar@Sun.COM
4157917SReza.Sabdar@Sun.COM cmd = ndmp_malloc(sizeof (tlm_cmd_t));
4167917SReza.Sabdar@Sun.COM if (cmd == NULL)
4177917SReza.Sabdar@Sun.COM return (NULL);
4187917SReza.Sabdar@Sun.COM
4197917SReza.Sabdar@Sun.COM cmd->tc_reader = TLM_BACKUP_RUN;
4207917SReza.Sabdar@Sun.COM cmd->tc_writer = TLM_BACKUP_RUN;
4217917SReza.Sabdar@Sun.COM cmd->tc_ref = 1;
4227917SReza.Sabdar@Sun.COM
4237917SReza.Sabdar@Sun.COM cmd->tc_buffers = tlm_allocate_buffers(write, data_transfer_size);
4247917SReza.Sabdar@Sun.COM if (cmd->tc_buffers == NULL) {
4257917SReza.Sabdar@Sun.COM free(cmd);
4267917SReza.Sabdar@Sun.COM return (NULL);
4277917SReza.Sabdar@Sun.COM }
4287917SReza.Sabdar@Sun.COM
4297917SReza.Sabdar@Sun.COM (void) mutex_init(&cmd->tc_mtx, 0, NULL);
4307917SReza.Sabdar@Sun.COM (void) cond_init(&cmd->tc_cv, 0, NULL);
4317917SReza.Sabdar@Sun.COM
4327917SReza.Sabdar@Sun.COM return (cmd);
4337917SReza.Sabdar@Sun.COM }
4347917SReza.Sabdar@Sun.COM
4357917SReza.Sabdar@Sun.COM /*
4367917SReza.Sabdar@Sun.COM * release(destroy) the IPC between the reader and writer
4377917SReza.Sabdar@Sun.COM */
4387917SReza.Sabdar@Sun.COM void
tlm_release_reader_writer_ipc(tlm_cmd_t * cmd)4397917SReza.Sabdar@Sun.COM tlm_release_reader_writer_ipc(tlm_cmd_t *cmd)
4407917SReza.Sabdar@Sun.COM {
4417917SReza.Sabdar@Sun.COM if (--cmd->tc_ref <= 0) {
4427917SReza.Sabdar@Sun.COM (void) mutex_lock(&cmd->tc_mtx);
4437917SReza.Sabdar@Sun.COM tlm_release_buffers(cmd->tc_buffers);
4447917SReza.Sabdar@Sun.COM (void) cond_destroy(&cmd->tc_cv);
4457917SReza.Sabdar@Sun.COM (void) mutex_unlock(&cmd->tc_mtx);
4467917SReza.Sabdar@Sun.COM (void) mutex_destroy(&cmd->tc_mtx);
4477917SReza.Sabdar@Sun.COM free(cmd);
4487917SReza.Sabdar@Sun.COM }
4497917SReza.Sabdar@Sun.COM }
4507917SReza.Sabdar@Sun.COM
4517917SReza.Sabdar@Sun.COM
4527917SReza.Sabdar@Sun.COM /*
4537917SReza.Sabdar@Sun.COM * NDMP support begins here.
4547917SReza.Sabdar@Sun.COM */
4557917SReza.Sabdar@Sun.COM
4567917SReza.Sabdar@Sun.COM /*
4577917SReza.Sabdar@Sun.COM * Initialize the file history callback functions
4587917SReza.Sabdar@Sun.COM */
4597917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *
lbrlog_callbacks_init(void * cookie,path_hist_func_t log_pname_func,dir_hist_func_t log_dir_func,node_hist_func_t log_node_func)4607917SReza.Sabdar@Sun.COM lbrlog_callbacks_init(void *cookie, path_hist_func_t log_pname_func,
4617917SReza.Sabdar@Sun.COM dir_hist_func_t log_dir_func, node_hist_func_t log_node_func)
4627917SReza.Sabdar@Sun.COM {
4637917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *p;
4647917SReza.Sabdar@Sun.COM
4657917SReza.Sabdar@Sun.COM p = ndmp_malloc(sizeof (lbr_fhlog_call_backs_t));
4667917SReza.Sabdar@Sun.COM if (p == NULL)
4677917SReza.Sabdar@Sun.COM return (NULL);
4687917SReza.Sabdar@Sun.COM
4697917SReza.Sabdar@Sun.COM p->fh_cookie = cookie;
4707917SReza.Sabdar@Sun.COM p->fh_logpname = (func_t)log_pname_func;
4717917SReza.Sabdar@Sun.COM p->fh_log_dir = (func_t)log_dir_func;
4727917SReza.Sabdar@Sun.COM p->fh_log_node = (func_t)log_node_func;
4737917SReza.Sabdar@Sun.COM return (p);
4747917SReza.Sabdar@Sun.COM }
4757917SReza.Sabdar@Sun.COM
4767917SReza.Sabdar@Sun.COM /*
4777917SReza.Sabdar@Sun.COM * Cleanup the callbacks
4787917SReza.Sabdar@Sun.COM */
4797917SReza.Sabdar@Sun.COM void
lbrlog_callbacks_done(lbr_fhlog_call_backs_t * p)4807917SReza.Sabdar@Sun.COM lbrlog_callbacks_done(lbr_fhlog_call_backs_t *p)
4817917SReza.Sabdar@Sun.COM {
4827917SReza.Sabdar@Sun.COM if (p != NULL)
4837917SReza.Sabdar@Sun.COM (void) free((char *)p);
4847917SReza.Sabdar@Sun.COM }
4857917SReza.Sabdar@Sun.COM
4867917SReza.Sabdar@Sun.COM /*
4877917SReza.Sabdar@Sun.COM * Call back for file history directory info
4887917SReza.Sabdar@Sun.COM */
4897917SReza.Sabdar@Sun.COM int
tlm_log_fhdir(tlm_job_stats_t * job_stats,char * dir,struct stat64 * stp,fs_fhandle_t * fhp)4907917SReza.Sabdar@Sun.COM tlm_log_fhdir(tlm_job_stats_t *job_stats, char *dir, struct stat64 *stp,
4917917SReza.Sabdar@Sun.COM fs_fhandle_t *fhp)
4927917SReza.Sabdar@Sun.COM {
4937917SReza.Sabdar@Sun.COM int rv;
4947917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
4957917SReza.Sabdar@Sun.COM
4967917SReza.Sabdar@Sun.COM rv = 0;
4977917SReza.Sabdar@Sun.COM if (job_stats == NULL) {
4987917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: jstat is NULL");
4997917SReza.Sabdar@Sun.COM } else if (dir == NULL) {
5007917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: dir is NULL");
5017917SReza.Sabdar@Sun.COM } else if (stp == NULL) {
5027917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: stp is NULL");
5037917SReza.Sabdar@Sun.COM } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
5047917SReza.Sabdar@Sun.COM == NULL) {
5057917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: cbp is NULL");
5067917SReza.Sabdar@Sun.COM } else if (cbp->fh_log_dir == NULL) {
5077917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhdir: callback is NULL");
5087917SReza.Sabdar@Sun.COM } else
5097917SReza.Sabdar@Sun.COM rv = (*cbp->fh_log_dir)(cbp, dir, stp, fhp);
5107917SReza.Sabdar@Sun.COM
5117917SReza.Sabdar@Sun.COM return (rv);
5127917SReza.Sabdar@Sun.COM }
5137917SReza.Sabdar@Sun.COM
5147917SReza.Sabdar@Sun.COM /*
5157917SReza.Sabdar@Sun.COM * Call back for file history node info
5167917SReza.Sabdar@Sun.COM */
5177917SReza.Sabdar@Sun.COM int
tlm_log_fhnode(tlm_job_stats_t * job_stats,char * dir,char * file,struct stat64 * stp,u_longlong_t off)5187917SReza.Sabdar@Sun.COM tlm_log_fhnode(tlm_job_stats_t *job_stats, char *dir, char *file,
5197917SReza.Sabdar@Sun.COM struct stat64 *stp, u_longlong_t off)
5207917SReza.Sabdar@Sun.COM {
5217917SReza.Sabdar@Sun.COM int rv;
5227917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
5237917SReza.Sabdar@Sun.COM
5247917SReza.Sabdar@Sun.COM rv = 0;
5257917SReza.Sabdar@Sun.COM if (job_stats == NULL) {
5267917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: jstat is NULL");
5277917SReza.Sabdar@Sun.COM } else if (dir == NULL) {
5287917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: dir is NULL");
5297917SReza.Sabdar@Sun.COM } else if (file == NULL) {
5307917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: file is NULL");
5317917SReza.Sabdar@Sun.COM } else if (stp == NULL) {
5327917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: stp is NULL");
5337917SReza.Sabdar@Sun.COM } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
5347917SReza.Sabdar@Sun.COM == NULL) {
5357917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: cbp is NULL");
5367917SReza.Sabdar@Sun.COM } else if (cbp->fh_log_node == NULL) {
5377917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhnode: callback is NULL");
5387917SReza.Sabdar@Sun.COM } else
5397917SReza.Sabdar@Sun.COM rv = (*cbp->fh_log_node)(cbp, dir, file, stp, off);
5407917SReza.Sabdar@Sun.COM
5417917SReza.Sabdar@Sun.COM return (rv);
5427917SReza.Sabdar@Sun.COM }
5437917SReza.Sabdar@Sun.COM
5447917SReza.Sabdar@Sun.COM /*
5457917SReza.Sabdar@Sun.COM * Call back for file history path info
5467917SReza.Sabdar@Sun.COM */
5477917SReza.Sabdar@Sun.COM int
tlm_log_fhpath_name(tlm_job_stats_t * job_stats,char * pathname,struct stat64 * stp,u_longlong_t off)5487917SReza.Sabdar@Sun.COM tlm_log_fhpath_name(tlm_job_stats_t *job_stats, char *pathname,
5497917SReza.Sabdar@Sun.COM struct stat64 *stp, u_longlong_t off)
5507917SReza.Sabdar@Sun.COM {
5517917SReza.Sabdar@Sun.COM int rv;
5527917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
5537917SReza.Sabdar@Sun.COM
5547917SReza.Sabdar@Sun.COM rv = 0;
5557917SReza.Sabdar@Sun.COM if (!job_stats) {
5567917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: jstat is NULL");
5577917SReza.Sabdar@Sun.COM } else if (!pathname) {
5587917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: pathname is NULL");
5597917SReza.Sabdar@Sun.COM } else if (!stp) {
5607917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: stp is NULL");
5617917SReza.Sabdar@Sun.COM } else if ((cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks)
5627917SReza.Sabdar@Sun.COM == 0) {
5637917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: cbp is NULL");
5647917SReza.Sabdar@Sun.COM } else if (!cbp->fh_logpname) {
5657917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "log_fhpath_name: callback is NULL");
5667917SReza.Sabdar@Sun.COM } else
5677917SReza.Sabdar@Sun.COM rv = (*cbp->fh_logpname)(cbp, pathname, stp, off);
5687917SReza.Sabdar@Sun.COM
5697917SReza.Sabdar@Sun.COM return (rv);
5707917SReza.Sabdar@Sun.COM }
5717917SReza.Sabdar@Sun.COM
5727917SReza.Sabdar@Sun.COM
5737917SReza.Sabdar@Sun.COM /*
5747917SReza.Sabdar@Sun.COM * Log call back to report the entry recovery
5757917SReza.Sabdar@Sun.COM */
5767917SReza.Sabdar@Sun.COM int
tlm_entry_restored(tlm_job_stats_t * job_stats,char * name,int pos)5777917SReza.Sabdar@Sun.COM tlm_entry_restored(tlm_job_stats_t *job_stats, char *name, int pos)
5787917SReza.Sabdar@Sun.COM {
5797917SReza.Sabdar@Sun.COM lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */
5807917SReza.Sabdar@Sun.COM
5817917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "name: \"%s\", pos: %d", name, pos);
5827917SReza.Sabdar@Sun.COM
5837917SReza.Sabdar@Sun.COM if (job_stats == NULL) {
5847917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "entry_restored: jstat is NULL");
5857917SReza.Sabdar@Sun.COM return (0);
5867917SReza.Sabdar@Sun.COM }
5877917SReza.Sabdar@Sun.COM cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks;
5887917SReza.Sabdar@Sun.COM if (cbp == NULL) {
5897917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "entry_restored is NULL");
5907917SReza.Sabdar@Sun.COM return (0);
5917917SReza.Sabdar@Sun.COM }
5927917SReza.Sabdar@Sun.COM return (*cbp->fh_logpname)(cbp, name, 0, (longlong_t)pos);
5937917SReza.Sabdar@Sun.COM }
5947917SReza.Sabdar@Sun.COM /*
5957917SReza.Sabdar@Sun.COM * NDMP support ends here.
5967917SReza.Sabdar@Sun.COM */
5977917SReza.Sabdar@Sun.COM
5987917SReza.Sabdar@Sun.COM /*
5997917SReza.Sabdar@Sun.COM * Function: tlm_cat_path
6007917SReza.Sabdar@Sun.COM * Concatenates two path names
6017917SReza.Sabdar@Sun.COM * or directory name and file name
6027917SReza.Sabdar@Sun.COM * into a buffer passed by the caller. A slash
6037917SReza.Sabdar@Sun.COM * is inserted if required. Buffer is assumed
6047917SReza.Sabdar@Sun.COM * to hold PATH_MAX characters.
6057917SReza.Sabdar@Sun.COM *
6067917SReza.Sabdar@Sun.COM * Parameters:
6077917SReza.Sabdar@Sun.COM * char *buf - buffer to write new dir/name string
6087917SReza.Sabdar@Sun.COM * char *dir - directory name
6097917SReza.Sabdar@Sun.COM * char *name - file name
6107917SReza.Sabdar@Sun.COM *
6117917SReza.Sabdar@Sun.COM * Returns:
6127917SReza.Sabdar@Sun.COM * TRUE - No errors. buf contains the dir/name string
6137917SReza.Sabdar@Sun.COM * FALSE - Error. buf is not modified.
6147917SReza.Sabdar@Sun.COM */
6157917SReza.Sabdar@Sun.COM boolean_t
tlm_cat_path(char * buf,char * dir,char * name)6167917SReza.Sabdar@Sun.COM tlm_cat_path(char *buf, char *dir, char *name)
6177917SReza.Sabdar@Sun.COM {
6187917SReza.Sabdar@Sun.COM char *fmt;
6197917SReza.Sabdar@Sun.COM int dirlen = strlen(dir);
6207917SReza.Sabdar@Sun.COM int filelen = strlen(name);
6217917SReza.Sabdar@Sun.COM
6227917SReza.Sabdar@Sun.COM if ((dirlen + filelen + 1) >= PATH_MAX) {
6237917SReza.Sabdar@Sun.COM return (FALSE);
6247917SReza.Sabdar@Sun.COM }
6257917SReza.Sabdar@Sun.COM
6267917SReza.Sabdar@Sun.COM if (*dir == '\0' || *name == '\0' || dir[dirlen - 1] == '/' ||
6277917SReza.Sabdar@Sun.COM *name == '/') {
6287917SReza.Sabdar@Sun.COM fmt = "%s%s";
6297917SReza.Sabdar@Sun.COM } else {
6307917SReza.Sabdar@Sun.COM fmt = "%s/%s";
6317917SReza.Sabdar@Sun.COM }
6327917SReza.Sabdar@Sun.COM
6337917SReza.Sabdar@Sun.COM /* check for ".../" and "/...." */
6347917SReza.Sabdar@Sun.COM if ((dirlen > 0) && (dir[dirlen - 1] == '/') && (*name == '/'))
6357917SReza.Sabdar@Sun.COM name += strspn(name, "/");
6367917SReza.Sabdar@Sun.COM
6377917SReza.Sabdar@Sun.COM /* LINTED variable format */
6387917SReza.Sabdar@Sun.COM (void) snprintf(buf, TLM_MAX_PATH_NAME, fmt, dir, name);
6397917SReza.Sabdar@Sun.COM
6407917SReza.Sabdar@Sun.COM return (TRUE);
6417917SReza.Sabdar@Sun.COM }
6427917SReza.Sabdar@Sun.COM
6437917SReza.Sabdar@Sun.COM /*
6447917SReza.Sabdar@Sun.COM * Get the checkpoint (snapshot) creation time.
6457917SReza.Sabdar@Sun.COM * This is necessary to check for checkpoints not being stale.
6467917SReza.Sabdar@Sun.COM */
6477917SReza.Sabdar@Sun.COM int
tlm_get_chkpnt_time(char * path,int auto_checkpoint,time_t * tp,char * jname)6487917SReza.Sabdar@Sun.COM tlm_get_chkpnt_time(char *path, int auto_checkpoint, time_t *tp, char *jname)
6497917SReza.Sabdar@Sun.COM {
6507917SReza.Sabdar@Sun.COM char volname[TLM_VOLNAME_MAX_LENGTH];
6517917SReza.Sabdar@Sun.COM char chk_name[PATH_MAX];
6527917SReza.Sabdar@Sun.COM char *cp_nm;
6537917SReza.Sabdar@Sun.COM
6547917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "path [%s] auto_checkpoint: %d",
6557917SReza.Sabdar@Sun.COM path, auto_checkpoint);
6567917SReza.Sabdar@Sun.COM
6577917SReza.Sabdar@Sun.COM if (path == NULL || *path == '\0' || tp == NULL)
6587917SReza.Sabdar@Sun.COM return (-1);
6597917SReza.Sabdar@Sun.COM
6607917SReza.Sabdar@Sun.COM if (get_zfsvolname(volname, TLM_VOLNAME_MAX_LENGTH,
6617917SReza.Sabdar@Sun.COM path) == -1)
6627917SReza.Sabdar@Sun.COM return (-1);
6637917SReza.Sabdar@Sun.COM
6647917SReza.Sabdar@Sun.COM if (auto_checkpoint) {
6657917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "volname [%s]", volname);
66612186SJanice.Chang@Sun.COM (void) snprintf(chk_name, PATH_MAX, "%s", jname);
6677917SReza.Sabdar@Sun.COM return (chkpnt_creationtime_bypattern(volname, chk_name, tp));
6687917SReza.Sabdar@Sun.COM }
6697917SReza.Sabdar@Sun.COM cp_nm = strchr(volname, '@');
6707917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "volname [%s] cp_nm [%s]", volname, cp_nm);
6717917SReza.Sabdar@Sun.COM
6727917SReza.Sabdar@Sun.COM return (chkpnt_creationtime_bypattern(volname, cp_nm, tp));
6737917SReza.Sabdar@Sun.COM }
6747917SReza.Sabdar@Sun.COM
6757917SReza.Sabdar@Sun.COM /*
6767917SReza.Sabdar@Sun.COM * Release an array of pointers and the pointers themselves.
6777917SReza.Sabdar@Sun.COM */
6787917SReza.Sabdar@Sun.COM void
tlm_release_list(char ** lpp)6797917SReza.Sabdar@Sun.COM tlm_release_list(char **lpp)
6807917SReza.Sabdar@Sun.COM {
6817917SReza.Sabdar@Sun.COM char **save;
6827917SReza.Sabdar@Sun.COM
6837917SReza.Sabdar@Sun.COM if ((save = lpp) == 0)
6847917SReza.Sabdar@Sun.COM return;
6857917SReza.Sabdar@Sun.COM
6867917SReza.Sabdar@Sun.COM while (*lpp)
6877917SReza.Sabdar@Sun.COM free(*lpp++);
6887917SReza.Sabdar@Sun.COM
6897917SReza.Sabdar@Sun.COM free(save);
6907917SReza.Sabdar@Sun.COM }
6917917SReza.Sabdar@Sun.COM
6927917SReza.Sabdar@Sun.COM /*
6937917SReza.Sabdar@Sun.COM * Print the list of array of strings in the backup log
6947917SReza.Sabdar@Sun.COM */
6957917SReza.Sabdar@Sun.COM void
tlm_log_list(char * title,char ** lpp)6967917SReza.Sabdar@Sun.COM tlm_log_list(char *title, char **lpp)
6977917SReza.Sabdar@Sun.COM {
6987917SReza.Sabdar@Sun.COM int i;
6997917SReza.Sabdar@Sun.COM
7007917SReza.Sabdar@Sun.COM if (!lpp)
7017917SReza.Sabdar@Sun.COM return;
7027917SReza.Sabdar@Sun.COM
7037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "%s:", title);
7047917SReza.Sabdar@Sun.COM
7057917SReza.Sabdar@Sun.COM for (i = 0; *lpp; lpp++, i++)
7067917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "%d: [%s]", i, *lpp);
7077917SReza.Sabdar@Sun.COM }
7087917SReza.Sabdar@Sun.COM
7097917SReza.Sabdar@Sun.COM /*
7107917SReza.Sabdar@Sun.COM * Insert the backup snapshot name into the path.
7117917SReza.Sabdar@Sun.COM *
7127917SReza.Sabdar@Sun.COM * Input:
71312186SJanice.Chang@Sun.COM * name: Original path name.
7147917SReza.Sabdar@Sun.COM *
7157917SReza.Sabdar@Sun.COM * Output:
71612186SJanice.Chang@Sun.COM * name: Original name modified to include a snapshot.
7177917SReza.Sabdar@Sun.COM *
7187917SReza.Sabdar@Sun.COM * Returns:
71912186SJanice.Chang@Sun.COM * Original name modified to include a snapshot.
7207917SReza.Sabdar@Sun.COM */
7217917SReza.Sabdar@Sun.COM char *
tlm_build_snapshot_name(char * name,char * sname,char * jname)7227917SReza.Sabdar@Sun.COM tlm_build_snapshot_name(char *name, char *sname, char *jname)
7237917SReza.Sabdar@Sun.COM {
7247917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
7257917SReza.Sabdar@Sun.COM char *rest;
7267917SReza.Sabdar@Sun.COM char volname[ZFS_MAXNAMELEN];
7277917SReza.Sabdar@Sun.COM char mountpoint[PATH_MAX];
7287917SReza.Sabdar@Sun.COM
7297917SReza.Sabdar@Sun.COM if (get_zfsvolname(volname, ZFS_MAXNAMELEN, name) == -1)
7307917SReza.Sabdar@Sun.COM goto notzfs;
7317917SReza.Sabdar@Sun.COM
7327917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
7337917SReza.Sabdar@Sun.COM if ((zlibh == NULL) ||
7347917SReza.Sabdar@Sun.COM (zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == NULL) {
7357917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
7367917SReza.Sabdar@Sun.COM goto notzfs;
7377917SReza.Sabdar@Sun.COM }
7387917SReza.Sabdar@Sun.COM
7397917SReza.Sabdar@Sun.COM if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, PATH_MAX, NULL,
7407917SReza.Sabdar@Sun.COM NULL, 0, B_FALSE) != 0) {
7417917SReza.Sabdar@Sun.COM zfs_close(zhp);
7427917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
7437917SReza.Sabdar@Sun.COM goto notzfs;
7447917SReza.Sabdar@Sun.COM }
7457917SReza.Sabdar@Sun.COM
7467917SReza.Sabdar@Sun.COM zfs_close(zhp);
7477917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
7487917SReza.Sabdar@Sun.COM
7497917SReza.Sabdar@Sun.COM rest = name + strlen(mountpoint);
75012186SJanice.Chang@Sun.COM (void) snprintf(sname, TLM_MAX_PATH_NAME, "%s/%s/%s%s", mountpoint,
7517917SReza.Sabdar@Sun.COM TLM_SNAPSHOT_DIR, jname, rest);
7527917SReza.Sabdar@Sun.COM
7537917SReza.Sabdar@Sun.COM return (sname);
7547917SReza.Sabdar@Sun.COM
7557917SReza.Sabdar@Sun.COM notzfs:
7567917SReza.Sabdar@Sun.COM (void) strlcpy(sname, name, TLM_MAX_PATH_NAME);
7577917SReza.Sabdar@Sun.COM return (sname);
7587917SReza.Sabdar@Sun.COM }
7597917SReza.Sabdar@Sun.COM
7607917SReza.Sabdar@Sun.COM /*
7617917SReza.Sabdar@Sun.COM * Remove the checkpoint from a path name.
7627917SReza.Sabdar@Sun.COM *
7637917SReza.Sabdar@Sun.COM * Input:
7647917SReza.Sabdar@Sun.COM * name: Full pathname with checkpoint embeded.
7657917SReza.Sabdar@Sun.COM *
7667917SReza.Sabdar@Sun.COM * Output:
7677917SReza.Sabdar@Sun.COM * unchkp_name: real pathname with no checkpoint.
7687917SReza.Sabdar@Sun.COM *
7697917SReza.Sabdar@Sun.COM * Returns:
7707917SReza.Sabdar@Sun.COM * Pointer to the un-checkpointed path.
7717917SReza.Sabdar@Sun.COM */
7727917SReza.Sabdar@Sun.COM char *
tlm_remove_checkpoint(char * name,char * unchkp_name)7737917SReza.Sabdar@Sun.COM tlm_remove_checkpoint(char *name, char *unchkp_name)
7747917SReza.Sabdar@Sun.COM {
7757917SReza.Sabdar@Sun.COM char *cp;
7767917SReza.Sabdar@Sun.COM int i;
7777917SReza.Sabdar@Sun.COM int plen;
7787917SReza.Sabdar@Sun.COM
7797917SReza.Sabdar@Sun.COM unchkp_name[0] = name[0];
7807917SReza.Sabdar@Sun.COM plen = strlen(TLM_SNAPSHOT_PREFIX);
7817917SReza.Sabdar@Sun.COM for (i = 1; i <= TLM_VOLNAME_MAX_LENGTH + 1; i++) {
7827917SReza.Sabdar@Sun.COM switch (name[i]) {
7837917SReza.Sabdar@Sun.COM case '.':
7847917SReza.Sabdar@Sun.COM if (strncmp(&name[i], TLM_SNAPSHOT_PREFIX,
7857917SReza.Sabdar@Sun.COM plen) == 0) {
7867917SReza.Sabdar@Sun.COM unchkp_name[i] = '\0';
7877917SReza.Sabdar@Sun.COM i += plen;
7887917SReza.Sabdar@Sun.COM if (name[i] == '\0') {
7897917SReza.Sabdar@Sun.COM /*
7907917SReza.Sabdar@Sun.COM * name == "/v1.chkpnt"
7917917SReza.Sabdar@Sun.COM */
7927917SReza.Sabdar@Sun.COM return (unchkp_name);
7937917SReza.Sabdar@Sun.COM }
7947917SReza.Sabdar@Sun.COM if ((cp = strchr(&name[++i], '/')) != NULL) {
7957917SReza.Sabdar@Sun.COM (void) strlcat(unchkp_name, cp,
7967917SReza.Sabdar@Sun.COM TLM_VOLNAME_MAX_LENGTH + 1);
7977917SReza.Sabdar@Sun.COM }
7987917SReza.Sabdar@Sun.COM return (unchkp_name);
7997917SReza.Sabdar@Sun.COM } else {
8007917SReza.Sabdar@Sun.COM unchkp_name[i] = name[i];
8017917SReza.Sabdar@Sun.COM }
8027917SReza.Sabdar@Sun.COM break;
8037917SReza.Sabdar@Sun.COM case '/':
8047917SReza.Sabdar@Sun.COM return (name);
8057917SReza.Sabdar@Sun.COM case 0:
8067917SReza.Sabdar@Sun.COM return (name);
8077917SReza.Sabdar@Sun.COM default:
8087917SReza.Sabdar@Sun.COM unchkp_name[i] = name[i];
8097917SReza.Sabdar@Sun.COM break;
8107917SReza.Sabdar@Sun.COM }
8117917SReza.Sabdar@Sun.COM }
8127917SReza.Sabdar@Sun.COM return (name);
8137917SReza.Sabdar@Sun.COM }
8147917SReza.Sabdar@Sun.COM
8157917SReza.Sabdar@Sun.COM /*
8167917SReza.Sabdar@Sun.COM * see if we should exclude this file.
8177917SReza.Sabdar@Sun.COM */
8187917SReza.Sabdar@Sun.COM boolean_t
tlm_is_excluded(char * dir,char * name,char ** excl_files)8197917SReza.Sabdar@Sun.COM tlm_is_excluded(char *dir, char *name, char **excl_files)
8207917SReza.Sabdar@Sun.COM {
8217917SReza.Sabdar@Sun.COM int i;
8227917SReza.Sabdar@Sun.COM char full_name[TLM_MAX_PATH_NAME];
8237917SReza.Sabdar@Sun.COM
8247917SReza.Sabdar@Sun.COM if (!dir || !name || !excl_files)
8257917SReza.Sabdar@Sun.COM return (FALSE);
8267917SReza.Sabdar@Sun.COM
8277917SReza.Sabdar@Sun.COM if (!tlm_cat_path(full_name, dir, name)) {
8287917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]",
8297917SReza.Sabdar@Sun.COM dir, name);
8307917SReza.Sabdar@Sun.COM return (FALSE);
8317917SReza.Sabdar@Sun.COM }
8327917SReza.Sabdar@Sun.COM for (i = 0; excl_files[i] != 0; i++) {
8337917SReza.Sabdar@Sun.COM if (match(excl_files[i], full_name)) {
8347917SReza.Sabdar@Sun.COM return (TRUE);
8357917SReza.Sabdar@Sun.COM }
8367917SReza.Sabdar@Sun.COM }
8377917SReza.Sabdar@Sun.COM return (FALSE);
8387917SReza.Sabdar@Sun.COM }
8397917SReza.Sabdar@Sun.COM
8407917SReza.Sabdar@Sun.COM /*
8417917SReza.Sabdar@Sun.COM * Check if the path is too long
8427917SReza.Sabdar@Sun.COM */
8437917SReza.Sabdar@Sun.COM boolean_t
tlm_is_too_long(int checkpointed,char * dir,char * nm)8447917SReza.Sabdar@Sun.COM tlm_is_too_long(int checkpointed, char *dir, char *nm)
8457917SReza.Sabdar@Sun.COM {
8467917SReza.Sabdar@Sun.COM int nlen, tot;
8477917SReza.Sabdar@Sun.COM
8487917SReza.Sabdar@Sun.COM tot = 0;
8497917SReza.Sabdar@Sun.COM if (dir)
8507917SReza.Sabdar@Sun.COM tot += strlen(dir);
8517917SReza.Sabdar@Sun.COM if (checkpointed)
8527917SReza.Sabdar@Sun.COM tot += strlen(TLM_SNAPSHOT_DIR) + 1;
8537917SReza.Sabdar@Sun.COM if (nm) {
8547917SReza.Sabdar@Sun.COM if ((nlen = strlen(nm)) > 0)
8557917SReza.Sabdar@Sun.COM tot += nlen + 1;
8567917SReza.Sabdar@Sun.COM }
8577917SReza.Sabdar@Sun.COM return ((tot >= PATH_MAX) ? TRUE : FALSE);
8587917SReza.Sabdar@Sun.COM }
8597917SReza.Sabdar@Sun.COM
8607917SReza.Sabdar@Sun.COM /*
8617917SReza.Sabdar@Sun.COM * Get the data offset of inside the buffer
8627917SReza.Sabdar@Sun.COM */
8637917SReza.Sabdar@Sun.COM longlong_t
tlm_get_data_offset(tlm_cmd_t * lcmds)8647917SReza.Sabdar@Sun.COM tlm_get_data_offset(tlm_cmd_t *lcmds)
8657917SReza.Sabdar@Sun.COM {
8667917SReza.Sabdar@Sun.COM if (!lcmds)
8677917SReza.Sabdar@Sun.COM return (0LL);
8687917SReza.Sabdar@Sun.COM
8697917SReza.Sabdar@Sun.COM return (lcmds->tc_buffers->tbs_offset);
8707917SReza.Sabdar@Sun.COM }
8717917SReza.Sabdar@Sun.COM
8727917SReza.Sabdar@Sun.COM /*
8737917SReza.Sabdar@Sun.COM * Enable the barcode capability on the library
8747917SReza.Sabdar@Sun.COM */
8757917SReza.Sabdar@Sun.COM void
tlm_enable_barcode(int l)8767917SReza.Sabdar@Sun.COM tlm_enable_barcode(int l)
8777917SReza.Sabdar@Sun.COM {
8787917SReza.Sabdar@Sun.COM tlm_library_t *lp;
8797917SReza.Sabdar@Sun.COM
8807917SReza.Sabdar@Sun.COM if ((lp = tlm_library(l))) {
8817917SReza.Sabdar@Sun.COM lp->tl_capability_barcodes = TRUE;
8827917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
8837917SReza.Sabdar@Sun.COM "Barcode capability on library %d enabled.", l);
8847917SReza.Sabdar@Sun.COM }
8857917SReza.Sabdar@Sun.COM }
8867917SReza.Sabdar@Sun.COM
8877917SReza.Sabdar@Sun.COM /*
8887917SReza.Sabdar@Sun.COM * SASD SCSI support
8897917SReza.Sabdar@Sun.COM */
8907917SReza.Sabdar@Sun.COM static scsi_adapter_t my_sa;
8917917SReza.Sabdar@Sun.COM static int sasd_drive_count = 0;
8927917SReza.Sabdar@Sun.COM static scsi_sasd_drive_t *scsi_sasd_drives[128];
8937917SReza.Sabdar@Sun.COM
8947917SReza.Sabdar@Sun.COM /*
8957917SReza.Sabdar@Sun.COM * Count of SCSI devices
8967917SReza.Sabdar@Sun.COM */
8977917SReza.Sabdar@Sun.COM int
sasd_dev_count(void)8987917SReza.Sabdar@Sun.COM sasd_dev_count(void)
8997917SReza.Sabdar@Sun.COM {
9007917SReza.Sabdar@Sun.COM return (sasd_drive_count);
9017917SReza.Sabdar@Sun.COM }
9027917SReza.Sabdar@Sun.COM
9037917SReza.Sabdar@Sun.COM /*
9047917SReza.Sabdar@Sun.COM * Return the SCSI device name
9057917SReza.Sabdar@Sun.COM */
9067917SReza.Sabdar@Sun.COM char *
sasd_slink_name(scsi_link_t * slink)9077917SReza.Sabdar@Sun.COM sasd_slink_name(scsi_link_t *slink)
9087917SReza.Sabdar@Sun.COM {
9097917SReza.Sabdar@Sun.COM int i;
9107917SReza.Sabdar@Sun.COM
9117917SReza.Sabdar@Sun.COM for (i = 0; i < sasd_drive_count; i++) {
9127917SReza.Sabdar@Sun.COM if (&scsi_sasd_drives[i]->ss_slink == slink)
9137917SReza.Sabdar@Sun.COM return (scsi_sasd_drives[i]->ss_sd.sd_name);
9147917SReza.Sabdar@Sun.COM }
9157917SReza.Sabdar@Sun.COM return (NULL);
9167917SReza.Sabdar@Sun.COM }
9177917SReza.Sabdar@Sun.COM
9187917SReza.Sabdar@Sun.COM /*
9197917SReza.Sabdar@Sun.COM * Return the SCSI drive structure
9207917SReza.Sabdar@Sun.COM */
9217917SReza.Sabdar@Sun.COM sasd_drive_t *
sasd_slink_drive(scsi_link_t * slink)9227917SReza.Sabdar@Sun.COM sasd_slink_drive(scsi_link_t *slink)
9237917SReza.Sabdar@Sun.COM {
9247917SReza.Sabdar@Sun.COM int i;
9257917SReza.Sabdar@Sun.COM
9267917SReza.Sabdar@Sun.COM for (i = 0; i < sasd_drive_count; i++) {
9277917SReza.Sabdar@Sun.COM if (&scsi_sasd_drives[i]->ss_slink == slink)
9287917SReza.Sabdar@Sun.COM return (&scsi_sasd_drives[i]->ss_sd);
9297917SReza.Sabdar@Sun.COM }
9307917SReza.Sabdar@Sun.COM return (NULL);
9317917SReza.Sabdar@Sun.COM }
9327917SReza.Sabdar@Sun.COM
9337917SReza.Sabdar@Sun.COM /*
9347917SReza.Sabdar@Sun.COM * Return the SCSI link pointer for the given index
9357917SReza.Sabdar@Sun.COM */
9367917SReza.Sabdar@Sun.COM scsi_link_t *
sasd_dev_slink(int entry)9377917SReza.Sabdar@Sun.COM sasd_dev_slink(int entry)
9387917SReza.Sabdar@Sun.COM {
9397917SReza.Sabdar@Sun.COM scsi_link_t *rv;
9407917SReza.Sabdar@Sun.COM
9417917SReza.Sabdar@Sun.COM if (entry >= 0 && entry < sasd_drive_count)
9427917SReza.Sabdar@Sun.COM rv = &scsi_sasd_drives[entry]->ss_slink;
9437917SReza.Sabdar@Sun.COM else
9447917SReza.Sabdar@Sun.COM rv = NULL;
9457917SReza.Sabdar@Sun.COM
9467917SReza.Sabdar@Sun.COM return (rv);
9477917SReza.Sabdar@Sun.COM }
9487917SReza.Sabdar@Sun.COM
9497917SReza.Sabdar@Sun.COM /*
9507917SReza.Sabdar@Sun.COM * Return the SCSI drive for the given index
9517917SReza.Sabdar@Sun.COM */
9527917SReza.Sabdar@Sun.COM sasd_drive_t *
sasd_drive(int entry)9537917SReza.Sabdar@Sun.COM sasd_drive(int entry)
9547917SReza.Sabdar@Sun.COM {
9557917SReza.Sabdar@Sun.COM sasd_drive_t *rv;
9567917SReza.Sabdar@Sun.COM
9577917SReza.Sabdar@Sun.COM if (entry >= 0 && entry < sasd_drive_count)
9587917SReza.Sabdar@Sun.COM rv = &scsi_sasd_drives[entry]->ss_sd;
9597917SReza.Sabdar@Sun.COM else
9607917SReza.Sabdar@Sun.COM rv = NULL;
9617917SReza.Sabdar@Sun.COM
9627917SReza.Sabdar@Sun.COM return (rv);
9637917SReza.Sabdar@Sun.COM }
9647917SReza.Sabdar@Sun.COM
9657917SReza.Sabdar@Sun.COM /*
9667917SReza.Sabdar@Sun.COM * Attach the SCSI device by updating the structures
9677917SReza.Sabdar@Sun.COM */
9687917SReza.Sabdar@Sun.COM void
scsi_sasd_attach(scsi_adapter_t * sa,int sid,int lun,char * name,int type)9697917SReza.Sabdar@Sun.COM scsi_sasd_attach(scsi_adapter_t *sa, int sid, int lun, char *name,
9707917SReza.Sabdar@Sun.COM int type)
9717917SReza.Sabdar@Sun.COM {
9727917SReza.Sabdar@Sun.COM scsi_link_t *sl, *next;
9737917SReza.Sabdar@Sun.COM scsi_sasd_drive_t *ssd;
9747917SReza.Sabdar@Sun.COM
9757917SReza.Sabdar@Sun.COM ssd = ndmp_malloc(sizeof (scsi_sasd_drive_t));
9767917SReza.Sabdar@Sun.COM if (ssd == NULL)
9777917SReza.Sabdar@Sun.COM return;
9787917SReza.Sabdar@Sun.COM
9797917SReza.Sabdar@Sun.COM scsi_sasd_drives[sasd_drive_count++] = ssd;
9807917SReza.Sabdar@Sun.COM
9817917SReza.Sabdar@Sun.COM switch (type) {
9827917SReza.Sabdar@Sun.COM case DTYPE_CHANGER:
9837917SReza.Sabdar@Sun.COM (void) snprintf(ssd->ss_sd.sd_name,
9847917SReza.Sabdar@Sun.COM sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_CHANGER_DIR,
9857917SReza.Sabdar@Sun.COM name);
9867917SReza.Sabdar@Sun.COM break;
9877917SReza.Sabdar@Sun.COM case DTYPE_SEQUENTIAL:
9887917SReza.Sabdar@Sun.COM (void) snprintf(ssd->ss_sd.sd_name,
9897917SReza.Sabdar@Sun.COM sizeof (ssd->ss_sd.sd_name), "%s/%s", SCSI_TAPE_DIR, name);
9907917SReza.Sabdar@Sun.COM break;
9917917SReza.Sabdar@Sun.COM }
9927917SReza.Sabdar@Sun.COM
9937917SReza.Sabdar@Sun.COM sl = &ssd->ss_slink;
9947917SReza.Sabdar@Sun.COM sl->sl_type = type;
9957917SReza.Sabdar@Sun.COM sl->sl_sa = sa;
9967917SReza.Sabdar@Sun.COM sl->sl_lun = lun;
9977917SReza.Sabdar@Sun.COM sl->sl_sid = sid;
9987917SReza.Sabdar@Sun.COM sl->sl_requested_max_active = 1;
9997917SReza.Sabdar@Sun.COM
10007917SReza.Sabdar@Sun.COM /* Insert slink */
10017917SReza.Sabdar@Sun.COM next = sa->sa_link_head.sl_next;
10027917SReza.Sabdar@Sun.COM sa->sa_link_head.sl_next = sl;
10037917SReza.Sabdar@Sun.COM sl->sl_next = next;
10047917SReza.Sabdar@Sun.COM }
10057917SReza.Sabdar@Sun.COM
10067917SReza.Sabdar@Sun.COM /*
10077917SReza.Sabdar@Sun.COM * Go through the attached devices and detect the tape
10087917SReza.Sabdar@Sun.COM * and robot by checking the /dev entries
10097917SReza.Sabdar@Sun.COM */
10107917SReza.Sabdar@Sun.COM int
probe_scsi(void)10117917SReza.Sabdar@Sun.COM probe_scsi(void)
10127917SReza.Sabdar@Sun.COM {
10137917SReza.Sabdar@Sun.COM DIR *dirp;
10147917SReza.Sabdar@Sun.COM struct dirent *dp;
10157917SReza.Sabdar@Sun.COM scsi_adapter_t *sa = &my_sa;
10167917SReza.Sabdar@Sun.COM char *p;
10177917SReza.Sabdar@Sun.COM int lun = 0;
10187917SReza.Sabdar@Sun.COM int sid = 0;
1019*13051SJanice.Chang@Sun.COM char *drive_type;
10207917SReza.Sabdar@Sun.COM
10217917SReza.Sabdar@Sun.COM /* Initialize the scsi adapter link */
10227917SReza.Sabdar@Sun.COM sa->sa_link_head.sl_next = &sa->sa_link_head;
10237917SReza.Sabdar@Sun.COM
10247917SReza.Sabdar@Sun.COM /* Scan for the changer */
10257917SReza.Sabdar@Sun.COM dirp = opendir(SCSI_CHANGER_DIR);
10267917SReza.Sabdar@Sun.COM if (dirp == NULL) {
10277917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
10287917SReza.Sabdar@Sun.COM "Changer directory read error %s", SCSI_CHANGER_DIR);
10297917SReza.Sabdar@Sun.COM } else {
10307917SReza.Sabdar@Sun.COM while ((dp = readdir(dirp)) != NULL) {
10317917SReza.Sabdar@Sun.COM if ((strcmp(dp->d_name, ".") == 0) ||
10327917SReza.Sabdar@Sun.COM (strcmp(dp->d_name, "..") == 0))
10337917SReza.Sabdar@Sun.COM continue;
10347917SReza.Sabdar@Sun.COM
10357917SReza.Sabdar@Sun.COM if ((p = strchr(dp->d_name, 'd')) != NULL) {
10367917SReza.Sabdar@Sun.COM lun = atoi(++p);
10377917SReza.Sabdar@Sun.COM p = strchr(dp->d_name, 't');
10387917SReza.Sabdar@Sun.COM sid = atoi(++p);
10397917SReza.Sabdar@Sun.COM }
10407917SReza.Sabdar@Sun.COM else
10417917SReza.Sabdar@Sun.COM sid = atoi(dp->d_name);
10427917SReza.Sabdar@Sun.COM
10437917SReza.Sabdar@Sun.COM scsi_sasd_attach(sa, 0, lun, dp->d_name,
10447917SReza.Sabdar@Sun.COM DTYPE_CHANGER);
10457917SReza.Sabdar@Sun.COM }
10467917SReza.Sabdar@Sun.COM (void) closedir(dirp);
10477917SReza.Sabdar@Sun.COM }
10487917SReza.Sabdar@Sun.COM
10497917SReza.Sabdar@Sun.COM /* Scan for tape drives */
10507917SReza.Sabdar@Sun.COM dirp = opendir(SCSI_TAPE_DIR);
10517917SReza.Sabdar@Sun.COM if (dirp == NULL) {
10527917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
10537917SReza.Sabdar@Sun.COM "Tape directory read error %s", SCSI_TAPE_DIR);
10547917SReza.Sabdar@Sun.COM } else {
1055*13051SJanice.Chang@Sun.COM drive_type = ndmpd_get_prop(NDMP_DRIVE_TYPE);
1056*13051SJanice.Chang@Sun.COM
1057*13051SJanice.Chang@Sun.COM if ((strcasecmp(drive_type, "sysv") != 0) &&
1058*13051SJanice.Chang@Sun.COM (strcasecmp(drive_type, "bsd") != 0)) {
1059*13051SJanice.Chang@Sun.COM NDMP_LOG(LOG_ERR, "Invalid ndmpd/drive-type value. "
1060*13051SJanice.Chang@Sun.COM "Valid values are 'sysv' and 'bsd'.");
1061*13051SJanice.Chang@Sun.COM return (-1);
1062*13051SJanice.Chang@Sun.COM }
1063*13051SJanice.Chang@Sun.COM
10647917SReza.Sabdar@Sun.COM while ((dp = readdir(dirp)) != NULL) {
10657917SReza.Sabdar@Sun.COM if ((strcmp(dp->d_name, ".") == 0) ||
10667917SReza.Sabdar@Sun.COM (strcmp(dp->d_name, "..") == 0))
10677917SReza.Sabdar@Sun.COM continue;
10687917SReza.Sabdar@Sun.COM
10697917SReza.Sabdar@Sun.COM /* Skip special modes */
1070*13051SJanice.Chang@Sun.COM if (strpbrk(dp->d_name, "chlmu") != NULL)
10717917SReza.Sabdar@Sun.COM continue;
10727917SReza.Sabdar@Sun.COM
10737917SReza.Sabdar@Sun.COM /* Pick the non-rewind device */
10747917SReza.Sabdar@Sun.COM if (strchr(dp->d_name, 'n') == NULL)
10757917SReza.Sabdar@Sun.COM continue;
10767917SReza.Sabdar@Sun.COM
1077*13051SJanice.Chang@Sun.COM if (strcasecmp(drive_type, "sysv") == 0) {
1078*13051SJanice.Chang@Sun.COM if (strchr(dp->d_name, 'b') != NULL)
1079*13051SJanice.Chang@Sun.COM continue;
1080*13051SJanice.Chang@Sun.COM } else if (strcasecmp(drive_type, "bsd") == 0) {
1081*13051SJanice.Chang@Sun.COM if (strchr(dp->d_name, 'b') == NULL)
1082*13051SJanice.Chang@Sun.COM continue;
1083*13051SJanice.Chang@Sun.COM }
1084*13051SJanice.Chang@Sun.COM
10857917SReza.Sabdar@Sun.COM sid = atoi(dp->d_name);
10867917SReza.Sabdar@Sun.COM
10877917SReza.Sabdar@Sun.COM /*
10887917SReza.Sabdar@Sun.COM * SCSI ID should match with the ID of the device
10897917SReza.Sabdar@Sun.COM * (will be checked by SCSI get elements page later)
10907917SReza.Sabdar@Sun.COM */
10917917SReza.Sabdar@Sun.COM scsi_sasd_attach(sa, sid, 0, dp->d_name,
10927917SReza.Sabdar@Sun.COM DTYPE_SEQUENTIAL);
10937917SReza.Sabdar@Sun.COM }
10947917SReza.Sabdar@Sun.COM (void) closedir(dirp);
10957917SReza.Sabdar@Sun.COM }
10967917SReza.Sabdar@Sun.COM
10977917SReza.Sabdar@Sun.COM return (0);
10987917SReza.Sabdar@Sun.COM }
10997917SReza.Sabdar@Sun.COM
11007917SReza.Sabdar@Sun.COM /*
11017917SReza.Sabdar@Sun.COM * Get the SCSI device type (tape, robot)
11027917SReza.Sabdar@Sun.COM */
11037917SReza.Sabdar@Sun.COM /*ARGSUSED*/
11047917SReza.Sabdar@Sun.COM int
scsi_get_devtype(char * adapter,int sid,int lun)11057917SReza.Sabdar@Sun.COM scsi_get_devtype(char *adapter, int sid, int lun)
11067917SReza.Sabdar@Sun.COM {
11077917SReza.Sabdar@Sun.COM int rv;
11087917SReza.Sabdar@Sun.COM scsi_adapter_t *sa = &my_sa;
11097917SReza.Sabdar@Sun.COM scsi_link_t *sl, *sh;
11107917SReza.Sabdar@Sun.COM
11117917SReza.Sabdar@Sun.COM rv = -1;
11127917SReza.Sabdar@Sun.COM sh = &sa->sa_link_head;
11137917SReza.Sabdar@Sun.COM for (sl = sh->sl_next; sl != sh; sl = sl->sl_next)
11147917SReza.Sabdar@Sun.COM if (sl->sl_sid == sid && sl->sl_lun == lun)
11157917SReza.Sabdar@Sun.COM rv = sl->sl_type;
11167917SReza.Sabdar@Sun.COM
11177917SReza.Sabdar@Sun.COM return (rv);
11187917SReza.Sabdar@Sun.COM }
11197917SReza.Sabdar@Sun.COM
11207917SReza.Sabdar@Sun.COM
11217917SReza.Sabdar@Sun.COM /*
11227917SReza.Sabdar@Sun.COM * Check if the SCSI device exists
11237917SReza.Sabdar@Sun.COM */
11247917SReza.Sabdar@Sun.COM /*ARGSUSED*/
11257917SReza.Sabdar@Sun.COM int
scsi_dev_exists(char * adapter,int sid,int lun)11267917SReza.Sabdar@Sun.COM scsi_dev_exists(char *adapter, int sid, int lun)
11277917SReza.Sabdar@Sun.COM {
11287917SReza.Sabdar@Sun.COM scsi_adapter_t *sa = &my_sa;
11297917SReza.Sabdar@Sun.COM scsi_link_t *sl, *sh;
11307917SReza.Sabdar@Sun.COM
11317917SReza.Sabdar@Sun.COM sh = &sa->sa_link_head;
11327917SReza.Sabdar@Sun.COM for (sl = sh->sl_next; sl != sh; sl = sl->sl_next)
11337917SReza.Sabdar@Sun.COM if (sl->sl_sid == sid && sl->sl_lun == lun)
11347917SReza.Sabdar@Sun.COM return (1);
11357917SReza.Sabdar@Sun.COM return (0);
11367917SReza.Sabdar@Sun.COM }
11377917SReza.Sabdar@Sun.COM
11387917SReza.Sabdar@Sun.COM
11397917SReza.Sabdar@Sun.COM /*
11407917SReza.Sabdar@Sun.COM * Count of SCSI adapters
11417917SReza.Sabdar@Sun.COM */
11427917SReza.Sabdar@Sun.COM int
scsi_get_adapter_count(void)11437917SReza.Sabdar@Sun.COM scsi_get_adapter_count(void)
11447917SReza.Sabdar@Sun.COM {
11457917SReza.Sabdar@Sun.COM /* Currently support one adapter only */
11467917SReza.Sabdar@Sun.COM return (1);
11477917SReza.Sabdar@Sun.COM }
11487917SReza.Sabdar@Sun.COM
11497917SReza.Sabdar@Sun.COM /*
11507917SReza.Sabdar@Sun.COM * Return the SCSI adapter structure
11517917SReza.Sabdar@Sun.COM */
11527917SReza.Sabdar@Sun.COM /*ARGSUSED*/
11537917SReza.Sabdar@Sun.COM scsi_adapter_t *
scsi_get_adapter(int adapter)11547917SReza.Sabdar@Sun.COM scsi_get_adapter(int adapter)
11557917SReza.Sabdar@Sun.COM {
11567917SReza.Sabdar@Sun.COM return (&my_sa);
11577917SReza.Sabdar@Sun.COM }
11587917SReza.Sabdar@Sun.COM
11597917SReza.Sabdar@Sun.COM /*
11607917SReza.Sabdar@Sun.COM * IOCTL wrapper with retries
11617917SReza.Sabdar@Sun.COM */
11627917SReza.Sabdar@Sun.COM int
tlm_ioctl(int fd,int cmd,void * data)11637917SReza.Sabdar@Sun.COM tlm_ioctl(int fd, int cmd, void *data)
11647917SReza.Sabdar@Sun.COM {
11657917SReza.Sabdar@Sun.COM int retries = 0;
11667917SReza.Sabdar@Sun.COM
11677917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "tlm_ioctl fd %d cmd %d", fd, cmd);
11687917SReza.Sabdar@Sun.COM if (fd == 0 || data == NULL)
11697917SReza.Sabdar@Sun.COM return (EINVAL);
11707917SReza.Sabdar@Sun.COM
11717917SReza.Sabdar@Sun.COM do {
11727917SReza.Sabdar@Sun.COM if (ioctl(fd, cmd, data) == 0)
11737917SReza.Sabdar@Sun.COM break;
11747917SReza.Sabdar@Sun.COM
11757917SReza.Sabdar@Sun.COM if (errno != EIO && errno != 0) {
11767917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR,
11777917SReza.Sabdar@Sun.COM "Failed to send command to device: %m.");
11787917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "IOCTL error %d", errno);
11797917SReza.Sabdar@Sun.COM return (errno);
11807917SReza.Sabdar@Sun.COM }
11817917SReza.Sabdar@Sun.COM (void) sleep(1);
11827917SReza.Sabdar@Sun.COM } while (retries++ < MAXIORETRY);
11837917SReza.Sabdar@Sun.COM
11847917SReza.Sabdar@Sun.COM return (0);
11857917SReza.Sabdar@Sun.COM }
11867917SReza.Sabdar@Sun.COM
11877917SReza.Sabdar@Sun.COM /*
11887917SReza.Sabdar@Sun.COM * Checkpoint or snapshot calls
11897917SReza.Sabdar@Sun.COM */
11907917SReza.Sabdar@Sun.COM
11917917SReza.Sabdar@Sun.COM /*
11927917SReza.Sabdar@Sun.COM * Get the snapshot creation time
11937917SReza.Sabdar@Sun.COM */
11947917SReza.Sabdar@Sun.COM int
chkpnt_creationtime_bypattern(char * volname,char * pattern,time_t * tp)11957917SReza.Sabdar@Sun.COM chkpnt_creationtime_bypattern(char *volname, char *pattern, time_t *tp)
11967917SReza.Sabdar@Sun.COM {
11977917SReza.Sabdar@Sun.COM char chk_name[PATH_MAX];
11987917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
11997917SReza.Sabdar@Sun.COM char *p;
12007917SReza.Sabdar@Sun.COM
12017917SReza.Sabdar@Sun.COM if (!volname || !*volname)
12027917SReza.Sabdar@Sun.COM return (-1);
12037917SReza.Sabdar@Sun.COM
12047917SReza.Sabdar@Sun.COM /* Should also return -1 if checkpoint not enabled */
12057917SReza.Sabdar@Sun.COM
12067917SReza.Sabdar@Sun.COM /* Remove the leading slash */
12077917SReza.Sabdar@Sun.COM p = volname;
12087917SReza.Sabdar@Sun.COM while (*p == '/')
12097917SReza.Sabdar@Sun.COM p++;
12107917SReza.Sabdar@Sun.COM
12117917SReza.Sabdar@Sun.COM (void) strlcpy(chk_name, p, PATH_MAX);
12127917SReza.Sabdar@Sun.COM (void) strlcat(chk_name, "@", PATH_MAX);
12137917SReza.Sabdar@Sun.COM (void) strlcat(chk_name, pattern, PATH_MAX);
12147917SReza.Sabdar@Sun.COM
12157917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
12167917SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, chk_name, ZFS_TYPE_DATASET)) == NULL) {
12177917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "chkpnt_creationtime: open %s failed",
12187917SReza.Sabdar@Sun.COM chk_name);
12197917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
12207917SReza.Sabdar@Sun.COM return (-1);
12217917SReza.Sabdar@Sun.COM }
12227917SReza.Sabdar@Sun.COM
12237917SReza.Sabdar@Sun.COM *tp = zfs_prop_get_int(zhp, ZFS_PROP_CREATION);
12247917SReza.Sabdar@Sun.COM zfs_close(zhp);
12257917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
12267917SReza.Sabdar@Sun.COM
12277917SReza.Sabdar@Sun.COM return (0);
12287917SReza.Sabdar@Sun.COM }
12297917SReza.Sabdar@Sun.COM
12307917SReza.Sabdar@Sun.COM
12317917SReza.Sabdar@Sun.COM /*
12327917SReza.Sabdar@Sun.COM * Get the ZFS volume name out of the given path
12337917SReza.Sabdar@Sun.COM */
12347917SReza.Sabdar@Sun.COM int
get_zfsvolname(char * volname,int len,char * path)12357917SReza.Sabdar@Sun.COM get_zfsvolname(char *volname, int len, char *path)
12367917SReza.Sabdar@Sun.COM {
12377917SReza.Sabdar@Sun.COM struct stat64 stbuf;
12387917SReza.Sabdar@Sun.COM struct extmnttab ent;
12397917SReza.Sabdar@Sun.COM FILE *mntfp;
12407917SReza.Sabdar@Sun.COM int rv;
12417917SReza.Sabdar@Sun.COM
12427917SReza.Sabdar@Sun.COM *volname = '\0';
12437917SReza.Sabdar@Sun.COM if (stat64(path, &stbuf) != 0) {
12447917SReza.Sabdar@Sun.COM return (-1);
12457917SReza.Sabdar@Sun.COM }
12467917SReza.Sabdar@Sun.COM
12477917SReza.Sabdar@Sun.COM if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
12487917SReza.Sabdar@Sun.COM return (-1);
12497917SReza.Sabdar@Sun.COM }
12507917SReza.Sabdar@Sun.COM while ((rv = getextmntent(mntfp, &ent, 0)) == 0) {
12517917SReza.Sabdar@Sun.COM if (makedevice(ent.mnt_major, ent.mnt_minor) ==
12527917SReza.Sabdar@Sun.COM stbuf.st_dev)
12537917SReza.Sabdar@Sun.COM break;
12547917SReza.Sabdar@Sun.COM }
12557917SReza.Sabdar@Sun.COM
12567917SReza.Sabdar@Sun.COM if (rv == 0 &&
12577917SReza.Sabdar@Sun.COM strcmp(ent.mnt_fstype, MNTTYPE_ZFS) == 0)
12587917SReza.Sabdar@Sun.COM (void) strlcpy(volname, ent.mnt_special, len);
12597917SReza.Sabdar@Sun.COM else
12607917SReza.Sabdar@Sun.COM rv = -1;
12617917SReza.Sabdar@Sun.COM
12627917SReza.Sabdar@Sun.COM (void) fclose(mntfp);
12637917SReza.Sabdar@Sun.COM return (rv);
12647917SReza.Sabdar@Sun.COM }
12657917SReza.Sabdar@Sun.COM
12667917SReza.Sabdar@Sun.COM
12677917SReza.Sabdar@Sun.COM /*
12687917SReza.Sabdar@Sun.COM * Check if the volume type is snapshot volume
12697917SReza.Sabdar@Sun.COM */
12707917SReza.Sabdar@Sun.COM boolean_t
fs_is_chkpntvol(char * path)12717917SReza.Sabdar@Sun.COM fs_is_chkpntvol(char *path)
12727917SReza.Sabdar@Sun.COM {
12737917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
12747917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN];
12757917SReza.Sabdar@Sun.COM
12767917SReza.Sabdar@Sun.COM if (!path || !*path)
12777917SReza.Sabdar@Sun.COM return (FALSE);
12787917SReza.Sabdar@Sun.COM
12797917SReza.Sabdar@Sun.COM if (get_zfsvolname(vol, sizeof (vol), path) == -1)
12807917SReza.Sabdar@Sun.COM return (FALSE);
12817917SReza.Sabdar@Sun.COM
12827917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
12837917SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) {
12847917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
12857917SReza.Sabdar@Sun.COM return (FALSE);
12867917SReza.Sabdar@Sun.COM }
12877917SReza.Sabdar@Sun.COM
12887917SReza.Sabdar@Sun.COM if (zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) {
12897917SReza.Sabdar@Sun.COM zfs_close(zhp);
12907917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
12917917SReza.Sabdar@Sun.COM return (FALSE);
12927917SReza.Sabdar@Sun.COM }
12937917SReza.Sabdar@Sun.COM zfs_close(zhp);
12947917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
12957917SReza.Sabdar@Sun.COM
12967917SReza.Sabdar@Sun.COM return (TRUE);
12977917SReza.Sabdar@Sun.COM }
12987917SReza.Sabdar@Sun.COM
12997917SReza.Sabdar@Sun.COM /*
13007917SReza.Sabdar@Sun.COM * Check if the volume is capable of checkpoints
13017917SReza.Sabdar@Sun.COM */
13027917SReza.Sabdar@Sun.COM boolean_t
fs_is_chkpnt_enabled(char * path)13037917SReza.Sabdar@Sun.COM fs_is_chkpnt_enabled(char *path)
13047917SReza.Sabdar@Sun.COM {
13057917SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
13067917SReza.Sabdar@Sun.COM char vol[ZFS_MAXNAMELEN];
13077917SReza.Sabdar@Sun.COM
13087917SReza.Sabdar@Sun.COM if (!path || !*path)
13097917SReza.Sabdar@Sun.COM return (FALSE);
13107917SReza.Sabdar@Sun.COM
13117917SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
13127917SReza.Sabdar@Sun.COM if (get_zfsvolname(vol, sizeof (vol), path) == -1) {
13137917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
13147917SReza.Sabdar@Sun.COM return (FALSE);
13157917SReza.Sabdar@Sun.COM }
13167917SReza.Sabdar@Sun.COM
13177917SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, vol, ZFS_TYPE_DATASET)) == NULL) {
13187917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
13197917SReza.Sabdar@Sun.COM return (FALSE);
13207917SReza.Sabdar@Sun.COM }
13217917SReza.Sabdar@Sun.COM zfs_close(zhp);
13227917SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
13237917SReza.Sabdar@Sun.COM
13247917SReza.Sabdar@Sun.COM return (TRUE);
13257917SReza.Sabdar@Sun.COM }
13267917SReza.Sabdar@Sun.COM
13277917SReza.Sabdar@Sun.COM /*
13287917SReza.Sabdar@Sun.COM * Check if the volume is read-only
13297917SReza.Sabdar@Sun.COM */
13307917SReza.Sabdar@Sun.COM boolean_t
fs_is_rdonly(char * path)13317917SReza.Sabdar@Sun.COM fs_is_rdonly(char *path)
13327917SReza.Sabdar@Sun.COM {
13337917SReza.Sabdar@Sun.COM return (fs_is_chkpntvol(path));
13347917SReza.Sabdar@Sun.COM }
13357917SReza.Sabdar@Sun.COM
13367917SReza.Sabdar@Sun.COM /*
13377917SReza.Sabdar@Sun.COM * Min/max functions
13387917SReza.Sabdar@Sun.COM */
13397917SReza.Sabdar@Sun.COM unsigned
min(a,b)13407917SReza.Sabdar@Sun.COM min(a, b)
13417917SReza.Sabdar@Sun.COM unsigned a, b;
13427917SReza.Sabdar@Sun.COM {
13437917SReza.Sabdar@Sun.COM return (a < b ? a : b);
13447917SReza.Sabdar@Sun.COM }
13457917SReza.Sabdar@Sun.COM
13467917SReza.Sabdar@Sun.COM unsigned
max(a,b)13477917SReza.Sabdar@Sun.COM max(a, b)
13487917SReza.Sabdar@Sun.COM unsigned a, b;
13497917SReza.Sabdar@Sun.COM {
13507917SReza.Sabdar@Sun.COM return (a > b ? a : b);
13517917SReza.Sabdar@Sun.COM }
13527917SReza.Sabdar@Sun.COM
13537917SReza.Sabdar@Sun.COM longlong_t
llmin(longlong_t a,longlong_t b)13547917SReza.Sabdar@Sun.COM llmin(longlong_t a, longlong_t b)
13557917SReza.Sabdar@Sun.COM {
13567917SReza.Sabdar@Sun.COM return (a < b ? a : b);
13577917SReza.Sabdar@Sun.COM }
1358