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; 757917SReza.Sabdar@Sun.COM 767917SReza.Sabdar@Sun.COM 777917SReza.Sabdar@Sun.COM /* 787917SReza.Sabdar@Sun.COM * output_mem 797917SReza.Sabdar@Sun.COM * 807917SReza.Sabdar@Sun.COM * Gets a IO write buffer and copies memory to the that. 817917SReza.Sabdar@Sun.COM */ 827917SReza.Sabdar@Sun.COM static void 837917SReza.Sabdar@Sun.COM output_mem(tlm_cmd_t *local_commands, char *mem, 847917SReza.Sabdar@Sun.COM int len) 857917SReza.Sabdar@Sun.COM { 867917SReza.Sabdar@Sun.COM long actual_size, rec_size; 877917SReza.Sabdar@Sun.COM char *rec; 887917SReza.Sabdar@Sun.COM 897917SReza.Sabdar@Sun.COM while (len > 0) { 907917SReza.Sabdar@Sun.COM rec = get_write_buffer(len, &actual_size, 917917SReza.Sabdar@Sun.COM FALSE, local_commands); 927917SReza.Sabdar@Sun.COM rec_size = min(actual_size, len); 937917SReza.Sabdar@Sun.COM (void) memcpy(rec, mem, rec_size); 947917SReza.Sabdar@Sun.COM mem += rec_size; 957917SReza.Sabdar@Sun.COM len -= rec_size; 967917SReza.Sabdar@Sun.COM } 977917SReza.Sabdar@Sun.COM } 987917SReza.Sabdar@Sun.COM 997917SReza.Sabdar@Sun.COM /* 1007917SReza.Sabdar@Sun.COM * tlm_output_dir 1017917SReza.Sabdar@Sun.COM * 1027917SReza.Sabdar@Sun.COM * Put the directory information into the output buffers. 1037917SReza.Sabdar@Sun.COM */ 1047917SReza.Sabdar@Sun.COM int 1057917SReza.Sabdar@Sun.COM tlm_output_dir(char *name, tlm_acls_t *tlm_acls, 1067917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 1077917SReza.Sabdar@Sun.COM { 1087917SReza.Sabdar@Sun.COM u_longlong_t pos; 1097917SReza.Sabdar@Sun.COM 1107917SReza.Sabdar@Sun.COM /* 1117917SReza.Sabdar@Sun.COM * Send the node or path history of the directory itself. 1127917SReza.Sabdar@Sun.COM */ 1137917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 1147917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 1157917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos); 1167917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos); 1177917SReza.Sabdar@Sun.COM /* fhdir_cb is handled in ndmpd_tar3.c */ 1187917SReza.Sabdar@Sun.COM 1197917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info, 1207917SReza.Sabdar@Sun.COM local_commands); 1217917SReza.Sabdar@Sun.COM (void) output_file_header(name, "", tlm_acls, 0, 1227917SReza.Sabdar@Sun.COM local_commands); 1237917SReza.Sabdar@Sun.COM 1247917SReza.Sabdar@Sun.COM return (0); 1257917SReza.Sabdar@Sun.COM } 1267917SReza.Sabdar@Sun.COM 1277917SReza.Sabdar@Sun.COM /* 1287917SReza.Sabdar@Sun.COM * tar_putdir 1297917SReza.Sabdar@Sun.COM * 1307917SReza.Sabdar@Sun.COM * Main dir backup function for tar 1317917SReza.Sabdar@Sun.COM */ 1327917SReza.Sabdar@Sun.COM int 1337917SReza.Sabdar@Sun.COM tar_putdir(char *name, tlm_acls_t *tlm_acls, 1347917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 1357917SReza.Sabdar@Sun.COM { 1367917SReza.Sabdar@Sun.COM int rv; 1377917SReza.Sabdar@Sun.COM 1387917SReza.Sabdar@Sun.COM rv = tlm_output_dir(name, tlm_acls, local_commands, job_stats); 1397917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0); 1407917SReza.Sabdar@Sun.COM } 1417917SReza.Sabdar@Sun.COM 1427917SReza.Sabdar@Sun.COM /* 1437917SReza.Sabdar@Sun.COM * output_acl_header 1447917SReza.Sabdar@Sun.COM * 1457917SReza.Sabdar@Sun.COM * output the ACL header record and data 1467917SReza.Sabdar@Sun.COM */ 1477917SReza.Sabdar@Sun.COM static int 1487917SReza.Sabdar@Sun.COM output_acl_header(sec_attr_t *acl_info, 1497917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands) 1507917SReza.Sabdar@Sun.COM { 1517917SReza.Sabdar@Sun.COM long actual_size; 1527917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 1537917SReza.Sabdar@Sun.COM long acl_size; 1547917SReza.Sabdar@Sun.COM 1557917SReza.Sabdar@Sun.COM if ((acl_info == NULL) || (*acl_info->attr_info == '\0')) 1567917SReza.Sabdar@Sun.COM return (0); 1577917SReza.Sabdar@Sun.COM 1587917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 1597917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 1607917SReza.Sabdar@Sun.COM if (!tar_hdr) 1617917SReza.Sabdar@Sun.COM return (0); 1627917SReza.Sabdar@Sun.COM 1637917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_ACL; 1647917SReza.Sabdar@Sun.COM acl_info->attr_type = UFSD_ACL; 1657917SReza.Sabdar@Sun.COM (void) snprintf(acl_info->attr_len, sizeof (acl_info->attr_len), 1667917SReza.Sabdar@Sun.COM "%06o", strlen(acl_info->attr_info)); 1677917SReza.Sabdar@Sun.COM 1687917SReza.Sabdar@Sun.COM acl_size = sizeof (*acl_info); 1697917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, "UFSACL", TLM_NAME_SIZE); 1707917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 1717917SReza.Sabdar@Sun.COM acl_size); 1727917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 1737917SReza.Sabdar@Sun.COM 0444); 1747917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 0); 1757917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 0); 1767917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 1777917SReza.Sabdar@Sun.COM "%011o ", 0); 1787917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 1797917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 1807917SReza.Sabdar@Sun.COM 1817917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 1827917SReza.Sabdar@Sun.COM 1837917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)acl_info, acl_size); 1847917SReza.Sabdar@Sun.COM return (0); 1857917SReza.Sabdar@Sun.COM } 1867917SReza.Sabdar@Sun.COM 1877917SReza.Sabdar@Sun.COM /* 1887917SReza.Sabdar@Sun.COM * output_humongus_header 1897917SReza.Sabdar@Sun.COM * 1907917SReza.Sabdar@Sun.COM * output a special header record for HUGE files 1917917SReza.Sabdar@Sun.COM * output is: 1) a TAR "HUGE" header redord 1927917SReza.Sabdar@Sun.COM * 2) a "file" of size, name 1937917SReza.Sabdar@Sun.COM */ 1947917SReza.Sabdar@Sun.COM static int 1957917SReza.Sabdar@Sun.COM output_humongus_header(char *fullname, longlong_t file_size, 1967917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands) 1977917SReza.Sabdar@Sun.COM { 1987917SReza.Sabdar@Sun.COM char *buf; 1997917SReza.Sabdar@Sun.COM int len; 2007917SReza.Sabdar@Sun.COM long actual_size; 2017917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 2027917SReza.Sabdar@Sun.COM 2037917SReza.Sabdar@Sun.COM /* 2047917SReza.Sabdar@Sun.COM * buf will contain: "%llu %s": 2057917SReza.Sabdar@Sun.COM * - 20 is the maximum length of 'ulong_tlong' decimal notation. 2067917SReza.Sabdar@Sun.COM * - The first '1' is for the ' ' between the "%llu" and the fullname. 2077917SReza.Sabdar@Sun.COM * - The last '1' is for the null-terminator of fullname. 2087917SReza.Sabdar@Sun.COM */ 2097917SReza.Sabdar@Sun.COM len = 20 + 1 + strlen(fullname) + 1; 2107917SReza.Sabdar@Sun.COM 2117917SReza.Sabdar@Sun.COM if ((buf = ndmp_malloc(sizeof (char) * len)) == NULL) 2127917SReza.Sabdar@Sun.COM return (-1); 2137917SReza.Sabdar@Sun.COM 2147917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 2157917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 2167917SReza.Sabdar@Sun.COM if (!tar_hdr) { 2177917SReza.Sabdar@Sun.COM free(buf); 2187917SReza.Sabdar@Sun.COM return (0); 2197917SReza.Sabdar@Sun.COM } 2207917SReza.Sabdar@Sun.COM 2217917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_HUMONGUS; 2227917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 2237917SReza.Sabdar@Sun.COM len); 2247917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 2257917SReza.Sabdar@Sun.COM (void) snprintf(buf, len, "%lld %s", file_size, fullname); 2267917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, buf, len); 2277917SReza.Sabdar@Sun.COM 2287917SReza.Sabdar@Sun.COM free(buf); 2297917SReza.Sabdar@Sun.COM return (0); 2307917SReza.Sabdar@Sun.COM } 2317917SReza.Sabdar@Sun.COM 2327917SReza.Sabdar@Sun.COM 2337917SReza.Sabdar@Sun.COM /* 2347917SReza.Sabdar@Sun.COM * output_xattr_header 2357917SReza.Sabdar@Sun.COM * 2367917SReza.Sabdar@Sun.COM * output the TAR header record for extended attributes 2377917SReza.Sabdar@Sun.COM */ 2387917SReza.Sabdar@Sun.COM static int 2397917SReza.Sabdar@Sun.COM output_xattr_header(char *fname, char *aname, int fd, 2407917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 2417917SReza.Sabdar@Sun.COM { 2427917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr; 2437917SReza.Sabdar@Sun.COM struct xattr_hdr *xhdr; 2447917SReza.Sabdar@Sun.COM struct xattr_buf *xbuf; 2457917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 2467917SReza.Sabdar@Sun.COM long actual_size; 2477917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 2487917SReza.Sabdar@Sun.COM int hsize; 2497917SReza.Sabdar@Sun.COM int comlen; 2507917SReza.Sabdar@Sun.COM int namesz; 2517917SReza.Sabdar@Sun.COM 2527917SReza.Sabdar@Sun.COM if (section_name == NULL) 2537917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 2547917SReza.Sabdar@Sun.COM 2557917SReza.Sabdar@Sun.COM if (fstat64(fd, attr) == -1) { 2567917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "output_file_header stat failed."); 2577917SReza.Sabdar@Sun.COM free(section_name); 2587917SReza.Sabdar@Sun.COM return (-TLM_OPEN_ERR); 2597917SReza.Sabdar@Sun.COM } 2607917SReza.Sabdar@Sun.COM 2617917SReza.Sabdar@Sun.COM /* 2627917SReza.Sabdar@Sun.COM * if the file has to go out in sections, 2637917SReza.Sabdar@Sun.COM * we must mung the name. 2647917SReza.Sabdar@Sun.COM */ 2657917SReza.Sabdar@Sun.COM if (section == 0) { 2667917SReza.Sabdar@Sun.COM (void) snprintf(section_name, TLM_MAX_PATH_NAME, 2677917SReza.Sabdar@Sun.COM "/dev/null/%s.hdr", aname); 2687917SReza.Sabdar@Sun.COM } else { 2697917SReza.Sabdar@Sun.COM (void) snprintf(section_name, 2707917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", aname, section); 2717917SReza.Sabdar@Sun.COM } 2727917SReza.Sabdar@Sun.COM namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */ 2737917SReza.Sabdar@Sun.COM hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 2747917SReza.Sabdar@Sun.COM comlen = namesz + sizeof (struct xattr_buf); 2757917SReza.Sabdar@Sun.COM 2767917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 2777917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 2787917SReza.Sabdar@Sun.COM if (!tar_hdr) { 2797917SReza.Sabdar@Sun.COM free(section_name); 2807917SReza.Sabdar@Sun.COM return (0); 2817917SReza.Sabdar@Sun.COM } 2827917SReza.Sabdar@Sun.COM 2837917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 2847917SReza.Sabdar@Sun.COM 2857917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_XATTR; 2867917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 2877917SReza.Sabdar@Sun.COM hsize); 2887917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 2897917SReza.Sabdar@Sun.COM attr->st_mode & 07777); 2907917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 2917917SReza.Sabdar@Sun.COM attr->st_uid); 2927917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 2937917SReza.Sabdar@Sun.COM attr->st_gid); 2947917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 2957917SReza.Sabdar@Sun.COM attr->st_mtime); 2967917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 2977917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 2987917SReza.Sabdar@Sun.COM 2998540SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d", 3008540SReza.Sabdar@Sun.COM aname, hsize, attr->st_mode & 07777, attr->st_uid, attr->st_gid); 3018540SReza.Sabdar@Sun.COM 3027917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 3037917SReza.Sabdar@Sun.COM 3047917SReza.Sabdar@Sun.COM xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE, 3057917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 3067917SReza.Sabdar@Sun.COM if (!xhdr) { 3077917SReza.Sabdar@Sun.COM free(section_name); 3087917SReza.Sabdar@Sun.COM return (0); 3097917SReza.Sabdar@Sun.COM } 3107917SReza.Sabdar@Sun.COM 3117917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s", 3127917SReza.Sabdar@Sun.COM XATTR_ARCH_VERS); 3137917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d", 3147917SReza.Sabdar@Sun.COM sizeof (xhdr->h_size) - 1, hsize); 3157917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len), 3167917SReza.Sabdar@Sun.COM "%0*d", sizeof (xhdr->h_component_len) - 1, comlen); 3177917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_link_component_len, 3187917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len), "%0*d", 3197917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len) - 1, 0); 3207917SReza.Sabdar@Sun.COM 3217917SReza.Sabdar@Sun.COM xbuf = (struct xattr_buf *)(((caddr_t)xhdr) + 3227917SReza.Sabdar@Sun.COM sizeof (struct xattr_hdr)); 3237917SReza.Sabdar@Sun.COM (void) snprintf(xbuf->h_namesz, sizeof (xbuf->h_namesz), "%0*d", 3247917SReza.Sabdar@Sun.COM sizeof (xbuf->h_namesz) - 1, namesz); 3257917SReza.Sabdar@Sun.COM 3267917SReza.Sabdar@Sun.COM /* No support for links in extended attributes */ 3277917SReza.Sabdar@Sun.COM xbuf->h_typeflag = LF_NORMAL; 3287917SReza.Sabdar@Sun.COM 3297917SReza.Sabdar@Sun.COM (void) strlcpy(xbuf->h_names, fname, TLM_NAME_SIZE); 3307917SReza.Sabdar@Sun.COM (void) strlcpy(&xbuf->h_names[strlen(fname) + 1], aname, 3317917SReza.Sabdar@Sun.COM TLM_NAME_SIZE); 3327917SReza.Sabdar@Sun.COM 3337917SReza.Sabdar@Sun.COM free(section_name); 3347917SReza.Sabdar@Sun.COM return (0); 3357917SReza.Sabdar@Sun.COM } 3367917SReza.Sabdar@Sun.COM 3377917SReza.Sabdar@Sun.COM 3387917SReza.Sabdar@Sun.COM /* 3397917SReza.Sabdar@Sun.COM * output_file_header 3407917SReza.Sabdar@Sun.COM * 3417917SReza.Sabdar@Sun.COM * output the TAR header record 3427917SReza.Sabdar@Sun.COM */ 3437917SReza.Sabdar@Sun.COM static int 3447917SReza.Sabdar@Sun.COM output_file_header(char *name, char *link, 3457917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 3467917SReza.Sabdar@Sun.COM { 3477917SReza.Sabdar@Sun.COM static longlong_t file_count = 0; 3487917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr; 3497917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 3507917SReza.Sabdar@Sun.COM long actual_size; 3517917SReza.Sabdar@Sun.COM boolean_t long_name = FALSE; 3527917SReza.Sabdar@Sun.COM boolean_t long_link = FALSE; 3537917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 3547917SReza.Sabdar@Sun.COM int nmlen, lnklen; 3558540SReza.Sabdar@Sun.COM uid_t uid; 3568540SReza.Sabdar@Sun.COM gid_t gid; 3578540SReza.Sabdar@Sun.COM char *uname = ""; 3588540SReza.Sabdar@Sun.COM char *gname = ""; 3598540SReza.Sabdar@Sun.COM struct passwd *pwd; 3608540SReza.Sabdar@Sun.COM struct group *grp; 3617917SReza.Sabdar@Sun.COM 3627917SReza.Sabdar@Sun.COM if (section_name == NULL) 3637917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 3647917SReza.Sabdar@Sun.COM 3657917SReza.Sabdar@Sun.COM /* 3667917SReza.Sabdar@Sun.COM * if the file has to go out in sections, 3677917SReza.Sabdar@Sun.COM * we must mung the name. 3687917SReza.Sabdar@Sun.COM */ 3697917SReza.Sabdar@Sun.COM if (section == 0) { 3707917SReza.Sabdar@Sun.COM (void) strlcpy(section_name, name, TLM_MAX_PATH_NAME); 3717917SReza.Sabdar@Sun.COM } else { 3727917SReza.Sabdar@Sun.COM (void) snprintf(section_name, 3737917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", name, section); 3747917SReza.Sabdar@Sun.COM } 3757917SReza.Sabdar@Sun.COM 3768540SReza.Sabdar@Sun.COM if ((pwd = getpwuid(attr->st_uid)) != NULL) 3778540SReza.Sabdar@Sun.COM uname = pwd->pw_name; 3788540SReza.Sabdar@Sun.COM if ((grp = getgrgid(attr->st_gid)) != NULL) 3798540SReza.Sabdar@Sun.COM gname = grp->gr_name; 3808540SReza.Sabdar@Sun.COM 3818540SReza.Sabdar@Sun.COM if ((ulong_t)(uid = attr->st_uid) > (ulong_t)OCTAL7CHAR) 3828540SReza.Sabdar@Sun.COM uid = UID_NOBODY; 3838540SReza.Sabdar@Sun.COM if ((ulong_t)(gid = attr->st_gid) > (ulong_t)OCTAL7CHAR) 3848540SReza.Sabdar@Sun.COM gid = GID_NOBODY; 3858540SReza.Sabdar@Sun.COM 3867917SReza.Sabdar@Sun.COM nmlen = strlen(section_name); 3877917SReza.Sabdar@Sun.COM if (nmlen >= NAMSIZ) { 3887917SReza.Sabdar@Sun.COM /* 3897917SReza.Sabdar@Sun.COM * file name is too big, it must go out 3907917SReza.Sabdar@Sun.COM * in its own data file 3917917SReza.Sabdar@Sun.COM */ 3927917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 3937917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 3947917SReza.Sabdar@Sun.COM if (!tar_hdr) { 3957917SReza.Sabdar@Sun.COM free(section_name); 3967917SReza.Sabdar@Sun.COM return (0); 3977917SReza.Sabdar@Sun.COM } 3987917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name, 3997917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4007917SReza.Sabdar@Sun.COM "%s%08qd.fil", 4017917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4027917SReza.Sabdar@Sun.COM file_count++); 4037917SReza.Sabdar@Sun.COM 4047917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGNAME; 4057917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 4067917SReza.Sabdar@Sun.COM "%011o ", nmlen); 4077917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 4087917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777); 4097917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 4108540SReza.Sabdar@Sun.COM "%06o ", uid); 4117917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 4128540SReza.Sabdar@Sun.COM "%06o ", gid); 4138540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), 4148540SReza.Sabdar@Sun.COM "%.31s", uname); 4158540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), 4168540SReza.Sabdar@Sun.COM "%.31s", gname); 4177917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 4187917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime); 4197917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 4207917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 4217917SReza.Sabdar@Sun.COM 4227917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 4237917SReza.Sabdar@Sun.COM 4247917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, 4257917SReza.Sabdar@Sun.COM (void *)section_name, nmlen); 4267917SReza.Sabdar@Sun.COM long_name = TRUE; 4277917SReza.Sabdar@Sun.COM } 4287917SReza.Sabdar@Sun.COM 4297917SReza.Sabdar@Sun.COM lnklen = strlen(link); 4307917SReza.Sabdar@Sun.COM if (lnklen >= NAMSIZ) { 4317917SReza.Sabdar@Sun.COM /* 4327917SReza.Sabdar@Sun.COM * link name is too big, it must go out 4337917SReza.Sabdar@Sun.COM * in its own data file 4347917SReza.Sabdar@Sun.COM */ 4357917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 4367917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 4377917SReza.Sabdar@Sun.COM if (!tar_hdr) { 4387917SReza.Sabdar@Sun.COM free(section_name); 4397917SReza.Sabdar@Sun.COM return (0); 4407917SReza.Sabdar@Sun.COM } 4417917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname, 4427917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4437917SReza.Sabdar@Sun.COM "%s%08qd.slk", 4447917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4457917SReza.Sabdar@Sun.COM file_count++); 4467917SReza.Sabdar@Sun.COM 4477917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGLINK; 4487917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 4497917SReza.Sabdar@Sun.COM "%011o ", lnklen); 4507917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 4517917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777); 4527917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 4538540SReza.Sabdar@Sun.COM "%06o ", uid); 4547917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 4558540SReza.Sabdar@Sun.COM "%06o ", gid); 4568540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), 4578540SReza.Sabdar@Sun.COM "%.31s", uname); 4588540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), 4598540SReza.Sabdar@Sun.COM "%.31s", gname); 4607917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 4617917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime); 4627917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 4637917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 4647917SReza.Sabdar@Sun.COM 4657917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 4667917SReza.Sabdar@Sun.COM 4677917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)link, 4687917SReza.Sabdar@Sun.COM lnklen); 4697917SReza.Sabdar@Sun.COM long_link = TRUE; 4707917SReza.Sabdar@Sun.COM } 4717917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 4727917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 4737917SReza.Sabdar@Sun.COM if (!tar_hdr) { 4747917SReza.Sabdar@Sun.COM free(section_name); 4757917SReza.Sabdar@Sun.COM return (0); 4767917SReza.Sabdar@Sun.COM } 4777917SReza.Sabdar@Sun.COM if (long_name) { 4787917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name, 4797917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4807917SReza.Sabdar@Sun.COM "%s%08qd.fil", 4817917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4827917SReza.Sabdar@Sun.COM file_count++); 4837917SReza.Sabdar@Sun.COM } else { 4847917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 4857917SReza.Sabdar@Sun.COM } 4867917SReza.Sabdar@Sun.COM 4877917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "long_link: %s [%s]", long_link ? "TRUE" : "FALSE", 4887917SReza.Sabdar@Sun.COM link); 4897917SReza.Sabdar@Sun.COM 4907917SReza.Sabdar@Sun.COM if (long_link) { 4917917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname, 4927917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4937917SReza.Sabdar@Sun.COM "%s%08qd.slk", 4947917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4957917SReza.Sabdar@Sun.COM file_count++); 4967917SReza.Sabdar@Sun.COM } else { 4977917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_linkname, link, TLM_NAME_SIZE); 4987917SReza.Sabdar@Sun.COM } 4997917SReza.Sabdar@Sun.COM if (S_ISDIR(attr->st_mode)) { 5007917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_DIR; 5017917SReza.Sabdar@Sun.COM } else if (S_ISFIFO(attr->st_mode)) { 5027917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_FIFO; 5037917SReza.Sabdar@Sun.COM } else if (attr->st_nlink > 1) { 5047917SReza.Sabdar@Sun.COM /* mark file with hardlink LF_LINK */ 5057917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LINK; 5067917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_shared.th_hlink_ino, 5077917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_shared.th_hlink_ino), 5088193SReza.Sabdar@Sun.COM "%011llo ", attr->st_ino); 5097917SReza.Sabdar@Sun.COM } else { 5107917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL : LF_SYMLINK; 5117917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "linkflag: '%c'", tar_hdr->th_linkflag); 5127917SReza.Sabdar@Sun.COM } 5137917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 5147917SReza.Sabdar@Sun.COM (long)attr->st_size); 5157917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 5167917SReza.Sabdar@Sun.COM attr->st_mode & 07777); 5177917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 5188540SReza.Sabdar@Sun.COM uid); 5197917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 5208540SReza.Sabdar@Sun.COM gid); 5218540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), "%.31s", 5228540SReza.Sabdar@Sun.COM uname); 5238540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), "%.31s", 5248540SReza.Sabdar@Sun.COM gname); 5257917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 5267917SReza.Sabdar@Sun.COM attr->st_mtime); 5277917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 5287917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 5297917SReza.Sabdar@Sun.COM 5307917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 5317917SReza.Sabdar@Sun.COM if (long_name || long_link) { 5327917SReza.Sabdar@Sun.COM if (file_count > 99999990) { 5337917SReza.Sabdar@Sun.COM file_count = 0; 5347917SReza.Sabdar@Sun.COM } 5357917SReza.Sabdar@Sun.COM } 5367917SReza.Sabdar@Sun.COM free(section_name); 5377917SReza.Sabdar@Sun.COM return (0); 5387917SReza.Sabdar@Sun.COM } 5397917SReza.Sabdar@Sun.COM 5407917SReza.Sabdar@Sun.COM 5417917SReza.Sabdar@Sun.COM /* 5427917SReza.Sabdar@Sun.COM * tlm_readlink 5437917SReza.Sabdar@Sun.COM * 5447917SReza.Sabdar@Sun.COM * Read where the softlink points to. Read the link in the checkpointed 5457917SReza.Sabdar@Sun.COM * path if the backup is being done on a checkpointed file system. 5467917SReza.Sabdar@Sun.COM */ 5477917SReza.Sabdar@Sun.COM static int 5487917SReza.Sabdar@Sun.COM tlm_readlink(char *nm, char *snap, char *buf, int bufsize) 5497917SReza.Sabdar@Sun.COM { 5507917SReza.Sabdar@Sun.COM int len; 5517917SReza.Sabdar@Sun.COM 5527917SReza.Sabdar@Sun.COM if ((len = readlink(snap, buf, bufsize)) >= 0) { 5537917SReza.Sabdar@Sun.COM /* 5547917SReza.Sabdar@Sun.COM * realink(2) doesn't null terminate the link name. We must 5557917SReza.Sabdar@Sun.COM * do it here. 5567917SReza.Sabdar@Sun.COM */ 5577917SReza.Sabdar@Sun.COM buf[len] = '\0'; 5587917SReza.Sabdar@Sun.COM } else { 5597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Error %d reading softlink of [%s]", 5607917SReza.Sabdar@Sun.COM errno, nm); 5617917SReza.Sabdar@Sun.COM buf[0] = '\0'; 5627917SReza.Sabdar@Sun.COM 5637917SReza.Sabdar@Sun.COM /* Backup the link if the destination missing */ 5647917SReza.Sabdar@Sun.COM if (errno == ENOENT) 5657917SReza.Sabdar@Sun.COM return (0); 5667917SReza.Sabdar@Sun.COM 5677917SReza.Sabdar@Sun.COM } 5687917SReza.Sabdar@Sun.COM 5697917SReza.Sabdar@Sun.COM return (len); 5707917SReza.Sabdar@Sun.COM } 5717917SReza.Sabdar@Sun.COM 5728540SReza.Sabdar@Sun.COM /* 5738540SReza.Sabdar@Sun.COM * Read the system attribute file in a single buffer to write 5748540SReza.Sabdar@Sun.COM * it as a single write. A partial write to system attribute would 5758540SReza.Sabdar@Sun.COM * cause an EINVAL on write. 5768540SReza.Sabdar@Sun.COM */ 5778540SReza.Sabdar@Sun.COM static char * 5788540SReza.Sabdar@Sun.COM get_write_one_buf(char *buf, char *rec, int buf_size, int rec_size, 5798540SReza.Sabdar@Sun.COM tlm_cmd_t *lc) 5808540SReza.Sabdar@Sun.COM { 5818540SReza.Sabdar@Sun.COM int len; 5828540SReza.Sabdar@Sun.COM long write_size; 5838540SReza.Sabdar@Sun.COM 5848540SReza.Sabdar@Sun.COM if (rec_size > buf_size) 5858540SReza.Sabdar@Sun.COM return (rec); 5868540SReza.Sabdar@Sun.COM 5878540SReza.Sabdar@Sun.COM len = rec_size; 5888540SReza.Sabdar@Sun.COM (void) memcpy(rec, buf, len); 5898540SReza.Sabdar@Sun.COM buf += len; 5908540SReza.Sabdar@Sun.COM while (rec_size < buf_size) { 5918540SReza.Sabdar@Sun.COM rec = get_write_buffer(buf_size - rec_size, 5928540SReza.Sabdar@Sun.COM &write_size, FALSE, lc); 5938540SReza.Sabdar@Sun.COM if (!rec) 5948540SReza.Sabdar@Sun.COM return (0); 5958540SReza.Sabdar@Sun.COM 5968540SReza.Sabdar@Sun.COM len = min(buf_size - rec_size, write_size); 5978540SReza.Sabdar@Sun.COM (void) memcpy(rec, buf, len); 5988540SReza.Sabdar@Sun.COM rec_size += len; 5998540SReza.Sabdar@Sun.COM buf += len; 6008540SReza.Sabdar@Sun.COM } 6018540SReza.Sabdar@Sun.COM return (rec); 6028540SReza.Sabdar@Sun.COM } 6038540SReza.Sabdar@Sun.COM 6047917SReza.Sabdar@Sun.COM 6057917SReza.Sabdar@Sun.COM /* 6067917SReza.Sabdar@Sun.COM * tlm_output_xattr 6077917SReza.Sabdar@Sun.COM * 6087917SReza.Sabdar@Sun.COM * Put this file into the output buffers. 6097917SReza.Sabdar@Sun.COM */ 6107917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 6117917SReza.Sabdar@Sun.COM longlong_t 6127917SReza.Sabdar@Sun.COM tlm_output_xattr(char *dir, char *name, char *chkdir, 6137917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, 6147917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 6157917SReza.Sabdar@Sun.COM { 6167917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */ 6177917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */ 6187917SReza.Sabdar@Sun.COM int section; /* section of a huge file */ 6197917SReza.Sabdar@Sun.COM int fd; 620*9323SReza.Sabdar@Sun.COM int afd = 0; 6217917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */ 6227917SReza.Sabdar@Sun.COM /* for Multi Volume record */ 6237917SReza.Sabdar@Sun.COM u_longlong_t pos; 6247917SReza.Sabdar@Sun.COM DIR *dp; 6257917SReza.Sabdar@Sun.COM struct dirent *dtp; 6267917SReza.Sabdar@Sun.COM char *attrname; 6277917SReza.Sabdar@Sun.COM char *fnamep; 6287917SReza.Sabdar@Sun.COM int rv = 0; 6297917SReza.Sabdar@Sun.COM 6307917SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode)) 6317917SReza.Sabdar@Sun.COM return (TLM_NO_SOURCE_FILE); 6327917SReza.Sabdar@Sun.COM 6337917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 6347917SReza.Sabdar@Sun.COM if (fullname == NULL) { 6357917SReza.Sabdar@Sun.COM free(fullname); 6367917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 6377917SReza.Sabdar@Sun.COM } 6387917SReza.Sabdar@Sun.COM 6397917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name)) { 6407917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 6417917SReza.Sabdar@Sun.COM free(fullname); 6427917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 6437917SReza.Sabdar@Sun.COM } 6447917SReza.Sabdar@Sun.COM 6458540SReza.Sabdar@Sun.COM if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 && 6468540SReza.Sabdar@Sun.COM sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) { 6477917SReza.Sabdar@Sun.COM free(fullname); 6487917SReza.Sabdar@Sun.COM return (0); 6497917SReza.Sabdar@Sun.COM } 6507917SReza.Sabdar@Sun.COM 6517917SReza.Sabdar@Sun.COM attrname = ndmp_malloc(TLM_MAX_PATH_NAME); 6527917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 6537917SReza.Sabdar@Sun.COM if (attrname == NULL || snapname == NULL) { 6547917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE; 6557917SReza.Sabdar@Sun.COM goto err_out; 6567917SReza.Sabdar@Sun.COM } 6577917SReza.Sabdar@Sun.COM 6587917SReza.Sabdar@Sun.COM if (!tlm_cat_path(snapname, chkdir, name)) { 6597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 6607917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE; 6617917SReza.Sabdar@Sun.COM goto err_out; 6627917SReza.Sabdar@Sun.COM } 6637917SReza.Sabdar@Sun.COM 6647917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 6657917SReza.Sabdar@Sun.COM 6667917SReza.Sabdar@Sun.COM /* 6677917SReza.Sabdar@Sun.COM * Open the file for reading. 6687917SReza.Sabdar@Sun.COM */ 6698540SReza.Sabdar@Sun.COM fd = attropen(fnamep, ".", O_RDONLY); 6707917SReza.Sabdar@Sun.COM if (fd == -1) { 6718540SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s][%s]", 6728540SReza.Sabdar@Sun.COM fullname, fnamep); 6737917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE; 6747917SReza.Sabdar@Sun.COM goto err_out; 6757917SReza.Sabdar@Sun.COM } 6767917SReza.Sabdar@Sun.COM 6777917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 6787917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 6797917SReza.Sabdar@Sun.COM 6807917SReza.Sabdar@Sun.COM section = 0; 6817917SReza.Sabdar@Sun.COM 6827917SReza.Sabdar@Sun.COM dp = (DIR *)fdopendir(fd); 6837917SReza.Sabdar@Sun.COM if (dp == NULL) { 6847917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname); 6857917SReza.Sabdar@Sun.COM (void) close(fd); 6867917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE; 6877917SReza.Sabdar@Sun.COM goto err_out; 6887917SReza.Sabdar@Sun.COM } 6897917SReza.Sabdar@Sun.COM 6907917SReza.Sabdar@Sun.COM while ((dtp = readdir(dp)) != NULL) { 6917917SReza.Sabdar@Sun.COM int section_size; 6927917SReza.Sabdar@Sun.COM 6937917SReza.Sabdar@Sun.COM if (*dtp->d_name == '.') 6947917SReza.Sabdar@Sun.COM continue; 6957917SReza.Sabdar@Sun.COM 6968540SReza.Sabdar@Sun.COM if (sysattr_rdonly(dtp->d_name)) 6978540SReza.Sabdar@Sun.COM continue; 6988540SReza.Sabdar@Sun.COM 699*9323SReza.Sabdar@Sun.COM afd = attropen(fnamep, dtp->d_name, O_RDONLY); 700*9323SReza.Sabdar@Sun.COM if (afd == -1) { 7017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 7028540SReza.Sabdar@Sun.COM "problem(%d) opening xattr file [%s][%s]", errno, 7038540SReza.Sabdar@Sun.COM fullname, fnamep); 7047917SReza.Sabdar@Sun.COM goto tear_down; 7057917SReza.Sabdar@Sun.COM } 7067917SReza.Sabdar@Sun.COM 707*9323SReza.Sabdar@Sun.COM (void) output_xattr_header(fullname, dtp->d_name, afd, 7087917SReza.Sabdar@Sun.COM tlm_acls, section, local_commands); 7097917SReza.Sabdar@Sun.COM (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s", 7107917SReza.Sabdar@Sun.COM dtp->d_name); 7117917SReza.Sabdar@Sun.COM (void) output_file_header(attrname, "", tlm_acls, 0, 7127917SReza.Sabdar@Sun.COM local_commands); 7137917SReza.Sabdar@Sun.COM 7147917SReza.Sabdar@Sun.COM section_size = (long)llmin(tlm_acls->acl_attr.st_size, 7157917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE); 7167917SReza.Sabdar@Sun.COM 7177917SReza.Sabdar@Sun.COM /* We only can read upto one section extended attribute */ 7187917SReza.Sabdar@Sun.COM while (section_size > 0) { 7197917SReza.Sabdar@Sun.COM char *buf; 7207917SReza.Sabdar@Sun.COM long actual_size; 7217917SReza.Sabdar@Sun.COM int read_size; 7228540SReza.Sabdar@Sun.COM int sysattr_read = 0; 7238540SReza.Sabdar@Sun.COM char *rec; 7248540SReza.Sabdar@Sun.COM int size; 7257917SReza.Sabdar@Sun.COM 7267917SReza.Sabdar@Sun.COM /* 7277917SReza.Sabdar@Sun.COM * check for Abort commands 7287917SReza.Sabdar@Sun.COM */ 7297917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 7307917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 7317917SReza.Sabdar@Sun.COM goto tear_down; 7327917SReza.Sabdar@Sun.COM } 7337917SReza.Sabdar@Sun.COM 7347917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 7357917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 7367917SReza.Sabdar@Sun.COM tb_file_size = section_size; 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_seek_spot = seek_spot; 7407917SReza.Sabdar@Sun.COM 7417917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size, 7427917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands); 7437917SReza.Sabdar@Sun.COM if (!buf) 7447917SReza.Sabdar@Sun.COM goto tear_down; 7457917SReza.Sabdar@Sun.COM 7468540SReza.Sabdar@Sun.COM if ((actual_size < section_size) && 7478540SReza.Sabdar@Sun.COM sysattr_rw(dtp->d_name)) { 7488540SReza.Sabdar@Sun.COM rec = buf; 7498540SReza.Sabdar@Sun.COM buf = ndmp_malloc(section_size); 7508540SReza.Sabdar@Sun.COM if (!buf) 7518540SReza.Sabdar@Sun.COM goto tear_down; 7528540SReza.Sabdar@Sun.COM size = actual_size; 7538540SReza.Sabdar@Sun.COM actual_size = section_size; 7548540SReza.Sabdar@Sun.COM sysattr_read = 1; 7558540SReza.Sabdar@Sun.COM } 7568540SReza.Sabdar@Sun.COM 7577917SReza.Sabdar@Sun.COM /* 7587917SReza.Sabdar@Sun.COM * check for Abort commands 7597917SReza.Sabdar@Sun.COM */ 7607917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 7617917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 7627917SReza.Sabdar@Sun.COM goto tear_down; 7637917SReza.Sabdar@Sun.COM } 7647917SReza.Sabdar@Sun.COM 7657917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size); 766*9323SReza.Sabdar@Sun.COM if ((actual_size = read(afd, buf, read_size)) < 0) 7678540SReza.Sabdar@Sun.COM break; 7688540SReza.Sabdar@Sun.COM 7698540SReza.Sabdar@Sun.COM if (sysattr_read) { 7708540SReza.Sabdar@Sun.COM if (get_write_one_buf(buf, rec, read_size, 7718540SReza.Sabdar@Sun.COM size, local_commands) == 0) { 7728540SReza.Sabdar@Sun.COM free(buf); 7738540SReza.Sabdar@Sun.COM goto tear_down; 7748540SReza.Sabdar@Sun.COM } 7758540SReza.Sabdar@Sun.COM free(buf); 7768540SReza.Sabdar@Sun.COM } 7778540SReza.Sabdar@Sun.COM 7788540SReza.Sabdar@Sun.COM 7797917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size); 7807917SReza.Sabdar@Sun.COM NS_INC(rfile); 7817917SReza.Sabdar@Sun.COM 7827917SReza.Sabdar@Sun.COM if (actual_size == -1) { 7837917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 7847917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]", 7857917SReza.Sabdar@Sun.COM errno, fullname, snapname); 7867917SReza.Sabdar@Sun.COM goto tear_down; 7877917SReza.Sabdar@Sun.COM } 7887917SReza.Sabdar@Sun.COM seek_spot += actual_size; 7897917SReza.Sabdar@Sun.COM section_size -= actual_size; 7907917SReza.Sabdar@Sun.COM } 791*9323SReza.Sabdar@Sun.COM (void) close(afd); 792*9323SReza.Sabdar@Sun.COM afd = -1; 7937917SReza.Sabdar@Sun.COM } 7947917SReza.Sabdar@Sun.COM 7957917SReza.Sabdar@Sun.COM tear_down: 7967917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 7977917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 7987917SReza.Sabdar@Sun.COM 799*9323SReza.Sabdar@Sun.COM if (afd > 0) 800*9323SReza.Sabdar@Sun.COM (void) close(afd); 801*9323SReza.Sabdar@Sun.COM 802*9323SReza.Sabdar@Sun.COM /* closedir closes fd too */ 8037917SReza.Sabdar@Sun.COM (void) closedir(dp); 8047917SReza.Sabdar@Sun.COM 8057917SReza.Sabdar@Sun.COM err_out: 8067917SReza.Sabdar@Sun.COM free(fullname); 8077917SReza.Sabdar@Sun.COM free(attrname); 8087917SReza.Sabdar@Sun.COM free(snapname); 8097917SReza.Sabdar@Sun.COM return (rv); 8107917SReza.Sabdar@Sun.COM } 8117917SReza.Sabdar@Sun.COM 8127917SReza.Sabdar@Sun.COM 8137917SReza.Sabdar@Sun.COM /* 8147917SReza.Sabdar@Sun.COM * tlm_output_file 8157917SReza.Sabdar@Sun.COM * 8167917SReza.Sabdar@Sun.COM * Put this file into the output buffers. 8177917SReza.Sabdar@Sun.COM */ 8187917SReza.Sabdar@Sun.COM longlong_t 8197917SReza.Sabdar@Sun.COM tlm_output_file(char *dir, char *name, char *chkdir, 8207917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands, 8217917SReza.Sabdar@Sun.COM tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q) 8227917SReza.Sabdar@Sun.COM { 8237917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */ 8247917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */ 8257917SReza.Sabdar@Sun.COM char *linkname; /* where this file points */ 8267917SReza.Sabdar@Sun.COM int section = 0; /* section of a huge file */ 8277917SReza.Sabdar@Sun.COM int fd; 8287917SReza.Sabdar@Sun.COM longlong_t real_size; /* the origional file size */ 8297917SReza.Sabdar@Sun.COM longlong_t file_size; /* real size of this file */ 8307917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */ 8317917SReza.Sabdar@Sun.COM /* for Multi Volume record */ 8327917SReza.Sabdar@Sun.COM u_longlong_t pos; 8337917SReza.Sabdar@Sun.COM char *fnamep; 8347917SReza.Sabdar@Sun.COM 8357917SReza.Sabdar@Sun.COM /* Indicate whether a file with the same inode has been backed up. */ 8367917SReza.Sabdar@Sun.COM int hardlink_done = 0; 8377917SReza.Sabdar@Sun.COM 8387917SReza.Sabdar@Sun.COM /* 8397917SReza.Sabdar@Sun.COM * If a file with the same inode has been backed up, hardlink_pos holds 8407917SReza.Sabdar@Sun.COM * the tape offset of the data record. 8417917SReza.Sabdar@Sun.COM */ 8427917SReza.Sabdar@Sun.COM u_longlong_t hardlink_pos = 0; 8437917SReza.Sabdar@Sun.COM 8447917SReza.Sabdar@Sun.COM if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) { 8457917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name); 8467917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 8477917SReza.Sabdar@Sun.COM } 8487917SReza.Sabdar@Sun.COM 8497917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 8507917SReza.Sabdar@Sun.COM linkname = ndmp_malloc(TLM_MAX_PATH_NAME); 8517917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 8527917SReza.Sabdar@Sun.COM if (fullname == NULL || linkname == NULL || snapname == NULL) { 8537917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 8547917SReza.Sabdar@Sun.COM goto err_out; 8557917SReza.Sabdar@Sun.COM } 8567917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name) || 8577917SReza.Sabdar@Sun.COM !tlm_cat_path(snapname, chkdir, name)) { 8587917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 8597917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 8607917SReza.Sabdar@Sun.COM goto err_out; 8617917SReza.Sabdar@Sun.COM } 8627917SReza.Sabdar@Sun.COM 8637917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 8647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 8657917SReza.Sabdar@Sun.COM 8667917SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode)) { 8677917SReza.Sabdar@Sun.COM file_size = tlm_readlink(fullname, snapname, linkname, 8687917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME-1); 8697917SReza.Sabdar@Sun.COM if (file_size < 0) { 8707917SReza.Sabdar@Sun.COM real_size = -ENOENT; 8717917SReza.Sabdar@Sun.COM goto err_out; 8727917SReza.Sabdar@Sun.COM } 8737917SReza.Sabdar@Sun.COM 8747917SReza.Sabdar@Sun.COM /* 8757917SReza.Sabdar@Sun.COM * Since soft links can not be read(2), we should only 8767917SReza.Sabdar@Sun.COM * backup the file header. 8777917SReza.Sabdar@Sun.COM */ 8787917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 8797917SReza.Sabdar@Sun.COM linkname, 8807917SReza.Sabdar@Sun.COM tlm_acls, 8817917SReza.Sabdar@Sun.COM section, 8827917SReza.Sabdar@Sun.COM local_commands); 8837917SReza.Sabdar@Sun.COM 8847917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name, 8857917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 8867917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname, 8877917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 8887917SReza.Sabdar@Sun.COM 8897917SReza.Sabdar@Sun.COM free(fullname); 8907917SReza.Sabdar@Sun.COM free(linkname); 8917917SReza.Sabdar@Sun.COM free(snapname); 8927917SReza.Sabdar@Sun.COM return (0); 8937917SReza.Sabdar@Sun.COM } 8947917SReza.Sabdar@Sun.COM 8957917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 8967917SReza.Sabdar@Sun.COM 8977917SReza.Sabdar@Sun.COM /* 8987917SReza.Sabdar@Sun.COM * For hardlink, only read the data if no other link 8997917SReza.Sabdar@Sun.COM * belonging to the same inode has been backed up. 9007917SReza.Sabdar@Sun.COM */ 9017917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1) { 9027917SReza.Sabdar@Sun.COM hardlink_done = !hardlink_q_get(hardlink_q, 9037917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL); 9047917SReza.Sabdar@Sun.COM } 9057917SReza.Sabdar@Sun.COM 9067917SReza.Sabdar@Sun.COM if (!hardlink_done) { 9077917SReza.Sabdar@Sun.COM /* 9087917SReza.Sabdar@Sun.COM * Open the file for reading. 9097917SReza.Sabdar@Sun.COM */ 9107917SReza.Sabdar@Sun.COM fd = open(fnamep, O_RDONLY); 9117917SReza.Sabdar@Sun.COM if (fd == -1) { 9127917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 9138540SReza.Sabdar@Sun.COM "BACKUP> Can't open file [%s][%s] err(%d)", 9148540SReza.Sabdar@Sun.COM fullname, fnamep, errno); 9157917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SOURCE_FILE; 9167917SReza.Sabdar@Sun.COM goto err_out; 9177917SReza.Sabdar@Sun.COM } 9187917SReza.Sabdar@Sun.COM } else { 9198193SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ", 9207917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, hardlink_pos); 9217917SReza.Sabdar@Sun.COM 9227917SReza.Sabdar@Sun.COM fd = -1; 9237917SReza.Sabdar@Sun.COM } 9247917SReza.Sabdar@Sun.COM 9257917SReza.Sabdar@Sun.COM linkname[0] = 0; 9267917SReza.Sabdar@Sun.COM 9277917SReza.Sabdar@Sun.COM real_size = tlm_acls->acl_attr.st_size; 9287917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info, 9297917SReza.Sabdar@Sun.COM local_commands); 9307917SReza.Sabdar@Sun.COM 9317917SReza.Sabdar@Sun.COM /* 9327917SReza.Sabdar@Sun.COM * section = 0: file is small enough for TAR 9337917SReza.Sabdar@Sun.COM * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks 9347917SReza.Sabdar@Sun.COM * and the file name gets munged 9357917SReza.Sabdar@Sun.COM */ 9367917SReza.Sabdar@Sun.COM file_size = real_size; 9377917SReza.Sabdar@Sun.COM if (file_size > TLM_MAX_TAR_IMAGE) { 9387917SReza.Sabdar@Sun.COM if (output_humongus_header(fullname, file_size, 9397917SReza.Sabdar@Sun.COM local_commands) < 0) { 9407917SReza.Sabdar@Sun.COM (void) close(fd); 9417917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 9427917SReza.Sabdar@Sun.COM goto err_out; 9437917SReza.Sabdar@Sun.COM } 9447917SReza.Sabdar@Sun.COM section = 1; 9457917SReza.Sabdar@Sun.COM } else { 9467917SReza.Sabdar@Sun.COM section = 0; 9477917SReza.Sabdar@Sun.COM } 9487917SReza.Sabdar@Sun.COM 9497917SReza.Sabdar@Sun.COM /* 9507917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode 9517917SReza.Sabdar@Sun.COM * has been backed up, only backup an empty record. 9527917SReza.Sabdar@Sun.COM */ 9537917SReza.Sabdar@Sun.COM if (hardlink_done) 9547917SReza.Sabdar@Sun.COM file_size = 0; 9557917SReza.Sabdar@Sun.COM 9567917SReza.Sabdar@Sun.COM /* 9577917SReza.Sabdar@Sun.COM * work 9587917SReza.Sabdar@Sun.COM */ 9597917SReza.Sabdar@Sun.COM if (file_size == 0) { 9607917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 9617917SReza.Sabdar@Sun.COM linkname, 9627917SReza.Sabdar@Sun.COM tlm_acls, 9637917SReza.Sabdar@Sun.COM section, 9647917SReza.Sabdar@Sun.COM local_commands); 9657917SReza.Sabdar@Sun.COM /* 9667917SReza.Sabdar@Sun.COM * this can fall right through since zero size files 9677917SReza.Sabdar@Sun.COM * will be skipped by the WHILE loop anyway 9687917SReza.Sabdar@Sun.COM */ 9697917SReza.Sabdar@Sun.COM } 9707917SReza.Sabdar@Sun.COM 9717917SReza.Sabdar@Sun.COM while (file_size > 0) { 9727917SReza.Sabdar@Sun.COM int section_size = llmin(file_size, 9737917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE); 9747917SReza.Sabdar@Sun.COM 9757917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_size = (longlong_t)section_size; 9767917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 9777917SReza.Sabdar@Sun.COM linkname, 9787917SReza.Sabdar@Sun.COM tlm_acls, 9797917SReza.Sabdar@Sun.COM section, 9807917SReza.Sabdar@Sun.COM local_commands); 9817917SReza.Sabdar@Sun.COM while (section_size > 0) { 9827917SReza.Sabdar@Sun.COM char *buf; 9837917SReza.Sabdar@Sun.COM long actual_size; 9847917SReza.Sabdar@Sun.COM int read_size; 9857917SReza.Sabdar@Sun.COM 9867917SReza.Sabdar@Sun.COM /* 9877917SReza.Sabdar@Sun.COM * check for Abort commands 9887917SReza.Sabdar@Sun.COM */ 9897917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 9907917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 9917917SReza.Sabdar@Sun.COM goto tear_down; 9927917SReza.Sabdar@Sun.COM } 9937917SReza.Sabdar@Sun.COM 9947917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 9957917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 9967917SReza.Sabdar@Sun.COM tb_file_size = section_size; 9977917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 9987917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 9997917SReza.Sabdar@Sun.COM tb_seek_spot = seek_spot; 10007917SReza.Sabdar@Sun.COM 10017917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size, 10027917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands); 10037917SReza.Sabdar@Sun.COM if (!buf) 10047917SReza.Sabdar@Sun.COM goto tear_down; 10057917SReza.Sabdar@Sun.COM 10067917SReza.Sabdar@Sun.COM /* 10077917SReza.Sabdar@Sun.COM * check for Abort commands 10087917SReza.Sabdar@Sun.COM */ 10097917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 10107917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 10117917SReza.Sabdar@Sun.COM goto tear_down; 10127917SReza.Sabdar@Sun.COM } 10137917SReza.Sabdar@Sun.COM 10147917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size); 10157917SReza.Sabdar@Sun.COM actual_size = read(fd, buf, read_size); 10167917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size); 10177917SReza.Sabdar@Sun.COM NS_INC(rfile); 10187917SReza.Sabdar@Sun.COM 10197917SReza.Sabdar@Sun.COM if (actual_size == 0) 10207917SReza.Sabdar@Sun.COM break; 10217917SReza.Sabdar@Sun.COM 10227917SReza.Sabdar@Sun.COM if (actual_size == -1) { 10237917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10247917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]", 10257917SReza.Sabdar@Sun.COM errno, fullname, snapname); 10267917SReza.Sabdar@Sun.COM goto tear_down; 10277917SReza.Sabdar@Sun.COM } 10287917SReza.Sabdar@Sun.COM seek_spot += actual_size; 10297917SReza.Sabdar@Sun.COM file_size -= actual_size; 10307917SReza.Sabdar@Sun.COM section_size -= actual_size; 10317917SReza.Sabdar@Sun.COM } 10327917SReza.Sabdar@Sun.COM section++; 10337917SReza.Sabdar@Sun.COM } 10347917SReza.Sabdar@Sun.COM 10357917SReza.Sabdar@Sun.COM /* 10367917SReza.Sabdar@Sun.COM * If data belonging to this hardlink has been backed up, add the link 10377917SReza.Sabdar@Sun.COM * to hardlink queue. 10387917SReza.Sabdar@Sun.COM */ 10397917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) { 10407917SReza.Sabdar@Sun.COM (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino, 10417917SReza.Sabdar@Sun.COM pos, NULL, 0); 10427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10438193SReza.Sabdar@Sun.COM "backed up hardlink file %s, inode = %llu, pos = %llu ", 10447917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, pos); 10457917SReza.Sabdar@Sun.COM } 10467917SReza.Sabdar@Sun.COM 10477917SReza.Sabdar@Sun.COM /* 10487917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode has been 10498193SReza.Sabdar@Sun.COM * backed up, no add_node entry should be sent for this link. 10507917SReza.Sabdar@Sun.COM */ 10517917SReza.Sabdar@Sun.COM if (hardlink_done) { 10527917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10538193SReza.Sabdar@Sun.COM "backed up hardlink link %s, inode = %llu, pos = %llu ", 10547917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, hardlink_pos); 10557917SReza.Sabdar@Sun.COM } else { 10567917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name, 10577917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 10587917SReza.Sabdar@Sun.COM } 10597917SReza.Sabdar@Sun.COM 10607917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr, 10617917SReza.Sabdar@Sun.COM pos); 10627917SReza.Sabdar@Sun.COM 10637917SReza.Sabdar@Sun.COM tear_down: 10647917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 10657917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 10667917SReza.Sabdar@Sun.COM 10677917SReza.Sabdar@Sun.COM (void) close(fd); 10687917SReza.Sabdar@Sun.COM 10697917SReza.Sabdar@Sun.COM err_out: 10707917SReza.Sabdar@Sun.COM free(fullname); 10717917SReza.Sabdar@Sun.COM free(linkname); 10727917SReza.Sabdar@Sun.COM free(snapname); 10737917SReza.Sabdar@Sun.COM return (real_size); 10747917SReza.Sabdar@Sun.COM } 10757917SReza.Sabdar@Sun.COM 10767917SReza.Sabdar@Sun.COM /* 10777917SReza.Sabdar@Sun.COM * tar_putfile 10787917SReza.Sabdar@Sun.COM * 10797917SReza.Sabdar@Sun.COM * Main file backup function for tar 10807917SReza.Sabdar@Sun.COM */ 10817917SReza.Sabdar@Sun.COM int 10827917SReza.Sabdar@Sun.COM tar_putfile(char *dir, char *name, char *chkdir, 10837917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, 10847917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats, 10857917SReza.Sabdar@Sun.COM struct hardlink_q *hardlink_q) 10867917SReza.Sabdar@Sun.COM { 10877917SReza.Sabdar@Sun.COM int rv; 10887917SReza.Sabdar@Sun.COM 10897917SReza.Sabdar@Sun.COM rv = tlm_output_file(dir, name, chkdir, tlm_acls, commands, 10907917SReza.Sabdar@Sun.COM local_commands, job_stats, hardlink_q); 10917917SReza.Sabdar@Sun.COM if (rv < 0) 10927917SReza.Sabdar@Sun.COM return (rv); 10937917SReza.Sabdar@Sun.COM 10947917SReza.Sabdar@Sun.COM rv = tlm_output_xattr(dir, name, chkdir, tlm_acls, commands, 10957917SReza.Sabdar@Sun.COM local_commands, job_stats); 10967917SReza.Sabdar@Sun.COM 10977917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0); 10987917SReza.Sabdar@Sun.COM } 10997917SReza.Sabdar@Sun.COM 11007917SReza.Sabdar@Sun.COM /* 11017917SReza.Sabdar@Sun.COM * get_write_buffer 11027917SReza.Sabdar@Sun.COM * 11037917SReza.Sabdar@Sun.COM * a wrapper to tlm_get_write_buffer so that 11047917SReza.Sabdar@Sun.COM * we can cleanly detect ABORT commands 11057917SReza.Sabdar@Sun.COM * without involving the TLM library with 11067917SReza.Sabdar@Sun.COM * our problems. 11077917SReza.Sabdar@Sun.COM */ 11087917SReza.Sabdar@Sun.COM static char * 11097917SReza.Sabdar@Sun.COM get_write_buffer(long size, long *actual_size, 11107917SReza.Sabdar@Sun.COM boolean_t zero, tlm_cmd_t *local_commands) 11117917SReza.Sabdar@Sun.COM { 11127917SReza.Sabdar@Sun.COM while (local_commands->tc_reader == TLM_BACKUP_RUN) { 11137917SReza.Sabdar@Sun.COM char *rec = tlm_get_write_buffer(size, actual_size, 11147917SReza.Sabdar@Sun.COM local_commands->tc_buffers, zero); 11157917SReza.Sabdar@Sun.COM if (rec != 0) { 11167917SReza.Sabdar@Sun.COM return (rec); 11177917SReza.Sabdar@Sun.COM } 11187917SReza.Sabdar@Sun.COM } 11197917SReza.Sabdar@Sun.COM return (NULL); 11207917SReza.Sabdar@Sun.COM } 11217917SReza.Sabdar@Sun.COM 11227917SReza.Sabdar@Sun.COM #define NDMP_MORE_RECORDS 2 11237917SReza.Sabdar@Sun.COM 11247917SReza.Sabdar@Sun.COM /* 11257917SReza.Sabdar@Sun.COM * write_tar_eof 11267917SReza.Sabdar@Sun.COM * 11277917SReza.Sabdar@Sun.COM * This function is initially written for NDMP support. It appends 11287917SReza.Sabdar@Sun.COM * two tar headers to the tar file, and also N more empty buffers 11297917SReza.Sabdar@Sun.COM * to make sure that the two tar headers will be read as a part of 11307917SReza.Sabdar@Sun.COM * a mover record and don't get locked because of EOM on the mover 11317917SReza.Sabdar@Sun.COM * side. 11327917SReza.Sabdar@Sun.COM */ 11337917SReza.Sabdar@Sun.COM void 11347917SReza.Sabdar@Sun.COM write_tar_eof(tlm_cmd_t *local_commands) 11357917SReza.Sabdar@Sun.COM { 11367917SReza.Sabdar@Sun.COM int i; 11377917SReza.Sabdar@Sun.COM long actual_size; 11387917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs; 11397917SReza.Sabdar@Sun.COM 11407917SReza.Sabdar@Sun.COM /* 11417917SReza.Sabdar@Sun.COM * output 2 zero filled records, 11427917SReza.Sabdar@Sun.COM * TAR wants this. 11437917SReza.Sabdar@Sun.COM */ 11447917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 11457917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11467917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 11477917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11487917SReza.Sabdar@Sun.COM 11497917SReza.Sabdar@Sun.COM /* 11507917SReza.Sabdar@Sun.COM * NDMP: Clear the rest of the buffer and write two more buffers 11517917SReza.Sabdar@Sun.COM * to the tape. 11527917SReza.Sabdar@Sun.COM */ 11537917SReza.Sabdar@Sun.COM bufs = local_commands->tc_buffers; 11547917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size, 11557917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11567917SReza.Sabdar@Sun.COM 11577917SReza.Sabdar@Sun.COM for (i = 0; i < NDMP_MORE_RECORDS && 11587917SReza.Sabdar@Sun.COM local_commands->tc_reader == TLM_BACKUP_RUN; i++) { 11597917SReza.Sabdar@Sun.COM /* 11607917SReza.Sabdar@Sun.COM * We don't need the return value of get_write_buffer(), 11617917SReza.Sabdar@Sun.COM * since it's already zeroed out if the buffer is returned. 11627917SReza.Sabdar@Sun.COM */ 11637917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size, 11647917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 11657917SReza.Sabdar@Sun.COM } 11667917SReza.Sabdar@Sun.COM 11677917SReza.Sabdar@Sun.COM bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE; 11687917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs); 11697917SReza.Sabdar@Sun.COM } 11707917SReza.Sabdar@Sun.COM 11717917SReza.Sabdar@Sun.COM /* 11727917SReza.Sabdar@Sun.COM * Callback to backup each ZFS property 11737917SReza.Sabdar@Sun.COM */ 11747917SReza.Sabdar@Sun.COM static int 11757917SReza.Sabdar@Sun.COM zfs_put_prop_cb(int prop, void *pp) 11767917SReza.Sabdar@Sun.COM { 11777917SReza.Sabdar@Sun.COM ndmp_metadata_header_t *mhp; 11787917SReza.Sabdar@Sun.COM ndmp_metadata_property_t *mpp; 11797917SReza.Sabdar@Sun.COM char buf[ZFS_MAXNAMELEN]; 11807917SReza.Sabdar@Sun.COM char sbuf[ZFS_MAXNAMELEN]; 11817917SReza.Sabdar@Sun.COM zprop_source_t stype; 11828800SReza.Sabdar@Sun.COM char *sourcestr; 11837917SReza.Sabdar@Sun.COM 11847917SReza.Sabdar@Sun.COM if (pp == NULL) 11857917SReza.Sabdar@Sun.COM return (ZPROP_INVAL); 11867917SReza.Sabdar@Sun.COM 11877917SReza.Sabdar@Sun.COM mhp = (ndmp_metadata_header_t *)pp; 11887917SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count++]; 11897917SReza.Sabdar@Sun.COM 11907917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, zfs_prop_to_name(prop), NAME_MAX); 11917917SReza.Sabdar@Sun.COM (void) zfs_prop_get(mhp->nh_handle, 11929169SReza.Sabdar@Sun.COM prop, buf, sizeof (buf), &stype, sbuf, sizeof (sbuf), B_TRUE); 11937917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, buf, NAME_MAX); 11948800SReza.Sabdar@Sun.COM 11958800SReza.Sabdar@Sun.COM switch (stype) { 11968800SReza.Sabdar@Sun.COM case ZPROP_SRC_NONE: 11978800SReza.Sabdar@Sun.COM sourcestr = "none"; 11988800SReza.Sabdar@Sun.COM break; 11998800SReza.Sabdar@Sun.COM case ZPROP_SRC_LOCAL: 12008800SReza.Sabdar@Sun.COM sourcestr = mhp->nh_dataset; 12018800SReza.Sabdar@Sun.COM break; 12028800SReza.Sabdar@Sun.COM case ZPROP_SRC_TEMPORARY: 12038800SReza.Sabdar@Sun.COM sourcestr = "temporary"; 12048800SReza.Sabdar@Sun.COM break; 12058800SReza.Sabdar@Sun.COM case ZPROP_SRC_DEFAULT: 12068800SReza.Sabdar@Sun.COM sourcestr = "default"; 12078800SReza.Sabdar@Sun.COM break; 12088800SReza.Sabdar@Sun.COM default: 12098800SReza.Sabdar@Sun.COM sourcestr = sbuf; 12108800SReza.Sabdar@Sun.COM break; 12118800SReza.Sabdar@Sun.COM } 12128800SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, sourcestr, NAME_MAX); 12137917SReza.Sabdar@Sun.COM 12147917SReza.Sabdar@Sun.COM return (ZPROP_CONT); 12157917SReza.Sabdar@Sun.COM } 12167917SReza.Sabdar@Sun.COM 12177917SReza.Sabdar@Sun.COM 12187917SReza.Sabdar@Sun.COM /* 12197917SReza.Sabdar@Sun.COM * Notifies ndmpd that the metadata associated with the given ZFS dataset 12207917SReza.Sabdar@Sun.COM * should be backed up. 12217917SReza.Sabdar@Sun.COM */ 12227917SReza.Sabdar@Sun.COM int 12237917SReza.Sabdar@Sun.COM ndmp_include_zfs(ndmp_context_t *nctx, const char *dataset) 12247917SReza.Sabdar@Sun.COM { 12257917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; 12267917SReza.Sabdar@Sun.COM ndmp_metadata_header_t *mhp; 12277917SReza.Sabdar@Sun.COM ndmp_metadata_property_t *mpp; 12287917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd; 12297917SReza.Sabdar@Sun.COM long actual_size; 12307917SReza.Sabdar@Sun.COM nvlist_t *uprops, *ulist; 12317917SReza.Sabdar@Sun.COM const char *pname; 12327917SReza.Sabdar@Sun.COM nvpair_t *elp; 12337917SReza.Sabdar@Sun.COM char *sval, *ssrc; 12347917SReza.Sabdar@Sun.COM char *wbuf, *pp, *tp; 12357917SReza.Sabdar@Sun.COM long size, lsize, sz; 12367917SReza.Sabdar@Sun.COM int align = RECORDSIZE - 1; 12377917SReza.Sabdar@Sun.COM 12387917SReza.Sabdar@Sun.COM if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 12397917SReza.Sabdar@Sun.COM return (-1); 12407917SReza.Sabdar@Sun.COM 12417917SReza.Sabdar@Sun.COM if ((lcmd = cmds->tcs_command) == NULL || 12427917SReza.Sabdar@Sun.COM lcmd->tc_buffers == NULL) 12437917SReza.Sabdar@Sun.COM return (-1); 12447917SReza.Sabdar@Sun.COM 12457917SReza.Sabdar@Sun.COM size = sizeof (ndmp_metadata_header_t) + 12467917SReza.Sabdar@Sun.COM ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 12477917SReza.Sabdar@Sun.COM size += align; 12487917SReza.Sabdar@Sun.COM size &= ~align; 12497917SReza.Sabdar@Sun.COM 12507917SReza.Sabdar@Sun.COM if ((mhp = malloc(size)) == NULL) 12517917SReza.Sabdar@Sun.COM return (-1); 12527917SReza.Sabdar@Sun.COM (void) memset(mhp, 0, size); 12537917SReza.Sabdar@Sun.COM 12547917SReza.Sabdar@Sun.COM mhp->nh_plversion = nctx->nc_plversion; 12557917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_plname, nctx->nc_plname, 12567917SReza.Sabdar@Sun.COM sizeof (mhp->nh_plname)); 12577917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_magic, ZFS_META_MAGIC, sizeof (mhp->nh_magic)); 12587917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_dataset, dataset, sizeof (mhp->nh_dataset)); 12597917SReza.Sabdar@Sun.COM 12607917SReza.Sabdar@Sun.COM if ((mhp->nh_handle = zfs_open(zlibh, dataset, 12617917SReza.Sabdar@Sun.COM ZFS_TYPE_DATASET)) == NULL) { 12627917SReza.Sabdar@Sun.COM free(mhp); 12637917SReza.Sabdar@Sun.COM return (ZPROP_INVAL); 12647917SReza.Sabdar@Sun.COM } 12657917SReza.Sabdar@Sun.COM 12667917SReza.Sabdar@Sun.COM /* Get all the ZFS properties */ 12677917SReza.Sabdar@Sun.COM (void) zprop_iter(zfs_put_prop_cb, mhp, TRUE, TRUE, 12687917SReza.Sabdar@Sun.COM ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET); 12697917SReza.Sabdar@Sun.COM 12707917SReza.Sabdar@Sun.COM /* Get user properties */ 12717917SReza.Sabdar@Sun.COM uprops = zfs_get_user_props(mhp->nh_handle); 12727917SReza.Sabdar@Sun.COM 12737917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, NULL); 12747917SReza.Sabdar@Sun.COM 12757917SReza.Sabdar@Sun.COM while (elp != NULL) { 12767917SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count]; 12777917SReza.Sabdar@Sun.COM if (nvpair_value_nvlist(elp, &ulist) != 0 || 12787917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_VALUE, &sval) != 0 || 12797917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_SOURCE, &ssrc) != 0) { 12807917SReza.Sabdar@Sun.COM zfs_close(mhp->nh_handle); 12817917SReza.Sabdar@Sun.COM free(mhp); 12827917SReza.Sabdar@Sun.COM return (-1); 12837917SReza.Sabdar@Sun.COM } 12847917SReza.Sabdar@Sun.COM if ((pname = nvpair_name(elp)) != NULL) 12857917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, pname, NAME_MAX); 12867917SReza.Sabdar@Sun.COM 12877917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, sval, NAME_MAX); 12887917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, ssrc, NAME_MAX); 12897917SReza.Sabdar@Sun.COM mhp->nh_count++; 12907917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, elp); 12917917SReza.Sabdar@Sun.COM } 12927917SReza.Sabdar@Sun.COM 12937917SReza.Sabdar@Sun.COM zfs_close(mhp->nh_handle); 12947917SReza.Sabdar@Sun.COM 12957917SReza.Sabdar@Sun.COM if ((wbuf = get_write_buffer(size, &actual_size, TRUE, 12967917SReza.Sabdar@Sun.COM lcmd)) != NULL) { 12977917SReza.Sabdar@Sun.COM pp = (char *)mhp; 12987917SReza.Sabdar@Sun.COM 12997917SReza.Sabdar@Sun.COM (void) memcpy(wbuf, pp, (actual_size < size) ? 13007917SReza.Sabdar@Sun.COM actual_size : size); 13017917SReza.Sabdar@Sun.COM pp += (actual_size < size) ? actual_size : size; 13027917SReza.Sabdar@Sun.COM 13037917SReza.Sabdar@Sun.COM sz = actual_size; 13047917SReza.Sabdar@Sun.COM while (sz < size && 13057917SReza.Sabdar@Sun.COM ((tp = get_write_buffer(size - sz, &lsize, 13067917SReza.Sabdar@Sun.COM TRUE, lcmd))) != NULL) { 13077917SReza.Sabdar@Sun.COM (void) memcpy(tp, pp, size - sz); 13087917SReza.Sabdar@Sun.COM sz += lsize; 13097917SReza.Sabdar@Sun.COM pp += lsize; 13107917SReza.Sabdar@Sun.COM } 13117917SReza.Sabdar@Sun.COM if (sz > size) { 13127917SReza.Sabdar@Sun.COM tlm_unget_write_buffer(lcmd->tc_buffers, sz - size); 13137917SReza.Sabdar@Sun.COM } 13147917SReza.Sabdar@Sun.COM } 13157917SReza.Sabdar@Sun.COM 13167917SReza.Sabdar@Sun.COM free(mhp); 13177917SReza.Sabdar@Sun.COM return (0); 13187917SReza.Sabdar@Sun.COM } 1319