17917SReza.Sabdar@Sun.COM /* 28540SReza.Sabdar@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37917SReza.Sabdar@Sun.COM * Use is subject to license terms. 47917SReza.Sabdar@Sun.COM */ 57917SReza.Sabdar@Sun.COM 67917SReza.Sabdar@Sun.COM /* 77917SReza.Sabdar@Sun.COM * BSD 3 Clause License 87917SReza.Sabdar@Sun.COM * 97917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association. 107917SReza.Sabdar@Sun.COM * 117917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without 127917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions 137917SReza.Sabdar@Sun.COM * are met: 147917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright 157917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer. 167917SReza.Sabdar@Sun.COM * 177917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright 187917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in 197917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the 207917SReza.Sabdar@Sun.COM * distribution. 217917SReza.Sabdar@Sun.COM * 227917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA) 237917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote 247917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written 257917SReza.Sabdar@Sun.COM * permission. 267917SReza.Sabdar@Sun.COM * 277917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 287917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 297917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 307917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 317917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 327917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 337917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 347917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 357917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 367917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 377917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE. 387917SReza.Sabdar@Sun.COM */ 397917SReza.Sabdar@Sun.COM #include <stdio.h> 407917SReza.Sabdar@Sun.COM #include <limits.h> 417917SReza.Sabdar@Sun.COM #include <time.h> 427917SReza.Sabdar@Sun.COM #include <sys/stat.h> 437917SReza.Sabdar@Sun.COM #include <unistd.h> 447917SReza.Sabdar@Sun.COM #include <dirent.h> 457917SReza.Sabdar@Sun.COM #include <pthread.h> 467917SReza.Sabdar@Sun.COM #include <archives.h> 477917SReza.Sabdar@Sun.COM #include <tlm.h> 487917SReza.Sabdar@Sun.COM #include <sys/fs/zfs.h> 497917SReza.Sabdar@Sun.COM #include <libzfs.h> 508540SReza.Sabdar@Sun.COM #include <libcmdutils.h> 518540SReza.Sabdar@Sun.COM #include <pwd.h> 528540SReza.Sabdar@Sun.COM #include <grp.h> 537917SReza.Sabdar@Sun.COM #include "tlm_proto.h" 547917SReza.Sabdar@Sun.COM 557917SReza.Sabdar@Sun.COM 567917SReza.Sabdar@Sun.COM static char *get_write_buffer(long size, 577917SReza.Sabdar@Sun.COM long *actual_size, 587917SReza.Sabdar@Sun.COM boolean_t zero, 597917SReza.Sabdar@Sun.COM tlm_cmd_t *); 607917SReza.Sabdar@Sun.COM static int output_acl_header(sec_attr_t *, 617917SReza.Sabdar@Sun.COM tlm_cmd_t *); 627917SReza.Sabdar@Sun.COM static int output_file_header(char *name, 637917SReza.Sabdar@Sun.COM char *link, 647917SReza.Sabdar@Sun.COM tlm_acls_t *, 657917SReza.Sabdar@Sun.COM int section, 667917SReza.Sabdar@Sun.COM tlm_cmd_t *); 677917SReza.Sabdar@Sun.COM static int output_xattr_header(char *fname, 687917SReza.Sabdar@Sun.COM char *aname, 697917SReza.Sabdar@Sun.COM int fd, 707917SReza.Sabdar@Sun.COM tlm_acls_t *, 717917SReza.Sabdar@Sun.COM int section, 727917SReza.Sabdar@Sun.COM tlm_cmd_t *); 737917SReza.Sabdar@Sun.COM 747917SReza.Sabdar@Sun.COM extern libzfs_handle_t *zlibh; 75*10260SReza.Sabdar@Sun.COM extern mutex_t zlib_mtx; 767917SReza.Sabdar@Sun.COM 777917SReza.Sabdar@Sun.COM 787917SReza.Sabdar@Sun.COM /* 797917SReza.Sabdar@Sun.COM * output_mem 807917SReza.Sabdar@Sun.COM * 817917SReza.Sabdar@Sun.COM * Gets a IO write buffer and copies memory to the that. 827917SReza.Sabdar@Sun.COM */ 837917SReza.Sabdar@Sun.COM static void 847917SReza.Sabdar@Sun.COM output_mem(tlm_cmd_t *local_commands, char *mem, 857917SReza.Sabdar@Sun.COM int len) 867917SReza.Sabdar@Sun.COM { 877917SReza.Sabdar@Sun.COM long actual_size, rec_size; 887917SReza.Sabdar@Sun.COM char *rec; 897917SReza.Sabdar@Sun.COM 907917SReza.Sabdar@Sun.COM while (len > 0) { 917917SReza.Sabdar@Sun.COM rec = get_write_buffer(len, &actual_size, 927917SReza.Sabdar@Sun.COM FALSE, local_commands); 937917SReza.Sabdar@Sun.COM rec_size = min(actual_size, len); 947917SReza.Sabdar@Sun.COM (void) memcpy(rec, mem, rec_size); 957917SReza.Sabdar@Sun.COM mem += rec_size; 967917SReza.Sabdar@Sun.COM len -= rec_size; 977917SReza.Sabdar@Sun.COM } 987917SReza.Sabdar@Sun.COM } 997917SReza.Sabdar@Sun.COM 1007917SReza.Sabdar@Sun.COM /* 1017917SReza.Sabdar@Sun.COM * tlm_output_dir 1027917SReza.Sabdar@Sun.COM * 1037917SReza.Sabdar@Sun.COM * Put the directory information into the output buffers. 1047917SReza.Sabdar@Sun.COM */ 1057917SReza.Sabdar@Sun.COM int 1067917SReza.Sabdar@Sun.COM tlm_output_dir(char *name, tlm_acls_t *tlm_acls, 1077917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 1087917SReza.Sabdar@Sun.COM { 1097917SReza.Sabdar@Sun.COM u_longlong_t pos; 1107917SReza.Sabdar@Sun.COM 1117917SReza.Sabdar@Sun.COM /* 1127917SReza.Sabdar@Sun.COM * Send the node or path history of the directory itself. 1137917SReza.Sabdar@Sun.COM */ 1147917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 1157917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 1167917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos); 1177917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos); 1187917SReza.Sabdar@Sun.COM /* fhdir_cb is handled in ndmpd_tar3.c */ 1197917SReza.Sabdar@Sun.COM 1207917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info, 1217917SReza.Sabdar@Sun.COM local_commands); 1227917SReza.Sabdar@Sun.COM (void) output_file_header(name, "", tlm_acls, 0, 1237917SReza.Sabdar@Sun.COM local_commands); 1247917SReza.Sabdar@Sun.COM 1257917SReza.Sabdar@Sun.COM return (0); 1267917SReza.Sabdar@Sun.COM } 1277917SReza.Sabdar@Sun.COM 1287917SReza.Sabdar@Sun.COM /* 1297917SReza.Sabdar@Sun.COM * tar_putdir 1307917SReza.Sabdar@Sun.COM * 1317917SReza.Sabdar@Sun.COM * Main dir backup function for tar 1327917SReza.Sabdar@Sun.COM */ 1337917SReza.Sabdar@Sun.COM int 1347917SReza.Sabdar@Sun.COM tar_putdir(char *name, tlm_acls_t *tlm_acls, 1357917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 1367917SReza.Sabdar@Sun.COM { 1377917SReza.Sabdar@Sun.COM int rv; 1387917SReza.Sabdar@Sun.COM 1397917SReza.Sabdar@Sun.COM rv = tlm_output_dir(name, tlm_acls, local_commands, job_stats); 1407917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0); 1417917SReza.Sabdar@Sun.COM } 1427917SReza.Sabdar@Sun.COM 1437917SReza.Sabdar@Sun.COM /* 1447917SReza.Sabdar@Sun.COM * output_acl_header 1457917SReza.Sabdar@Sun.COM * 1467917SReza.Sabdar@Sun.COM * output the ACL header record and data 1477917SReza.Sabdar@Sun.COM */ 1487917SReza.Sabdar@Sun.COM static int 1497917SReza.Sabdar@Sun.COM output_acl_header(sec_attr_t *acl_info, 1507917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands) 1517917SReza.Sabdar@Sun.COM { 1527917SReza.Sabdar@Sun.COM long actual_size; 1537917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 1547917SReza.Sabdar@Sun.COM long acl_size; 1557917SReza.Sabdar@Sun.COM 1567917SReza.Sabdar@Sun.COM if ((acl_info == NULL) || (*acl_info->attr_info == '\0')) 1577917SReza.Sabdar@Sun.COM return (0); 1587917SReza.Sabdar@Sun.COM 1597917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 1607917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 1617917SReza.Sabdar@Sun.COM if (!tar_hdr) 1627917SReza.Sabdar@Sun.COM return (0); 1637917SReza.Sabdar@Sun.COM 1647917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_ACL; 1657917SReza.Sabdar@Sun.COM acl_info->attr_type = UFSD_ACL; 1667917SReza.Sabdar@Sun.COM (void) snprintf(acl_info->attr_len, sizeof (acl_info->attr_len), 1677917SReza.Sabdar@Sun.COM "%06o", strlen(acl_info->attr_info)); 1687917SReza.Sabdar@Sun.COM 1697917SReza.Sabdar@Sun.COM acl_size = sizeof (*acl_info); 1707917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, "UFSACL", TLM_NAME_SIZE); 1717917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 1727917SReza.Sabdar@Sun.COM acl_size); 1737917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 1747917SReza.Sabdar@Sun.COM 0444); 1757917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 0); 1767917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 0); 1777917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 1787917SReza.Sabdar@Sun.COM "%011o ", 0); 1797917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 1807917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 1817917SReza.Sabdar@Sun.COM 1827917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 1837917SReza.Sabdar@Sun.COM 1847917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)acl_info, acl_size); 1857917SReza.Sabdar@Sun.COM return (0); 1867917SReza.Sabdar@Sun.COM } 1877917SReza.Sabdar@Sun.COM 1887917SReza.Sabdar@Sun.COM /* 1897917SReza.Sabdar@Sun.COM * output_humongus_header 1907917SReza.Sabdar@Sun.COM * 1917917SReza.Sabdar@Sun.COM * output a special header record for HUGE files 1927917SReza.Sabdar@Sun.COM * output is: 1) a TAR "HUGE" header redord 1937917SReza.Sabdar@Sun.COM * 2) a "file" of size, name 1947917SReza.Sabdar@Sun.COM */ 1957917SReza.Sabdar@Sun.COM static int 1967917SReza.Sabdar@Sun.COM output_humongus_header(char *fullname, longlong_t file_size, 1977917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands) 1987917SReza.Sabdar@Sun.COM { 1997917SReza.Sabdar@Sun.COM char *buf; 2007917SReza.Sabdar@Sun.COM int len; 2017917SReza.Sabdar@Sun.COM long actual_size; 2027917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 2037917SReza.Sabdar@Sun.COM 2047917SReza.Sabdar@Sun.COM /* 2057917SReza.Sabdar@Sun.COM * buf will contain: "%llu %s": 2067917SReza.Sabdar@Sun.COM * - 20 is the maximum length of 'ulong_tlong' decimal notation. 2077917SReza.Sabdar@Sun.COM * - The first '1' is for the ' ' between the "%llu" and the fullname. 2087917SReza.Sabdar@Sun.COM * - The last '1' is for the null-terminator of fullname. 2097917SReza.Sabdar@Sun.COM */ 2107917SReza.Sabdar@Sun.COM len = 20 + 1 + strlen(fullname) + 1; 2117917SReza.Sabdar@Sun.COM 2127917SReza.Sabdar@Sun.COM if ((buf = ndmp_malloc(sizeof (char) * len)) == NULL) 2137917SReza.Sabdar@Sun.COM return (-1); 2147917SReza.Sabdar@Sun.COM 2157917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 2167917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 2177917SReza.Sabdar@Sun.COM if (!tar_hdr) { 2187917SReza.Sabdar@Sun.COM free(buf); 2197917SReza.Sabdar@Sun.COM return (0); 2207917SReza.Sabdar@Sun.COM } 2217917SReza.Sabdar@Sun.COM 2227917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_HUMONGUS; 2237917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 2247917SReza.Sabdar@Sun.COM len); 2257917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 2267917SReza.Sabdar@Sun.COM (void) snprintf(buf, len, "%lld %s", file_size, fullname); 2277917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, buf, len); 2287917SReza.Sabdar@Sun.COM 2297917SReza.Sabdar@Sun.COM free(buf); 2307917SReza.Sabdar@Sun.COM return (0); 2317917SReza.Sabdar@Sun.COM } 2327917SReza.Sabdar@Sun.COM 2337917SReza.Sabdar@Sun.COM 2347917SReza.Sabdar@Sun.COM /* 2357917SReza.Sabdar@Sun.COM * output_xattr_header 2367917SReza.Sabdar@Sun.COM * 2377917SReza.Sabdar@Sun.COM * output the TAR header record for extended attributes 2387917SReza.Sabdar@Sun.COM */ 2397917SReza.Sabdar@Sun.COM static int 2407917SReza.Sabdar@Sun.COM output_xattr_header(char *fname, char *aname, int fd, 2417917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 2427917SReza.Sabdar@Sun.COM { 2437917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr; 2447917SReza.Sabdar@Sun.COM struct xattr_hdr *xhdr; 2457917SReza.Sabdar@Sun.COM struct xattr_buf *xbuf; 2467917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 2477917SReza.Sabdar@Sun.COM long actual_size; 2487917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 2497917SReza.Sabdar@Sun.COM int hsize; 2507917SReza.Sabdar@Sun.COM int comlen; 2517917SReza.Sabdar@Sun.COM int namesz; 2527917SReza.Sabdar@Sun.COM 2537917SReza.Sabdar@Sun.COM if (section_name == NULL) 2547917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 2557917SReza.Sabdar@Sun.COM 2567917SReza.Sabdar@Sun.COM if (fstat64(fd, attr) == -1) { 2577917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "output_file_header stat failed."); 2587917SReza.Sabdar@Sun.COM free(section_name); 2597917SReza.Sabdar@Sun.COM return (-TLM_OPEN_ERR); 2607917SReza.Sabdar@Sun.COM } 2617917SReza.Sabdar@Sun.COM 2627917SReza.Sabdar@Sun.COM /* 2637917SReza.Sabdar@Sun.COM * if the file has to go out in sections, 2647917SReza.Sabdar@Sun.COM * we must mung the name. 2657917SReza.Sabdar@Sun.COM */ 2667917SReza.Sabdar@Sun.COM if (section == 0) { 2677917SReza.Sabdar@Sun.COM (void) snprintf(section_name, TLM_MAX_PATH_NAME, 2687917SReza.Sabdar@Sun.COM "/dev/null/%s.hdr", aname); 2697917SReza.Sabdar@Sun.COM } else { 2707917SReza.Sabdar@Sun.COM (void) snprintf(section_name, 2717917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", aname, section); 2727917SReza.Sabdar@Sun.COM } 2737917SReza.Sabdar@Sun.COM namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */ 2747917SReza.Sabdar@Sun.COM hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 2757917SReza.Sabdar@Sun.COM comlen = namesz + sizeof (struct xattr_buf); 2767917SReza.Sabdar@Sun.COM 2777917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 2787917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 2797917SReza.Sabdar@Sun.COM if (!tar_hdr) { 2807917SReza.Sabdar@Sun.COM free(section_name); 2817917SReza.Sabdar@Sun.COM return (0); 2827917SReza.Sabdar@Sun.COM } 2837917SReza.Sabdar@Sun.COM 2847917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 2857917SReza.Sabdar@Sun.COM 2867917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_XATTR; 2877917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 2887917SReza.Sabdar@Sun.COM hsize); 2897917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 2907917SReza.Sabdar@Sun.COM attr->st_mode & 07777); 2917917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 2927917SReza.Sabdar@Sun.COM attr->st_uid); 2937917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 2947917SReza.Sabdar@Sun.COM attr->st_gid); 2957917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 2967917SReza.Sabdar@Sun.COM attr->st_mtime); 2977917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 2987917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 2997917SReza.Sabdar@Sun.COM 3008540SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d", 3018540SReza.Sabdar@Sun.COM aname, hsize, attr->st_mode & 07777, attr->st_uid, attr->st_gid); 3028540SReza.Sabdar@Sun.COM 3037917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 3047917SReza.Sabdar@Sun.COM 3057917SReza.Sabdar@Sun.COM xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE, 3067917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 3077917SReza.Sabdar@Sun.COM if (!xhdr) { 3087917SReza.Sabdar@Sun.COM free(section_name); 3097917SReza.Sabdar@Sun.COM return (0); 3107917SReza.Sabdar@Sun.COM } 3117917SReza.Sabdar@Sun.COM 3127917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s", 3137917SReza.Sabdar@Sun.COM XATTR_ARCH_VERS); 3147917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d", 3157917SReza.Sabdar@Sun.COM sizeof (xhdr->h_size) - 1, hsize); 3167917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len), 3177917SReza.Sabdar@Sun.COM "%0*d", sizeof (xhdr->h_component_len) - 1, comlen); 3187917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_link_component_len, 3197917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len), "%0*d", 3207917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len) - 1, 0); 3217917SReza.Sabdar@Sun.COM 3227917SReza.Sabdar@Sun.COM xbuf = (struct xattr_buf *)(((caddr_t)xhdr) + 3237917SReza.Sabdar@Sun.COM sizeof (struct xattr_hdr)); 3247917SReza.Sabdar@Sun.COM (void) snprintf(xbuf->h_namesz, sizeof (xbuf->h_namesz), "%0*d", 3257917SReza.Sabdar@Sun.COM sizeof (xbuf->h_namesz) - 1, namesz); 3267917SReza.Sabdar@Sun.COM 3277917SReza.Sabdar@Sun.COM /* No support for links in extended attributes */ 3287917SReza.Sabdar@Sun.COM xbuf->h_typeflag = LF_NORMAL; 3297917SReza.Sabdar@Sun.COM 3307917SReza.Sabdar@Sun.COM (void) strlcpy(xbuf->h_names, fname, TLM_NAME_SIZE); 3317917SReza.Sabdar@Sun.COM (void) strlcpy(&xbuf->h_names[strlen(fname) + 1], aname, 3327917SReza.Sabdar@Sun.COM TLM_NAME_SIZE); 3337917SReza.Sabdar@Sun.COM 3347917SReza.Sabdar@Sun.COM free(section_name); 3357917SReza.Sabdar@Sun.COM return (0); 3367917SReza.Sabdar@Sun.COM } 3377917SReza.Sabdar@Sun.COM 3387917SReza.Sabdar@Sun.COM 3397917SReza.Sabdar@Sun.COM /* 3407917SReza.Sabdar@Sun.COM * output_file_header 3417917SReza.Sabdar@Sun.COM * 3427917SReza.Sabdar@Sun.COM * output the TAR header record 3437917SReza.Sabdar@Sun.COM */ 3447917SReza.Sabdar@Sun.COM static int 3457917SReza.Sabdar@Sun.COM output_file_header(char *name, char *link, 3467917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 3477917SReza.Sabdar@Sun.COM { 3487917SReza.Sabdar@Sun.COM static longlong_t file_count = 0; 3497917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr; 3507917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 3517917SReza.Sabdar@Sun.COM long actual_size; 3527917SReza.Sabdar@Sun.COM boolean_t long_name = FALSE; 3537917SReza.Sabdar@Sun.COM boolean_t long_link = FALSE; 3547917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 3557917SReza.Sabdar@Sun.COM int nmlen, lnklen; 3568540SReza.Sabdar@Sun.COM uid_t uid; 3578540SReza.Sabdar@Sun.COM gid_t gid; 3588540SReza.Sabdar@Sun.COM char *uname = ""; 3598540SReza.Sabdar@Sun.COM char *gname = ""; 3608540SReza.Sabdar@Sun.COM struct passwd *pwd; 3618540SReza.Sabdar@Sun.COM struct group *grp; 3627917SReza.Sabdar@Sun.COM 3637917SReza.Sabdar@Sun.COM if (section_name == NULL) 3647917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 3657917SReza.Sabdar@Sun.COM 3667917SReza.Sabdar@Sun.COM /* 3677917SReza.Sabdar@Sun.COM * if the file has to go out in sections, 3687917SReza.Sabdar@Sun.COM * we must mung the name. 3697917SReza.Sabdar@Sun.COM */ 3707917SReza.Sabdar@Sun.COM if (section == 0) { 3717917SReza.Sabdar@Sun.COM (void) strlcpy(section_name, name, TLM_MAX_PATH_NAME); 3727917SReza.Sabdar@Sun.COM } else { 3737917SReza.Sabdar@Sun.COM (void) snprintf(section_name, 3747917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", name, section); 3757917SReza.Sabdar@Sun.COM } 3767917SReza.Sabdar@Sun.COM 3778540SReza.Sabdar@Sun.COM if ((pwd = getpwuid(attr->st_uid)) != NULL) 3788540SReza.Sabdar@Sun.COM uname = pwd->pw_name; 3798540SReza.Sabdar@Sun.COM if ((grp = getgrgid(attr->st_gid)) != NULL) 3808540SReza.Sabdar@Sun.COM gname = grp->gr_name; 3818540SReza.Sabdar@Sun.COM 3828540SReza.Sabdar@Sun.COM if ((ulong_t)(uid = attr->st_uid) > (ulong_t)OCTAL7CHAR) 3838540SReza.Sabdar@Sun.COM uid = UID_NOBODY; 3848540SReza.Sabdar@Sun.COM if ((ulong_t)(gid = attr->st_gid) > (ulong_t)OCTAL7CHAR) 3858540SReza.Sabdar@Sun.COM gid = GID_NOBODY; 3868540SReza.Sabdar@Sun.COM 3877917SReza.Sabdar@Sun.COM nmlen = strlen(section_name); 3887917SReza.Sabdar@Sun.COM if (nmlen >= NAMSIZ) { 3897917SReza.Sabdar@Sun.COM /* 3907917SReza.Sabdar@Sun.COM * file name is too big, it must go out 3917917SReza.Sabdar@Sun.COM * in its own data file 3927917SReza.Sabdar@Sun.COM */ 3937917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 3947917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 3957917SReza.Sabdar@Sun.COM if (!tar_hdr) { 3967917SReza.Sabdar@Sun.COM free(section_name); 3977917SReza.Sabdar@Sun.COM return (0); 3987917SReza.Sabdar@Sun.COM } 3997917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name, 4007917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4017917SReza.Sabdar@Sun.COM "%s%08qd.fil", 4027917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4037917SReza.Sabdar@Sun.COM file_count++); 4047917SReza.Sabdar@Sun.COM 4057917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGNAME; 4067917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 4077917SReza.Sabdar@Sun.COM "%011o ", nmlen); 4087917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 4097917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777); 4107917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 4118540SReza.Sabdar@Sun.COM "%06o ", uid); 4127917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 4138540SReza.Sabdar@Sun.COM "%06o ", gid); 4148540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), 4158540SReza.Sabdar@Sun.COM "%.31s", uname); 4168540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), 4178540SReza.Sabdar@Sun.COM "%.31s", gname); 4187917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 4197917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime); 4207917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 4217917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 4227917SReza.Sabdar@Sun.COM 4237917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 4247917SReza.Sabdar@Sun.COM 4257917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, 4267917SReza.Sabdar@Sun.COM (void *)section_name, nmlen); 4277917SReza.Sabdar@Sun.COM long_name = TRUE; 4287917SReza.Sabdar@Sun.COM } 4297917SReza.Sabdar@Sun.COM 4307917SReza.Sabdar@Sun.COM lnklen = strlen(link); 4317917SReza.Sabdar@Sun.COM if (lnklen >= NAMSIZ) { 4327917SReza.Sabdar@Sun.COM /* 4337917SReza.Sabdar@Sun.COM * link name is too big, it must go out 4347917SReza.Sabdar@Sun.COM * in its own data file 4357917SReza.Sabdar@Sun.COM */ 4367917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 4377917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 4387917SReza.Sabdar@Sun.COM if (!tar_hdr) { 4397917SReza.Sabdar@Sun.COM free(section_name); 4407917SReza.Sabdar@Sun.COM return (0); 4417917SReza.Sabdar@Sun.COM } 4427917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname, 4437917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4447917SReza.Sabdar@Sun.COM "%s%08qd.slk", 4457917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4467917SReza.Sabdar@Sun.COM file_count++); 4477917SReza.Sabdar@Sun.COM 4487917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGLINK; 4497917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 4507917SReza.Sabdar@Sun.COM "%011o ", lnklen); 4517917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 4527917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777); 4537917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 4548540SReza.Sabdar@Sun.COM "%06o ", uid); 4557917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 4568540SReza.Sabdar@Sun.COM "%06o ", gid); 4578540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), 4588540SReza.Sabdar@Sun.COM "%.31s", uname); 4598540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), 4608540SReza.Sabdar@Sun.COM "%.31s", gname); 4617917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 4627917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime); 4637917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 4647917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 4657917SReza.Sabdar@Sun.COM 4667917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 4677917SReza.Sabdar@Sun.COM 4687917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)link, 4697917SReza.Sabdar@Sun.COM lnklen); 4707917SReza.Sabdar@Sun.COM long_link = TRUE; 4717917SReza.Sabdar@Sun.COM } 4727917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 4737917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 4747917SReza.Sabdar@Sun.COM if (!tar_hdr) { 4757917SReza.Sabdar@Sun.COM free(section_name); 4767917SReza.Sabdar@Sun.COM return (0); 4777917SReza.Sabdar@Sun.COM } 4787917SReza.Sabdar@Sun.COM if (long_name) { 4797917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name, 4807917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4817917SReza.Sabdar@Sun.COM "%s%08qd.fil", 4827917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4837917SReza.Sabdar@Sun.COM file_count++); 4847917SReza.Sabdar@Sun.COM } else { 4857917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 4867917SReza.Sabdar@Sun.COM } 4877917SReza.Sabdar@Sun.COM 4887917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "long_link: %s [%s]", long_link ? "TRUE" : "FALSE", 4897917SReza.Sabdar@Sun.COM link); 4907917SReza.Sabdar@Sun.COM 4917917SReza.Sabdar@Sun.COM if (long_link) { 4927917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname, 4937917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4947917SReza.Sabdar@Sun.COM "%s%08qd.slk", 4957917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4967917SReza.Sabdar@Sun.COM file_count++); 4977917SReza.Sabdar@Sun.COM } else { 4987917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_linkname, link, TLM_NAME_SIZE); 4997917SReza.Sabdar@Sun.COM } 5007917SReza.Sabdar@Sun.COM if (S_ISDIR(attr->st_mode)) { 5017917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_DIR; 5027917SReza.Sabdar@Sun.COM } else if (S_ISFIFO(attr->st_mode)) { 5037917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_FIFO; 5047917SReza.Sabdar@Sun.COM } else if (attr->st_nlink > 1) { 5057917SReza.Sabdar@Sun.COM /* mark file with hardlink LF_LINK */ 5067917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LINK; 5077917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_shared.th_hlink_ino, 5087917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_shared.th_hlink_ino), 5098193SReza.Sabdar@Sun.COM "%011llo ", attr->st_ino); 5107917SReza.Sabdar@Sun.COM } else { 5117917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL : LF_SYMLINK; 5127917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "linkflag: '%c'", tar_hdr->th_linkflag); 5137917SReza.Sabdar@Sun.COM } 5147917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 5157917SReza.Sabdar@Sun.COM (long)attr->st_size); 5167917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 5177917SReza.Sabdar@Sun.COM attr->st_mode & 07777); 5187917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 5198540SReza.Sabdar@Sun.COM uid); 5207917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 5218540SReza.Sabdar@Sun.COM gid); 5228540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), "%.31s", 5238540SReza.Sabdar@Sun.COM uname); 5248540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), "%.31s", 5258540SReza.Sabdar@Sun.COM gname); 5267917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 5277917SReza.Sabdar@Sun.COM attr->st_mtime); 5287917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 5297917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 5307917SReza.Sabdar@Sun.COM 5317917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 5327917SReza.Sabdar@Sun.COM if (long_name || long_link) { 5337917SReza.Sabdar@Sun.COM if (file_count > 99999990) { 5347917SReza.Sabdar@Sun.COM file_count = 0; 5357917SReza.Sabdar@Sun.COM } 5367917SReza.Sabdar@Sun.COM } 5377917SReza.Sabdar@Sun.COM free(section_name); 5387917SReza.Sabdar@Sun.COM return (0); 5397917SReza.Sabdar@Sun.COM } 5407917SReza.Sabdar@Sun.COM 5417917SReza.Sabdar@Sun.COM 5427917SReza.Sabdar@Sun.COM /* 5437917SReza.Sabdar@Sun.COM * tlm_readlink 5447917SReza.Sabdar@Sun.COM * 5457917SReza.Sabdar@Sun.COM * Read where the softlink points to. Read the link in the checkpointed 5467917SReza.Sabdar@Sun.COM * path if the backup is being done on a checkpointed file system. 5477917SReza.Sabdar@Sun.COM */ 5487917SReza.Sabdar@Sun.COM static int 5497917SReza.Sabdar@Sun.COM tlm_readlink(char *nm, char *snap, char *buf, int bufsize) 5507917SReza.Sabdar@Sun.COM { 5517917SReza.Sabdar@Sun.COM int len; 5527917SReza.Sabdar@Sun.COM 5537917SReza.Sabdar@Sun.COM if ((len = readlink(snap, buf, bufsize)) >= 0) { 5547917SReza.Sabdar@Sun.COM /* 5557917SReza.Sabdar@Sun.COM * realink(2) doesn't null terminate the link name. We must 5567917SReza.Sabdar@Sun.COM * do it here. 5577917SReza.Sabdar@Sun.COM */ 5587917SReza.Sabdar@Sun.COM buf[len] = '\0'; 5597917SReza.Sabdar@Sun.COM } else { 5607917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Error %d reading softlink of [%s]", 5617917SReza.Sabdar@Sun.COM errno, nm); 5627917SReza.Sabdar@Sun.COM buf[0] = '\0'; 5637917SReza.Sabdar@Sun.COM 5647917SReza.Sabdar@Sun.COM /* Backup the link if the destination missing */ 5657917SReza.Sabdar@Sun.COM if (errno == ENOENT) 5667917SReza.Sabdar@Sun.COM return (0); 5677917SReza.Sabdar@Sun.COM 5687917SReza.Sabdar@Sun.COM } 5697917SReza.Sabdar@Sun.COM 5707917SReza.Sabdar@Sun.COM return (len); 5717917SReza.Sabdar@Sun.COM } 5727917SReza.Sabdar@Sun.COM 5738540SReza.Sabdar@Sun.COM /* 5748540SReza.Sabdar@Sun.COM * Read the system attribute file in a single buffer to write 5758540SReza.Sabdar@Sun.COM * it as a single write. A partial write to system attribute would 5768540SReza.Sabdar@Sun.COM * cause an EINVAL on write. 5778540SReza.Sabdar@Sun.COM */ 5788540SReza.Sabdar@Sun.COM static char * 5798540SReza.Sabdar@Sun.COM get_write_one_buf(char *buf, char *rec, int buf_size, int rec_size, 5808540SReza.Sabdar@Sun.COM tlm_cmd_t *lc) 5818540SReza.Sabdar@Sun.COM { 5828540SReza.Sabdar@Sun.COM int len; 5838540SReza.Sabdar@Sun.COM long write_size; 5848540SReza.Sabdar@Sun.COM 5858540SReza.Sabdar@Sun.COM if (rec_size > buf_size) 5868540SReza.Sabdar@Sun.COM return (rec); 5878540SReza.Sabdar@Sun.COM 5888540SReza.Sabdar@Sun.COM len = rec_size; 5898540SReza.Sabdar@Sun.COM (void) memcpy(rec, buf, len); 5908540SReza.Sabdar@Sun.COM buf += len; 5918540SReza.Sabdar@Sun.COM while (rec_size < buf_size) { 5928540SReza.Sabdar@Sun.COM rec = get_write_buffer(buf_size - rec_size, 5938540SReza.Sabdar@Sun.COM &write_size, FALSE, lc); 5948540SReza.Sabdar@Sun.COM if (!rec) 5958540SReza.Sabdar@Sun.COM return (0); 5968540SReza.Sabdar@Sun.COM 5978540SReza.Sabdar@Sun.COM len = min(buf_size - rec_size, write_size); 5988540SReza.Sabdar@Sun.COM (void) memcpy(rec, buf, len); 5998540SReza.Sabdar@Sun.COM rec_size += len; 6008540SReza.Sabdar@Sun.COM buf += len; 6018540SReza.Sabdar@Sun.COM } 6028540SReza.Sabdar@Sun.COM return (rec); 6038540SReza.Sabdar@Sun.COM } 6048540SReza.Sabdar@Sun.COM 6057917SReza.Sabdar@Sun.COM 6067917SReza.Sabdar@Sun.COM /* 6077917SReza.Sabdar@Sun.COM * tlm_output_xattr 6087917SReza.Sabdar@Sun.COM * 6097917SReza.Sabdar@Sun.COM * Put this file into the output buffers. 6107917SReza.Sabdar@Sun.COM */ 6117917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 6127917SReza.Sabdar@Sun.COM longlong_t 6137917SReza.Sabdar@Sun.COM tlm_output_xattr(char *dir, char *name, char *chkdir, 6147917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, 6157917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 6167917SReza.Sabdar@Sun.COM { 6177917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */ 6187917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */ 6197917SReza.Sabdar@Sun.COM int section; /* section of a huge file */ 6207917SReza.Sabdar@Sun.COM int fd; 6219323SReza.Sabdar@Sun.COM int afd = 0; 6227917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */ 6237917SReza.Sabdar@Sun.COM /* for Multi Volume record */ 6247917SReza.Sabdar@Sun.COM u_longlong_t pos; 6257917SReza.Sabdar@Sun.COM DIR *dp; 6267917SReza.Sabdar@Sun.COM struct dirent *dtp; 6277917SReza.Sabdar@Sun.COM char *attrname; 6287917SReza.Sabdar@Sun.COM char *fnamep; 6297917SReza.Sabdar@Sun.COM int rv = 0; 6307917SReza.Sabdar@Sun.COM 6319659SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode) || 6329659SReza.Sabdar@Sun.COM S_ISFIFO(tlm_acls->acl_attr.st_mode)) { 6337917SReza.Sabdar@Sun.COM return (TLM_NO_SOURCE_FILE); 6349659SReza.Sabdar@Sun.COM } 6357917SReza.Sabdar@Sun.COM 6367917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 6377917SReza.Sabdar@Sun.COM if (fullname == NULL) { 6387917SReza.Sabdar@Sun.COM free(fullname); 6397917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 6407917SReza.Sabdar@Sun.COM } 6417917SReza.Sabdar@Sun.COM 6427917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name)) { 6437917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 6447917SReza.Sabdar@Sun.COM free(fullname); 6457917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 6467917SReza.Sabdar@Sun.COM } 6477917SReza.Sabdar@Sun.COM 6488540SReza.Sabdar@Sun.COM if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 && 6498540SReza.Sabdar@Sun.COM sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) { 6507917SReza.Sabdar@Sun.COM free(fullname); 6517917SReza.Sabdar@Sun.COM return (0); 6527917SReza.Sabdar@Sun.COM } 6537917SReza.Sabdar@Sun.COM 6547917SReza.Sabdar@Sun.COM attrname = ndmp_malloc(TLM_MAX_PATH_NAME); 6557917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 6567917SReza.Sabdar@Sun.COM if (attrname == NULL || snapname == NULL) { 6577917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE; 6587917SReza.Sabdar@Sun.COM goto err_out; 6597917SReza.Sabdar@Sun.COM } 6607917SReza.Sabdar@Sun.COM 6617917SReza.Sabdar@Sun.COM if (!tlm_cat_path(snapname, chkdir, name)) { 6627917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 6637917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE; 6647917SReza.Sabdar@Sun.COM goto err_out; 6657917SReza.Sabdar@Sun.COM } 6667917SReza.Sabdar@Sun.COM 6677917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 6687917SReza.Sabdar@Sun.COM 6697917SReza.Sabdar@Sun.COM /* 6707917SReza.Sabdar@Sun.COM * Open the file for reading. 6717917SReza.Sabdar@Sun.COM */ 6728540SReza.Sabdar@Sun.COM fd = attropen(fnamep, ".", O_RDONLY); 6737917SReza.Sabdar@Sun.COM if (fd == -1) { 6748540SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s][%s]", 6758540SReza.Sabdar@Sun.COM fullname, fnamep); 6767917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE; 6777917SReza.Sabdar@Sun.COM goto err_out; 6787917SReza.Sabdar@Sun.COM } 6797917SReza.Sabdar@Sun.COM 6807917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 6817917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 6827917SReza.Sabdar@Sun.COM 6837917SReza.Sabdar@Sun.COM section = 0; 6847917SReza.Sabdar@Sun.COM 6857917SReza.Sabdar@Sun.COM dp = (DIR *)fdopendir(fd); 6867917SReza.Sabdar@Sun.COM if (dp == NULL) { 6877917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname); 6887917SReza.Sabdar@Sun.COM (void) close(fd); 6897917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE; 6907917SReza.Sabdar@Sun.COM goto err_out; 6917917SReza.Sabdar@Sun.COM } 6927917SReza.Sabdar@Sun.COM 6937917SReza.Sabdar@Sun.COM while ((dtp = readdir(dp)) != NULL) { 6947917SReza.Sabdar@Sun.COM int section_size; 6957917SReza.Sabdar@Sun.COM 6967917SReza.Sabdar@Sun.COM if (*dtp->d_name == '.') 6977917SReza.Sabdar@Sun.COM continue; 6987917SReza.Sabdar@Sun.COM 6998540SReza.Sabdar@Sun.COM if (sysattr_rdonly(dtp->d_name)) 7008540SReza.Sabdar@Sun.COM continue; 7018540SReza.Sabdar@Sun.COM 7029323SReza.Sabdar@Sun.COM afd = attropen(fnamep, dtp->d_name, O_RDONLY); 7039323SReza.Sabdar@Sun.COM if (afd == -1) { 7047917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 7058540SReza.Sabdar@Sun.COM "problem(%d) opening xattr file [%s][%s]", errno, 7068540SReza.Sabdar@Sun.COM fullname, fnamep); 7077917SReza.Sabdar@Sun.COM goto tear_down; 7087917SReza.Sabdar@Sun.COM } 7097917SReza.Sabdar@Sun.COM 7109323SReza.Sabdar@Sun.COM (void) output_xattr_header(fullname, dtp->d_name, afd, 7117917SReza.Sabdar@Sun.COM tlm_acls, section, local_commands); 7127917SReza.Sabdar@Sun.COM (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s", 7137917SReza.Sabdar@Sun.COM dtp->d_name); 7147917SReza.Sabdar@Sun.COM (void) output_file_header(attrname, "", tlm_acls, 0, 7157917SReza.Sabdar@Sun.COM local_commands); 7167917SReza.Sabdar@Sun.COM 7177917SReza.Sabdar@Sun.COM section_size = (long)llmin(tlm_acls->acl_attr.st_size, 7187917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE); 7197917SReza.Sabdar@Sun.COM 7207917SReza.Sabdar@Sun.COM /* We only can read upto one section extended attribute */ 7217917SReza.Sabdar@Sun.COM while (section_size > 0) { 7227917SReza.Sabdar@Sun.COM char *buf; 7237917SReza.Sabdar@Sun.COM long actual_size; 7247917SReza.Sabdar@Sun.COM int read_size; 7258540SReza.Sabdar@Sun.COM int sysattr_read = 0; 7268540SReza.Sabdar@Sun.COM char *rec; 7278540SReza.Sabdar@Sun.COM int size; 7287917SReza.Sabdar@Sun.COM 7297917SReza.Sabdar@Sun.COM /* 7307917SReza.Sabdar@Sun.COM * check for Abort commands 7317917SReza.Sabdar@Sun.COM */ 7327917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 7337917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 7347917SReza.Sabdar@Sun.COM goto tear_down; 7357917SReza.Sabdar@Sun.COM } 7367917SReza.Sabdar@Sun.COM 7377917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 7387917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 7397917SReza.Sabdar@Sun.COM tb_file_size = section_size; 7407917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 7417917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 7427917SReza.Sabdar@Sun.COM tb_seek_spot = seek_spot; 7437917SReza.Sabdar@Sun.COM 7447917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size, 7457917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands); 7467917SReza.Sabdar@Sun.COM if (!buf) 7477917SReza.Sabdar@Sun.COM goto tear_down; 7487917SReza.Sabdar@Sun.COM 7498540SReza.Sabdar@Sun.COM if ((actual_size < section_size) && 7508540SReza.Sabdar@Sun.COM sysattr_rw(dtp->d_name)) { 7518540SReza.Sabdar@Sun.COM rec = buf; 7528540SReza.Sabdar@Sun.COM buf = ndmp_malloc(section_size); 7538540SReza.Sabdar@Sun.COM if (!buf) 7548540SReza.Sabdar@Sun.COM goto tear_down; 7558540SReza.Sabdar@Sun.COM size = actual_size; 7568540SReza.Sabdar@Sun.COM actual_size = section_size; 7578540SReza.Sabdar@Sun.COM sysattr_read = 1; 7588540SReza.Sabdar@Sun.COM } 7598540SReza.Sabdar@Sun.COM 7607917SReza.Sabdar@Sun.COM /* 7617917SReza.Sabdar@Sun.COM * check for Abort commands 7627917SReza.Sabdar@Sun.COM */ 7637917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 7647917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 7657917SReza.Sabdar@Sun.COM goto tear_down; 7667917SReza.Sabdar@Sun.COM } 7677917SReza.Sabdar@Sun.COM 7687917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size); 7699323SReza.Sabdar@Sun.COM if ((actual_size = read(afd, buf, read_size)) < 0) 7708540SReza.Sabdar@Sun.COM break; 7718540SReza.Sabdar@Sun.COM 7728540SReza.Sabdar@Sun.COM if (sysattr_read) { 7738540SReza.Sabdar@Sun.COM if (get_write_one_buf(buf, rec, read_size, 7748540SReza.Sabdar@Sun.COM size, local_commands) == 0) { 7758540SReza.Sabdar@Sun.COM free(buf); 7768540SReza.Sabdar@Sun.COM goto tear_down; 7778540SReza.Sabdar@Sun.COM } 7788540SReza.Sabdar@Sun.COM free(buf); 7798540SReza.Sabdar@Sun.COM } 7808540SReza.Sabdar@Sun.COM 7818540SReza.Sabdar@Sun.COM 7827917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size); 7837917SReza.Sabdar@Sun.COM NS_INC(rfile); 7847917SReza.Sabdar@Sun.COM 7857917SReza.Sabdar@Sun.COM if (actual_size == -1) { 7867917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 7877917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]", 7887917SReza.Sabdar@Sun.COM errno, fullname, snapname); 7897917SReza.Sabdar@Sun.COM goto tear_down; 7907917SReza.Sabdar@Sun.COM } 7917917SReza.Sabdar@Sun.COM seek_spot += actual_size; 7927917SReza.Sabdar@Sun.COM section_size -= actual_size; 7937917SReza.Sabdar@Sun.COM } 7949323SReza.Sabdar@Sun.COM (void) close(afd); 7959323SReza.Sabdar@Sun.COM afd = -1; 7967917SReza.Sabdar@Sun.COM } 7977917SReza.Sabdar@Sun.COM 7987917SReza.Sabdar@Sun.COM tear_down: 7997917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 8007917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 8017917SReza.Sabdar@Sun.COM 8029323SReza.Sabdar@Sun.COM if (afd > 0) 8039323SReza.Sabdar@Sun.COM (void) close(afd); 8049323SReza.Sabdar@Sun.COM 8059323SReza.Sabdar@Sun.COM /* closedir closes fd too */ 8067917SReza.Sabdar@Sun.COM (void) closedir(dp); 8077917SReza.Sabdar@Sun.COM 8087917SReza.Sabdar@Sun.COM err_out: 8097917SReza.Sabdar@Sun.COM free(fullname); 8107917SReza.Sabdar@Sun.COM free(attrname); 8117917SReza.Sabdar@Sun.COM free(snapname); 8127917SReza.Sabdar@Sun.COM return (rv); 8137917SReza.Sabdar@Sun.COM } 8147917SReza.Sabdar@Sun.COM 8157917SReza.Sabdar@Sun.COM 8167917SReza.Sabdar@Sun.COM /* 8177917SReza.Sabdar@Sun.COM * tlm_output_file 8187917SReza.Sabdar@Sun.COM * 8197917SReza.Sabdar@Sun.COM * Put this file into the output buffers. 8207917SReza.Sabdar@Sun.COM */ 8217917SReza.Sabdar@Sun.COM longlong_t 8227917SReza.Sabdar@Sun.COM tlm_output_file(char *dir, char *name, char *chkdir, 8237917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands, 8247917SReza.Sabdar@Sun.COM tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q) 8257917SReza.Sabdar@Sun.COM { 8267917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */ 8277917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */ 8287917SReza.Sabdar@Sun.COM char *linkname; /* where this file points */ 8297917SReza.Sabdar@Sun.COM int section = 0; /* section of a huge file */ 8307917SReza.Sabdar@Sun.COM int fd; 8317917SReza.Sabdar@Sun.COM longlong_t real_size; /* the origional file size */ 8327917SReza.Sabdar@Sun.COM longlong_t file_size; /* real size of this file */ 8337917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */ 8347917SReza.Sabdar@Sun.COM /* for Multi Volume record */ 8357917SReza.Sabdar@Sun.COM u_longlong_t pos; 8367917SReza.Sabdar@Sun.COM char *fnamep; 8377917SReza.Sabdar@Sun.COM 8387917SReza.Sabdar@Sun.COM /* Indicate whether a file with the same inode has been backed up. */ 8397917SReza.Sabdar@Sun.COM int hardlink_done = 0; 8407917SReza.Sabdar@Sun.COM 8417917SReza.Sabdar@Sun.COM /* 8427917SReza.Sabdar@Sun.COM * If a file with the same inode has been backed up, hardlink_pos holds 8437917SReza.Sabdar@Sun.COM * the tape offset of the data record. 8447917SReza.Sabdar@Sun.COM */ 8457917SReza.Sabdar@Sun.COM u_longlong_t hardlink_pos = 0; 8467917SReza.Sabdar@Sun.COM 8477917SReza.Sabdar@Sun.COM if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) { 8487917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name); 8497917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 8507917SReza.Sabdar@Sun.COM } 8517917SReza.Sabdar@Sun.COM 8527917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 8537917SReza.Sabdar@Sun.COM linkname = ndmp_malloc(TLM_MAX_PATH_NAME); 8547917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 8557917SReza.Sabdar@Sun.COM if (fullname == NULL || linkname == NULL || snapname == NULL) { 8567917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 8577917SReza.Sabdar@Sun.COM goto err_out; 8587917SReza.Sabdar@Sun.COM } 8597917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name) || 8607917SReza.Sabdar@Sun.COM !tlm_cat_path(snapname, chkdir, name)) { 8617917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 8627917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 8637917SReza.Sabdar@Sun.COM goto err_out; 8647917SReza.Sabdar@Sun.COM } 8657917SReza.Sabdar@Sun.COM 8667917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 8677917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 8687917SReza.Sabdar@Sun.COM 8699659SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode) || 8709659SReza.Sabdar@Sun.COM S_ISFIFO(tlm_acls->acl_attr.st_mode)) { 8719659SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode)) { 8729659SReza.Sabdar@Sun.COM file_size = tlm_readlink(fullname, snapname, linkname, 8739659SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME-1); 8749659SReza.Sabdar@Sun.COM if (file_size < 0) { 8759659SReza.Sabdar@Sun.COM real_size = -ENOENT; 8769659SReza.Sabdar@Sun.COM goto err_out; 8779659SReza.Sabdar@Sun.COM } 8787917SReza.Sabdar@Sun.COM } 8797917SReza.Sabdar@Sun.COM 8807917SReza.Sabdar@Sun.COM /* 8817917SReza.Sabdar@Sun.COM * Since soft links can not be read(2), we should only 8827917SReza.Sabdar@Sun.COM * backup the file header. 8837917SReza.Sabdar@Sun.COM */ 8847917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 8857917SReza.Sabdar@Sun.COM linkname, 8867917SReza.Sabdar@Sun.COM tlm_acls, 8877917SReza.Sabdar@Sun.COM section, 8887917SReza.Sabdar@Sun.COM local_commands); 8897917SReza.Sabdar@Sun.COM 8907917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name, 8917917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 8927917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname, 8937917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 8947917SReza.Sabdar@Sun.COM 8957917SReza.Sabdar@Sun.COM free(fullname); 8967917SReza.Sabdar@Sun.COM free(linkname); 8977917SReza.Sabdar@Sun.COM free(snapname); 8987917SReza.Sabdar@Sun.COM return (0); 8997917SReza.Sabdar@Sun.COM } 9007917SReza.Sabdar@Sun.COM 9017917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 9027917SReza.Sabdar@Sun.COM 9037917SReza.Sabdar@Sun.COM /* 9047917SReza.Sabdar@Sun.COM * For hardlink, only read the data if no other link 9057917SReza.Sabdar@Sun.COM * belonging to the same inode has been backed up. 9067917SReza.Sabdar@Sun.COM */ 9077917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1) { 9087917SReza.Sabdar@Sun.COM hardlink_done = !hardlink_q_get(hardlink_q, 9097917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL); 9107917SReza.Sabdar@Sun.COM } 9117917SReza.Sabdar@Sun.COM 9127917SReza.Sabdar@Sun.COM if (!hardlink_done) { 9137917SReza.Sabdar@Sun.COM /* 9147917SReza.Sabdar@Sun.COM * Open the file for reading. 9157917SReza.Sabdar@Sun.COM */ 9167917SReza.Sabdar@Sun.COM fd = open(fnamep, O_RDONLY); 9177917SReza.Sabdar@Sun.COM if (fd == -1) { 9187917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 9198540SReza.Sabdar@Sun.COM "BACKUP> Can't open file [%s][%s] err(%d)", 9208540SReza.Sabdar@Sun.COM fullname, fnamep, errno); 9217917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SOURCE_FILE; 9227917SReza.Sabdar@Sun.COM goto err_out; 9237917SReza.Sabdar@Sun.COM } 9247917SReza.Sabdar@Sun.COM } else { 9258193SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ", 9267917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, hardlink_pos); 9277917SReza.Sabdar@Sun.COM 9287917SReza.Sabdar@Sun.COM fd = -1; 9297917SReza.Sabdar@Sun.COM } 9307917SReza.Sabdar@Sun.COM 9317917SReza.Sabdar@Sun.COM linkname[0] = 0; 9327917SReza.Sabdar@Sun.COM 9337917SReza.Sabdar@Sun.COM real_size = tlm_acls->acl_attr.st_size; 9347917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info, 9357917SReza.Sabdar@Sun.COM local_commands); 9367917SReza.Sabdar@Sun.COM 9377917SReza.Sabdar@Sun.COM /* 9387917SReza.Sabdar@Sun.COM * section = 0: file is small enough for TAR 9397917SReza.Sabdar@Sun.COM * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks 9407917SReza.Sabdar@Sun.COM * and the file name gets munged 9417917SReza.Sabdar@Sun.COM */ 9427917SReza.Sabdar@Sun.COM file_size = real_size; 9437917SReza.Sabdar@Sun.COM if (file_size > TLM_MAX_TAR_IMAGE) { 9447917SReza.Sabdar@Sun.COM if (output_humongus_header(fullname, file_size, 9457917SReza.Sabdar@Sun.COM local_commands) < 0) { 9467917SReza.Sabdar@Sun.COM (void) close(fd); 9477917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 9487917SReza.Sabdar@Sun.COM goto err_out; 9497917SReza.Sabdar@Sun.COM } 9507917SReza.Sabdar@Sun.COM section = 1; 9517917SReza.Sabdar@Sun.COM } else { 9527917SReza.Sabdar@Sun.COM section = 0; 9537917SReza.Sabdar@Sun.COM } 9547917SReza.Sabdar@Sun.COM 9557917SReza.Sabdar@Sun.COM /* 9567917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode 9577917SReza.Sabdar@Sun.COM * has been backed up, only backup an empty record. 9587917SReza.Sabdar@Sun.COM */ 9597917SReza.Sabdar@Sun.COM if (hardlink_done) 9607917SReza.Sabdar@Sun.COM file_size = 0; 9617917SReza.Sabdar@Sun.COM 9627917SReza.Sabdar@Sun.COM /* 9637917SReza.Sabdar@Sun.COM * work 9647917SReza.Sabdar@Sun.COM */ 9657917SReza.Sabdar@Sun.COM if (file_size == 0) { 9667917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 9677917SReza.Sabdar@Sun.COM linkname, 9687917SReza.Sabdar@Sun.COM tlm_acls, 9697917SReza.Sabdar@Sun.COM section, 9707917SReza.Sabdar@Sun.COM local_commands); 9717917SReza.Sabdar@Sun.COM /* 9727917SReza.Sabdar@Sun.COM * this can fall right through since zero size files 9737917SReza.Sabdar@Sun.COM * will be skipped by the WHILE loop anyway 9747917SReza.Sabdar@Sun.COM */ 9757917SReza.Sabdar@Sun.COM } 9767917SReza.Sabdar@Sun.COM 9777917SReza.Sabdar@Sun.COM while (file_size > 0) { 9787917SReza.Sabdar@Sun.COM int section_size = llmin(file_size, 9797917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE); 9807917SReza.Sabdar@Sun.COM 9817917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_size = (longlong_t)section_size; 9827917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 9837917SReza.Sabdar@Sun.COM linkname, 9847917SReza.Sabdar@Sun.COM tlm_acls, 9857917SReza.Sabdar@Sun.COM section, 9867917SReza.Sabdar@Sun.COM local_commands); 9877917SReza.Sabdar@Sun.COM while (section_size > 0) { 9887917SReza.Sabdar@Sun.COM char *buf; 9897917SReza.Sabdar@Sun.COM long actual_size; 9907917SReza.Sabdar@Sun.COM int read_size; 9917917SReza.Sabdar@Sun.COM 9927917SReza.Sabdar@Sun.COM /* 9937917SReza.Sabdar@Sun.COM * check for Abort commands 9947917SReza.Sabdar@Sun.COM */ 9957917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 9967917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 9977917SReza.Sabdar@Sun.COM goto tear_down; 9987917SReza.Sabdar@Sun.COM } 9997917SReza.Sabdar@Sun.COM 10007917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 10017917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 10027917SReza.Sabdar@Sun.COM tb_file_size = section_size; 10037917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 10047917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 10057917SReza.Sabdar@Sun.COM tb_seek_spot = seek_spot; 10067917SReza.Sabdar@Sun.COM 10077917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size, 10087917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands); 10097917SReza.Sabdar@Sun.COM if (!buf) 10107917SReza.Sabdar@Sun.COM goto tear_down; 10117917SReza.Sabdar@Sun.COM 10127917SReza.Sabdar@Sun.COM /* 10137917SReza.Sabdar@Sun.COM * check for Abort commands 10147917SReza.Sabdar@Sun.COM */ 10157917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 10167917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 10177917SReza.Sabdar@Sun.COM goto tear_down; 10187917SReza.Sabdar@Sun.COM } 10197917SReza.Sabdar@Sun.COM 10207917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size); 10217917SReza.Sabdar@Sun.COM actual_size = read(fd, buf, read_size); 10227917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size); 10237917SReza.Sabdar@Sun.COM NS_INC(rfile); 10247917SReza.Sabdar@Sun.COM 10257917SReza.Sabdar@Sun.COM if (actual_size == 0) 10267917SReza.Sabdar@Sun.COM break; 10277917SReza.Sabdar@Sun.COM 10287917SReza.Sabdar@Sun.COM if (actual_size == -1) { 10297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10307917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]", 10317917SReza.Sabdar@Sun.COM errno, fullname, snapname); 10327917SReza.Sabdar@Sun.COM goto tear_down; 10337917SReza.Sabdar@Sun.COM } 10347917SReza.Sabdar@Sun.COM seek_spot += actual_size; 10357917SReza.Sabdar@Sun.COM file_size -= actual_size; 10367917SReza.Sabdar@Sun.COM section_size -= actual_size; 10377917SReza.Sabdar@Sun.COM } 10387917SReza.Sabdar@Sun.COM section++; 10397917SReza.Sabdar@Sun.COM } 10407917SReza.Sabdar@Sun.COM 10417917SReza.Sabdar@Sun.COM /* 10427917SReza.Sabdar@Sun.COM * If data belonging to this hardlink has been backed up, add the link 10437917SReza.Sabdar@Sun.COM * to hardlink queue. 10447917SReza.Sabdar@Sun.COM */ 10457917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) { 10467917SReza.Sabdar@Sun.COM (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino, 10477917SReza.Sabdar@Sun.COM pos, NULL, 0); 10487917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10498193SReza.Sabdar@Sun.COM "backed up hardlink file %s, inode = %llu, pos = %llu ", 10507917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, pos); 10517917SReza.Sabdar@Sun.COM } 10527917SReza.Sabdar@Sun.COM 10537917SReza.Sabdar@Sun.COM /* 10547917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode has been 10558193SReza.Sabdar@Sun.COM * backed up, no add_node entry should be sent for this link. 10567917SReza.Sabdar@Sun.COM */ 10577917SReza.Sabdar@Sun.COM if (hardlink_done) { 10587917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10598193SReza.Sabdar@Sun.COM "backed up hardlink link %s, inode = %llu, pos = %llu ", 10607917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, hardlink_pos); 10617917SReza.Sabdar@Sun.COM } else { 10627917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name, 10637917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 10647917SReza.Sabdar@Sun.COM } 10657917SReza.Sabdar@Sun.COM 10667917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr, 10677917SReza.Sabdar@Sun.COM pos); 10687917SReza.Sabdar@Sun.COM 10697917SReza.Sabdar@Sun.COM tear_down: 10707917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 10717917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 10727917SReza.Sabdar@Sun.COM 10737917SReza.Sabdar@Sun.COM (void) close(fd); 10747917SReza.Sabdar@Sun.COM 10757917SReza.Sabdar@Sun.COM err_out: 10767917SReza.Sabdar@Sun.COM free(fullname); 10777917SReza.Sabdar@Sun.COM free(linkname); 10787917SReza.Sabdar@Sun.COM free(snapname); 10797917SReza.Sabdar@Sun.COM return (real_size); 10807917SReza.Sabdar@Sun.COM } 10817917SReza.Sabdar@Sun.COM 10827917SReza.Sabdar@Sun.COM /* 10837917SReza.Sabdar@Sun.COM * tar_putfile 10847917SReza.Sabdar@Sun.COM * 10857917SReza.Sabdar@Sun.COM * Main file backup function for tar 10867917SReza.Sabdar@Sun.COM */ 10877917SReza.Sabdar@Sun.COM int 10887917SReza.Sabdar@Sun.COM tar_putfile(char *dir, char *name, char *chkdir, 10897917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, 10907917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats, 10917917SReza.Sabdar@Sun.COM struct hardlink_q *hardlink_q) 10927917SReza.Sabdar@Sun.COM { 10937917SReza.Sabdar@Sun.COM int rv; 10947917SReza.Sabdar@Sun.COM 10957917SReza.Sabdar@Sun.COM rv = tlm_output_file(dir, name, chkdir, tlm_acls, commands, 10967917SReza.Sabdar@Sun.COM local_commands, job_stats, hardlink_q); 10977917SReza.Sabdar@Sun.COM if (rv < 0) 10987917SReza.Sabdar@Sun.COM return (rv); 10997917SReza.Sabdar@Sun.COM 11007917SReza.Sabdar@Sun.COM rv = tlm_output_xattr(dir, name, chkdir, tlm_acls, commands, 11017917SReza.Sabdar@Sun.COM local_commands, job_stats); 11027917SReza.Sabdar@Sun.COM 11037917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0); 11047917SReza.Sabdar@Sun.COM } 11057917SReza.Sabdar@Sun.COM 11067917SReza.Sabdar@Sun.COM /* 11077917SReza.Sabdar@Sun.COM * get_write_buffer 11087917SReza.Sabdar@Sun.COM * 11097917SReza.Sabdar@Sun.COM * a wrapper to tlm_get_write_buffer so that 11107917SReza.Sabdar@Sun.COM * we can cleanly detect ABORT commands 11117917SReza.Sabdar@Sun.COM * without involving the TLM library with 11127917SReza.Sabdar@Sun.COM * our problems. 11137917SReza.Sabdar@Sun.COM */ 11147917SReza.Sabdar@Sun.COM static char * 11157917SReza.Sabdar@Sun.COM get_write_buffer(long size, long *actual_size, 11167917SReza.Sabdar@Sun.COM boolean_t zero, tlm_cmd_t *local_commands) 11177917SReza.Sabdar@Sun.COM { 11187917SReza.Sabdar@Sun.COM while (local_commands->tc_reader == TLM_BACKUP_RUN) { 11197917SReza.Sabdar@Sun.COM char *rec = tlm_get_write_buffer(size, actual_size, 11207917SReza.Sabdar@Sun.COM local_commands->tc_buffers, zero); 11217917SReza.Sabdar@Sun.COM if (rec != 0) { 11227917SReza.Sabdar@Sun.COM return (rec); 11237917SReza.Sabdar@Sun.COM } 11247917SReza.Sabdar@Sun.COM } 11257917SReza.Sabdar@Sun.COM return (NULL); 11267917SReza.Sabdar@Sun.COM } 11277917SReza.Sabdar@Sun.COM 11287917SReza.Sabdar@Sun.COM #define NDMP_MORE_RECORDS 2 11297917SReza.Sabdar@Sun.COM 11307917SReza.Sabdar@Sun.COM /* 11317917SReza.Sabdar@Sun.COM * write_tar_eof 11327917SReza.Sabdar@Sun.COM * 11337917SReza.Sabdar@Sun.COM * This function is initially written for NDMP support. It appends 11347917SReza.Sabdar@Sun.COM * two tar headers to the tar file, and also N more empty buffers 11357917SReza.Sabdar@Sun.COM * to make sure that the two tar headers will be read as a part of 11367917SReza.Sabdar@Sun.COM * a mover record and don't get locked because of EOM on the mover 11377917SReza.Sabdar@Sun.COM * side. 11387917SReza.Sabdar@Sun.COM */ 11397917SReza.Sabdar@Sun.COM void 11407917SReza.Sabdar@Sun.COM write_tar_eof(tlm_cmd_t *local_commands) 11417917SReza.Sabdar@Sun.COM { 11427917SReza.Sabdar@Sun.COM int i; 11437917SReza.Sabdar@Sun.COM long actual_size; 11447917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs; 11457917SReza.Sabdar@Sun.COM 11467917SReza.Sabdar@Sun.COM /* 11477917SReza.Sabdar@Sun.COM * output 2 zero filled records, 11487917SReza.Sabdar@Sun.COM * TAR wants this. 11497917SReza.Sabdar@Sun.COM */ 11507917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 11517917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11527917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 11537917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11547917SReza.Sabdar@Sun.COM 11557917SReza.Sabdar@Sun.COM /* 11567917SReza.Sabdar@Sun.COM * NDMP: Clear the rest of the buffer and write two more buffers 11577917SReza.Sabdar@Sun.COM * to the tape. 11587917SReza.Sabdar@Sun.COM */ 11597917SReza.Sabdar@Sun.COM bufs = local_commands->tc_buffers; 11607917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size, 11617917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11627917SReza.Sabdar@Sun.COM 11637917SReza.Sabdar@Sun.COM for (i = 0; i < NDMP_MORE_RECORDS && 11647917SReza.Sabdar@Sun.COM local_commands->tc_reader == TLM_BACKUP_RUN; i++) { 11657917SReza.Sabdar@Sun.COM /* 11667917SReza.Sabdar@Sun.COM * We don't need the return value of get_write_buffer(), 11677917SReza.Sabdar@Sun.COM * since it's already zeroed out if the buffer is returned. 11687917SReza.Sabdar@Sun.COM */ 11697917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size, 11707917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11717917SReza.Sabdar@Sun.COM } 11727917SReza.Sabdar@Sun.COM 11737917SReza.Sabdar@Sun.COM bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE; 11747917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs); 11757917SReza.Sabdar@Sun.COM } 11767917SReza.Sabdar@Sun.COM 11777917SReza.Sabdar@Sun.COM /* 11787917SReza.Sabdar@Sun.COM * Callback to backup each ZFS property 11797917SReza.Sabdar@Sun.COM */ 11807917SReza.Sabdar@Sun.COM static int 11817917SReza.Sabdar@Sun.COM zfs_put_prop_cb(int prop, void *pp) 11827917SReza.Sabdar@Sun.COM { 11837917SReza.Sabdar@Sun.COM ndmp_metadata_header_t *mhp; 11847917SReza.Sabdar@Sun.COM ndmp_metadata_property_t *mpp; 11857917SReza.Sabdar@Sun.COM char buf[ZFS_MAXNAMELEN]; 11867917SReza.Sabdar@Sun.COM char sbuf[ZFS_MAXNAMELEN]; 11877917SReza.Sabdar@Sun.COM zprop_source_t stype; 11888800SReza.Sabdar@Sun.COM char *sourcestr; 11897917SReza.Sabdar@Sun.COM 11907917SReza.Sabdar@Sun.COM if (pp == NULL) 11917917SReza.Sabdar@Sun.COM return (ZPROP_INVAL); 11927917SReza.Sabdar@Sun.COM 11937917SReza.Sabdar@Sun.COM mhp = (ndmp_metadata_header_t *)pp; 11947917SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count++]; 11957917SReza.Sabdar@Sun.COM 11967917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, zfs_prop_to_name(prop), NAME_MAX); 11977917SReza.Sabdar@Sun.COM (void) zfs_prop_get(mhp->nh_handle, 11989169SReza.Sabdar@Sun.COM prop, buf, sizeof (buf), &stype, sbuf, sizeof (sbuf), B_TRUE); 11997917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, buf, NAME_MAX); 12008800SReza.Sabdar@Sun.COM 12018800SReza.Sabdar@Sun.COM switch (stype) { 12028800SReza.Sabdar@Sun.COM case ZPROP_SRC_NONE: 12038800SReza.Sabdar@Sun.COM sourcestr = "none"; 12048800SReza.Sabdar@Sun.COM break; 12058800SReza.Sabdar@Sun.COM case ZPROP_SRC_LOCAL: 12068800SReza.Sabdar@Sun.COM sourcestr = mhp->nh_dataset; 12078800SReza.Sabdar@Sun.COM break; 12088800SReza.Sabdar@Sun.COM case ZPROP_SRC_TEMPORARY: 12098800SReza.Sabdar@Sun.COM sourcestr = "temporary"; 12108800SReza.Sabdar@Sun.COM break; 12118800SReza.Sabdar@Sun.COM case ZPROP_SRC_DEFAULT: 12128800SReza.Sabdar@Sun.COM sourcestr = "default"; 12138800SReza.Sabdar@Sun.COM break; 12148800SReza.Sabdar@Sun.COM default: 12158800SReza.Sabdar@Sun.COM sourcestr = sbuf; 12168800SReza.Sabdar@Sun.COM break; 12178800SReza.Sabdar@Sun.COM } 12188800SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, sourcestr, NAME_MAX); 12197917SReza.Sabdar@Sun.COM 12207917SReza.Sabdar@Sun.COM return (ZPROP_CONT); 12217917SReza.Sabdar@Sun.COM } 12227917SReza.Sabdar@Sun.COM 12237917SReza.Sabdar@Sun.COM 12247917SReza.Sabdar@Sun.COM /* 12257917SReza.Sabdar@Sun.COM * Notifies ndmpd that the metadata associated with the given ZFS dataset 12267917SReza.Sabdar@Sun.COM * should be backed up. 12277917SReza.Sabdar@Sun.COM */ 12287917SReza.Sabdar@Sun.COM int 12297917SReza.Sabdar@Sun.COM ndmp_include_zfs(ndmp_context_t *nctx, const char *dataset) 12307917SReza.Sabdar@Sun.COM { 12317917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; 12327917SReza.Sabdar@Sun.COM ndmp_metadata_header_t *mhp; 12337917SReza.Sabdar@Sun.COM ndmp_metadata_property_t *mpp; 12347917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd; 12357917SReza.Sabdar@Sun.COM long actual_size; 12367917SReza.Sabdar@Sun.COM nvlist_t *uprops, *ulist; 12377917SReza.Sabdar@Sun.COM const char *pname; 12387917SReza.Sabdar@Sun.COM nvpair_t *elp; 12397917SReza.Sabdar@Sun.COM char *sval, *ssrc; 12407917SReza.Sabdar@Sun.COM char *wbuf, *pp, *tp; 12417917SReza.Sabdar@Sun.COM long size, lsize, sz; 12427917SReza.Sabdar@Sun.COM int align = RECORDSIZE - 1; 12437917SReza.Sabdar@Sun.COM 12447917SReza.Sabdar@Sun.COM if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 12457917SReza.Sabdar@Sun.COM return (-1); 12467917SReza.Sabdar@Sun.COM 12477917SReza.Sabdar@Sun.COM if ((lcmd = cmds->tcs_command) == NULL || 12487917SReza.Sabdar@Sun.COM lcmd->tc_buffers == NULL) 12497917SReza.Sabdar@Sun.COM return (-1); 12507917SReza.Sabdar@Sun.COM 12517917SReza.Sabdar@Sun.COM size = sizeof (ndmp_metadata_header_t) + 12527917SReza.Sabdar@Sun.COM ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 12537917SReza.Sabdar@Sun.COM size += align; 12547917SReza.Sabdar@Sun.COM size &= ~align; 12557917SReza.Sabdar@Sun.COM 12567917SReza.Sabdar@Sun.COM if ((mhp = malloc(size)) == NULL) 12577917SReza.Sabdar@Sun.COM return (-1); 12587917SReza.Sabdar@Sun.COM (void) memset(mhp, 0, size); 12597917SReza.Sabdar@Sun.COM 12607917SReza.Sabdar@Sun.COM mhp->nh_plversion = nctx->nc_plversion; 12617917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_plname, nctx->nc_plname, 12627917SReza.Sabdar@Sun.COM sizeof (mhp->nh_plname)); 12637917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_magic, ZFS_META_MAGIC, sizeof (mhp->nh_magic)); 12647917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_dataset, dataset, sizeof (mhp->nh_dataset)); 12657917SReza.Sabdar@Sun.COM 1266*10260SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx); 12677917SReza.Sabdar@Sun.COM if ((mhp->nh_handle = zfs_open(zlibh, dataset, 12687917SReza.Sabdar@Sun.COM ZFS_TYPE_DATASET)) == NULL) { 1269*10260SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 12707917SReza.Sabdar@Sun.COM free(mhp); 12717917SReza.Sabdar@Sun.COM return (ZPROP_INVAL); 12727917SReza.Sabdar@Sun.COM } 12737917SReza.Sabdar@Sun.COM 12747917SReza.Sabdar@Sun.COM /* Get all the ZFS properties */ 12757917SReza.Sabdar@Sun.COM (void) zprop_iter(zfs_put_prop_cb, mhp, TRUE, TRUE, 12767917SReza.Sabdar@Sun.COM ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET); 12777917SReza.Sabdar@Sun.COM 12787917SReza.Sabdar@Sun.COM /* Get user properties */ 12797917SReza.Sabdar@Sun.COM uprops = zfs_get_user_props(mhp->nh_handle); 12807917SReza.Sabdar@Sun.COM 12817917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, NULL); 12827917SReza.Sabdar@Sun.COM 12837917SReza.Sabdar@Sun.COM while (elp != NULL) { 12847917SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count]; 12857917SReza.Sabdar@Sun.COM if (nvpair_value_nvlist(elp, &ulist) != 0 || 12867917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_VALUE, &sval) != 0 || 12877917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_SOURCE, &ssrc) != 0) { 12887917SReza.Sabdar@Sun.COM zfs_close(mhp->nh_handle); 1289*10260SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 12907917SReza.Sabdar@Sun.COM free(mhp); 12917917SReza.Sabdar@Sun.COM return (-1); 12927917SReza.Sabdar@Sun.COM } 12937917SReza.Sabdar@Sun.COM if ((pname = nvpair_name(elp)) != NULL) 12947917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, pname, NAME_MAX); 12957917SReza.Sabdar@Sun.COM 12967917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, sval, NAME_MAX); 12977917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, ssrc, NAME_MAX); 12987917SReza.Sabdar@Sun.COM mhp->nh_count++; 12997917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, elp); 13007917SReza.Sabdar@Sun.COM } 13017917SReza.Sabdar@Sun.COM 13027917SReza.Sabdar@Sun.COM zfs_close(mhp->nh_handle); 1303*10260SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx); 13047917SReza.Sabdar@Sun.COM 13057917SReza.Sabdar@Sun.COM if ((wbuf = get_write_buffer(size, &actual_size, TRUE, 13067917SReza.Sabdar@Sun.COM lcmd)) != NULL) { 13077917SReza.Sabdar@Sun.COM pp = (char *)mhp; 13087917SReza.Sabdar@Sun.COM 13097917SReza.Sabdar@Sun.COM (void) memcpy(wbuf, pp, (actual_size < size) ? 13107917SReza.Sabdar@Sun.COM actual_size : size); 13117917SReza.Sabdar@Sun.COM pp += (actual_size < size) ? actual_size : size; 13127917SReza.Sabdar@Sun.COM 13137917SReza.Sabdar@Sun.COM sz = actual_size; 13147917SReza.Sabdar@Sun.COM while (sz < size && 13157917SReza.Sabdar@Sun.COM ((tp = get_write_buffer(size - sz, &lsize, 13167917SReza.Sabdar@Sun.COM TRUE, lcmd))) != NULL) { 13177917SReza.Sabdar@Sun.COM (void) memcpy(tp, pp, size - sz); 13187917SReza.Sabdar@Sun.COM sz += lsize; 13197917SReza.Sabdar@Sun.COM pp += lsize; 13207917SReza.Sabdar@Sun.COM } 13217917SReza.Sabdar@Sun.COM if (sz > size) { 13227917SReza.Sabdar@Sun.COM tlm_unget_write_buffer(lcmd->tc_buffers, sz - size); 13237917SReza.Sabdar@Sun.COM } 13247917SReza.Sabdar@Sun.COM } 13257917SReza.Sabdar@Sun.COM 13267917SReza.Sabdar@Sun.COM free(mhp); 13277917SReza.Sabdar@Sun.COM return (0); 13287917SReza.Sabdar@Sun.COM } 1329