17917SReza.Sabdar@Sun.COM /*
2*12353SReza.Sabdar@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
37917SReza.Sabdar@Sun.COM */
47917SReza.Sabdar@Sun.COM
57917SReza.Sabdar@Sun.COM /*
67917SReza.Sabdar@Sun.COM * BSD 3 Clause License
77917SReza.Sabdar@Sun.COM *
87917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association.
97917SReza.Sabdar@Sun.COM *
107917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without
117917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions
127917SReza.Sabdar@Sun.COM * are met:
137917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright
147917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer.
157917SReza.Sabdar@Sun.COM *
167917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright
177917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in
187917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the
197917SReza.Sabdar@Sun.COM * distribution.
207917SReza.Sabdar@Sun.COM *
217917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA)
227917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote
237917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written
247917SReza.Sabdar@Sun.COM * permission.
257917SReza.Sabdar@Sun.COM *
267917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
277917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
307917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
327917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
337917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
347917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
357917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
367917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE.
377917SReza.Sabdar@Sun.COM */
387917SReza.Sabdar@Sun.COM #include <stdio.h>
397917SReza.Sabdar@Sun.COM #include <limits.h>
407917SReza.Sabdar@Sun.COM #include <time.h>
417917SReza.Sabdar@Sun.COM #include <sys/stat.h>
427917SReza.Sabdar@Sun.COM #include <unistd.h>
437917SReza.Sabdar@Sun.COM #include <dirent.h>
447917SReza.Sabdar@Sun.COM #include <pthread.h>
457917SReza.Sabdar@Sun.COM #include <archives.h>
467917SReza.Sabdar@Sun.COM #include <tlm.h>
477917SReza.Sabdar@Sun.COM #include <sys/fs/zfs.h>
48*12353SReza.Sabdar@Sun.COM #include <sys/mkdev.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;
7511170SReza.Sabdar@Sun.COM extern mutex_t zlib_mtx;
767917SReza.Sabdar@Sun.COM
77*12353SReza.Sabdar@Sun.COM #define S_ISPECIAL(a) (S_ISLNK(a) || S_ISFIFO(a) || S_ISBLK(a) || \
78*12353SReza.Sabdar@Sun.COM S_ISCHR(a))
797917SReza.Sabdar@Sun.COM
807917SReza.Sabdar@Sun.COM /*
817917SReza.Sabdar@Sun.COM * output_mem
827917SReza.Sabdar@Sun.COM *
837917SReza.Sabdar@Sun.COM * Gets a IO write buffer and copies memory to the that.
847917SReza.Sabdar@Sun.COM */
857917SReza.Sabdar@Sun.COM static void
output_mem(tlm_cmd_t * local_commands,char * mem,int len)867917SReza.Sabdar@Sun.COM output_mem(tlm_cmd_t *local_commands, char *mem,
877917SReza.Sabdar@Sun.COM int len)
887917SReza.Sabdar@Sun.COM {
897917SReza.Sabdar@Sun.COM long actual_size, rec_size;
907917SReza.Sabdar@Sun.COM char *rec;
917917SReza.Sabdar@Sun.COM
927917SReza.Sabdar@Sun.COM while (len > 0) {
937917SReza.Sabdar@Sun.COM rec = get_write_buffer(len, &actual_size,
947917SReza.Sabdar@Sun.COM FALSE, local_commands);
957917SReza.Sabdar@Sun.COM rec_size = min(actual_size, len);
967917SReza.Sabdar@Sun.COM (void) memcpy(rec, mem, rec_size);
977917SReza.Sabdar@Sun.COM mem += rec_size;
987917SReza.Sabdar@Sun.COM len -= rec_size;
997917SReza.Sabdar@Sun.COM }
1007917SReza.Sabdar@Sun.COM }
1017917SReza.Sabdar@Sun.COM
1027917SReza.Sabdar@Sun.COM /*
1037917SReza.Sabdar@Sun.COM * tlm_output_dir
1047917SReza.Sabdar@Sun.COM *
1057917SReza.Sabdar@Sun.COM * Put the directory information into the output buffers.
1067917SReza.Sabdar@Sun.COM */
1077917SReza.Sabdar@Sun.COM int
tlm_output_dir(char * name,tlm_acls_t * tlm_acls,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats)1087917SReza.Sabdar@Sun.COM tlm_output_dir(char *name, tlm_acls_t *tlm_acls,
1097917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
1107917SReza.Sabdar@Sun.COM {
1117917SReza.Sabdar@Sun.COM u_longlong_t pos;
1127917SReza.Sabdar@Sun.COM
1137917SReza.Sabdar@Sun.COM /*
1147917SReza.Sabdar@Sun.COM * Send the node or path history of the directory itself.
1157917SReza.Sabdar@Sun.COM */
1167917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands);
1177917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name);
1187917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos);
1197917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos);
1207917SReza.Sabdar@Sun.COM /* fhdir_cb is handled in ndmpd_tar3.c */
1217917SReza.Sabdar@Sun.COM
1227917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info,
1237917SReza.Sabdar@Sun.COM local_commands);
1247917SReza.Sabdar@Sun.COM (void) output_file_header(name, "", tlm_acls, 0,
1257917SReza.Sabdar@Sun.COM local_commands);
1267917SReza.Sabdar@Sun.COM
1277917SReza.Sabdar@Sun.COM return (0);
1287917SReza.Sabdar@Sun.COM }
1297917SReza.Sabdar@Sun.COM
1307917SReza.Sabdar@Sun.COM /*
1317917SReza.Sabdar@Sun.COM * tar_putdir
1327917SReza.Sabdar@Sun.COM *
1337917SReza.Sabdar@Sun.COM * Main dir backup function for tar
1347917SReza.Sabdar@Sun.COM */
1357917SReza.Sabdar@Sun.COM int
tar_putdir(char * name,tlm_acls_t * tlm_acls,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats)1367917SReza.Sabdar@Sun.COM tar_putdir(char *name, tlm_acls_t *tlm_acls,
1377917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
1387917SReza.Sabdar@Sun.COM {
1397917SReza.Sabdar@Sun.COM int rv;
1407917SReza.Sabdar@Sun.COM
1417917SReza.Sabdar@Sun.COM rv = tlm_output_dir(name, tlm_acls, local_commands, job_stats);
1427917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0);
1437917SReza.Sabdar@Sun.COM }
1447917SReza.Sabdar@Sun.COM
1457917SReza.Sabdar@Sun.COM /*
1467917SReza.Sabdar@Sun.COM * output_acl_header
1477917SReza.Sabdar@Sun.COM *
1487917SReza.Sabdar@Sun.COM * output the ACL header record and data
1497917SReza.Sabdar@Sun.COM */
1507917SReza.Sabdar@Sun.COM static int
output_acl_header(sec_attr_t * acl_info,tlm_cmd_t * local_commands)1517917SReza.Sabdar@Sun.COM output_acl_header(sec_attr_t *acl_info,
1527917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands)
1537917SReza.Sabdar@Sun.COM {
1547917SReza.Sabdar@Sun.COM long actual_size;
1557917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr;
1567917SReza.Sabdar@Sun.COM long acl_size;
1577917SReza.Sabdar@Sun.COM
1587917SReza.Sabdar@Sun.COM if ((acl_info == NULL) || (*acl_info->attr_info == '\0'))
1597917SReza.Sabdar@Sun.COM return (0);
1607917SReza.Sabdar@Sun.COM
1617917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
1627917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
1637917SReza.Sabdar@Sun.COM if (!tar_hdr)
1647917SReza.Sabdar@Sun.COM return (0);
1657917SReza.Sabdar@Sun.COM
1667917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_ACL;
1677917SReza.Sabdar@Sun.COM acl_info->attr_type = UFSD_ACL;
1687917SReza.Sabdar@Sun.COM (void) snprintf(acl_info->attr_len, sizeof (acl_info->attr_len),
1697917SReza.Sabdar@Sun.COM "%06o", strlen(acl_info->attr_info));
1707917SReza.Sabdar@Sun.COM
1717917SReza.Sabdar@Sun.COM acl_size = sizeof (*acl_info);
1727917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, "UFSACL", TLM_NAME_SIZE);
1737917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
1747917SReza.Sabdar@Sun.COM acl_size);
1757917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
1767917SReza.Sabdar@Sun.COM 0444);
1777917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 0);
1787917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 0);
1797917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime),
1807917SReza.Sabdar@Sun.COM "%011o ", 0);
1817917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
1827917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic));
1837917SReza.Sabdar@Sun.COM
1847917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr);
1857917SReza.Sabdar@Sun.COM
1867917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)acl_info, acl_size);
1877917SReza.Sabdar@Sun.COM return (0);
1887917SReza.Sabdar@Sun.COM }
1897917SReza.Sabdar@Sun.COM
1907917SReza.Sabdar@Sun.COM /*
1917917SReza.Sabdar@Sun.COM * output_humongus_header
1927917SReza.Sabdar@Sun.COM *
1937917SReza.Sabdar@Sun.COM * output a special header record for HUGE files
1947917SReza.Sabdar@Sun.COM * output is: 1) a TAR "HUGE" header redord
1957917SReza.Sabdar@Sun.COM * 2) a "file" of size, name
1967917SReza.Sabdar@Sun.COM */
1977917SReza.Sabdar@Sun.COM static int
output_humongus_header(char * fullname,longlong_t file_size,tlm_cmd_t * local_commands)1987917SReza.Sabdar@Sun.COM output_humongus_header(char *fullname, longlong_t file_size,
1997917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands)
2007917SReza.Sabdar@Sun.COM {
2017917SReza.Sabdar@Sun.COM char *buf;
2027917SReza.Sabdar@Sun.COM int len;
2037917SReza.Sabdar@Sun.COM long actual_size;
2047917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr;
2057917SReza.Sabdar@Sun.COM
2067917SReza.Sabdar@Sun.COM /*
2077917SReza.Sabdar@Sun.COM * buf will contain: "%llu %s":
2087917SReza.Sabdar@Sun.COM * - 20 is the maximum length of 'ulong_tlong' decimal notation.
2097917SReza.Sabdar@Sun.COM * - The first '1' is for the ' ' between the "%llu" and the fullname.
2107917SReza.Sabdar@Sun.COM * - The last '1' is for the null-terminator of fullname.
2117917SReza.Sabdar@Sun.COM */
2127917SReza.Sabdar@Sun.COM len = 20 + 1 + strlen(fullname) + 1;
2137917SReza.Sabdar@Sun.COM
2147917SReza.Sabdar@Sun.COM if ((buf = ndmp_malloc(sizeof (char) * len)) == NULL)
2157917SReza.Sabdar@Sun.COM return (-1);
2167917SReza.Sabdar@Sun.COM
2177917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
2187917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
2197917SReza.Sabdar@Sun.COM if (!tar_hdr) {
2207917SReza.Sabdar@Sun.COM free(buf);
2217917SReza.Sabdar@Sun.COM return (0);
2227917SReza.Sabdar@Sun.COM }
2237917SReza.Sabdar@Sun.COM
2247917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_HUMONGUS;
2257917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
2267917SReza.Sabdar@Sun.COM len);
2277917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr);
2287917SReza.Sabdar@Sun.COM (void) snprintf(buf, len, "%lld %s", file_size, fullname);
2297917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, buf, len);
2307917SReza.Sabdar@Sun.COM
2317917SReza.Sabdar@Sun.COM free(buf);
2327917SReza.Sabdar@Sun.COM return (0);
2337917SReza.Sabdar@Sun.COM }
2347917SReza.Sabdar@Sun.COM
2357917SReza.Sabdar@Sun.COM
2367917SReza.Sabdar@Sun.COM /*
2377917SReza.Sabdar@Sun.COM * output_xattr_header
2387917SReza.Sabdar@Sun.COM *
2397917SReza.Sabdar@Sun.COM * output the TAR header record for extended attributes
2407917SReza.Sabdar@Sun.COM */
2417917SReza.Sabdar@Sun.COM static int
output_xattr_header(char * fname,char * aname,int fd,tlm_acls_t * tlm_acls,int section,tlm_cmd_t * local_commands)2427917SReza.Sabdar@Sun.COM output_xattr_header(char *fname, char *aname, int fd,
2437917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands)
2447917SReza.Sabdar@Sun.COM {
2457917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr;
2467917SReza.Sabdar@Sun.COM struct xattr_hdr *xhdr;
2477917SReza.Sabdar@Sun.COM struct xattr_buf *xbuf;
2487917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr;
2497917SReza.Sabdar@Sun.COM long actual_size;
2507917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME);
2517917SReza.Sabdar@Sun.COM int hsize;
2527917SReza.Sabdar@Sun.COM int comlen;
2537917SReza.Sabdar@Sun.COM int namesz;
2547917SReza.Sabdar@Sun.COM
2557917SReza.Sabdar@Sun.COM if (section_name == NULL)
2567917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE);
2577917SReza.Sabdar@Sun.COM
2587917SReza.Sabdar@Sun.COM if (fstat64(fd, attr) == -1) {
2597917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "output_file_header stat failed.");
2607917SReza.Sabdar@Sun.COM free(section_name);
2617917SReza.Sabdar@Sun.COM return (-TLM_OPEN_ERR);
2627917SReza.Sabdar@Sun.COM }
2637917SReza.Sabdar@Sun.COM
2647917SReza.Sabdar@Sun.COM /*
2657917SReza.Sabdar@Sun.COM * if the file has to go out in sections,
2667917SReza.Sabdar@Sun.COM * we must mung the name.
2677917SReza.Sabdar@Sun.COM */
2687917SReza.Sabdar@Sun.COM if (section == 0) {
2697917SReza.Sabdar@Sun.COM (void) snprintf(section_name, TLM_MAX_PATH_NAME,
2707917SReza.Sabdar@Sun.COM "/dev/null/%s.hdr", aname);
2717917SReza.Sabdar@Sun.COM } else {
2727917SReza.Sabdar@Sun.COM (void) snprintf(section_name,
2737917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", aname, section);
2747917SReza.Sabdar@Sun.COM }
2757917SReza.Sabdar@Sun.COM namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */
2767917SReza.Sabdar@Sun.COM hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf);
2777917SReza.Sabdar@Sun.COM comlen = namesz + sizeof (struct xattr_buf);
2787917SReza.Sabdar@Sun.COM
2797917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
2807917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
2817917SReza.Sabdar@Sun.COM if (!tar_hdr) {
2827917SReza.Sabdar@Sun.COM free(section_name);
2837917SReza.Sabdar@Sun.COM return (0);
2847917SReza.Sabdar@Sun.COM }
2857917SReza.Sabdar@Sun.COM
2867917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
2877917SReza.Sabdar@Sun.COM
2887917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_XATTR;
2897917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
2907917SReza.Sabdar@Sun.COM hsize);
2917917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
2927917SReza.Sabdar@Sun.COM attr->st_mode & 07777);
2937917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
2947917SReza.Sabdar@Sun.COM attr->st_uid);
2957917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
2967917SReza.Sabdar@Sun.COM attr->st_gid);
2977917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
2987917SReza.Sabdar@Sun.COM attr->st_mtime);
2997917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
3007917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic));
3017917SReza.Sabdar@Sun.COM
3028540SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d",
3038540SReza.Sabdar@Sun.COM aname, hsize, attr->st_mode & 07777, attr->st_uid, attr->st_gid);
3048540SReza.Sabdar@Sun.COM
3057917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr);
3067917SReza.Sabdar@Sun.COM
3077917SReza.Sabdar@Sun.COM xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE,
3087917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
3097917SReza.Sabdar@Sun.COM if (!xhdr) {
3107917SReza.Sabdar@Sun.COM free(section_name);
3117917SReza.Sabdar@Sun.COM return (0);
3127917SReza.Sabdar@Sun.COM }
3137917SReza.Sabdar@Sun.COM
3147917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s",
3157917SReza.Sabdar@Sun.COM XATTR_ARCH_VERS);
3167917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d",
3177917SReza.Sabdar@Sun.COM sizeof (xhdr->h_size) - 1, hsize);
3187917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len),
3197917SReza.Sabdar@Sun.COM "%0*d", sizeof (xhdr->h_component_len) - 1, comlen);
3207917SReza.Sabdar@Sun.COM (void) snprintf(xhdr->h_link_component_len,
3217917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len), "%0*d",
3227917SReza.Sabdar@Sun.COM sizeof (xhdr->h_link_component_len) - 1, 0);
3237917SReza.Sabdar@Sun.COM
3247917SReza.Sabdar@Sun.COM xbuf = (struct xattr_buf *)(((caddr_t)xhdr) +
3257917SReza.Sabdar@Sun.COM sizeof (struct xattr_hdr));
3267917SReza.Sabdar@Sun.COM (void) snprintf(xbuf->h_namesz, sizeof (xbuf->h_namesz), "%0*d",
3277917SReza.Sabdar@Sun.COM sizeof (xbuf->h_namesz) - 1, namesz);
3287917SReza.Sabdar@Sun.COM
3297917SReza.Sabdar@Sun.COM /* No support for links in extended attributes */
3307917SReza.Sabdar@Sun.COM xbuf->h_typeflag = LF_NORMAL;
3317917SReza.Sabdar@Sun.COM
3327917SReza.Sabdar@Sun.COM (void) strlcpy(xbuf->h_names, fname, TLM_NAME_SIZE);
3337917SReza.Sabdar@Sun.COM (void) strlcpy(&xbuf->h_names[strlen(fname) + 1], aname,
3347917SReza.Sabdar@Sun.COM TLM_NAME_SIZE);
3357917SReza.Sabdar@Sun.COM
3367917SReza.Sabdar@Sun.COM free(section_name);
3377917SReza.Sabdar@Sun.COM return (0);
3387917SReza.Sabdar@Sun.COM }
3397917SReza.Sabdar@Sun.COM
3407917SReza.Sabdar@Sun.COM
3417917SReza.Sabdar@Sun.COM /*
3427917SReza.Sabdar@Sun.COM * output_file_header
3437917SReza.Sabdar@Sun.COM *
3447917SReza.Sabdar@Sun.COM * output the TAR header record
3457917SReza.Sabdar@Sun.COM */
3467917SReza.Sabdar@Sun.COM static int
output_file_header(char * name,char * link,tlm_acls_t * tlm_acls,int section,tlm_cmd_t * local_commands)3477917SReza.Sabdar@Sun.COM output_file_header(char *name, char *link,
3487917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands)
3497917SReza.Sabdar@Sun.COM {
3507917SReza.Sabdar@Sun.COM static longlong_t file_count = 0;
3517917SReza.Sabdar@Sun.COM struct stat64 *attr = &tlm_acls->acl_attr;
3527917SReza.Sabdar@Sun.COM tlm_tar_hdr_t *tar_hdr;
3537917SReza.Sabdar@Sun.COM long actual_size;
3547917SReza.Sabdar@Sun.COM boolean_t long_name = FALSE;
3557917SReza.Sabdar@Sun.COM boolean_t long_link = FALSE;
3567917SReza.Sabdar@Sun.COM char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME);
3577917SReza.Sabdar@Sun.COM int nmlen, lnklen;
3588540SReza.Sabdar@Sun.COM uid_t uid;
3598540SReza.Sabdar@Sun.COM gid_t gid;
3608540SReza.Sabdar@Sun.COM char *uname = "";
3618540SReza.Sabdar@Sun.COM char *gname = "";
3628540SReza.Sabdar@Sun.COM struct passwd *pwd;
3638540SReza.Sabdar@Sun.COM struct group *grp;
3647917SReza.Sabdar@Sun.COM
3657917SReza.Sabdar@Sun.COM if (section_name == NULL)
3667917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE);
3677917SReza.Sabdar@Sun.COM
3687917SReza.Sabdar@Sun.COM /*
3697917SReza.Sabdar@Sun.COM * if the file has to go out in sections,
3707917SReza.Sabdar@Sun.COM * we must mung the name.
3717917SReza.Sabdar@Sun.COM */
3727917SReza.Sabdar@Sun.COM if (section == 0) {
3737917SReza.Sabdar@Sun.COM (void) strlcpy(section_name, name, TLM_MAX_PATH_NAME);
3747917SReza.Sabdar@Sun.COM } else {
3757917SReza.Sabdar@Sun.COM (void) snprintf(section_name,
3767917SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME, "%s.%03d", name, section);
3777917SReza.Sabdar@Sun.COM }
3787917SReza.Sabdar@Sun.COM
3798540SReza.Sabdar@Sun.COM if ((pwd = getpwuid(attr->st_uid)) != NULL)
3808540SReza.Sabdar@Sun.COM uname = pwd->pw_name;
3818540SReza.Sabdar@Sun.COM if ((grp = getgrgid(attr->st_gid)) != NULL)
3828540SReza.Sabdar@Sun.COM gname = grp->gr_name;
3838540SReza.Sabdar@Sun.COM
3848540SReza.Sabdar@Sun.COM if ((ulong_t)(uid = attr->st_uid) > (ulong_t)OCTAL7CHAR)
3858540SReza.Sabdar@Sun.COM uid = UID_NOBODY;
3868540SReza.Sabdar@Sun.COM if ((ulong_t)(gid = attr->st_gid) > (ulong_t)OCTAL7CHAR)
3878540SReza.Sabdar@Sun.COM gid = GID_NOBODY;
3888540SReza.Sabdar@Sun.COM
3897917SReza.Sabdar@Sun.COM nmlen = strlen(section_name);
3907917SReza.Sabdar@Sun.COM if (nmlen >= NAMSIZ) {
3917917SReza.Sabdar@Sun.COM /*
3927917SReza.Sabdar@Sun.COM * file name is too big, it must go out
3937917SReza.Sabdar@Sun.COM * in its own data file
3947917SReza.Sabdar@Sun.COM */
3957917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
3967917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
3977917SReza.Sabdar@Sun.COM if (!tar_hdr) {
3987917SReza.Sabdar@Sun.COM free(section_name);
3997917SReza.Sabdar@Sun.COM return (0);
4007917SReza.Sabdar@Sun.COM }
4017917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name,
4027917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name),
4037917SReza.Sabdar@Sun.COM "%s%08qd.fil",
4047917SReza.Sabdar@Sun.COM LONGNAME_PREFIX,
4057917SReza.Sabdar@Sun.COM file_count++);
4067917SReza.Sabdar@Sun.COM
4077917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGNAME;
4087917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size),
4097917SReza.Sabdar@Sun.COM "%011o ", nmlen);
4107917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode),
4117917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777);
4127917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid),
4138540SReza.Sabdar@Sun.COM "%06o ", uid);
4147917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid),
4158540SReza.Sabdar@Sun.COM "%06o ", gid);
4168540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname),
4178540SReza.Sabdar@Sun.COM "%.31s", uname);
4188540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname),
4198540SReza.Sabdar@Sun.COM "%.31s", gname);
4207917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime),
4217917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime);
4227917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
4237917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic));
4247917SReza.Sabdar@Sun.COM
4257917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr);
4267917SReza.Sabdar@Sun.COM
4277917SReza.Sabdar@Sun.COM (void) output_mem(local_commands,
4287917SReza.Sabdar@Sun.COM (void *)section_name, nmlen);
4297917SReza.Sabdar@Sun.COM long_name = TRUE;
4307917SReza.Sabdar@Sun.COM }
4317917SReza.Sabdar@Sun.COM
4327917SReza.Sabdar@Sun.COM lnklen = strlen(link);
4337917SReza.Sabdar@Sun.COM if (lnklen >= NAMSIZ) {
4347917SReza.Sabdar@Sun.COM /*
4357917SReza.Sabdar@Sun.COM * link name is too big, it must go out
4367917SReza.Sabdar@Sun.COM * in its own data file
4377917SReza.Sabdar@Sun.COM */
4387917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
4397917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
4407917SReza.Sabdar@Sun.COM if (!tar_hdr) {
4417917SReza.Sabdar@Sun.COM free(section_name);
4427917SReza.Sabdar@Sun.COM return (0);
4437917SReza.Sabdar@Sun.COM }
4447917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname,
4457917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name),
4467917SReza.Sabdar@Sun.COM "%s%08qd.slk",
4477917SReza.Sabdar@Sun.COM LONGNAME_PREFIX,
4487917SReza.Sabdar@Sun.COM file_count++);
4497917SReza.Sabdar@Sun.COM
4507917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LONGLINK;
4517917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size),
4527917SReza.Sabdar@Sun.COM "%011o ", lnklen);
4537917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode),
4547917SReza.Sabdar@Sun.COM "%06o ", attr->st_mode & 07777);
4557917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid),
4568540SReza.Sabdar@Sun.COM "%06o ", uid);
4577917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid),
4588540SReza.Sabdar@Sun.COM "%06o ", gid);
4598540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname),
4608540SReza.Sabdar@Sun.COM "%.31s", uname);
4618540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname),
4628540SReza.Sabdar@Sun.COM "%.31s", gname);
4637917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime),
4647917SReza.Sabdar@Sun.COM "%011o ", attr->st_mtime);
4657917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
4667917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic));
4677917SReza.Sabdar@Sun.COM
4687917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr);
4697917SReza.Sabdar@Sun.COM
4707917SReza.Sabdar@Sun.COM (void) output_mem(local_commands, (void *)link,
4717917SReza.Sabdar@Sun.COM lnklen);
4727917SReza.Sabdar@Sun.COM long_link = TRUE;
4737917SReza.Sabdar@Sun.COM }
4747917SReza.Sabdar@Sun.COM tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
4757917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
4767917SReza.Sabdar@Sun.COM if (!tar_hdr) {
4777917SReza.Sabdar@Sun.COM free(section_name);
4787917SReza.Sabdar@Sun.COM return (0);
4797917SReza.Sabdar@Sun.COM }
4807917SReza.Sabdar@Sun.COM if (long_name) {
4817917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_name,
4827917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name),
4837917SReza.Sabdar@Sun.COM "%s%08qd.fil",
4847917SReza.Sabdar@Sun.COM LONGNAME_PREFIX,
4857917SReza.Sabdar@Sun.COM file_count++);
4867917SReza.Sabdar@Sun.COM } else {
4877917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
4887917SReza.Sabdar@Sun.COM }
4897917SReza.Sabdar@Sun.COM
4907917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "long_link: %s [%s]", long_link ? "TRUE" : "FALSE",
4917917SReza.Sabdar@Sun.COM link);
4927917SReza.Sabdar@Sun.COM
4937917SReza.Sabdar@Sun.COM if (long_link) {
4947917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_linkname,
4957917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_name),
4967917SReza.Sabdar@Sun.COM "%s%08qd.slk",
4977917SReza.Sabdar@Sun.COM LONGNAME_PREFIX,
4987917SReza.Sabdar@Sun.COM file_count++);
4997917SReza.Sabdar@Sun.COM } else {
5007917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_linkname, link, TLM_NAME_SIZE);
5017917SReza.Sabdar@Sun.COM }
502*12353SReza.Sabdar@Sun.COM switch (attr->st_mode & S_IFMT) {
503*12353SReza.Sabdar@Sun.COM case S_IFDIR:
5047917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_DIR;
505*12353SReza.Sabdar@Sun.COM break;
506*12353SReza.Sabdar@Sun.COM case S_IFIFO:
5077917SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_FIFO;
508*12353SReza.Sabdar@Sun.COM break;
509*12353SReza.Sabdar@Sun.COM case S_IFBLK:
510*12353SReza.Sabdar@Sun.COM case S_IFCHR:
511*12353SReza.Sabdar@Sun.COM if (S_ISBLK(attr->st_mode))
512*12353SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_BLK;
513*12353SReza.Sabdar@Sun.COM else
514*12353SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_CHR;
515*12353SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_shared.th_dev.th_devmajor,
516*12353SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_shared.th_dev.th_devmajor), "%06o ",
517*12353SReza.Sabdar@Sun.COM major(attr->st_rdev));
518*12353SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_shared.th_dev.th_devminor,
519*12353SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_shared.th_dev.th_devminor), "%06o ",
520*12353SReza.Sabdar@Sun.COM minor(attr->st_rdev));
521*12353SReza.Sabdar@Sun.COM break;
522*12353SReza.Sabdar@Sun.COM default:
523*12353SReza.Sabdar@Sun.COM if (attr->st_nlink > 1) {
524*12353SReza.Sabdar@Sun.COM /* mark file with hardlink LF_LINK */
525*12353SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = LF_LINK;
526*12353SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_shared.th_hlink_ino,
527*12353SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_shared.th_hlink_ino),
528*12353SReza.Sabdar@Sun.COM "%011llo ", attr->st_ino);
529*12353SReza.Sabdar@Sun.COM } else {
530*12353SReza.Sabdar@Sun.COM tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL :
531*12353SReza.Sabdar@Sun.COM LF_SYMLINK;
532*12353SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "linkflag: '%c'",
533*12353SReza.Sabdar@Sun.COM tar_hdr->th_linkflag);
534*12353SReza.Sabdar@Sun.COM }
5357917SReza.Sabdar@Sun.COM }
5367917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
5377917SReza.Sabdar@Sun.COM (long)attr->st_size);
5387917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
5397917SReza.Sabdar@Sun.COM attr->st_mode & 07777);
5407917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
5418540SReza.Sabdar@Sun.COM uid);
5427917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
5438540SReza.Sabdar@Sun.COM gid);
5448540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), "%.31s",
5458540SReza.Sabdar@Sun.COM uname);
5468540SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), "%.31s",
5478540SReza.Sabdar@Sun.COM gname);
5487917SReza.Sabdar@Sun.COM (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
5497917SReza.Sabdar@Sun.COM attr->st_mtime);
5507917SReza.Sabdar@Sun.COM (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
5517917SReza.Sabdar@Sun.COM sizeof (tar_hdr->th_magic));
5527917SReza.Sabdar@Sun.COM
5537917SReza.Sabdar@Sun.COM tlm_build_header_checksum(tar_hdr);
5547917SReza.Sabdar@Sun.COM if (long_name || long_link) {
5557917SReza.Sabdar@Sun.COM if (file_count > 99999990) {
5567917SReza.Sabdar@Sun.COM file_count = 0;
5577917SReza.Sabdar@Sun.COM }
5587917SReza.Sabdar@Sun.COM }
5597917SReza.Sabdar@Sun.COM free(section_name);
5607917SReza.Sabdar@Sun.COM return (0);
5617917SReza.Sabdar@Sun.COM }
5627917SReza.Sabdar@Sun.COM
5637917SReza.Sabdar@Sun.COM
5647917SReza.Sabdar@Sun.COM /*
5657917SReza.Sabdar@Sun.COM * tlm_readlink
5667917SReza.Sabdar@Sun.COM *
5677917SReza.Sabdar@Sun.COM * Read where the softlink points to. Read the link in the checkpointed
5687917SReza.Sabdar@Sun.COM * path if the backup is being done on a checkpointed file system.
5697917SReza.Sabdar@Sun.COM */
5707917SReza.Sabdar@Sun.COM static int
tlm_readlink(char * nm,char * snap,char * buf,int bufsize)5717917SReza.Sabdar@Sun.COM tlm_readlink(char *nm, char *snap, char *buf, int bufsize)
5727917SReza.Sabdar@Sun.COM {
5737917SReza.Sabdar@Sun.COM int len;
5747917SReza.Sabdar@Sun.COM
5757917SReza.Sabdar@Sun.COM if ((len = readlink(snap, buf, bufsize)) >= 0) {
5767917SReza.Sabdar@Sun.COM /*
5777917SReza.Sabdar@Sun.COM * realink(2) doesn't null terminate the link name. We must
5787917SReza.Sabdar@Sun.COM * do it here.
5797917SReza.Sabdar@Sun.COM */
5807917SReza.Sabdar@Sun.COM buf[len] = '\0';
5817917SReza.Sabdar@Sun.COM } else {
5827917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Error %d reading softlink of [%s]",
5837917SReza.Sabdar@Sun.COM errno, nm);
5847917SReza.Sabdar@Sun.COM buf[0] = '\0';
5857917SReza.Sabdar@Sun.COM
5867917SReza.Sabdar@Sun.COM /* Backup the link if the destination missing */
5877917SReza.Sabdar@Sun.COM if (errno == ENOENT)
5887917SReza.Sabdar@Sun.COM return (0);
5897917SReza.Sabdar@Sun.COM
5907917SReza.Sabdar@Sun.COM }
5917917SReza.Sabdar@Sun.COM
5927917SReza.Sabdar@Sun.COM return (len);
5937917SReza.Sabdar@Sun.COM }
5947917SReza.Sabdar@Sun.COM
5958540SReza.Sabdar@Sun.COM /*
5968540SReza.Sabdar@Sun.COM * Read the system attribute file in a single buffer to write
5978540SReza.Sabdar@Sun.COM * it as a single write. A partial write to system attribute would
5988540SReza.Sabdar@Sun.COM * cause an EINVAL on write.
5998540SReza.Sabdar@Sun.COM */
6008540SReza.Sabdar@Sun.COM static char *
get_write_one_buf(char * buf,char * rec,int buf_size,int rec_size,tlm_cmd_t * lc)6018540SReza.Sabdar@Sun.COM get_write_one_buf(char *buf, char *rec, int buf_size, int rec_size,
6028540SReza.Sabdar@Sun.COM tlm_cmd_t *lc)
6038540SReza.Sabdar@Sun.COM {
6048540SReza.Sabdar@Sun.COM int len;
6058540SReza.Sabdar@Sun.COM long write_size;
6068540SReza.Sabdar@Sun.COM
6078540SReza.Sabdar@Sun.COM if (rec_size > buf_size)
6088540SReza.Sabdar@Sun.COM return (rec);
6098540SReza.Sabdar@Sun.COM
6108540SReza.Sabdar@Sun.COM len = rec_size;
6118540SReza.Sabdar@Sun.COM (void) memcpy(rec, buf, len);
6128540SReza.Sabdar@Sun.COM buf += len;
6138540SReza.Sabdar@Sun.COM while (rec_size < buf_size) {
6148540SReza.Sabdar@Sun.COM rec = get_write_buffer(buf_size - rec_size,
6158540SReza.Sabdar@Sun.COM &write_size, FALSE, lc);
6168540SReza.Sabdar@Sun.COM if (!rec)
6178540SReza.Sabdar@Sun.COM return (0);
6188540SReza.Sabdar@Sun.COM
6198540SReza.Sabdar@Sun.COM len = min(buf_size - rec_size, write_size);
6208540SReza.Sabdar@Sun.COM (void) memcpy(rec, buf, len);
6218540SReza.Sabdar@Sun.COM rec_size += len;
6228540SReza.Sabdar@Sun.COM buf += len;
6238540SReza.Sabdar@Sun.COM }
6248540SReza.Sabdar@Sun.COM return (rec);
6258540SReza.Sabdar@Sun.COM }
6268540SReza.Sabdar@Sun.COM
6277917SReza.Sabdar@Sun.COM
6287917SReza.Sabdar@Sun.COM /*
6297917SReza.Sabdar@Sun.COM * tlm_output_xattr
6307917SReza.Sabdar@Sun.COM *
6317917SReza.Sabdar@Sun.COM * Put this file into the output buffers.
6327917SReza.Sabdar@Sun.COM */
6337917SReza.Sabdar@Sun.COM /*ARGSUSED*/
6347917SReza.Sabdar@Sun.COM longlong_t
tlm_output_xattr(char * dir,char * name,char * chkdir,tlm_acls_t * tlm_acls,tlm_commands_t * commands,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats)6357917SReza.Sabdar@Sun.COM tlm_output_xattr(char *dir, char *name, char *chkdir,
6367917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands,
6377917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
6387917SReza.Sabdar@Sun.COM {
6397917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */
6407917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */
6417917SReza.Sabdar@Sun.COM int section; /* section of a huge file */
6427917SReza.Sabdar@Sun.COM int fd;
6439323SReza.Sabdar@Sun.COM int afd = 0;
6447917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */
6457917SReza.Sabdar@Sun.COM /* for Multi Volume record */
6467917SReza.Sabdar@Sun.COM u_longlong_t pos;
6477917SReza.Sabdar@Sun.COM DIR *dp;
6487917SReza.Sabdar@Sun.COM struct dirent *dtp;
6497917SReza.Sabdar@Sun.COM char *attrname;
6507917SReza.Sabdar@Sun.COM char *fnamep;
6517917SReza.Sabdar@Sun.COM int rv = 0;
6527917SReza.Sabdar@Sun.COM
653*12353SReza.Sabdar@Sun.COM if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
6547917SReza.Sabdar@Sun.COM return (TLM_NO_SOURCE_FILE);
6559659SReza.Sabdar@Sun.COM }
6567917SReza.Sabdar@Sun.COM
6577917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
6587917SReza.Sabdar@Sun.COM if (fullname == NULL) {
6597917SReza.Sabdar@Sun.COM free(fullname);
6607917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE);
6617917SReza.Sabdar@Sun.COM }
6627917SReza.Sabdar@Sun.COM
6637917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name)) {
6647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long.");
6657917SReza.Sabdar@Sun.COM free(fullname);
6667917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE);
6677917SReza.Sabdar@Sun.COM }
6687917SReza.Sabdar@Sun.COM
6698540SReza.Sabdar@Sun.COM if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 &&
6708540SReza.Sabdar@Sun.COM sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) {
6717917SReza.Sabdar@Sun.COM free(fullname);
6727917SReza.Sabdar@Sun.COM return (0);
6737917SReza.Sabdar@Sun.COM }
6747917SReza.Sabdar@Sun.COM
6757917SReza.Sabdar@Sun.COM attrname = ndmp_malloc(TLM_MAX_PATH_NAME);
6767917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
6777917SReza.Sabdar@Sun.COM if (attrname == NULL || snapname == NULL) {
6787917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE;
6797917SReza.Sabdar@Sun.COM goto err_out;
6807917SReza.Sabdar@Sun.COM }
6817917SReza.Sabdar@Sun.COM
6827917SReza.Sabdar@Sun.COM if (!tlm_cat_path(snapname, chkdir, name)) {
6837917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long.");
6847917SReza.Sabdar@Sun.COM rv = -TLM_NO_SCRATCH_SPACE;
6857917SReza.Sabdar@Sun.COM goto err_out;
6867917SReza.Sabdar@Sun.COM }
6877917SReza.Sabdar@Sun.COM
6887917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
6897917SReza.Sabdar@Sun.COM
6907917SReza.Sabdar@Sun.COM /*
6917917SReza.Sabdar@Sun.COM * Open the file for reading.
6927917SReza.Sabdar@Sun.COM */
6938540SReza.Sabdar@Sun.COM fd = attropen(fnamep, ".", O_RDONLY);
6947917SReza.Sabdar@Sun.COM if (fd == -1) {
6958540SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s][%s]",
6968540SReza.Sabdar@Sun.COM fullname, fnamep);
6977917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE;
6987917SReza.Sabdar@Sun.COM goto err_out;
6997917SReza.Sabdar@Sun.COM }
7007917SReza.Sabdar@Sun.COM
7017917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands);
7027917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name);
7037917SReza.Sabdar@Sun.COM
7047917SReza.Sabdar@Sun.COM section = 0;
7057917SReza.Sabdar@Sun.COM
7067917SReza.Sabdar@Sun.COM dp = (DIR *)fdopendir(fd);
7077917SReza.Sabdar@Sun.COM if (dp == NULL) {
7087917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname);
7097917SReza.Sabdar@Sun.COM (void) close(fd);
7107917SReza.Sabdar@Sun.COM rv = TLM_NO_SOURCE_FILE;
7117917SReza.Sabdar@Sun.COM goto err_out;
7127917SReza.Sabdar@Sun.COM }
7137917SReza.Sabdar@Sun.COM
7147917SReza.Sabdar@Sun.COM while ((dtp = readdir(dp)) != NULL) {
7157917SReza.Sabdar@Sun.COM int section_size;
7167917SReza.Sabdar@Sun.COM
7177917SReza.Sabdar@Sun.COM if (*dtp->d_name == '.')
7187917SReza.Sabdar@Sun.COM continue;
7197917SReza.Sabdar@Sun.COM
7208540SReza.Sabdar@Sun.COM if (sysattr_rdonly(dtp->d_name))
7218540SReza.Sabdar@Sun.COM continue;
7228540SReza.Sabdar@Sun.COM
7239323SReza.Sabdar@Sun.COM afd = attropen(fnamep, dtp->d_name, O_RDONLY);
7249323SReza.Sabdar@Sun.COM if (afd == -1) {
7257917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
7268540SReza.Sabdar@Sun.COM "problem(%d) opening xattr file [%s][%s]", errno,
7278540SReza.Sabdar@Sun.COM fullname, fnamep);
7287917SReza.Sabdar@Sun.COM goto tear_down;
7297917SReza.Sabdar@Sun.COM }
7307917SReza.Sabdar@Sun.COM
7319323SReza.Sabdar@Sun.COM (void) output_xattr_header(fullname, dtp->d_name, afd,
7327917SReza.Sabdar@Sun.COM tlm_acls, section, local_commands);
7337917SReza.Sabdar@Sun.COM (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s",
7347917SReza.Sabdar@Sun.COM dtp->d_name);
7357917SReza.Sabdar@Sun.COM (void) output_file_header(attrname, "", tlm_acls, 0,
7367917SReza.Sabdar@Sun.COM local_commands);
7377917SReza.Sabdar@Sun.COM
7387917SReza.Sabdar@Sun.COM section_size = (long)llmin(tlm_acls->acl_attr.st_size,
7397917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE);
7407917SReza.Sabdar@Sun.COM
7417917SReza.Sabdar@Sun.COM /* We only can read upto one section extended attribute */
7427917SReza.Sabdar@Sun.COM while (section_size > 0) {
7437917SReza.Sabdar@Sun.COM char *buf;
7447917SReza.Sabdar@Sun.COM long actual_size;
7457917SReza.Sabdar@Sun.COM int read_size;
7468540SReza.Sabdar@Sun.COM int sysattr_read = 0;
7478540SReza.Sabdar@Sun.COM char *rec;
7488540SReza.Sabdar@Sun.COM int size;
7497917SReza.Sabdar@Sun.COM
7507917SReza.Sabdar@Sun.COM /*
7517917SReza.Sabdar@Sun.COM * check for Abort commands
7527917SReza.Sabdar@Sun.COM */
7537917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) {
7547917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT;
7557917SReza.Sabdar@Sun.COM goto tear_down;
7567917SReza.Sabdar@Sun.COM }
7577917SReza.Sabdar@Sun.COM
7587917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[
7597917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].
7607917SReza.Sabdar@Sun.COM tb_file_size = section_size;
7617917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[
7627917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].
7637917SReza.Sabdar@Sun.COM tb_seek_spot = seek_spot;
7647917SReza.Sabdar@Sun.COM
7657917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size,
7667917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands);
7677917SReza.Sabdar@Sun.COM if (!buf)
7687917SReza.Sabdar@Sun.COM goto tear_down;
7697917SReza.Sabdar@Sun.COM
7708540SReza.Sabdar@Sun.COM if ((actual_size < section_size) &&
7718540SReza.Sabdar@Sun.COM sysattr_rw(dtp->d_name)) {
7728540SReza.Sabdar@Sun.COM rec = buf;
7738540SReza.Sabdar@Sun.COM buf = ndmp_malloc(section_size);
7748540SReza.Sabdar@Sun.COM if (!buf)
7758540SReza.Sabdar@Sun.COM goto tear_down;
7768540SReza.Sabdar@Sun.COM size = actual_size;
7778540SReza.Sabdar@Sun.COM actual_size = section_size;
7788540SReza.Sabdar@Sun.COM sysattr_read = 1;
7798540SReza.Sabdar@Sun.COM }
7808540SReza.Sabdar@Sun.COM
7817917SReza.Sabdar@Sun.COM /*
7827917SReza.Sabdar@Sun.COM * check for Abort commands
7837917SReza.Sabdar@Sun.COM */
7847917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) {
7857917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT;
7867917SReza.Sabdar@Sun.COM goto tear_down;
7877917SReza.Sabdar@Sun.COM }
7887917SReza.Sabdar@Sun.COM
7897917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size);
7909323SReza.Sabdar@Sun.COM if ((actual_size = read(afd, buf, read_size)) < 0)
7918540SReza.Sabdar@Sun.COM break;
7928540SReza.Sabdar@Sun.COM
7938540SReza.Sabdar@Sun.COM if (sysattr_read) {
7948540SReza.Sabdar@Sun.COM if (get_write_one_buf(buf, rec, read_size,
7958540SReza.Sabdar@Sun.COM size, local_commands) == 0) {
7968540SReza.Sabdar@Sun.COM free(buf);
7978540SReza.Sabdar@Sun.COM goto tear_down;
7988540SReza.Sabdar@Sun.COM }
7998540SReza.Sabdar@Sun.COM free(buf);
8008540SReza.Sabdar@Sun.COM }
8018540SReza.Sabdar@Sun.COM
8028540SReza.Sabdar@Sun.COM
8037917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size);
8047917SReza.Sabdar@Sun.COM NS_INC(rfile);
8057917SReza.Sabdar@Sun.COM
8067917SReza.Sabdar@Sun.COM if (actual_size == -1) {
8077917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
8087917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]",
8097917SReza.Sabdar@Sun.COM errno, fullname, snapname);
8107917SReza.Sabdar@Sun.COM goto tear_down;
8117917SReza.Sabdar@Sun.COM }
8127917SReza.Sabdar@Sun.COM seek_spot += actual_size;
8137917SReza.Sabdar@Sun.COM section_size -= actual_size;
8147917SReza.Sabdar@Sun.COM }
8159323SReza.Sabdar@Sun.COM (void) close(afd);
8169323SReza.Sabdar@Sun.COM afd = -1;
8177917SReza.Sabdar@Sun.COM }
8187917SReza.Sabdar@Sun.COM
8197917SReza.Sabdar@Sun.COM tear_down:
8207917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[
8217917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
8227917SReza.Sabdar@Sun.COM
8239323SReza.Sabdar@Sun.COM if (afd > 0)
8249323SReza.Sabdar@Sun.COM (void) close(afd);
8259323SReza.Sabdar@Sun.COM
8269323SReza.Sabdar@Sun.COM /* closedir closes fd too */
8277917SReza.Sabdar@Sun.COM (void) closedir(dp);
8287917SReza.Sabdar@Sun.COM
8297917SReza.Sabdar@Sun.COM err_out:
8307917SReza.Sabdar@Sun.COM free(fullname);
8317917SReza.Sabdar@Sun.COM free(attrname);
8327917SReza.Sabdar@Sun.COM free(snapname);
8337917SReza.Sabdar@Sun.COM return (rv);
8347917SReza.Sabdar@Sun.COM }
8357917SReza.Sabdar@Sun.COM
8367917SReza.Sabdar@Sun.COM
8377917SReza.Sabdar@Sun.COM /*
8387917SReza.Sabdar@Sun.COM * tlm_output_file
8397917SReza.Sabdar@Sun.COM *
8407917SReza.Sabdar@Sun.COM * Put this file into the output buffers.
8417917SReza.Sabdar@Sun.COM */
8427917SReza.Sabdar@Sun.COM longlong_t
tlm_output_file(char * dir,char * name,char * chkdir,tlm_acls_t * tlm_acls,tlm_commands_t * commands,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats,struct hardlink_q * hardlink_q)8437917SReza.Sabdar@Sun.COM tlm_output_file(char *dir, char *name, char *chkdir,
8447917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands,
8457917SReza.Sabdar@Sun.COM tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q)
8467917SReza.Sabdar@Sun.COM {
8477917SReza.Sabdar@Sun.COM char *fullname; /* directory + name */
8487917SReza.Sabdar@Sun.COM char *snapname; /* snapshot name */
8497917SReza.Sabdar@Sun.COM char *linkname; /* where this file points */
8507917SReza.Sabdar@Sun.COM int section = 0; /* section of a huge file */
8517917SReza.Sabdar@Sun.COM int fd;
8527917SReza.Sabdar@Sun.COM longlong_t real_size; /* the origional file size */
8537917SReza.Sabdar@Sun.COM longlong_t file_size; /* real size of this file */
8547917SReza.Sabdar@Sun.COM longlong_t seek_spot = 0; /* location in the file */
8557917SReza.Sabdar@Sun.COM /* for Multi Volume record */
8567917SReza.Sabdar@Sun.COM u_longlong_t pos;
8577917SReza.Sabdar@Sun.COM char *fnamep;
8587917SReza.Sabdar@Sun.COM
8597917SReza.Sabdar@Sun.COM /* Indicate whether a file with the same inode has been backed up. */
8607917SReza.Sabdar@Sun.COM int hardlink_done = 0;
8617917SReza.Sabdar@Sun.COM
8627917SReza.Sabdar@Sun.COM /*
8637917SReza.Sabdar@Sun.COM * If a file with the same inode has been backed up, hardlink_pos holds
8647917SReza.Sabdar@Sun.COM * the tape offset of the data record.
8657917SReza.Sabdar@Sun.COM */
8667917SReza.Sabdar@Sun.COM u_longlong_t hardlink_pos = 0;
8677917SReza.Sabdar@Sun.COM
8687917SReza.Sabdar@Sun.COM if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) {
8697917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name);
8707917SReza.Sabdar@Sun.COM return (-TLM_NO_SCRATCH_SPACE);
8717917SReza.Sabdar@Sun.COM }
8727917SReza.Sabdar@Sun.COM
8737917SReza.Sabdar@Sun.COM fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
8747917SReza.Sabdar@Sun.COM linkname = ndmp_malloc(TLM_MAX_PATH_NAME);
8757917SReza.Sabdar@Sun.COM snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
8767917SReza.Sabdar@Sun.COM if (fullname == NULL || linkname == NULL || snapname == NULL) {
8777917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE;
8787917SReza.Sabdar@Sun.COM goto err_out;
8797917SReza.Sabdar@Sun.COM }
8807917SReza.Sabdar@Sun.COM if (!tlm_cat_path(fullname, dir, name) ||
8817917SReza.Sabdar@Sun.COM !tlm_cat_path(snapname, chkdir, name)) {
8827917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Path too long.");
8837917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE;
8847917SReza.Sabdar@Sun.COM goto err_out;
8857917SReza.Sabdar@Sun.COM }
8867917SReza.Sabdar@Sun.COM
8877917SReza.Sabdar@Sun.COM pos = tlm_get_data_offset(local_commands);
8887917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name);
8897917SReza.Sabdar@Sun.COM
890*12353SReza.Sabdar@Sun.COM if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
8919659SReza.Sabdar@Sun.COM if (S_ISLNK(tlm_acls->acl_attr.st_mode)) {
8929659SReza.Sabdar@Sun.COM file_size = tlm_readlink(fullname, snapname, linkname,
8939659SReza.Sabdar@Sun.COM TLM_MAX_PATH_NAME-1);
8949659SReza.Sabdar@Sun.COM if (file_size < 0) {
8959659SReza.Sabdar@Sun.COM real_size = -ENOENT;
8969659SReza.Sabdar@Sun.COM goto err_out;
8979659SReza.Sabdar@Sun.COM }
8987917SReza.Sabdar@Sun.COM }
8997917SReza.Sabdar@Sun.COM
9007917SReza.Sabdar@Sun.COM /*
9017917SReza.Sabdar@Sun.COM * Since soft links can not be read(2), we should only
9027917SReza.Sabdar@Sun.COM * backup the file header.
9037917SReza.Sabdar@Sun.COM */
9047917SReza.Sabdar@Sun.COM (void) output_file_header(fullname,
9057917SReza.Sabdar@Sun.COM linkname,
9067917SReza.Sabdar@Sun.COM tlm_acls,
9077917SReza.Sabdar@Sun.COM section,
9087917SReza.Sabdar@Sun.COM local_commands);
9097917SReza.Sabdar@Sun.COM
9107917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name,
9117917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos);
9127917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname,
9137917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos);
9147917SReza.Sabdar@Sun.COM
9157917SReza.Sabdar@Sun.COM free(fullname);
9167917SReza.Sabdar@Sun.COM free(linkname);
9177917SReza.Sabdar@Sun.COM free(snapname);
9187917SReza.Sabdar@Sun.COM return (0);
9197917SReza.Sabdar@Sun.COM }
9207917SReza.Sabdar@Sun.COM
9217917SReza.Sabdar@Sun.COM fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
9227917SReza.Sabdar@Sun.COM
9237917SReza.Sabdar@Sun.COM /*
9247917SReza.Sabdar@Sun.COM * For hardlink, only read the data if no other link
9257917SReza.Sabdar@Sun.COM * belonging to the same inode has been backed up.
9267917SReza.Sabdar@Sun.COM */
9277917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1) {
9287917SReza.Sabdar@Sun.COM hardlink_done = !hardlink_q_get(hardlink_q,
9297917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL);
9307917SReza.Sabdar@Sun.COM }
9317917SReza.Sabdar@Sun.COM
9327917SReza.Sabdar@Sun.COM if (!hardlink_done) {
9337917SReza.Sabdar@Sun.COM /*
9347917SReza.Sabdar@Sun.COM * Open the file for reading.
9357917SReza.Sabdar@Sun.COM */
9367917SReza.Sabdar@Sun.COM fd = open(fnamep, O_RDONLY);
9377917SReza.Sabdar@Sun.COM if (fd == -1) {
9387917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
9398540SReza.Sabdar@Sun.COM "BACKUP> Can't open file [%s][%s] err(%d)",
9408540SReza.Sabdar@Sun.COM fullname, fnamep, errno);
9417917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SOURCE_FILE;
9427917SReza.Sabdar@Sun.COM goto err_out;
9437917SReza.Sabdar@Sun.COM }
9447917SReza.Sabdar@Sun.COM } else {
9458193SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ",
9467917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_ino, hardlink_pos);
9477917SReza.Sabdar@Sun.COM
9487917SReza.Sabdar@Sun.COM fd = -1;
9497917SReza.Sabdar@Sun.COM }
9507917SReza.Sabdar@Sun.COM
9517917SReza.Sabdar@Sun.COM linkname[0] = 0;
9527917SReza.Sabdar@Sun.COM
9537917SReza.Sabdar@Sun.COM real_size = tlm_acls->acl_attr.st_size;
9547917SReza.Sabdar@Sun.COM (void) output_acl_header(&tlm_acls->acl_info,
9557917SReza.Sabdar@Sun.COM local_commands);
9567917SReza.Sabdar@Sun.COM
9577917SReza.Sabdar@Sun.COM /*
9587917SReza.Sabdar@Sun.COM * section = 0: file is small enough for TAR
9597917SReza.Sabdar@Sun.COM * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks
9607917SReza.Sabdar@Sun.COM * and the file name gets munged
9617917SReza.Sabdar@Sun.COM */
9627917SReza.Sabdar@Sun.COM file_size = real_size;
9637917SReza.Sabdar@Sun.COM if (file_size > TLM_MAX_TAR_IMAGE) {
9647917SReza.Sabdar@Sun.COM if (output_humongus_header(fullname, file_size,
9657917SReza.Sabdar@Sun.COM local_commands) < 0) {
9667917SReza.Sabdar@Sun.COM (void) close(fd);
9677917SReza.Sabdar@Sun.COM real_size = -TLM_NO_SCRATCH_SPACE;
9687917SReza.Sabdar@Sun.COM goto err_out;
9697917SReza.Sabdar@Sun.COM }
9707917SReza.Sabdar@Sun.COM section = 1;
9717917SReza.Sabdar@Sun.COM } else {
9727917SReza.Sabdar@Sun.COM section = 0;
9737917SReza.Sabdar@Sun.COM }
9747917SReza.Sabdar@Sun.COM
9757917SReza.Sabdar@Sun.COM /*
9767917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode
9777917SReza.Sabdar@Sun.COM * has been backed up, only backup an empty record.
9787917SReza.Sabdar@Sun.COM */
9797917SReza.Sabdar@Sun.COM if (hardlink_done)
9807917SReza.Sabdar@Sun.COM file_size = 0;
9817917SReza.Sabdar@Sun.COM
9827917SReza.Sabdar@Sun.COM /*
9837917SReza.Sabdar@Sun.COM * work
9847917SReza.Sabdar@Sun.COM */
9857917SReza.Sabdar@Sun.COM if (file_size == 0) {
9867917SReza.Sabdar@Sun.COM (void) output_file_header(fullname,
9877917SReza.Sabdar@Sun.COM linkname,
9887917SReza.Sabdar@Sun.COM tlm_acls,
9897917SReza.Sabdar@Sun.COM section,
9907917SReza.Sabdar@Sun.COM local_commands);
9917917SReza.Sabdar@Sun.COM /*
9927917SReza.Sabdar@Sun.COM * this can fall right through since zero size files
9937917SReza.Sabdar@Sun.COM * will be skipped by the WHILE loop anyway
9947917SReza.Sabdar@Sun.COM */
9957917SReza.Sabdar@Sun.COM }
9967917SReza.Sabdar@Sun.COM
9977917SReza.Sabdar@Sun.COM while (file_size > 0) {
9987917SReza.Sabdar@Sun.COM int section_size = llmin(file_size,
9997917SReza.Sabdar@Sun.COM (longlong_t)TLM_MAX_TAR_IMAGE);
10007917SReza.Sabdar@Sun.COM
10017917SReza.Sabdar@Sun.COM tlm_acls->acl_attr.st_size = (longlong_t)section_size;
10027917SReza.Sabdar@Sun.COM (void) output_file_header(fullname,
10037917SReza.Sabdar@Sun.COM linkname,
10047917SReza.Sabdar@Sun.COM tlm_acls,
10057917SReza.Sabdar@Sun.COM section,
10067917SReza.Sabdar@Sun.COM local_commands);
10077917SReza.Sabdar@Sun.COM while (section_size > 0) {
10087917SReza.Sabdar@Sun.COM char *buf;
10097917SReza.Sabdar@Sun.COM long actual_size;
10107917SReza.Sabdar@Sun.COM int read_size;
10117917SReza.Sabdar@Sun.COM
10127917SReza.Sabdar@Sun.COM /*
10137917SReza.Sabdar@Sun.COM * check for Abort commands
10147917SReza.Sabdar@Sun.COM */
10157917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) {
10167917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT;
10177917SReza.Sabdar@Sun.COM goto tear_down;
10187917SReza.Sabdar@Sun.COM }
10197917SReza.Sabdar@Sun.COM
10207917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[
10217917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].
10227917SReza.Sabdar@Sun.COM tb_file_size = section_size;
10237917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[
10247917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].
10257917SReza.Sabdar@Sun.COM tb_seek_spot = seek_spot;
10267917SReza.Sabdar@Sun.COM
10277917SReza.Sabdar@Sun.COM buf = get_write_buffer(section_size,
10287917SReza.Sabdar@Sun.COM &actual_size, FALSE, local_commands);
10297917SReza.Sabdar@Sun.COM if (!buf)
10307917SReza.Sabdar@Sun.COM goto tear_down;
10317917SReza.Sabdar@Sun.COM
10327917SReza.Sabdar@Sun.COM /*
10337917SReza.Sabdar@Sun.COM * check for Abort commands
10347917SReza.Sabdar@Sun.COM */
10357917SReza.Sabdar@Sun.COM if (commands->tcs_reader != TLM_BACKUP_RUN) {
10367917SReza.Sabdar@Sun.COM local_commands->tc_writer = TLM_ABORT;
10377917SReza.Sabdar@Sun.COM goto tear_down;
10387917SReza.Sabdar@Sun.COM }
10397917SReza.Sabdar@Sun.COM
10407917SReza.Sabdar@Sun.COM read_size = min(section_size, actual_size);
10417917SReza.Sabdar@Sun.COM actual_size = read(fd, buf, read_size);
10427917SReza.Sabdar@Sun.COM NS_ADD(rdisk, actual_size);
10437917SReza.Sabdar@Sun.COM NS_INC(rfile);
10447917SReza.Sabdar@Sun.COM
10457917SReza.Sabdar@Sun.COM if (actual_size == 0)
10467917SReza.Sabdar@Sun.COM break;
10477917SReza.Sabdar@Sun.COM
10487917SReza.Sabdar@Sun.COM if (actual_size == -1) {
10497917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
10507917SReza.Sabdar@Sun.COM "problem(%d) reading file [%s][%s]",
10517917SReza.Sabdar@Sun.COM errno, fullname, snapname);
10527917SReza.Sabdar@Sun.COM goto tear_down;
10537917SReza.Sabdar@Sun.COM }
10547917SReza.Sabdar@Sun.COM seek_spot += actual_size;
10557917SReza.Sabdar@Sun.COM file_size -= actual_size;
10567917SReza.Sabdar@Sun.COM section_size -= actual_size;
10577917SReza.Sabdar@Sun.COM }
10587917SReza.Sabdar@Sun.COM section++;
10597917SReza.Sabdar@Sun.COM }
10607917SReza.Sabdar@Sun.COM
10617917SReza.Sabdar@Sun.COM /*
10627917SReza.Sabdar@Sun.COM * If data belonging to this hardlink has been backed up, add the link
10637917SReza.Sabdar@Sun.COM * to hardlink queue.
10647917SReza.Sabdar@Sun.COM */
10657917SReza.Sabdar@Sun.COM if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) {
10667917SReza.Sabdar@Sun.COM (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino,
10677917SReza.Sabdar@Sun.COM pos, NULL, 0);
10687917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
10698193SReza.Sabdar@Sun.COM "backed up hardlink file %s, inode = %llu, pos = %llu ",
10707917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, pos);
10717917SReza.Sabdar@Sun.COM }
10727917SReza.Sabdar@Sun.COM
10737917SReza.Sabdar@Sun.COM /*
10747917SReza.Sabdar@Sun.COM * For hardlink, if other link belonging to the same inode has been
10758193SReza.Sabdar@Sun.COM * backed up, no add_node entry should be sent for this link.
10767917SReza.Sabdar@Sun.COM */
10777917SReza.Sabdar@Sun.COM if (hardlink_done) {
10787917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG,
10798193SReza.Sabdar@Sun.COM "backed up hardlink link %s, inode = %llu, pos = %llu ",
10807917SReza.Sabdar@Sun.COM fullname, tlm_acls->acl_attr.st_ino, hardlink_pos);
10817917SReza.Sabdar@Sun.COM } else {
10827917SReza.Sabdar@Sun.COM (void) tlm_log_fhnode(job_stats, dir, name,
10837917SReza.Sabdar@Sun.COM &tlm_acls->acl_attr, pos);
10847917SReza.Sabdar@Sun.COM }
10857917SReza.Sabdar@Sun.COM
10867917SReza.Sabdar@Sun.COM (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr,
10877917SReza.Sabdar@Sun.COM pos);
10887917SReza.Sabdar@Sun.COM
10897917SReza.Sabdar@Sun.COM tear_down:
10907917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer[
10917917SReza.Sabdar@Sun.COM local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
10927917SReza.Sabdar@Sun.COM
10937917SReza.Sabdar@Sun.COM (void) close(fd);
10947917SReza.Sabdar@Sun.COM
10957917SReza.Sabdar@Sun.COM err_out:
10967917SReza.Sabdar@Sun.COM free(fullname);
10977917SReza.Sabdar@Sun.COM free(linkname);
10987917SReza.Sabdar@Sun.COM free(snapname);
10997917SReza.Sabdar@Sun.COM return (real_size);
11007917SReza.Sabdar@Sun.COM }
11017917SReza.Sabdar@Sun.COM
11027917SReza.Sabdar@Sun.COM /*
11037917SReza.Sabdar@Sun.COM * tar_putfile
11047917SReza.Sabdar@Sun.COM *
11057917SReza.Sabdar@Sun.COM * Main file backup function for tar
11067917SReza.Sabdar@Sun.COM */
11077917SReza.Sabdar@Sun.COM int
tar_putfile(char * dir,char * name,char * chkdir,tlm_acls_t * tlm_acls,tlm_commands_t * commands,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats,struct hardlink_q * hardlink_q)11087917SReza.Sabdar@Sun.COM tar_putfile(char *dir, char *name, char *chkdir,
11097917SReza.Sabdar@Sun.COM tlm_acls_t *tlm_acls, tlm_commands_t *commands,
11107917SReza.Sabdar@Sun.COM tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats,
11117917SReza.Sabdar@Sun.COM struct hardlink_q *hardlink_q)
11127917SReza.Sabdar@Sun.COM {
11137917SReza.Sabdar@Sun.COM int rv;
11147917SReza.Sabdar@Sun.COM
11157917SReza.Sabdar@Sun.COM rv = tlm_output_file(dir, name, chkdir, tlm_acls, commands,
11167917SReza.Sabdar@Sun.COM local_commands, job_stats, hardlink_q);
11177917SReza.Sabdar@Sun.COM if (rv < 0)
11187917SReza.Sabdar@Sun.COM return (rv);
11197917SReza.Sabdar@Sun.COM
11207917SReza.Sabdar@Sun.COM rv = tlm_output_xattr(dir, name, chkdir, tlm_acls, commands,
11217917SReza.Sabdar@Sun.COM local_commands, job_stats);
11227917SReza.Sabdar@Sun.COM
11237917SReza.Sabdar@Sun.COM return (rv < 0 ? rv : 0);
11247917SReza.Sabdar@Sun.COM }
11257917SReza.Sabdar@Sun.COM
11267917SReza.Sabdar@Sun.COM /*
11277917SReza.Sabdar@Sun.COM * get_write_buffer
11287917SReza.Sabdar@Sun.COM *
11297917SReza.Sabdar@Sun.COM * a wrapper to tlm_get_write_buffer so that
11307917SReza.Sabdar@Sun.COM * we can cleanly detect ABORT commands
11317917SReza.Sabdar@Sun.COM * without involving the TLM library with
11327917SReza.Sabdar@Sun.COM * our problems.
11337917SReza.Sabdar@Sun.COM */
11347917SReza.Sabdar@Sun.COM static char *
get_write_buffer(long size,long * actual_size,boolean_t zero,tlm_cmd_t * local_commands)11357917SReza.Sabdar@Sun.COM get_write_buffer(long size, long *actual_size,
11367917SReza.Sabdar@Sun.COM boolean_t zero, tlm_cmd_t *local_commands)
11377917SReza.Sabdar@Sun.COM {
11387917SReza.Sabdar@Sun.COM while (local_commands->tc_reader == TLM_BACKUP_RUN) {
11397917SReza.Sabdar@Sun.COM char *rec = tlm_get_write_buffer(size, actual_size,
11407917SReza.Sabdar@Sun.COM local_commands->tc_buffers, zero);
11417917SReza.Sabdar@Sun.COM if (rec != 0) {
11427917SReza.Sabdar@Sun.COM return (rec);
11437917SReza.Sabdar@Sun.COM }
11447917SReza.Sabdar@Sun.COM }
11457917SReza.Sabdar@Sun.COM return (NULL);
11467917SReza.Sabdar@Sun.COM }
11477917SReza.Sabdar@Sun.COM
11487917SReza.Sabdar@Sun.COM #define NDMP_MORE_RECORDS 2
11497917SReza.Sabdar@Sun.COM
11507917SReza.Sabdar@Sun.COM /*
11517917SReza.Sabdar@Sun.COM * write_tar_eof
11527917SReza.Sabdar@Sun.COM *
11537917SReza.Sabdar@Sun.COM * This function is initially written for NDMP support. It appends
11547917SReza.Sabdar@Sun.COM * two tar headers to the tar file, and also N more empty buffers
11557917SReza.Sabdar@Sun.COM * to make sure that the two tar headers will be read as a part of
11567917SReza.Sabdar@Sun.COM * a mover record and don't get locked because of EOM on the mover
11577917SReza.Sabdar@Sun.COM * side.
11587917SReza.Sabdar@Sun.COM */
11597917SReza.Sabdar@Sun.COM void
write_tar_eof(tlm_cmd_t * local_commands)11607917SReza.Sabdar@Sun.COM write_tar_eof(tlm_cmd_t *local_commands)
11617917SReza.Sabdar@Sun.COM {
11627917SReza.Sabdar@Sun.COM int i;
11637917SReza.Sabdar@Sun.COM long actual_size;
11647917SReza.Sabdar@Sun.COM tlm_buffers_t *bufs;
11657917SReza.Sabdar@Sun.COM
11667917SReza.Sabdar@Sun.COM /*
11677917SReza.Sabdar@Sun.COM * output 2 zero filled records,
11687917SReza.Sabdar@Sun.COM * TAR wants this.
11697917SReza.Sabdar@Sun.COM */
11707917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t),
11717917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
11727917SReza.Sabdar@Sun.COM (void) get_write_buffer(sizeof (tlm_tar_hdr_t),
11737917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
11747917SReza.Sabdar@Sun.COM
11757917SReza.Sabdar@Sun.COM /*
11767917SReza.Sabdar@Sun.COM * NDMP: Clear the rest of the buffer and write two more buffers
11777917SReza.Sabdar@Sun.COM * to the tape.
11787917SReza.Sabdar@Sun.COM */
11797917SReza.Sabdar@Sun.COM bufs = local_commands->tc_buffers;
11807917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size,
11817917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
11827917SReza.Sabdar@Sun.COM
11837917SReza.Sabdar@Sun.COM for (i = 0; i < NDMP_MORE_RECORDS &&
11847917SReza.Sabdar@Sun.COM local_commands->tc_reader == TLM_BACKUP_RUN; i++) {
11857917SReza.Sabdar@Sun.COM /*
11867917SReza.Sabdar@Sun.COM * We don't need the return value of get_write_buffer(),
11877917SReza.Sabdar@Sun.COM * since it's already zeroed out if the buffer is returned.
11887917SReza.Sabdar@Sun.COM */
11897917SReza.Sabdar@Sun.COM (void) get_write_buffer(bufs->tbs_data_transfer_size,
11907917SReza.Sabdar@Sun.COM &actual_size, TRUE, local_commands);
11917917SReza.Sabdar@Sun.COM }
11927917SReza.Sabdar@Sun.COM
11937917SReza.Sabdar@Sun.COM bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE;
11947917SReza.Sabdar@Sun.COM tlm_buffer_release_in_buf(bufs);
11957917SReza.Sabdar@Sun.COM }
11967917SReza.Sabdar@Sun.COM
11977917SReza.Sabdar@Sun.COM /*
11987917SReza.Sabdar@Sun.COM * Callback to backup each ZFS property
11997917SReza.Sabdar@Sun.COM */
12007917SReza.Sabdar@Sun.COM static int
zfs_put_prop_cb(int prop,void * pp)12017917SReza.Sabdar@Sun.COM zfs_put_prop_cb(int prop, void *pp)
12027917SReza.Sabdar@Sun.COM {
120311170SReza.Sabdar@Sun.COM ndmp_metadata_handle_t *mhd;
120411170SReza.Sabdar@Sun.COM ndmp_metadata_header_ext_t *mhp;
120511170SReza.Sabdar@Sun.COM ndmp_metadata_property_ext_t *mpp;
120611170SReza.Sabdar@Sun.COM char vbuf[ZFS_MAXPROPLEN];
120711170SReza.Sabdar@Sun.COM char sbuf[ZFS_MAXPROPLEN];
12087917SReza.Sabdar@Sun.COM zprop_source_t stype;
12098800SReza.Sabdar@Sun.COM char *sourcestr;
12107917SReza.Sabdar@Sun.COM
12117917SReza.Sabdar@Sun.COM if (pp == NULL)
12127917SReza.Sabdar@Sun.COM return (ZPROP_INVAL);
12137917SReza.Sabdar@Sun.COM
121411170SReza.Sabdar@Sun.COM mhd = (ndmp_metadata_handle_t *)pp;
121511170SReza.Sabdar@Sun.COM mhp = mhd->ml_xhdr;
121611170SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count];
121710608SReza.Sabdar@Sun.COM
121811170SReza.Sabdar@Sun.COM if (mhp->nh_count * sizeof (ndmp_metadata_property_ext_t) +
121911170SReza.Sabdar@Sun.COM sizeof (ndmp_metadata_header_ext_t) > mhp->nh_total_bytes)
122011170SReza.Sabdar@Sun.COM return (ZPROP_INVAL);
122111170SReza.Sabdar@Sun.COM
122211170SReza.Sabdar@Sun.COM if (zfs_prop_get(mhd->ml_handle, prop, vbuf, sizeof (vbuf),
122311170SReza.Sabdar@Sun.COM &stype, sbuf, sizeof (sbuf), B_TRUE) != 0) {
122411170SReza.Sabdar@Sun.COM mhp->nh_count++;
122510608SReza.Sabdar@Sun.COM return (ZPROP_CONT);
122611170SReza.Sabdar@Sun.COM }
122710608SReza.Sabdar@Sun.COM
122811170SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, zfs_prop_to_name(prop), ZFS_MAXNAMELEN);
122911170SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, vbuf, ZFS_MAXPROPLEN);
12308800SReza.Sabdar@Sun.COM
12318800SReza.Sabdar@Sun.COM switch (stype) {
12328800SReza.Sabdar@Sun.COM case ZPROP_SRC_NONE:
12338800SReza.Sabdar@Sun.COM sourcestr = "none";
12348800SReza.Sabdar@Sun.COM break;
123511170SReza.Sabdar@Sun.COM case ZPROP_SRC_RECEIVED:
123611170SReza.Sabdar@Sun.COM sourcestr = "received";
123711170SReza.Sabdar@Sun.COM break;
12388800SReza.Sabdar@Sun.COM case ZPROP_SRC_LOCAL:
12398800SReza.Sabdar@Sun.COM sourcestr = mhp->nh_dataset;
12408800SReza.Sabdar@Sun.COM break;
12418800SReza.Sabdar@Sun.COM case ZPROP_SRC_TEMPORARY:
12428800SReza.Sabdar@Sun.COM sourcestr = "temporary";
12438800SReza.Sabdar@Sun.COM break;
12448800SReza.Sabdar@Sun.COM case ZPROP_SRC_DEFAULT:
12458800SReza.Sabdar@Sun.COM sourcestr = "default";
12468800SReza.Sabdar@Sun.COM break;
12478800SReza.Sabdar@Sun.COM default:
12488800SReza.Sabdar@Sun.COM sourcestr = sbuf;
12498800SReza.Sabdar@Sun.COM break;
12508800SReza.Sabdar@Sun.COM }
125111170SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, sourcestr, ZFS_MAXPROPLEN);
12527917SReza.Sabdar@Sun.COM
125311170SReza.Sabdar@Sun.COM mhp->nh_count++;
12547917SReza.Sabdar@Sun.COM return (ZPROP_CONT);
12557917SReza.Sabdar@Sun.COM }
12567917SReza.Sabdar@Sun.COM
125711170SReza.Sabdar@Sun.COM /*
125811170SReza.Sabdar@Sun.COM * Callback to backup each ZFS user/group quota
125911170SReza.Sabdar@Sun.COM */
126011170SReza.Sabdar@Sun.COM static int
zfs_put_quota_cb(void * pp,const char * domain,uid_t rid,uint64_t space)126111170SReza.Sabdar@Sun.COM zfs_put_quota_cb(void *pp, const char *domain, uid_t rid, uint64_t space)
126211170SReza.Sabdar@Sun.COM {
126311170SReza.Sabdar@Sun.COM ndmp_metadata_handle_t *mhd;
126411170SReza.Sabdar@Sun.COM ndmp_metadata_header_ext_t *mhp;
126511170SReza.Sabdar@Sun.COM ndmp_metadata_property_ext_t *mpp;
126611170SReza.Sabdar@Sun.COM char *typestr;
126711170SReza.Sabdar@Sun.COM
126811170SReza.Sabdar@Sun.COM if (pp == NULL)
126911170SReza.Sabdar@Sun.COM return (ZPROP_INVAL);
127011170SReza.Sabdar@Sun.COM
127111170SReza.Sabdar@Sun.COM mhd = (ndmp_metadata_handle_t *)pp;
127211170SReza.Sabdar@Sun.COM mhp = mhd->ml_xhdr;
127311170SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count];
127411170SReza.Sabdar@Sun.COM
127511170SReza.Sabdar@Sun.COM if (mhp->nh_count * sizeof (ndmp_metadata_property_ext_t) +
127611170SReza.Sabdar@Sun.COM sizeof (ndmp_metadata_header_ext_t) > mhp->nh_total_bytes)
127711170SReza.Sabdar@Sun.COM return (ZPROP_INVAL);
127811170SReza.Sabdar@Sun.COM
127911170SReza.Sabdar@Sun.COM if (mhd->ml_quota_prop == ZFS_PROP_USERQUOTA)
128011170SReza.Sabdar@Sun.COM typestr = "userquota";
128111170SReza.Sabdar@Sun.COM else
128211170SReza.Sabdar@Sun.COM typestr = "groupquota";
128311170SReza.Sabdar@Sun.COM
128411170SReza.Sabdar@Sun.COM if (domain == NULL || *domain == '\0')
128511170SReza.Sabdar@Sun.COM (void) snprintf(mpp->mp_name, ZFS_MAXNAMELEN, "%s@%llu",
128611170SReza.Sabdar@Sun.COM typestr, (longlong_t)rid);
128711170SReza.Sabdar@Sun.COM else
128811170SReza.Sabdar@Sun.COM (void) snprintf(mpp->mp_name, ZFS_MAXNAMELEN, "%s@%s-%llu",
128911170SReza.Sabdar@Sun.COM typestr, domain, (longlong_t)rid);
129011170SReza.Sabdar@Sun.COM (void) snprintf(mpp->mp_value, ZFS_MAXPROPLEN, "%llu", space);
129111170SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, mhp->nh_dataset, ZFS_MAXPROPLEN);
129211170SReza.Sabdar@Sun.COM
129311170SReza.Sabdar@Sun.COM mhp->nh_count++;
129411170SReza.Sabdar@Sun.COM return (0);
129511170SReza.Sabdar@Sun.COM }
129611170SReza.Sabdar@Sun.COM
129711170SReza.Sabdar@Sun.COM /*
129811170SReza.Sabdar@Sun.COM * Callback to count each ZFS property
129911170SReza.Sabdar@Sun.COM */
130011170SReza.Sabdar@Sun.COM /*ARGSUSED*/
130111170SReza.Sabdar@Sun.COM static int
zfs_count_prop_cb(int prop,void * pp)130211170SReza.Sabdar@Sun.COM zfs_count_prop_cb(int prop, void *pp)
130311170SReza.Sabdar@Sun.COM {
130411170SReza.Sabdar@Sun.COM (*(int *)pp)++;
130511170SReza.Sabdar@Sun.COM return (ZPROP_CONT);
130611170SReza.Sabdar@Sun.COM }
130711170SReza.Sabdar@Sun.COM
130811170SReza.Sabdar@Sun.COM /*
130911170SReza.Sabdar@Sun.COM * Callback to count each ZFS user/group quota
131011170SReza.Sabdar@Sun.COM */
131111170SReza.Sabdar@Sun.COM /*ARGSUSED*/
131211170SReza.Sabdar@Sun.COM static int
zfs_count_quota_cb(void * pp,const char * domain,uid_t rid,uint64_t space)131311170SReza.Sabdar@Sun.COM zfs_count_quota_cb(void *pp, const char *domain, uid_t rid, uint64_t space)
131411170SReza.Sabdar@Sun.COM {
131511170SReza.Sabdar@Sun.COM (*(int *)pp)++;
131611170SReza.Sabdar@Sun.COM return (0);
131711170SReza.Sabdar@Sun.COM }
131811170SReza.Sabdar@Sun.COM
131911170SReza.Sabdar@Sun.COM /*
132011170SReza.Sabdar@Sun.COM * Count the number of ZFS properties and user/group quotas
132111170SReza.Sabdar@Sun.COM */
132211170SReza.Sabdar@Sun.COM int
zfs_get_prop_counts(zfs_handle_t * zhp)132311170SReza.Sabdar@Sun.COM zfs_get_prop_counts(zfs_handle_t *zhp)
132411170SReza.Sabdar@Sun.COM {
132511170SReza.Sabdar@Sun.COM int count = 0;
132611170SReza.Sabdar@Sun.COM nvlist_t *uprops;
132711170SReza.Sabdar@Sun.COM nvpair_t *elp;
132811170SReza.Sabdar@Sun.COM
132911170SReza.Sabdar@Sun.COM if (zhp == NULL)
133011170SReza.Sabdar@Sun.COM return (0);
133111170SReza.Sabdar@Sun.COM
133211170SReza.Sabdar@Sun.COM (void) zprop_iter(zfs_count_prop_cb, &count, TRUE, TRUE,
133311170SReza.Sabdar@Sun.COM ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET);
133411170SReza.Sabdar@Sun.COM
133511170SReza.Sabdar@Sun.COM (void) zfs_userspace(zhp, ZFS_PROP_USERQUOTA, zfs_count_quota_cb,
133611170SReza.Sabdar@Sun.COM &count);
133711170SReza.Sabdar@Sun.COM (void) zfs_userspace(zhp, ZFS_PROP_GROUPQUOTA, zfs_count_quota_cb,
133811170SReza.Sabdar@Sun.COM &count);
133911170SReza.Sabdar@Sun.COM
134011170SReza.Sabdar@Sun.COM uprops = zfs_get_user_props(zhp);
134111170SReza.Sabdar@Sun.COM
134211170SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, NULL);
134311170SReza.Sabdar@Sun.COM for (; elp != NULL; elp = nvlist_next_nvpair(uprops, elp))
134411170SReza.Sabdar@Sun.COM count++;
134511170SReza.Sabdar@Sun.COM
134611170SReza.Sabdar@Sun.COM return (count);
134711170SReza.Sabdar@Sun.COM }
13487917SReza.Sabdar@Sun.COM
13497917SReza.Sabdar@Sun.COM /*
13507917SReza.Sabdar@Sun.COM * Notifies ndmpd that the metadata associated with the given ZFS dataset
13517917SReza.Sabdar@Sun.COM * should be backed up.
13527917SReza.Sabdar@Sun.COM */
13537917SReza.Sabdar@Sun.COM int
ndmp_include_zfs(ndmp_context_t * nctx,const char * dataset)13547917SReza.Sabdar@Sun.COM ndmp_include_zfs(ndmp_context_t *nctx, const char *dataset)
13557917SReza.Sabdar@Sun.COM {
13567917SReza.Sabdar@Sun.COM tlm_commands_t *cmds;
135711170SReza.Sabdar@Sun.COM ndmp_metadata_handle_t mhd;
135811170SReza.Sabdar@Sun.COM ndmp_metadata_header_ext_t *mhp;
135911170SReza.Sabdar@Sun.COM ndmp_metadata_property_ext_t *mpp;
136011170SReza.Sabdar@Sun.COM zfs_handle_t *zhp;
13617917SReza.Sabdar@Sun.COM tlm_cmd_t *lcmd;
13627917SReza.Sabdar@Sun.COM long actual_size;
13637917SReza.Sabdar@Sun.COM nvlist_t *uprops, *ulist;
13647917SReza.Sabdar@Sun.COM const char *pname;
13657917SReza.Sabdar@Sun.COM nvpair_t *elp;
13667917SReza.Sabdar@Sun.COM char *sval, *ssrc;
13677917SReza.Sabdar@Sun.COM char *wbuf, *pp, *tp;
13687917SReza.Sabdar@Sun.COM long size, lsize, sz;
13697917SReza.Sabdar@Sun.COM int align = RECORDSIZE - 1;
137011170SReza.Sabdar@Sun.COM int pcount;
13717917SReza.Sabdar@Sun.COM
13727917SReza.Sabdar@Sun.COM if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
13737917SReza.Sabdar@Sun.COM return (-1);
13747917SReza.Sabdar@Sun.COM
13757917SReza.Sabdar@Sun.COM if ((lcmd = cmds->tcs_command) == NULL ||
13767917SReza.Sabdar@Sun.COM lcmd->tc_buffers == NULL)
13777917SReza.Sabdar@Sun.COM return (-1);
13787917SReza.Sabdar@Sun.COM
137911170SReza.Sabdar@Sun.COM (void) mutex_lock(&zlib_mtx);
138011170SReza.Sabdar@Sun.COM if ((zhp = zfs_open(zlibh, dataset, ZFS_TYPE_DATASET)) == NULL) {
138111170SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
138211170SReza.Sabdar@Sun.COM return (-1);
138311170SReza.Sabdar@Sun.COM }
138411170SReza.Sabdar@Sun.COM
138511170SReza.Sabdar@Sun.COM pcount = zfs_get_prop_counts(zhp);
138611170SReza.Sabdar@Sun.COM size = sizeof (ndmp_metadata_header_ext_t) +
138711170SReza.Sabdar@Sun.COM pcount * sizeof (ndmp_metadata_property_ext_t);
138811170SReza.Sabdar@Sun.COM
13897917SReza.Sabdar@Sun.COM size += align;
13907917SReza.Sabdar@Sun.COM size &= ~align;
13917917SReza.Sabdar@Sun.COM
139211170SReza.Sabdar@Sun.COM if ((mhp = malloc(size)) == NULL) {
139311170SReza.Sabdar@Sun.COM zfs_close(zhp);
139411170SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
13957917SReza.Sabdar@Sun.COM return (-1);
139611170SReza.Sabdar@Sun.COM }
139711170SReza.Sabdar@Sun.COM
13987917SReza.Sabdar@Sun.COM (void) memset(mhp, 0, size);
13997917SReza.Sabdar@Sun.COM
140011170SReza.Sabdar@Sun.COM mhd.ml_handle = zhp;
140111170SReza.Sabdar@Sun.COM mhd.ml_xhdr = mhp;
140211170SReza.Sabdar@Sun.COM mhp->nh_total_bytes = size;
140311170SReza.Sabdar@Sun.COM mhp->nh_major = META_HDR_MAJOR_VERSION;
140411170SReza.Sabdar@Sun.COM mhp->nh_minor = META_HDR_MINOR_VERSION;
14057917SReza.Sabdar@Sun.COM mhp->nh_plversion = nctx->nc_plversion;
140611170SReza.Sabdar@Sun.COM
14077917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_plname, nctx->nc_plname,
14087917SReza.Sabdar@Sun.COM sizeof (mhp->nh_plname));
140911170SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_magic, ZFS_META_MAGIC_EXT,
141011170SReza.Sabdar@Sun.COM sizeof (mhp->nh_magic));
14117917SReza.Sabdar@Sun.COM (void) strlcpy(mhp->nh_dataset, dataset, sizeof (mhp->nh_dataset));
14127917SReza.Sabdar@Sun.COM
14137917SReza.Sabdar@Sun.COM /* Get all the ZFS properties */
141411170SReza.Sabdar@Sun.COM (void) zprop_iter(zfs_put_prop_cb, &mhd, TRUE, TRUE,
14157917SReza.Sabdar@Sun.COM ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET);
14167917SReza.Sabdar@Sun.COM
14177917SReza.Sabdar@Sun.COM /* Get user properties */
141811170SReza.Sabdar@Sun.COM uprops = zfs_get_user_props(mhd.ml_handle);
14197917SReza.Sabdar@Sun.COM
14207917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, NULL);
14217917SReza.Sabdar@Sun.COM
14227917SReza.Sabdar@Sun.COM while (elp != NULL) {
14237917SReza.Sabdar@Sun.COM mpp = &mhp->nh_property[mhp->nh_count];
14247917SReza.Sabdar@Sun.COM if (nvpair_value_nvlist(elp, &ulist) != 0 ||
14257917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_VALUE, &sval) != 0 ||
14267917SReza.Sabdar@Sun.COM nvlist_lookup_string(ulist, ZPROP_SOURCE, &ssrc) != 0) {
142711170SReza.Sabdar@Sun.COM zfs_close(mhd.ml_handle);
142810260SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
14297917SReza.Sabdar@Sun.COM free(mhp);
14307917SReza.Sabdar@Sun.COM return (-1);
14317917SReza.Sabdar@Sun.COM }
14327917SReza.Sabdar@Sun.COM if ((pname = nvpair_name(elp)) != NULL)
143311170SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_name, pname, ZFS_MAXNAMELEN);
14347917SReza.Sabdar@Sun.COM
143511170SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_value, sval, ZFS_MAXPROPLEN);
143611170SReza.Sabdar@Sun.COM (void) strlcpy(mpp->mp_source, ssrc, ZFS_MAXPROPLEN);
14377917SReza.Sabdar@Sun.COM mhp->nh_count++;
14387917SReza.Sabdar@Sun.COM elp = nvlist_next_nvpair(uprops, elp);
14397917SReza.Sabdar@Sun.COM }
14407917SReza.Sabdar@Sun.COM
144111170SReza.Sabdar@Sun.COM mhd.ml_quota_prop = ZFS_PROP_USERQUOTA;
144211170SReza.Sabdar@Sun.COM (void) zfs_userspace(mhd.ml_handle, ZFS_PROP_USERQUOTA,
144311170SReza.Sabdar@Sun.COM zfs_put_quota_cb, &mhd);
144411170SReza.Sabdar@Sun.COM mhd.ml_quota_prop = ZFS_PROP_GROUPQUOTA;
144511170SReza.Sabdar@Sun.COM (void) zfs_userspace(mhd.ml_handle, ZFS_PROP_GROUPQUOTA,
144611170SReza.Sabdar@Sun.COM zfs_put_quota_cb, &mhd);
144711170SReza.Sabdar@Sun.COM mhp->nh_count = pcount;
144811170SReza.Sabdar@Sun.COM
144911170SReza.Sabdar@Sun.COM zfs_close(mhd.ml_handle);
145010260SReza.Sabdar@Sun.COM (void) mutex_unlock(&zlib_mtx);
14517917SReza.Sabdar@Sun.COM
14527917SReza.Sabdar@Sun.COM if ((wbuf = get_write_buffer(size, &actual_size, TRUE,
14537917SReza.Sabdar@Sun.COM lcmd)) != NULL) {
14547917SReza.Sabdar@Sun.COM pp = (char *)mhp;
14557917SReza.Sabdar@Sun.COM
14567917SReza.Sabdar@Sun.COM (void) memcpy(wbuf, pp, (actual_size < size) ?
14577917SReza.Sabdar@Sun.COM actual_size : size);
14587917SReza.Sabdar@Sun.COM pp += (actual_size < size) ? actual_size : size;
14597917SReza.Sabdar@Sun.COM
14607917SReza.Sabdar@Sun.COM sz = actual_size;
14617917SReza.Sabdar@Sun.COM while (sz < size &&
14627917SReza.Sabdar@Sun.COM ((tp = get_write_buffer(size - sz, &lsize,
14637917SReza.Sabdar@Sun.COM TRUE, lcmd))) != NULL) {
146411170SReza.Sabdar@Sun.COM (void) memcpy(tp, pp, lsize);
14657917SReza.Sabdar@Sun.COM sz += lsize;
14667917SReza.Sabdar@Sun.COM pp += lsize;
14677917SReza.Sabdar@Sun.COM }
14687917SReza.Sabdar@Sun.COM if (sz > size) {
14697917SReza.Sabdar@Sun.COM tlm_unget_write_buffer(lcmd->tc_buffers, sz - size);
14707917SReza.Sabdar@Sun.COM }
14717917SReza.Sabdar@Sun.COM }
14727917SReza.Sabdar@Sun.COM
14737917SReza.Sabdar@Sun.COM free(mhp);
14747917SReza.Sabdar@Sun.COM return (0);
14757917SReza.Sabdar@Sun.COM }
1476