17917SReza.Sabdar@Sun.COM /* 27917SReza.Sabdar@Sun.COM * Copyright 2008 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> 507917SReza.Sabdar@Sun.COM #include "tlm_proto.h" 517917SReza.Sabdar@Sun.COM 527917SReza.Sabdar@Sun.COM 537917SReza.Sabdar@Sun.COM static char *get_write_buffer(long size, 547917SReza.Sabdar@Sun.COM long *actual_size, 557917SReza.Sabdar@Sun.COM boolean_t zero, 567917SReza.Sabdar@Sun.COM tlm_cmd_t *); 577917SReza.Sabdar@Sun.COM static int output_acl_header(sec_attr_t *, 587917SReza.Sabdar@Sun.COM tlm_cmd_t *); 597917SReza.Sabdar@Sun.COM static int output_file_header(char *name, 607917SReza.Sabdar@Sun.COM char *link, 617917SReza.Sabdar@Sun.COM tlm_acls_t *, 627917SReza.Sabdar@Sun.COM int section, 637917SReza.Sabdar@Sun.COM tlm_cmd_t *); 647917SReza.Sabdar@Sun.COM static int output_xattr_header(char *fname, 657917SReza.Sabdar@Sun.COM char *aname, 667917SReza.Sabdar@Sun.COM int fd, 677917SReza.Sabdar@Sun.COM tlm_acls_t *, 687917SReza.Sabdar@Sun.COM int section, 697917SReza.Sabdar@Sun.COM tlm_cmd_t *); 707917SReza.Sabdar@Sun.COM 717917SReza.Sabdar@Sun.COM extern libzfs_handle_t *zlibh; 727917SReza.Sabdar@Sun.COM 737917SReza.Sabdar@Sun.COM 747917SReza.Sabdar@Sun.COM /* 757917SReza.Sabdar@Sun.COM * output_mem 767917SReza.Sabdar@Sun.COM * 777917SReza.Sabdar@Sun.COM * Gets a IO write buffer and copies memory to the that. 787917SReza.Sabdar@Sun.COM */ 797917SReza.Sabdar@Sun.COM static void 807917SReza.Sabdar@Sun.COM output_mem(tlm_cmd_t *local_commands, char *mem, 817917SReza.Sabdar@Sun.COM int len) 827917SReza.Sabdar@Sun.COM { 837917SReza.Sabdar@Sun.COM long actual_size, rec_size; 847917SReza.Sabdar@Sun.COM char *rec; 857917SReza.Sabdar@Sun.COM 867917SReza.Sabdar@Sun.COM while (len > 0) { 877917SReza.Sabdar@Sun.COM rec = get_write_buffer(len, &actual_size, 887917SReza.Sabdar@Sun.COM FALSE, local_commands); 897917SReza.Sabdar@Sun.COM rec_size = min(actual_size, len); 907917SReza.Sabdar@Sun.COM (void) memcpy(rec, mem, rec_size); 917917SReza.Sabdar@Sun.COM mem += rec_size; 927917SReza.Sabdar@Sun.COM len -= rec_size; 937917SReza.Sabdar@Sun.COM } 947917SReza.Sabdar@Sun.COM } 957917SReza.Sabdar@Sun.COM 967917SReza.Sabdar@Sun.COM /* 977917SReza.Sabdar@Sun.COM * tlm_output_dir 987917SReza.Sabdar@Sun.COM * 997917SReza.Sabdar@Sun.COM * Put the directory information into the output buffers. 1007917SReza.Sabdar@Sun.COM */ 1017917SReza.Sabdar@Sun.COM int 1027917SReza.Sabdar@Sun.COM tlm_output_dir(char *name, tlm_acls_t *tlm_acls, 1037917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 1047917SReza.Sabdar@Sun.COM { 1057917SReza.Sabdar@Sun.COM u_longlong_t pos; 1067917SReza.Sabdar@Sun.COM 1077917SReza.Sabdar@Sun.COM /* 1087917SReza.Sabdar@Sun.COM * Send the node or path history of the directory itself. 1097917SReza.Sabdar@Sun.COM */ 1107917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 1117917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 1127917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos); 1137917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos); 1147917SReza.Sabdar@Sun.COM /* fhdir_cb is handled in ndmpd_tar3.c */ 1157917SReza.Sabdar@Sun.COM 1167917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info, 1177917SReza.Sabdar@Sun.COM local_commands); 1187917SReza.Sabdar@Sun.COM (void) output_file_header(name, "", tlm_acls, 0, 1197917SReza.Sabdar@Sun.COM local_commands); 1207917SReza.Sabdar@Sun.COM 1217917SReza.Sabdar@Sun.COM return (0); 1227917SReza.Sabdar@Sun.COM } 1237917SReza.Sabdar@Sun.COM 1247917SReza.Sabdar@Sun.COM /* 1257917SReza.Sabdar@Sun.COM * tar_putdir 1267917SReza.Sabdar@Sun.COM * 1277917SReza.Sabdar@Sun.COM * Main dir backup function for tar 1287917SReza.Sabdar@Sun.COM */ 1297917SReza.Sabdar@Sun.COM int 1307917SReza.Sabdar@Sun.COM tar_putdir(char *name, tlm_acls_t *tlm_acls, 1317917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 1327917SReza.Sabdar@Sun.COM { 1337917SReza.Sabdar@Sun.COM int rv; 1347917SReza.Sabdar@Sun.COM 1357917SReza.Sabdar@Sun.COM rv = tlm_output_dir(name, tlm_acls, local_commands, job_stats); 1367917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0); 1377917SReza.Sabdar@Sun.COM } 1387917SReza.Sabdar@Sun.COM 1397917SReza.Sabdar@Sun.COM /* 1407917SReza.Sabdar@Sun.COM * output_acl_header 1417917SReza.Sabdar@Sun.COM * 1427917SReza.Sabdar@Sun.COM * output the ACL header record and data 1437917SReza.Sabdar@Sun.COM */ 1447917SReza.Sabdar@Sun.COM static int 1457917SReza.Sabdar@Sun.COM output_acl_header(sec_attr_t *acl_info, 1467917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands) 1477917SReza.Sabdar@Sun.COM { 1487917SReza.Sabdar@Sun.COM long actual_size; 1497917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 1507917SReza.Sabdar@Sun.COM long acl_size; 1517917SReza.Sabdar@Sun.COM 1527917SReza.Sabdar@Sun.COM if ((acl_info == NULL) || (*acl_info->attr_info == '\0')) 1537917SReza.Sabdar@Sun.COM return (0); 1547917SReza.Sabdar@Sun.COM 1557917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 1567917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 1577917SReza.Sabdar@Sun.COM if (!tar_hdr) 1587917SReza.Sabdar@Sun.COM return (0); 1597917SReza.Sabdar@Sun.COM 1607917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_ACL; 1617917SReza.Sabdar@Sun.COM acl_info->attr_type = UFSD_ACL; 1627917SReza.Sabdar@Sun.COM (void) snprintf(acl_info->attr_len, sizeof (acl_info->attr_len), 1637917SReza.Sabdar@Sun.COM "%06o", strlen(acl_info->attr_info)); 1647917SReza.Sabdar@Sun.COM 1657917SReza.Sabdar@Sun.COM acl_size = sizeof (*acl_info); 1667917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, "UFSACL", TLM_NAME_SIZE); 1677917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 1687917SReza.Sabdar@Sun.COM acl_size); 1697917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 1707917SReza.Sabdar@Sun.COM 0444); 1717917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 0); 1727917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 0); 1737917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 1747917SReza.Sabdar@Sun.COM "%011o ", 0); 1757917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 1767917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 1777917SReza.Sabdar@Sun.COM 1787917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 1797917SReza.Sabdar@Sun.COM 1807917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)acl_info, acl_size); 1817917SReza.Sabdar@Sun.COM return (0); 1827917SReza.Sabdar@Sun.COM } 1837917SReza.Sabdar@Sun.COM 1847917SReza.Sabdar@Sun.COM /* 1857917SReza.Sabdar@Sun.COM * output_humongus_header 1867917SReza.Sabdar@Sun.COM * 1877917SReza.Sabdar@Sun.COM * output a special header record for HUGE files 1887917SReza.Sabdar@Sun.COM * output is: 1) a TAR "HUGE" header redord 1897917SReza.Sabdar@Sun.COM * 2) a "file" of size, name 1907917SReza.Sabdar@Sun.COM */ 1917917SReza.Sabdar@Sun.COM static int 1927917SReza.Sabdar@Sun.COM output_humongus_header(char *fullname, longlong_t file_size, 1937917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands) 1947917SReza.Sabdar@Sun.COM { 1957917SReza.Sabdar@Sun.COM char *buf; 1967917SReza.Sabdar@Sun.COM int len; 1977917SReza.Sabdar@Sun.COM long actual_size; 1987917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 1997917SReza.Sabdar@Sun.COM 2007917SReza.Sabdar@Sun.COM /* 2017917SReza.Sabdar@Sun.COM * buf will contain: "%llu %s": 2027917SReza.Sabdar@Sun.COM * - 20 is the maximum length of 'ulong_tlong' decimal notation. 2037917SReza.Sabdar@Sun.COM * - The first '1' is for the ' ' between the "%llu" and the fullname. 2047917SReza.Sabdar@Sun.COM * - The last '1' is for the null-terminator of fullname. 2057917SReza.Sabdar@Sun.COM */ 2067917SReza.Sabdar@Sun.COM len = 20 + 1 + strlen(fullname) + 1; 2077917SReza.Sabdar@Sun.COM 2087917SReza.Sabdar@Sun.COM if ((buf = ndmp_malloc(sizeof (char) * len)) == NULL) 2097917SReza.Sabdar@Sun.COM return (-1); 2107917SReza.Sabdar@Sun.COM 2117917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 2127917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 2137917SReza.Sabdar@Sun.COM if (!tar_hdr) { 2147917SReza.Sabdar@Sun.COM free(buf); 2157917SReza.Sabdar@Sun.COM return (0); 2167917SReza.Sabdar@Sun.COM } 2177917SReza.Sabdar@Sun.COM 2187917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_HUMONGUS; 2197917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 2207917SReza.Sabdar@Sun.COM len); 2217917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 2227917SReza.Sabdar@Sun.COM (void) snprintf(buf, len, "%lld %s", file_size, fullname); 2237917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, buf, len); 2247917SReza.Sabdar@Sun.COM 2257917SReza.Sabdar@Sun.COM free(buf); 2267917SReza.Sabdar@Sun.COM return (0); 2277917SReza.Sabdar@Sun.COM } 2287917SReza.Sabdar@Sun.COM 2297917SReza.Sabdar@Sun.COM 2307917SReza.Sabdar@Sun.COM /* 2317917SReza.Sabdar@Sun.COM * output_xattr_header 2327917SReza.Sabdar@Sun.COM * 2337917SReza.Sabdar@Sun.COM * output the TAR header record for extended attributes 2347917SReza.Sabdar@Sun.COM */ 2357917SReza.Sabdar@Sun.COM static int 2367917SReza.Sabdar@Sun.COM output_xattr_header(char *fname, char *aname, int fd, 2377917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 2387917SReza.Sabdar@Sun.COM { 2397917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr; 2407917SReza.Sabdar@Sun.COM struct xattr_hdr *xhdr; 2417917SReza.Sabdar@Sun.COM struct xattr_buf *xbuf; 2427917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 2437917SReza.Sabdar@Sun.COM long actual_size; 2447917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 2457917SReza.Sabdar@Sun.COM int hsize; 2467917SReza.Sabdar@Sun.COM int comlen; 2477917SReza.Sabdar@Sun.COM int namesz; 2487917SReza.Sabdar@Sun.COM 2497917SReza.Sabdar@Sun.COM if (section_name == NULL) 2507917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 2517917SReza.Sabdar@Sun.COM 2527917SReza.Sabdar@Sun.COM if (fstat64(fd, attr) == -1) { 2537917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "output_file_header stat failed."); 2547917SReza.Sabdar@Sun.COM free(section_name); 2557917SReza.Sabdar@Sun.COM return (-TLM_OPEN_ERR); 2567917SReza.Sabdar@Sun.COM } 2577917SReza.Sabdar@Sun.COM 2587917SReza.Sabdar@Sun.COM /* 2597917SReza.Sabdar@Sun.COM * if the file has to go out in sections, 2607917SReza.Sabdar@Sun.COM * we must mung the name. 2617917SReza.Sabdar@Sun.COM */ 2627917SReza.Sabdar@Sun.COM if (section == 0) { 2637917SReza.Sabdar@Sun.COM (void) snprintf(section_name, TLM_MAX_PATH_NAME, 2647917SReza.Sabdar@Sun.COM "/dev/null/%s.hdr", aname); 2657917SReza.Sabdar@Sun.COM } else { 2667917SReza.Sabdar@Sun.COM (void) snprintf(section_name, 2677917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", aname, section); 2687917SReza.Sabdar@Sun.COM } 2697917SReza.Sabdar@Sun.COM namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */ 2707917SReza.Sabdar@Sun.COM hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 2717917SReza.Sabdar@Sun.COM comlen = namesz + sizeof (struct xattr_buf); 2727917SReza.Sabdar@Sun.COM 2737917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 2747917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 2757917SReza.Sabdar@Sun.COM if (!tar_hdr) { 2767917SReza.Sabdar@Sun.COM free(section_name); 2777917SReza.Sabdar@Sun.COM return (0); 2787917SReza.Sabdar@Sun.COM } 2797917SReza.Sabdar@Sun.COM 2807917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 2817917SReza.Sabdar@Sun.COM 2827917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_XATTR; 2837917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 2847917SReza.Sabdar@Sun.COM hsize); 2857917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 2867917SReza.Sabdar@Sun.COM attr->st_mode & 07777); 2877917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 2887917SReza.Sabdar@Sun.COM attr->st_uid); 2897917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 2907917SReza.Sabdar@Sun.COM attr->st_gid); 2917917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 2927917SReza.Sabdar@Sun.COM attr->st_mtime); 2937917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 2947917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 2957917SReza.Sabdar@Sun.COM 2967917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 2977917SReza.Sabdar@Sun.COM 2987917SReza.Sabdar@Sun.COM xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE, 2997917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 3007917SReza.Sabdar@Sun.COM if (!xhdr) { 3017917SReza.Sabdar@Sun.COM free(section_name); 3027917SReza.Sabdar@Sun.COM return (0); 3037917SReza.Sabdar@Sun.COM } 3047917SReza.Sabdar@Sun.COM 3057917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s", 3067917SReza.Sabdar@Sun.COM XATTR_ARCH_VERS); 3077917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d", 3087917SReza.Sabdar@Sun.COM sizeof (xhdr->h_size) - 1, hsize); 3097917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len), 3107917SReza.Sabdar@Sun.COM "%0*d", sizeof (xhdr->h_component_len) - 1, comlen); 3117917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_link_component_len, 3127917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len), "%0*d", 3137917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len) - 1, 0); 3147917SReza.Sabdar@Sun.COM 3157917SReza.Sabdar@Sun.COM xbuf = (struct xattr_buf *)(((caddr_t)xhdr) + 3167917SReza.Sabdar@Sun.COM sizeof (struct xattr_hdr)); 3177917SReza.Sabdar@Sun.COM (void) snprintf(xbuf->h_namesz, sizeof (xbuf->h_namesz), "%0*d", 3187917SReza.Sabdar@Sun.COM sizeof (xbuf->h_namesz) - 1, namesz); 3197917SReza.Sabdar@Sun.COM 3207917SReza.Sabdar@Sun.COM /* No support for links in extended attributes */ 3217917SReza.Sabdar@Sun.COM xbuf->h_typeflag = LF_NORMAL; 3227917SReza.Sabdar@Sun.COM 3237917SReza.Sabdar@Sun.COM (void) strlcpy(xbuf->h_names, fname, TLM_NAME_SIZE); 3247917SReza.Sabdar@Sun.COM (void) strlcpy(&xbuf->h_names[strlen(fname) + 1], aname, 3257917SReza.Sabdar@Sun.COM TLM_NAME_SIZE); 3267917SReza.Sabdar@Sun.COM 3277917SReza.Sabdar@Sun.COM free(section_name); 3287917SReza.Sabdar@Sun.COM return (0); 3297917SReza.Sabdar@Sun.COM } 3307917SReza.Sabdar@Sun.COM 3317917SReza.Sabdar@Sun.COM 3327917SReza.Sabdar@Sun.COM /* 3337917SReza.Sabdar@Sun.COM * output_file_header 3347917SReza.Sabdar@Sun.COM * 3357917SReza.Sabdar@Sun.COM * output the TAR header record 3367917SReza.Sabdar@Sun.COM */ 3377917SReza.Sabdar@Sun.COM static int 3387917SReza.Sabdar@Sun.COM output_file_header(char *name, char *link, 3397917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 3407917SReza.Sabdar@Sun.COM { 3417917SReza.Sabdar@Sun.COM static longlong_t file_count = 0; 3427917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr; 3437917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr; 3447917SReza.Sabdar@Sun.COM long actual_size; 3457917SReza.Sabdar@Sun.COM boolean_t long_name = FALSE; 3467917SReza.Sabdar@Sun.COM boolean_t long_link = FALSE; 3477917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 3487917SReza.Sabdar@Sun.COM int nmlen, lnklen; 3497917SReza.Sabdar@Sun.COM 3507917SReza.Sabdar@Sun.COM if (section_name == NULL) 3517917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 3527917SReza.Sabdar@Sun.COM 3537917SReza.Sabdar@Sun.COM /* 3547917SReza.Sabdar@Sun.COM * if the file has to go out in sections, 3557917SReza.Sabdar@Sun.COM * we must mung the name. 3567917SReza.Sabdar@Sun.COM */ 3577917SReza.Sabdar@Sun.COM if (section == 0) { 3587917SReza.Sabdar@Sun.COM (void) strlcpy(section_name, name, TLM_MAX_PATH_NAME); 3597917SReza.Sabdar@Sun.COM } else { 3607917SReza.Sabdar@Sun.COM (void) snprintf(section_name, 3617917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", name, section); 3627917SReza.Sabdar@Sun.COM } 3637917SReza.Sabdar@Sun.COM 3647917SReza.Sabdar@Sun.COM nmlen = strlen(section_name); 3657917SReza.Sabdar@Sun.COM if (nmlen >= NAMSIZ) { 3667917SReza.Sabdar@Sun.COM /* 3677917SReza.Sabdar@Sun.COM * file name is too big, it must go out 3687917SReza.Sabdar@Sun.COM * in its own data file 3697917SReza.Sabdar@Sun.COM */ 3707917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 3717917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 3727917SReza.Sabdar@Sun.COM if (!tar_hdr) { 3737917SReza.Sabdar@Sun.COM free(section_name); 3747917SReza.Sabdar@Sun.COM return (0); 3757917SReza.Sabdar@Sun.COM } 3767917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name, 3777917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 3787917SReza.Sabdar@Sun.COM "%s%08qd.fil", 3797917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 3807917SReza.Sabdar@Sun.COM file_count++); 3817917SReza.Sabdar@Sun.COM 3827917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGNAME; 3837917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 3847917SReza.Sabdar@Sun.COM "%011o ", nmlen); 3857917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 3867917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777); 3877917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 3887917SReza.Sabdar@Sun.COM "%06o ", attr->st_uid); 3897917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 3907917SReza.Sabdar@Sun.COM "%06o ", attr->st_gid); 3917917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 3927917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime); 3937917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 3947917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 3957917SReza.Sabdar@Sun.COM 3967917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 3977917SReza.Sabdar@Sun.COM 3987917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, 3997917SReza.Sabdar@Sun.COM (void *)section_name, nmlen); 4007917SReza.Sabdar@Sun.COM long_name = TRUE; 4017917SReza.Sabdar@Sun.COM } 4027917SReza.Sabdar@Sun.COM 4037917SReza.Sabdar@Sun.COM lnklen = strlen(link); 4047917SReza.Sabdar@Sun.COM if (lnklen >= NAMSIZ) { 4057917SReza.Sabdar@Sun.COM /* 4067917SReza.Sabdar@Sun.COM * link name is too big, it must go out 4077917SReza.Sabdar@Sun.COM * in its own data file 4087917SReza.Sabdar@Sun.COM */ 4097917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 4107917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 4117917SReza.Sabdar@Sun.COM if (!tar_hdr) { 4127917SReza.Sabdar@Sun.COM free(section_name); 4137917SReza.Sabdar@Sun.COM return (0); 4147917SReza.Sabdar@Sun.COM } 4157917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname, 4167917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4177917SReza.Sabdar@Sun.COM "%s%08qd.slk", 4187917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4197917SReza.Sabdar@Sun.COM file_count++); 4207917SReza.Sabdar@Sun.COM 4217917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGLINK; 4227917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 4237917SReza.Sabdar@Sun.COM "%011o ", lnklen); 4247917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 4257917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777); 4267917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 4277917SReza.Sabdar@Sun.COM "%06o ", attr->st_uid); 4287917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 4297917SReza.Sabdar@Sun.COM "%06o ", attr->st_gid); 4307917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 4317917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime); 4327917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 4337917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 4347917SReza.Sabdar@Sun.COM 4357917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 4367917SReza.Sabdar@Sun.COM 4377917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)link, 4387917SReza.Sabdar@Sun.COM lnklen); 4397917SReza.Sabdar@Sun.COM long_link = TRUE; 4407917SReza.Sabdar@Sun.COM } 4417917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 4427917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 4437917SReza.Sabdar@Sun.COM if (!tar_hdr) { 4447917SReza.Sabdar@Sun.COM free(section_name); 4457917SReza.Sabdar@Sun.COM return (0); 4467917SReza.Sabdar@Sun.COM } 4477917SReza.Sabdar@Sun.COM if (long_name) { 4487917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name, 4497917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4507917SReza.Sabdar@Sun.COM "%s%08qd.fil", 4517917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4527917SReza.Sabdar@Sun.COM file_count++); 4537917SReza.Sabdar@Sun.COM } else { 4547917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 4557917SReza.Sabdar@Sun.COM } 4567917SReza.Sabdar@Sun.COM 4577917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "long_link: %s [%s]", long_link ? "TRUE" : "FALSE", 4587917SReza.Sabdar@Sun.COM link); 4597917SReza.Sabdar@Sun.COM 4607917SReza.Sabdar@Sun.COM if (long_link) { 4617917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname, 4627917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name), 4637917SReza.Sabdar@Sun.COM "%s%08qd.slk", 4647917SReza.Sabdar@Sun.COM LONGNAME_PREFIX, 4657917SReza.Sabdar@Sun.COM file_count++); 4667917SReza.Sabdar@Sun.COM } else { 4677917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_linkname, link, TLM_NAME_SIZE); 4687917SReza.Sabdar@Sun.COM } 4697917SReza.Sabdar@Sun.COM if (S_ISDIR(attr->st_mode)) { 4707917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_DIR; 4717917SReza.Sabdar@Sun.COM } else if (S_ISFIFO(attr->st_mode)) { 4727917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_FIFO; 4737917SReza.Sabdar@Sun.COM } else if (attr->st_nlink > 1) { 4747917SReza.Sabdar@Sun.COM /* mark file with hardlink LF_LINK */ 4757917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LINK; 4767917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_shared.th_hlink_ino, 4777917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_shared.th_hlink_ino), 478*8193SReza.Sabdar@Sun.COM "%011llo ", attr->st_ino); 4797917SReza.Sabdar@Sun.COM } else { 4807917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL : LF_SYMLINK; 4817917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "linkflag: '%c'", tar_hdr->th_linkflag); 4827917SReza.Sabdar@Sun.COM } 4837917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 4847917SReza.Sabdar@Sun.COM (long)attr->st_size); 4857917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 4867917SReza.Sabdar@Sun.COM attr->st_mode & 07777); 4877917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 4887917SReza.Sabdar@Sun.COM attr->st_uid); 4897917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 4907917SReza.Sabdar@Sun.COM attr->st_gid); 4917917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 4927917SReza.Sabdar@Sun.COM attr->st_mtime); 4937917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 4947917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic)); 4957917SReza.Sabdar@Sun.COM 4967917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr); 4977917SReza.Sabdar@Sun.COM if (long_name || long_link) { 4987917SReza.Sabdar@Sun.COM if (file_count > 99999990) { 4997917SReza.Sabdar@Sun.COM file_count = 0; 5007917SReza.Sabdar@Sun.COM } 5017917SReza.Sabdar@Sun.COM } 5027917SReza.Sabdar@Sun.COM free(section_name); 5037917SReza.Sabdar@Sun.COM return (0); 5047917SReza.Sabdar@Sun.COM } 5057917SReza.Sabdar@Sun.COM 5067917SReza.Sabdar@Sun.COM 5077917SReza.Sabdar@Sun.COM /* 5087917SReza.Sabdar@Sun.COM * tlm_readlink 5097917SReza.Sabdar@Sun.COM * 5107917SReza.Sabdar@Sun.COM * Read where the softlink points to. Read the link in the checkpointed 5117917SReza.Sabdar@Sun.COM * path if the backup is being done on a checkpointed file system. 5127917SReza.Sabdar@Sun.COM */ 5137917SReza.Sabdar@Sun.COM static int 5147917SReza.Sabdar@Sun.COM tlm_readlink(char *nm, char *snap, char *buf, int bufsize) 5157917SReza.Sabdar@Sun.COM { 5167917SReza.Sabdar@Sun.COM int len; 5177917SReza.Sabdar@Sun.COM 5187917SReza.Sabdar@Sun.COM if ((len = readlink(snap, buf, bufsize)) >= 0) { 5197917SReza.Sabdar@Sun.COM /* 5207917SReza.Sabdar@Sun.COM * realink(2) doesn't null terminate the link name. We must 5217917SReza.Sabdar@Sun.COM * do it here. 5227917SReza.Sabdar@Sun.COM */ 5237917SReza.Sabdar@Sun.COM buf[len] = '\0'; 5247917SReza.Sabdar@Sun.COM } else { 5257917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Error %d reading softlink of [%s]", 5267917SReza.Sabdar@Sun.COM errno, nm); 5277917SReza.Sabdar@Sun.COM buf[0] = '\0'; 5287917SReza.Sabdar@Sun.COM 5297917SReza.Sabdar@Sun.COM /* Backup the link if the destination missing */ 5307917SReza.Sabdar@Sun.COM if (errno == ENOENT) 5317917SReza.Sabdar@Sun.COM return (0); 5327917SReza.Sabdar@Sun.COM 5337917SReza.Sabdar@Sun.COM } 5347917SReza.Sabdar@Sun.COM 5357917SReza.Sabdar@Sun.COM return (len); 5367917SReza.Sabdar@Sun.COM } 5377917SReza.Sabdar@Sun.COM 5387917SReza.Sabdar@Sun.COM 5397917SReza.Sabdar@Sun.COM /* 5407917SReza.Sabdar@Sun.COM * tlm_output_xattr 5417917SReza.Sabdar@Sun.COM * 5427917SReza.Sabdar@Sun.COM * Put this file into the output buffers. 5437917SReza.Sabdar@Sun.COM */ 5447917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 5457917SReza.Sabdar@Sun.COM longlong_t 5467917SReza.Sabdar@Sun.COM tlm_output_xattr(char *dir, char *name, char *chkdir, 5477917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, 5487917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 5497917SReza.Sabdar@Sun.COM { 5507917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */ 5517917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */ 5527917SReza.Sabdar@Sun.COM int section; /* section of a huge file */ 5537917SReza.Sabdar@Sun.COM int fd; 5547917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */ 5557917SReza.Sabdar@Sun.COM /* for Multi Volume record */ 5567917SReza.Sabdar@Sun.COM u_longlong_t pos; 5577917SReza.Sabdar@Sun.COM DIR *dp; 5587917SReza.Sabdar@Sun.COM struct dirent *dtp; 5597917SReza.Sabdar@Sun.COM char *attrname; 5607917SReza.Sabdar@Sun.COM char *fnamep; 5617917SReza.Sabdar@Sun.COM int rv = 0; 5627917SReza.Sabdar@Sun.COM 5637917SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode)) 5647917SReza.Sabdar@Sun.COM return (TLM_NO_SOURCE_FILE); 5657917SReza.Sabdar@Sun.COM 5667917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 5677917SReza.Sabdar@Sun.COM if (fullname == NULL) { 5687917SReza.Sabdar@Sun.COM free(fullname); 5697917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 5707917SReza.Sabdar@Sun.COM } 5717917SReza.Sabdar@Sun.COM 5727917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name)) { 5737917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 5747917SReza.Sabdar@Sun.COM free(fullname); 5757917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 5767917SReza.Sabdar@Sun.COM } 5777917SReza.Sabdar@Sun.COM 5787917SReza.Sabdar@Sun.COM if (pathconf(fullname, _PC_XATTR_EXISTS) != 1) { 5797917SReza.Sabdar@Sun.COM free(fullname); 5807917SReza.Sabdar@Sun.COM return (0); 5817917SReza.Sabdar@Sun.COM } 5827917SReza.Sabdar@Sun.COM 5837917SReza.Sabdar@Sun.COM attrname = ndmp_malloc(TLM_MAX_PATH_NAME); 5847917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 5857917SReza.Sabdar@Sun.COM if (attrname == NULL || snapname == NULL) { 5867917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE; 5877917SReza.Sabdar@Sun.COM goto err_out; 5887917SReza.Sabdar@Sun.COM } 5897917SReza.Sabdar@Sun.COM 5907917SReza.Sabdar@Sun.COM if (!tlm_cat_path(snapname, chkdir, name)) { 5917917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 5927917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE; 5937917SReza.Sabdar@Sun.COM goto err_out; 5947917SReza.Sabdar@Sun.COM } 5957917SReza.Sabdar@Sun.COM 5967917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 5977917SReza.Sabdar@Sun.COM 5987917SReza.Sabdar@Sun.COM /* 5997917SReza.Sabdar@Sun.COM * Open the file for reading. 6007917SReza.Sabdar@Sun.COM */ 6017917SReza.Sabdar@Sun.COM fd = open(fnamep, O_RDONLY | O_XATTR); 6027917SReza.Sabdar@Sun.COM if (fd == -1) { 6037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname); 6047917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE; 6057917SReza.Sabdar@Sun.COM goto err_out; 6067917SReza.Sabdar@Sun.COM } 6077917SReza.Sabdar@Sun.COM 6087917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 6097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 6107917SReza.Sabdar@Sun.COM 6117917SReza.Sabdar@Sun.COM section = 0; 6127917SReza.Sabdar@Sun.COM 6137917SReza.Sabdar@Sun.COM dp = (DIR *)fdopendir(fd); 6147917SReza.Sabdar@Sun.COM if (dp == NULL) { 6157917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname); 6167917SReza.Sabdar@Sun.COM (void) close(fd); 6177917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE; 6187917SReza.Sabdar@Sun.COM goto err_out; 6197917SReza.Sabdar@Sun.COM } 6207917SReza.Sabdar@Sun.COM 6217917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info, 6227917SReza.Sabdar@Sun.COM local_commands); 6237917SReza.Sabdar@Sun.COM 6247917SReza.Sabdar@Sun.COM while ((dtp = readdir(dp)) != NULL) { 6257917SReza.Sabdar@Sun.COM int section_size; 6267917SReza.Sabdar@Sun.COM 6277917SReza.Sabdar@Sun.COM if (*dtp->d_name == '.') 6287917SReza.Sabdar@Sun.COM continue; 6297917SReza.Sabdar@Sun.COM 6307917SReza.Sabdar@Sun.COM (void) close(fd); 6317917SReza.Sabdar@Sun.COM fd = attropen(fnamep, dtp->d_name, O_RDONLY); 6327917SReza.Sabdar@Sun.COM if (fd == -1) { 6337917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 6347917SReza.Sabdar@Sun.COM "problem(%d) opening xattr file [%s]", errno, 6357917SReza.Sabdar@Sun.COM fullname); 6367917SReza.Sabdar@Sun.COM goto tear_down; 6377917SReza.Sabdar@Sun.COM } 6387917SReza.Sabdar@Sun.COM 6397917SReza.Sabdar@Sun.COM (void) output_xattr_header(fullname, dtp->d_name, fd, 6407917SReza.Sabdar@Sun.COM tlm_acls, section, local_commands); 6417917SReza.Sabdar@Sun.COM (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s", 6427917SReza.Sabdar@Sun.COM dtp->d_name); 6437917SReza.Sabdar@Sun.COM (void) output_file_header(attrname, "", tlm_acls, 0, 6447917SReza.Sabdar@Sun.COM local_commands); 6457917SReza.Sabdar@Sun.COM 6467917SReza.Sabdar@Sun.COM section_size = (long)llmin(tlm_acls->acl_attr.st_size, 6477917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE); 6487917SReza.Sabdar@Sun.COM 6497917SReza.Sabdar@Sun.COM /* We only can read upto one section extended attribute */ 6507917SReza.Sabdar@Sun.COM while (section_size > 0) { 6517917SReza.Sabdar@Sun.COM char *buf; 6527917SReza.Sabdar@Sun.COM long actual_size; 6537917SReza.Sabdar@Sun.COM int read_size; 6547917SReza.Sabdar@Sun.COM 6557917SReza.Sabdar@Sun.COM /* 6567917SReza.Sabdar@Sun.COM * check for Abort commands 6577917SReza.Sabdar@Sun.COM */ 6587917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 6597917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 6607917SReza.Sabdar@Sun.COM goto tear_down; 6617917SReza.Sabdar@Sun.COM } 6627917SReza.Sabdar@Sun.COM 6637917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 6647917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 6657917SReza.Sabdar@Sun.COM tb_file_size = section_size; 6667917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 6677917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 6687917SReza.Sabdar@Sun.COM tb_seek_spot = seek_spot; 6697917SReza.Sabdar@Sun.COM 6707917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size, 6717917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands); 6727917SReza.Sabdar@Sun.COM if (!buf) 6737917SReza.Sabdar@Sun.COM goto tear_down; 6747917SReza.Sabdar@Sun.COM 6757917SReza.Sabdar@Sun.COM /* 6767917SReza.Sabdar@Sun.COM * check for Abort commands 6777917SReza.Sabdar@Sun.COM */ 6787917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 6797917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 6807917SReza.Sabdar@Sun.COM goto tear_down; 6817917SReza.Sabdar@Sun.COM } 6827917SReza.Sabdar@Sun.COM 6837917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size); 6847917SReza.Sabdar@Sun.COM actual_size = read(fd, buf, read_size); 6857917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size); 6867917SReza.Sabdar@Sun.COM NS_INC(rfile); 6877917SReza.Sabdar@Sun.COM 6887917SReza.Sabdar@Sun.COM if (actual_size == -1) { 6897917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 6907917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]", 6917917SReza.Sabdar@Sun.COM errno, fullname, snapname); 6927917SReza.Sabdar@Sun.COM goto tear_down; 6937917SReza.Sabdar@Sun.COM } 6947917SReza.Sabdar@Sun.COM seek_spot += actual_size; 6957917SReza.Sabdar@Sun.COM section_size -= actual_size; 6967917SReza.Sabdar@Sun.COM } 6977917SReza.Sabdar@Sun.COM } 6987917SReza.Sabdar@Sun.COM 6997917SReza.Sabdar@Sun.COM tear_down: 7007917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 7017917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 7027917SReza.Sabdar@Sun.COM 7037917SReza.Sabdar@Sun.COM (void) closedir(dp); 7047917SReza.Sabdar@Sun.COM (void) close(fd); 7057917SReza.Sabdar@Sun.COM 7067917SReza.Sabdar@Sun.COM err_out: 7077917SReza.Sabdar@Sun.COM free(fullname); 7087917SReza.Sabdar@Sun.COM free(attrname); 7097917SReza.Sabdar@Sun.COM free(snapname); 7107917SReza.Sabdar@Sun.COM return (rv); 7117917SReza.Sabdar@Sun.COM } 7127917SReza.Sabdar@Sun.COM 7137917SReza.Sabdar@Sun.COM 7147917SReza.Sabdar@Sun.COM /* 7157917SReza.Sabdar@Sun.COM * tlm_output_file 7167917SReza.Sabdar@Sun.COM * 7177917SReza.Sabdar@Sun.COM * Put this file into the output buffers. 7187917SReza.Sabdar@Sun.COM */ 7197917SReza.Sabdar@Sun.COM longlong_t 7207917SReza.Sabdar@Sun.COM tlm_output_file(char *dir, char *name, char *chkdir, 7217917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands, 7227917SReza.Sabdar@Sun.COM tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q) 7237917SReza.Sabdar@Sun.COM { 7247917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */ 7257917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */ 7267917SReza.Sabdar@Sun.COM char *linkname; /* where this file points */ 7277917SReza.Sabdar@Sun.COM int section = 0; /* section of a huge file */ 7287917SReza.Sabdar@Sun.COM int fd; 7297917SReza.Sabdar@Sun.COM longlong_t real_size; /* the origional file size */ 7307917SReza.Sabdar@Sun.COM longlong_t file_size; /* real size of this file */ 7317917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */ 7327917SReza.Sabdar@Sun.COM /* for Multi Volume record */ 7337917SReza.Sabdar@Sun.COM u_longlong_t pos; 7347917SReza.Sabdar@Sun.COM char *fnamep; 7357917SReza.Sabdar@Sun.COM 7367917SReza.Sabdar@Sun.COM /* Indicate whether a file with the same inode has been backed up. */ 7377917SReza.Sabdar@Sun.COM int hardlink_done = 0; 7387917SReza.Sabdar@Sun.COM 7397917SReza.Sabdar@Sun.COM /* 7407917SReza.Sabdar@Sun.COM * If a file with the same inode has been backed up, hardlink_pos holds 7417917SReza.Sabdar@Sun.COM * the tape offset of the data record. 7427917SReza.Sabdar@Sun.COM */ 7437917SReza.Sabdar@Sun.COM u_longlong_t hardlink_pos = 0; 7447917SReza.Sabdar@Sun.COM 7457917SReza.Sabdar@Sun.COM if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) { 7467917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name); 7477917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE); 7487917SReza.Sabdar@Sun.COM } 7497917SReza.Sabdar@Sun.COM 7507917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 7517917SReza.Sabdar@Sun.COM linkname = ndmp_malloc(TLM_MAX_PATH_NAME); 7527917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 7537917SReza.Sabdar@Sun.COM if (fullname == NULL || linkname == NULL || snapname == NULL) { 7547917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 7557917SReza.Sabdar@Sun.COM goto err_out; 7567917SReza.Sabdar@Sun.COM } 7577917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name) || 7587917SReza.Sabdar@Sun.COM !tlm_cat_path(snapname, chkdir, name)) { 7597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long."); 7607917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 7617917SReza.Sabdar@Sun.COM goto err_out; 7627917SReza.Sabdar@Sun.COM } 7637917SReza.Sabdar@Sun.COM 7647917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands); 7657917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 7667917SReza.Sabdar@Sun.COM 7677917SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode)) { 7687917SReza.Sabdar@Sun.COM file_size = tlm_readlink(fullname, snapname, linkname, 7697917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME-1); 7707917SReza.Sabdar@Sun.COM if (file_size < 0) { 7717917SReza.Sabdar@Sun.COM real_size = -ENOENT; 7727917SReza.Sabdar@Sun.COM goto err_out; 7737917SReza.Sabdar@Sun.COM } 7747917SReza.Sabdar@Sun.COM 7757917SReza.Sabdar@Sun.COM /* 7767917SReza.Sabdar@Sun.COM * Since soft links can not be read(2), we should only 7777917SReza.Sabdar@Sun.COM * backup the file header. 7787917SReza.Sabdar@Sun.COM */ 7797917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 7807917SReza.Sabdar@Sun.COM linkname, 7817917SReza.Sabdar@Sun.COM tlm_acls, 7827917SReza.Sabdar@Sun.COM section, 7837917SReza.Sabdar@Sun.COM local_commands); 7847917SReza.Sabdar@Sun.COM 7857917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name, 7867917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 7877917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname, 7887917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 7897917SReza.Sabdar@Sun.COM 7907917SReza.Sabdar@Sun.COM free(fullname); 7917917SReza.Sabdar@Sun.COM free(linkname); 7927917SReza.Sabdar@Sun.COM free(snapname); 7937917SReza.Sabdar@Sun.COM return (0); 7947917SReza.Sabdar@Sun.COM } 7957917SReza.Sabdar@Sun.COM 7967917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 7977917SReza.Sabdar@Sun.COM 7987917SReza.Sabdar@Sun.COM /* 7997917SReza.Sabdar@Sun.COM * For hardlink, only read the data if no other link 8007917SReza.Sabdar@Sun.COM * belonging to the same inode has been backed up. 8017917SReza.Sabdar@Sun.COM */ 8027917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1) { 8037917SReza.Sabdar@Sun.COM hardlink_done = !hardlink_q_get(hardlink_q, 8047917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL); 8057917SReza.Sabdar@Sun.COM } 8067917SReza.Sabdar@Sun.COM 8077917SReza.Sabdar@Sun.COM if (!hardlink_done) { 8087917SReza.Sabdar@Sun.COM /* 8097917SReza.Sabdar@Sun.COM * Open the file for reading. 8107917SReza.Sabdar@Sun.COM */ 8117917SReza.Sabdar@Sun.COM fd = open(fnamep, O_RDONLY); 8127917SReza.Sabdar@Sun.COM if (fd == -1) { 8137917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 8147917SReza.Sabdar@Sun.COM "BACKUP> Can't open file [%s] err(%d)", 8157917SReza.Sabdar@Sun.COM fullname, errno); 8167917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SOURCE_FILE; 8177917SReza.Sabdar@Sun.COM goto err_out; 8187917SReza.Sabdar@Sun.COM } 8197917SReza.Sabdar@Sun.COM } else { 820*8193SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ", 8217917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, hardlink_pos); 8227917SReza.Sabdar@Sun.COM 8237917SReza.Sabdar@Sun.COM fd = -1; 8247917SReza.Sabdar@Sun.COM } 8257917SReza.Sabdar@Sun.COM 8267917SReza.Sabdar@Sun.COM linkname[0] = 0; 8277917SReza.Sabdar@Sun.COM 8287917SReza.Sabdar@Sun.COM real_size = tlm_acls->acl_attr.st_size; 8297917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info, 8307917SReza.Sabdar@Sun.COM local_commands); 8317917SReza.Sabdar@Sun.COM 8327917SReza.Sabdar@Sun.COM /* 8337917SReza.Sabdar@Sun.COM * section = 0: file is small enough for TAR 8347917SReza.Sabdar@Sun.COM * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks 8357917SReza.Sabdar@Sun.COM * and the file name gets munged 8367917SReza.Sabdar@Sun.COM */ 8377917SReza.Sabdar@Sun.COM file_size = real_size; 8387917SReza.Sabdar@Sun.COM if (file_size > TLM_MAX_TAR_IMAGE) { 8397917SReza.Sabdar@Sun.COM if (output_humongus_header(fullname, file_size, 8407917SReza.Sabdar@Sun.COM local_commands) < 0) { 8417917SReza.Sabdar@Sun.COM (void) close(fd); 8427917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE; 8437917SReza.Sabdar@Sun.COM goto err_out; 8447917SReza.Sabdar@Sun.COM } 8457917SReza.Sabdar@Sun.COM section = 1; 8467917SReza.Sabdar@Sun.COM } else { 8477917SReza.Sabdar@Sun.COM section = 0; 8487917SReza.Sabdar@Sun.COM } 8497917SReza.Sabdar@Sun.COM 8507917SReza.Sabdar@Sun.COM /* 8517917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode 8527917SReza.Sabdar@Sun.COM * has been backed up, only backup an empty record. 8537917SReza.Sabdar@Sun.COM */ 8547917SReza.Sabdar@Sun.COM if (hardlink_done) 8557917SReza.Sabdar@Sun.COM file_size = 0; 8567917SReza.Sabdar@Sun.COM 8577917SReza.Sabdar@Sun.COM /* 8587917SReza.Sabdar@Sun.COM * work 8597917SReza.Sabdar@Sun.COM */ 8607917SReza.Sabdar@Sun.COM if (file_size == 0) { 8617917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 8627917SReza.Sabdar@Sun.COM linkname, 8637917SReza.Sabdar@Sun.COM tlm_acls, 8647917SReza.Sabdar@Sun.COM section, 8657917SReza.Sabdar@Sun.COM local_commands); 8667917SReza.Sabdar@Sun.COM /* 8677917SReza.Sabdar@Sun.COM * this can fall right through since zero size files 8687917SReza.Sabdar@Sun.COM * will be skipped by the WHILE loop anyway 8697917SReza.Sabdar@Sun.COM */ 8707917SReza.Sabdar@Sun.COM } 8717917SReza.Sabdar@Sun.COM 8727917SReza.Sabdar@Sun.COM while (file_size > 0) { 8737917SReza.Sabdar@Sun.COM int section_size = llmin(file_size, 8747917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE); 8757917SReza.Sabdar@Sun.COM 8767917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_size = (longlong_t)section_size; 8777917SReza.Sabdar@Sun.COM (void) output_file_header(fullname, 8787917SReza.Sabdar@Sun.COM linkname, 8797917SReza.Sabdar@Sun.COM tlm_acls, 8807917SReza.Sabdar@Sun.COM section, 8817917SReza.Sabdar@Sun.COM local_commands); 8827917SReza.Sabdar@Sun.COM while (section_size > 0) { 8837917SReza.Sabdar@Sun.COM char *buf; 8847917SReza.Sabdar@Sun.COM long actual_size; 8857917SReza.Sabdar@Sun.COM int read_size; 8867917SReza.Sabdar@Sun.COM 8877917SReza.Sabdar@Sun.COM /* 8887917SReza.Sabdar@Sun.COM * check for Abort commands 8897917SReza.Sabdar@Sun.COM */ 8907917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 8917917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 8927917SReza.Sabdar@Sun.COM goto tear_down; 8937917SReza.Sabdar@Sun.COM } 8947917SReza.Sabdar@Sun.COM 8957917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 8967917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 8977917SReza.Sabdar@Sun.COM tb_file_size = section_size; 8987917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 8997917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in]. 9007917SReza.Sabdar@Sun.COM tb_seek_spot = seek_spot; 9017917SReza.Sabdar@Sun.COM 9027917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size, 9037917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands); 9047917SReza.Sabdar@Sun.COM if (!buf) 9057917SReza.Sabdar@Sun.COM goto tear_down; 9067917SReza.Sabdar@Sun.COM 9077917SReza.Sabdar@Sun.COM /* 9087917SReza.Sabdar@Sun.COM * check for Abort commands 9097917SReza.Sabdar@Sun.COM */ 9107917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) { 9117917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT; 9127917SReza.Sabdar@Sun.COM goto tear_down; 9137917SReza.Sabdar@Sun.COM } 9147917SReza.Sabdar@Sun.COM 9157917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size); 9167917SReza.Sabdar@Sun.COM actual_size = read(fd, buf, read_size); 9177917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size); 9187917SReza.Sabdar@Sun.COM NS_INC(rfile); 9197917SReza.Sabdar@Sun.COM 9207917SReza.Sabdar@Sun.COM if (actual_size == 0) 9217917SReza.Sabdar@Sun.COM break; 9227917SReza.Sabdar@Sun.COM 9237917SReza.Sabdar@Sun.COM if (actual_size == -1) { 9247917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 9257917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]", 9267917SReza.Sabdar@Sun.COM errno, fullname, snapname); 9277917SReza.Sabdar@Sun.COM goto tear_down; 9287917SReza.Sabdar@Sun.COM } 9297917SReza.Sabdar@Sun.COM seek_spot += actual_size; 9307917SReza.Sabdar@Sun.COM file_size -= actual_size; 9317917SReza.Sabdar@Sun.COM section_size -= actual_size; 9327917SReza.Sabdar@Sun.COM } 9337917SReza.Sabdar@Sun.COM section++; 9347917SReza.Sabdar@Sun.COM } 9357917SReza.Sabdar@Sun.COM 9367917SReza.Sabdar@Sun.COM /* 9377917SReza.Sabdar@Sun.COM * If data belonging to this hardlink has been backed up, add the link 9387917SReza.Sabdar@Sun.COM * to hardlink queue. 9397917SReza.Sabdar@Sun.COM */ 9407917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) { 9417917SReza.Sabdar@Sun.COM (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino, 9427917SReza.Sabdar@Sun.COM pos, NULL, 0); 9437917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 944*8193SReza.Sabdar@Sun.COM "backed up hardlink file %s, inode = %llu, pos = %llu ", 9457917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, pos); 9467917SReza.Sabdar@Sun.COM } 9477917SReza.Sabdar@Sun.COM 9487917SReza.Sabdar@Sun.COM /* 9497917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode has been 950*8193SReza.Sabdar@Sun.COM * backed up, no add_node entry should be sent for this link. 9517917SReza.Sabdar@Sun.COM */ 9527917SReza.Sabdar@Sun.COM if (hardlink_done) { 9537917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 954*8193SReza.Sabdar@Sun.COM "backed up hardlink link %s, inode = %llu, pos = %llu ", 9557917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, hardlink_pos); 9567917SReza.Sabdar@Sun.COM } else { 9577917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name, 9587917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos); 9597917SReza.Sabdar@Sun.COM } 9607917SReza.Sabdar@Sun.COM 9617917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr, 9627917SReza.Sabdar@Sun.COM pos); 9637917SReza.Sabdar@Sun.COM 9647917SReza.Sabdar@Sun.COM tear_down: 9657917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[ 9667917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 9677917SReza.Sabdar@Sun.COM 9687917SReza.Sabdar@Sun.COM (void) close(fd); 9697917SReza.Sabdar@Sun.COM 9707917SReza.Sabdar@Sun.COM err_out: 9717917SReza.Sabdar@Sun.COM free(fullname); 9727917SReza.Sabdar@Sun.COM free(linkname); 9737917SReza.Sabdar@Sun.COM free(snapname); 9747917SReza.Sabdar@Sun.COM return (real_size); 9757917SReza.Sabdar@Sun.COM } 9767917SReza.Sabdar@Sun.COM 9777917SReza.Sabdar@Sun.COM /* 9787917SReza.Sabdar@Sun.COM * tar_putfile 9797917SReza.Sabdar@Sun.COM * 9807917SReza.Sabdar@Sun.COM * Main file backup function for tar 9817917SReza.Sabdar@Sun.COM */ 9827917SReza.Sabdar@Sun.COM int 9837917SReza.Sabdar@Sun.COM tar_putfile(char *dir, char *name, char *chkdir, 9847917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, 9857917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats, 9867917SReza.Sabdar@Sun.COM struct hardlink_q *hardlink_q) 9877917SReza.Sabdar@Sun.COM { 9887917SReza.Sabdar@Sun.COM int rv; 9897917SReza.Sabdar@Sun.COM 9907917SReza.Sabdar@Sun.COM rv = tlm_output_file(dir, name, chkdir, tlm_acls, commands, 9917917SReza.Sabdar@Sun.COM local_commands, job_stats, hardlink_q); 9927917SReza.Sabdar@Sun.COM if (rv < 0) 9937917SReza.Sabdar@Sun.COM return (rv); 9947917SReza.Sabdar@Sun.COM 9957917SReza.Sabdar@Sun.COM rv = tlm_output_xattr(dir, name, chkdir, tlm_acls, commands, 9967917SReza.Sabdar@Sun.COM local_commands, job_stats); 9977917SReza.Sabdar@Sun.COM 9987917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0); 9997917SReza.Sabdar@Sun.COM } 10007917SReza.Sabdar@Sun.COM 10017917SReza.Sabdar@Sun.COM /* 10027917SReza.Sabdar@Sun.COM * get_write_buffer 10037917SReza.Sabdar@Sun.COM * 10047917SReza.Sabdar@Sun.COM * a wrapper to tlm_get_write_buffer so that 10057917SReza.Sabdar@Sun.COM * we can cleanly detect ABORT commands 10067917SReza.Sabdar@Sun.COM * without involving the TLM library with 10077917SReza.Sabdar@Sun.COM * our problems. 10087917SReza.Sabdar@Sun.COM */ 10097917SReza.Sabdar@Sun.COM static char * 10107917SReza.Sabdar@Sun.COM get_write_buffer(long size, long *actual_size, 10117917SReza.Sabdar@Sun.COM boolean_t zero, tlm_cmd_t *local_commands) 10127917SReza.Sabdar@Sun.COM { 10137917SReza.Sabdar@Sun.COM while (local_commands->tc_reader == TLM_BACKUP_RUN) { 10147917SReza.Sabdar@Sun.COM char *rec = tlm_get_write_buffer(size, actual_size, 10157917SReza.Sabdar@Sun.COM local_commands->tc_buffers, zero); 10167917SReza.Sabdar@Sun.COM if (rec != 0) { 10177917SReza.Sabdar@Sun.COM return (rec); 10187917SReza.Sabdar@Sun.COM } 10197917SReza.Sabdar@Sun.COM } 10207917SReza.Sabdar@Sun.COM return (NULL); 10217917SReza.Sabdar@Sun.COM } 10227917SReza.Sabdar@Sun.COM 10237917SReza.Sabdar@Sun.COM #define NDMP_MORE_RECORDS 2 10247917SReza.Sabdar@Sun.COM 10257917SReza.Sabdar@Sun.COM /* 10267917SReza.Sabdar@Sun.COM * write_tar_eof 10277917SReza.Sabdar@Sun.COM * 10287917SReza.Sabdar@Sun.COM * This function is initially written for NDMP support. It appends 10297917SReza.Sabdar@Sun.COM * two tar headers to the tar file, and also N more empty buffers 10307917SReza.Sabdar@Sun.COM * to make sure that the two tar headers will be read as a part of 10317917SReza.Sabdar@Sun.COM * a mover record and don't get locked because of EOM on the mover 10327917SReza.Sabdar@Sun.COM * side. 10337917SReza.Sabdar@Sun.COM */ 10347917SReza.Sabdar@Sun.COM void 10357917SReza.Sabdar@Sun.COM write_tar_eof(tlm_cmd_t *local_commands) 10367917SReza.Sabdar@Sun.COM { 10377917SReza.Sabdar@Sun.COM int i; 10387917SReza.Sabdar@Sun.COM long actual_size; 10397917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs; 10407917SReza.Sabdar@Sun.COM 10417917SReza.Sabdar@Sun.COM /* 10427917SReza.Sabdar@Sun.COM * output 2 zero filled records, 10437917SReza.Sabdar@Sun.COM * TAR wants this. 10447917SReza.Sabdar@Sun.COM */ 10457917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 10467917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 10477917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 10487917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 10497917SReza.Sabdar@Sun.COM 10507917SReza.Sabdar@Sun.COM /* 10517917SReza.Sabdar@Sun.COM * NDMP: Clear the rest of the buffer and write two more buffers 10527917SReza.Sabdar@Sun.COM * to the tape. 10537917SReza.Sabdar@Sun.COM */ 10547917SReza.Sabdar@Sun.COM bufs = local_commands->tc_buffers; 10557917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size, 10567917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 10577917SReza.Sabdar@Sun.COM 10587917SReza.Sabdar@Sun.COM for (i = 0; i < NDMP_MORE_RECORDS && 10597917SReza.Sabdar@Sun.COM local_commands->tc_reader == TLM_BACKUP_RUN; i++) { 10607917SReza.Sabdar@Sun.COM /* 10617917SReza.Sabdar@Sun.COM * We don't need the return value of get_write_buffer(), 10627917SReza.Sabdar@Sun.COM * since it's already zeroed out if the buffer is returned. 10637917SReza.Sabdar@Sun.COM */ 10647917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size, 10657917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands); 10667917SReza.Sabdar@Sun.COM } 10677917SReza.Sabdar@Sun.COM 10687917SReza.Sabdar@Sun.COM bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE; 10697917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs); 10707917SReza.Sabdar@Sun.COM } 10717917SReza.Sabdar@Sun.COM 10727917SReza.Sabdar@Sun.COM /* 10737917SReza.Sabdar@Sun.COM * Callback to backup each ZFS property 10747917SReza.Sabdar@Sun.COM */ 10757917SReza.Sabdar@Sun.COM static int 10767917SReza.Sabdar@Sun.COM zfs_put_prop_cb(int prop, void *pp) 10777917SReza.Sabdar@Sun.COM { 10787917SReza.Sabdar@Sun.COM ndmp_metadata_header_t *mhp; 10797917SReza.Sabdar@Sun.COM ndmp_metadata_property_t *mpp; 10807917SReza.Sabdar@Sun.COM char buf[ZFS_MAXNAMELEN]; 10817917SReza.Sabdar@Sun.COM char sbuf[ZFS_MAXNAMELEN]; 10827917SReza.Sabdar@Sun.COM zprop_source_t stype; 10837917SReza.Sabdar@Sun.COM 10847917SReza.Sabdar@Sun.COM if (pp == NULL) 10857917SReza.Sabdar@Sun.COM return (ZPROP_INVAL); 10867917SReza.Sabdar@Sun.COM 10877917SReza.Sabdar@Sun.COM mhp = (ndmp_metadata_header_t *)pp; 10887917SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count++]; 10897917SReza.Sabdar@Sun.COM 10907917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, zfs_prop_to_name(prop), NAME_MAX); 10917917SReza.Sabdar@Sun.COM (void) zfs_prop_get(mhp->nh_handle, 10927917SReza.Sabdar@Sun.COM prop, buf, sizeof (buf), &stype, sbuf, sizeof (sbuf), FALSE); 10937917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, buf, NAME_MAX); 10947917SReza.Sabdar@Sun.COM if (stype == ZPROP_SRC_LOCAL) 10957917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, mhp->nh_dataset, NAME_MAX); 10967917SReza.Sabdar@Sun.COM else 10977917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, sbuf, NAME_MAX); 10987917SReza.Sabdar@Sun.COM 10997917SReza.Sabdar@Sun.COM return (ZPROP_CONT); 11007917SReza.Sabdar@Sun.COM } 11017917SReza.Sabdar@Sun.COM 11027917SReza.Sabdar@Sun.COM 11037917SReza.Sabdar@Sun.COM /* 11047917SReza.Sabdar@Sun.COM * Notifies ndmpd that the metadata associated with the given ZFS dataset 11057917SReza.Sabdar@Sun.COM * should be backed up. 11067917SReza.Sabdar@Sun.COM */ 11077917SReza.Sabdar@Sun.COM int 11087917SReza.Sabdar@Sun.COM ndmp_include_zfs(ndmp_context_t *nctx, const char *dataset) 11097917SReza.Sabdar@Sun.COM { 11107917SReza.Sabdar@Sun.COM tlm_commands_t *cmds; 11117917SReza.Sabdar@Sun.COM ndmp_metadata_header_t *mhp; 11127917SReza.Sabdar@Sun.COM ndmp_metadata_property_t *mpp; 11137917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd; 11147917SReza.Sabdar@Sun.COM long actual_size; 11157917SReza.Sabdar@Sun.COM nvlist_t *uprops, *ulist; 11167917SReza.Sabdar@Sun.COM const char *pname; 11177917SReza.Sabdar@Sun.COM nvpair_t *elp; 11187917SReza.Sabdar@Sun.COM char *sval, *ssrc; 11197917SReza.Sabdar@Sun.COM char *wbuf, *pp, *tp; 11207917SReza.Sabdar@Sun.COM long size, lsize, sz; 11217917SReza.Sabdar@Sun.COM int align = RECORDSIZE - 1; 11227917SReza.Sabdar@Sun.COM 11237917SReza.Sabdar@Sun.COM if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 11247917SReza.Sabdar@Sun.COM return (-1); 11257917SReza.Sabdar@Sun.COM 11267917SReza.Sabdar@Sun.COM if ((lcmd = cmds->tcs_command) == NULL || 11277917SReza.Sabdar@Sun.COM lcmd->tc_buffers == NULL) 11287917SReza.Sabdar@Sun.COM return (-1); 11297917SReza.Sabdar@Sun.COM 11307917SReza.Sabdar@Sun.COM size = sizeof (ndmp_metadata_header_t) + 11317917SReza.Sabdar@Sun.COM ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 11327917SReza.Sabdar@Sun.COM size += align; 11337917SReza.Sabdar@Sun.COM size &= ~align; 11347917SReza.Sabdar@Sun.COM 11357917SReza.Sabdar@Sun.COM if ((mhp = malloc(size)) == NULL) 11367917SReza.Sabdar@Sun.COM return (-1); 11377917SReza.Sabdar@Sun.COM (void) memset(mhp, 0, size); 11387917SReza.Sabdar@Sun.COM 11397917SReza.Sabdar@Sun.COM mhp->nh_plversion = nctx->nc_plversion; 11407917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_plname, nctx->nc_plname, 11417917SReza.Sabdar@Sun.COM sizeof (mhp->nh_plname)); 11427917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_magic, ZFS_META_MAGIC, sizeof (mhp->nh_magic)); 11437917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_dataset, dataset, sizeof (mhp->nh_dataset)); 11447917SReza.Sabdar@Sun.COM 11457917SReza.Sabdar@Sun.COM if ((mhp->nh_handle = zfs_open(zlibh, dataset, 11467917SReza.Sabdar@Sun.COM ZFS_TYPE_DATASET)) == NULL) { 11477917SReza.Sabdar@Sun.COM free(mhp); 11487917SReza.Sabdar@Sun.COM return (ZPROP_INVAL); 11497917SReza.Sabdar@Sun.COM } 11507917SReza.Sabdar@Sun.COM 11517917SReza.Sabdar@Sun.COM /* Get all the ZFS properties */ 11527917SReza.Sabdar@Sun.COM (void) zprop_iter(zfs_put_prop_cb, mhp, TRUE, TRUE, 11537917SReza.Sabdar@Sun.COM ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET); 11547917SReza.Sabdar@Sun.COM 11557917SReza.Sabdar@Sun.COM /* Get user properties */ 11567917SReza.Sabdar@Sun.COM uprops = zfs_get_user_props(mhp->nh_handle); 11577917SReza.Sabdar@Sun.COM 11587917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, NULL); 11597917SReza.Sabdar@Sun.COM 11607917SReza.Sabdar@Sun.COM while (elp != NULL) { 11617917SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count]; 11627917SReza.Sabdar@Sun.COM if (nvpair_value_nvlist(elp, &ulist) != 0 || 11637917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_VALUE, &sval) != 0 || 11647917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_SOURCE, &ssrc) != 0) { 11657917SReza.Sabdar@Sun.COM zfs_close(mhp->nh_handle); 11667917SReza.Sabdar@Sun.COM free(mhp); 11677917SReza.Sabdar@Sun.COM return (-1); 11687917SReza.Sabdar@Sun.COM } 11697917SReza.Sabdar@Sun.COM if ((pname = nvpair_name(elp)) != NULL) 11707917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, pname, NAME_MAX); 11717917SReza.Sabdar@Sun.COM 11727917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, sval, NAME_MAX); 11737917SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, ssrc, NAME_MAX); 11747917SReza.Sabdar@Sun.COM mhp->nh_count++; 11757917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, elp); 11767917SReza.Sabdar@Sun.COM } 11777917SReza.Sabdar@Sun.COM 11787917SReza.Sabdar@Sun.COM zfs_close(mhp->nh_handle); 11797917SReza.Sabdar@Sun.COM 11807917SReza.Sabdar@Sun.COM if ((wbuf = get_write_buffer(size, &actual_size, TRUE, 11817917SReza.Sabdar@Sun.COM lcmd)) != NULL) { 11827917SReza.Sabdar@Sun.COM pp = (char *)mhp; 11837917SReza.Sabdar@Sun.COM 11847917SReza.Sabdar@Sun.COM (void) memcpy(wbuf, pp, (actual_size < size) ? 11857917SReza.Sabdar@Sun.COM actual_size : size); 11867917SReza.Sabdar@Sun.COM pp += (actual_size < size) ? actual_size : size; 11877917SReza.Sabdar@Sun.COM 11887917SReza.Sabdar@Sun.COM sz = actual_size; 11897917SReza.Sabdar@Sun.COM while (sz < size && 11907917SReza.Sabdar@Sun.COM ((tp = get_write_buffer(size - sz, &lsize, 11917917SReza.Sabdar@Sun.COM TRUE, lcmd))) != NULL) { 11927917SReza.Sabdar@Sun.COM (void) memcpy(tp, pp, size - sz); 11937917SReza.Sabdar@Sun.COM sz += lsize; 11947917SReza.Sabdar@Sun.COM pp += lsize; 11957917SReza.Sabdar@Sun.COM } 11967917SReza.Sabdar@Sun.COM if (sz > size) { 11977917SReza.Sabdar@Sun.COM tlm_unget_write_buffer(lcmd->tc_buffers, sz - size); 11987917SReza.Sabdar@Sun.COM } 11997917SReza.Sabdar@Sun.COM } 12007917SReza.Sabdar@Sun.COM 12017917SReza.Sabdar@Sun.COM free(mhp); 12027917SReza.Sabdar@Sun.COM return (0); 12037917SReza.Sabdar@Sun.COM } 1204