12654012fSReza Sabdar /* 2*5181c2afSReza Sabdar * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 32654012fSReza Sabdar */ 42654012fSReza Sabdar 52654012fSReza Sabdar /* 62654012fSReza Sabdar * BSD 3 Clause License 72654012fSReza Sabdar * 82654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 92654012fSReza Sabdar * 102654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 112654012fSReza Sabdar * modification, are permitted provided that the following conditions 122654012fSReza Sabdar * are met: 132654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 142654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 152654012fSReza Sabdar * 162654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 172654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 182654012fSReza Sabdar * the documentation and/or other materials provided with the 192654012fSReza Sabdar * distribution. 202654012fSReza Sabdar * 212654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 222654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 232654012fSReza Sabdar * products derived from this software without specific prior written 242654012fSReza Sabdar * permission. 252654012fSReza Sabdar * 262654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 272654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 282654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 292654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 302654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 312654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 322654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 332654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 342654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 352654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 362654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 372654012fSReza Sabdar */ 382654012fSReza Sabdar #include <stdlib.h> 392654012fSReza Sabdar #include <ctype.h> 402654012fSReza Sabdar #include <stdio.h> 412654012fSReza Sabdar #include <limits.h> 422654012fSReza Sabdar #include <string.h> 432654012fSReza Sabdar #include <time.h> 442654012fSReza Sabdar #include <sys/types.h> 452654012fSReza Sabdar #include <sys/acl.h> 46*5181c2afSReza Sabdar #include <sys/mkdev.h> 472654012fSReza Sabdar #include <utime.h> 482654012fSReza Sabdar #include <unistd.h> 492654012fSReza Sabdar #include <pthread.h> 502654012fSReza Sabdar #include <archives.h> 512654012fSReza Sabdar #include <priv.h> 522654012fSReza Sabdar #include <tlm.h> 532654012fSReza Sabdar #include <libzfs.h> 54b6b15642SReza Sabdar #include <pwd.h> 55b6b15642SReza Sabdar #include <grp.h> 562654012fSReza Sabdar #include <ndmpd_prop.h> 572654012fSReza Sabdar #include "tlm_proto.h" 582654012fSReza Sabdar 592654012fSReza Sabdar 602654012fSReza Sabdar #define PM_EXACT_OR_CHILD(m) ((m) == PM_EXACT || (m) == PM_CHILD) 612654012fSReza Sabdar 622654012fSReza Sabdar typedef boolean_t name_match_fp_t(char *s, char *t); 632654012fSReza Sabdar 642654012fSReza Sabdar static void set_acl(char *name, 652654012fSReza Sabdar tlm_acls_t *acls); 662654012fSReza Sabdar static long restore_file(int *fp, 672654012fSReza Sabdar char *real_name, 682654012fSReza Sabdar long size, 692654012fSReza Sabdar longlong_t huge_size, 702654012fSReza Sabdar tlm_acls_t *, 712654012fSReza Sabdar boolean_t want_this_file, 722654012fSReza Sabdar tlm_cmd_t *, 732654012fSReza Sabdar tlm_job_stats_t *); 742654012fSReza Sabdar static long restore_xattr_hdr(int *fp, 752654012fSReza Sabdar char *name, 762654012fSReza Sabdar char *fname, 772654012fSReza Sabdar long size, 782654012fSReza Sabdar tlm_acls_t *acls, 792654012fSReza Sabdar tlm_cmd_t *local_commands, 802654012fSReza Sabdar tlm_job_stats_t *job_stats); 812654012fSReza Sabdar static int get_long_name(int lib, 822654012fSReza Sabdar int drv, 832654012fSReza Sabdar long recsize, 842654012fSReza Sabdar char *name, 852654012fSReza Sabdar long *buf_spot, 862654012fSReza Sabdar tlm_cmd_t *local_commands); 872654012fSReza Sabdar static int get_humongus_file_header(int lib, 882654012fSReza Sabdar int drv, 892654012fSReza Sabdar long recsize, 902654012fSReza Sabdar longlong_t *size, 912654012fSReza Sabdar char *name, 922654012fSReza Sabdar tlm_cmd_t *); 932654012fSReza Sabdar static int create_directory(char *dir, 942654012fSReza Sabdar tlm_job_stats_t *); 952654012fSReza Sabdar static int create_hard_link(char *name, 962654012fSReza Sabdar char *link, 972654012fSReza Sabdar tlm_acls_t *, 982654012fSReza Sabdar tlm_job_stats_t *); 992654012fSReza Sabdar static int create_sym_link(char *dst, 1002654012fSReza Sabdar char *target, 1012654012fSReza Sabdar tlm_acls_t *, 1022654012fSReza Sabdar tlm_job_stats_t *); 103*5181c2afSReza Sabdar static int create_special(char, 104*5181c2afSReza Sabdar char *name, 105*5181c2afSReza Sabdar tlm_acls_t *, 106*5181c2afSReza Sabdar int, 107*5181c2afSReza Sabdar int, 108*5181c2afSReza Sabdar tlm_job_stats_t *); 1092654012fSReza Sabdar static long load_acl_info(int lib, 1102654012fSReza Sabdar int drv, 1112654012fSReza Sabdar long size, 1122654012fSReza Sabdar tlm_acls_t *, 1132654012fSReza Sabdar long *acl_spot, 1142654012fSReza Sabdar tlm_cmd_t *); 1152654012fSReza Sabdar static char *get_read_buffer(int want, 1162654012fSReza Sabdar int *error, 1172654012fSReza Sabdar int *actual_size, 1182654012fSReza Sabdar tlm_cmd_t *); 1192654012fSReza Sabdar static boolean_t wildcard_enabled(void); 1202654012fSReza Sabdar static boolean_t is_file_wanted(char *name, 1212654012fSReza Sabdar char **sels, 1222654012fSReza Sabdar char **exls, 1232654012fSReza Sabdar int flags, 1242654012fSReza Sabdar int *mchtype, 1252654012fSReza Sabdar int *pos); 1262654012fSReza Sabdar static char *catnames(struct rs_name_maker *rnp, 1272654012fSReza Sabdar char *buf, 1282654012fSReza Sabdar int pos, 1292654012fSReza Sabdar char *path); 1302654012fSReza Sabdar 1312654012fSReza Sabdar static char *rs_new_name(struct rs_name_maker *rnp, 1322654012fSReza Sabdar char *real_name, 1332654012fSReza Sabdar int pos, 1342654012fSReza Sabdar char *path); 1352654012fSReza Sabdar 136fb4eb4e8SReza Sabdar static void rs_create_new_bkpath(char *bk_path, 137fb4eb4e8SReza Sabdar char *path, 138fb4eb4e8SReza Sabdar char *pbuf); 139fb4eb4e8SReza Sabdar 1402654012fSReza Sabdar typedef struct stack_ent { 1412654012fSReza Sabdar char *se_name; 1422654012fSReza Sabdar tlm_acls_t se_acls; 1432654012fSReza Sabdar } stack_ent_t; 1442654012fSReza Sabdar 1452654012fSReza Sabdar 1462654012fSReza Sabdar /* 1472654012fSReza Sabdar * dtree_push 1482654012fSReza Sabdar */ 1492654012fSReza Sabdar int 1502654012fSReza Sabdar dtree_push(cstack_t *stp, char *nmp, tlm_acls_t *acls) 1512654012fSReza Sabdar { 1522654012fSReza Sabdar int len; 1532654012fSReza Sabdar stack_ent_t *sp; 1542654012fSReza Sabdar 1552654012fSReza Sabdar sp = ndmp_malloc(sizeof (stack_ent_t)); 1562654012fSReza Sabdar if (!sp || !nmp || !acls) { 1572654012fSReza Sabdar free(sp); 1582654012fSReza Sabdar return (-1); 1592654012fSReza Sabdar } 1602654012fSReza Sabdar 1612654012fSReza Sabdar len = strlen(nmp) + 1; 1622654012fSReza Sabdar sp->se_name = ndmp_malloc(len); 1632654012fSReza Sabdar if (!sp->se_name) { 1642654012fSReza Sabdar free(sp); 1652654012fSReza Sabdar return (-1); 1662654012fSReza Sabdar } 1672654012fSReza Sabdar 1682654012fSReza Sabdar (void) strlcpy(sp->se_name, nmp, len); 1692654012fSReza Sabdar (void) memcpy(&sp->se_acls, acls, sizeof (*acls)); 17086c48bbfSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 1712654012fSReza Sabdar 1722654012fSReza Sabdar return (cstack_push(stp, (void *)sp, sizeof (*sp))); 1732654012fSReza Sabdar } 1742654012fSReza Sabdar 1752654012fSReza Sabdar /* 1762654012fSReza Sabdar * dtree_pop 1772654012fSReza Sabdar */ 1782654012fSReza Sabdar int 1792654012fSReza Sabdar dtree_pop(cstack_t *stp) 1802654012fSReza Sabdar { 1812654012fSReza Sabdar int err; 1822654012fSReza Sabdar stack_ent_t *sp; 1832654012fSReza Sabdar 1842654012fSReza Sabdar err = cstack_pop(stp, (void **)&sp, (void *)NULL); 1852654012fSReza Sabdar if (err) 1862654012fSReza Sabdar return (-1); 1872654012fSReza Sabdar 1882654012fSReza Sabdar set_acl(sp->se_name, &sp->se_acls); 1892654012fSReza Sabdar 1902654012fSReza Sabdar free(sp->se_name); 1912654012fSReza Sabdar free(sp); 1922654012fSReza Sabdar return (err); 1932654012fSReza Sabdar } 1942654012fSReza Sabdar 1952654012fSReza Sabdar 1962654012fSReza Sabdar /* 1972654012fSReza Sabdar * dtree_peek 1982654012fSReza Sabdar */ 1992654012fSReza Sabdar char * 2002654012fSReza Sabdar dtree_peek(cstack_t *stp) 2012654012fSReza Sabdar { 2022654012fSReza Sabdar int err; 2032654012fSReza Sabdar stack_ent_t *sp; 2042654012fSReza Sabdar 2052654012fSReza Sabdar err = cstack_top(stp, (void **)&sp, (void *)NULL); 2062654012fSReza Sabdar if (err) 2072654012fSReza Sabdar return (NULL); 2082654012fSReza Sabdar 2092654012fSReza Sabdar return (sp->se_name); 2102654012fSReza Sabdar } 2112654012fSReza Sabdar 2122654012fSReza Sabdar /* 2132654012fSReza Sabdar * NBU and EBS may not send us the correct file list containing hardlinks 2142654012fSReza Sabdar * during a DAR restore, e.g. they appear always send the first name 2152654012fSReza Sabdar * associated with an inode, even if other link names were 2162654012fSReza Sabdar * selected for the restore. As a workaround, we use the file name entry 2172654012fSReza Sabdar * in sels[] (ignore the name in the tar header) as restore target. 2182654012fSReza Sabdar */ 2192654012fSReza Sabdar static char * 2202654012fSReza Sabdar rs_darhl_new_name(struct rs_name_maker *rnp, char *name, char **sels, int *pos, 2212654012fSReza Sabdar char *longname) 2222654012fSReza Sabdar { 2232654012fSReza Sabdar int x; 2242654012fSReza Sabdar 2252654012fSReza Sabdar for (x = 0; sels[x] != NULL; x++) { 2262654012fSReza Sabdar if (strcmp(sels[x], " ")) { 2272654012fSReza Sabdar *pos = x; 2282654012fSReza Sabdar (void) strlcpy(longname, sels[x], TLM_MAX_PATH_NAME); 2292654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 2302654012fSReza Sabdar "to replace hardlink name [%s], pos [%d]", 2312654012fSReza Sabdar longname, *pos); 2322654012fSReza Sabdar 2332654012fSReza Sabdar return (rs_new_name(rnp, name, *pos, longname)); 2342654012fSReza Sabdar } 2352654012fSReza Sabdar } 2362654012fSReza Sabdar 2372654012fSReza Sabdar return (NULL); 2382654012fSReza Sabdar } 2392654012fSReza Sabdar 2402654012fSReza Sabdar 2412654012fSReza Sabdar /* 242859b7745SReza Sabdar * Main dir restore function for tar 2432654012fSReza Sabdar */ 2442654012fSReza Sabdar int 2452654012fSReza Sabdar tar_getdir(tlm_commands_t *commands, 2462654012fSReza Sabdar tlm_cmd_t *local_commands, 2472654012fSReza Sabdar tlm_job_stats_t *job_stats, 2482654012fSReza Sabdar struct rs_name_maker *rnp, 2492654012fSReza Sabdar int lib, 2502654012fSReza Sabdar int drv, 2512654012fSReza Sabdar char **sels, /* what to get off the tape */ 2522654012fSReza Sabdar char **exls, /* what to leave behind */ 2532654012fSReza Sabdar int flags, 254fb4eb4e8SReza Sabdar int DAR, 255fb4eb4e8SReza Sabdar char *bk_path, 256fb4eb4e8SReza Sabdar struct hardlink_q *hardlink_q) 2572654012fSReza Sabdar { 2582654012fSReza Sabdar int fp = 0; /* file being restored ... */ 2592654012fSReza Sabdar /* ...need to preserve across volume changes */ 2602654012fSReza Sabdar tlm_acls_t *acls; /* file access info */ 2612654012fSReza Sabdar char *longname; 2622654012fSReza Sabdar boolean_t is_long_name = FALSE; 2632654012fSReza Sabdar char *longlink; 2642654012fSReza Sabdar char *hugename; 2652654012fSReza Sabdar longlong_t huge_size = 0; /* size of a HUGE file */ 2662654012fSReza Sabdar long acl_spot; /* any ACL info on the next volume */ 2672654012fSReza Sabdar long file_size; /* size of file to restore */ 2682654012fSReza Sabdar long size_left = 0; /* need this after volume change */ 2692654012fSReza Sabdar int last_action = 0; /* what we are doing at EOT */ 2702654012fSReza Sabdar boolean_t multi_volume = FALSE; /* is this a multi-volume switch ? */ 2712654012fSReza Sabdar int chk_rv; /* scratch area */ 2722654012fSReza Sabdar 2732654012fSReza Sabdar int mchtype, pos; 2742654012fSReza Sabdar /* 2752654012fSReza Sabdar * if an exact match is found for 2762654012fSReza Sabdar * restore and its position in the 2772654012fSReza Sabdar * selections list 2782654012fSReza Sabdar */ 2792654012fSReza Sabdar int nzerohdr; /* the number of empty tar headers */ 2802654012fSReza Sabdar boolean_t break_flg; /* exit the while loop */ 2812654012fSReza Sabdar int rv; 2822654012fSReza Sabdar long nm_end, lnk_end; 2832654012fSReza Sabdar char *name, *nmp; 2842654012fSReza Sabdar cstack_t *stp; 2852654012fSReza Sabdar char *bkpath; 2862654012fSReza Sabdar char *parentlnk; 287c9fd6b31SReza Sabdar int dir_dar = 0; 288c9fd6b31SReza Sabdar 2892654012fSReza Sabdar /* 2902654012fSReza Sabdar * The directory where temporary files may be created during a partial 2912654012fSReza Sabdar * non-DAR restore of hardlinks. It is intended to be initialized by 2922654012fSReza Sabdar * an environment variable that can be set by user. 2932654012fSReza Sabdar * 2942654012fSReza Sabdar * It is not initialized for now. We keep it here for future use. 2952654012fSReza Sabdar */ 2962654012fSReza Sabdar char *tmplink_dir = NULL; 297b6b15642SReza Sabdar int dar_recovered = 0; 298fb4eb4e8SReza Sabdar char *thname_buf; 2992654012fSReza Sabdar 3002654012fSReza Sabdar /* 3012654012fSReza Sabdar * startup 3022654012fSReza Sabdar */ 3032654012fSReza Sabdar 3042654012fSReza Sabdar longname = ndmp_malloc(TLM_MAX_PATH_NAME); 3052654012fSReza Sabdar longlink = ndmp_malloc(TLM_MAX_PATH_NAME); 3062654012fSReza Sabdar hugename = ndmp_malloc(TLM_MAX_PATH_NAME); 3072654012fSReza Sabdar parentlnk = ndmp_malloc(TLM_MAX_PATH_NAME); 308fb4eb4e8SReza Sabdar thname_buf = ndmp_malloc(TLM_MAX_PATH_NAME); 3092654012fSReza Sabdar name = ndmp_malloc(TLM_MAX_PATH_NAME); 3102654012fSReza Sabdar acls = ndmp_malloc(sizeof (tlm_acls_t)); 3112654012fSReza Sabdar stp = cstack_new(); 3122654012fSReza Sabdar if (longname == NULL || longlink == NULL || hugename == NULL || 313fb4eb4e8SReza Sabdar name == NULL || acls == NULL || stp == NULL || parentlnk == NULL || 314fb4eb4e8SReza Sabdar thname_buf == NULL) { 3152654012fSReza Sabdar cstack_delete(stp); 3162654012fSReza Sabdar free(longname); 3172654012fSReza Sabdar free(longlink); 3182654012fSReza Sabdar free(hugename); 3192654012fSReza Sabdar free(parentlnk); 3202654012fSReza Sabdar free(name); 3212654012fSReza Sabdar free(acls); 322fb4eb4e8SReza Sabdar free(thname_buf); 3232654012fSReza Sabdar return (-TLM_NO_SCRATCH_SPACE); 3242654012fSReza Sabdar } 3252654012fSReza Sabdar 3262654012fSReza Sabdar acl_spot = 0; 3272654012fSReza Sabdar *hugename = '\0'; 3282654012fSReza Sabdar *parentlnk = '\0'; 3292654012fSReza Sabdar nm_end = 0; 3302654012fSReza Sabdar *longname = '\0'; 3312654012fSReza Sabdar lnk_end = 0; 3322654012fSReza Sabdar *longlink = '\0'; 3332654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 3342654012fSReza Sabdar if (IS_SET(flags, RSFLG_OVR_ALWAYS)) { 3352654012fSReza Sabdar acls->acl_overwrite = TRUE; 3362654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_ALWAYS"); 3372654012fSReza Sabdar } else if (IS_SET(flags, RSFLG_OVR_UPDATE)) { 3382654012fSReza Sabdar acls->acl_update = TRUE; 3392654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_UPDATE"); 3402654012fSReza Sabdar } 3412654012fSReza Sabdar 3422654012fSReza Sabdar /* 3432654012fSReza Sabdar * work 3442654012fSReza Sabdar */ 3452654012fSReza Sabdar rv = 0; 3462654012fSReza Sabdar nzerohdr = 0; 3472654012fSReza Sabdar break_flg = FALSE; 3482654012fSReza Sabdar while (commands->tcs_writer != TLM_ABORT && 3492654012fSReza Sabdar local_commands->tc_writer != TLM_STOP) { 3502654012fSReza Sabdar tlm_tar_hdr_t fake_tar_hdr; 3512654012fSReza Sabdar char *file_name; 3522654012fSReza Sabdar char *link_name; 3532654012fSReza Sabdar int erc; 3542654012fSReza Sabdar int actual_size; 3552654012fSReza Sabdar boolean_t want_this_file; 3562654012fSReza Sabdar int want = sizeof (tlm_tar_hdr_t); 3572654012fSReza Sabdar tlm_tar_hdr_t *tar_hdr; 3582654012fSReza Sabdar 3592654012fSReza Sabdar /* The inode of an LF_LINK type. */ 3602654012fSReza Sabdar unsigned long hardlink_inode = 0; 3612654012fSReza Sabdar 3622654012fSReza Sabdar /* 3632654012fSReza Sabdar * Indicate whether a file with the same inode has been 3642654012fSReza Sabdar * restored. 3652654012fSReza Sabdar */ 3662654012fSReza Sabdar int hardlink_done = 0; 3672654012fSReza Sabdar 3682654012fSReza Sabdar /* The path of the restored hardlink file */ 3692654012fSReza Sabdar char *hardlink_target = NULL; 3702654012fSReza Sabdar int is_hardlink = 0; 3712654012fSReza Sabdar 3722654012fSReza Sabdar /* 3732654012fSReza Sabdar * Whether a temporary file should be created for restoring 3742654012fSReza Sabdar * hardlink. 3752654012fSReza Sabdar */ 3762654012fSReza Sabdar int hardlink_tmp_file = 0; 3772654012fSReza Sabdar char *hardlink_tmp_name = ".tmphlrsnondar"; 3782654012fSReza Sabdar 3792654012fSReza Sabdar /* used to make up hardlink_tmp_name */ 3802654012fSReza Sabdar static int hardlink_tmp_idx = 0; 3812654012fSReza Sabdar 3822654012fSReza Sabdar if (break_flg) { 3832654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 3842654012fSReza Sabdar "Exiting writer thread drive %d", drv); 3852654012fSReza Sabdar break; 3862654012fSReza Sabdar } 3872654012fSReza Sabdar 3882654012fSReza Sabdar if (multi_volume) { 3892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "multi_volume %c %d", 3902654012fSReza Sabdar last_action, size_left); 3912654012fSReza Sabdar 3922654012fSReza Sabdar /* 3932654012fSReza Sabdar * the previous volume is out of data 3942654012fSReza Sabdar * and is back in the rack, a new tape 3952654012fSReza Sabdar * is loaded and ready to read. 3962654012fSReza Sabdar * 3972654012fSReza Sabdar * We need to pick up where we left off. 3982654012fSReza Sabdar */ 3992654012fSReza Sabdar (void) memset(&fake_tar_hdr, 0, sizeof (fake_tar_hdr)); 4002654012fSReza Sabdar file_size = size_left; 4012654012fSReza Sabdar tar_hdr = &fake_tar_hdr; 4022654012fSReza Sabdar tar_hdr->th_linkflag = last_action; 4032654012fSReza Sabdar 4042654012fSReza Sabdar multi_volume = FALSE; 4052654012fSReza Sabdar last_action = 0; 4062654012fSReza Sabdar } else { 4072654012fSReza Sabdar tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(want, 4082654012fSReza Sabdar &erc, &actual_size, local_commands); 4097bc22e45SReza Sabdar 4107bc22e45SReza Sabdar if (tar_hdr == NULL) { 4117bc22e45SReza Sabdar rv = -1; 4127bc22e45SReza Sabdar continue; 4137bc22e45SReza Sabdar } 4147bc22e45SReza Sabdar 4152654012fSReza Sabdar /* 4162654012fSReza Sabdar * we can ignore read errors here because 4172654012fSReza Sabdar * 1) they are logged by Restore Reader 4182654012fSReza Sabdar * 2) we are not doing anything important here 4192654012fSReza Sabdar * just looking for the next work record. 4202654012fSReza Sabdar */ 4212654012fSReza Sabdar if (actual_size < want) { 4222654012fSReza Sabdar /* 4232654012fSReza Sabdar * EOF hits here 4242654012fSReza Sabdar * 4252654012fSReza Sabdar * wait for another buffer to come along 4262654012fSReza Sabdar * or until the Reader thread tells us 4272654012fSReza Sabdar * that no more tapes will be loaded ... 4282654012fSReza Sabdar * time to stop. 4292654012fSReza Sabdar */ 4302654012fSReza Sabdar continue; 4312654012fSReza Sabdar } 4322654012fSReza Sabdar 4332654012fSReza Sabdar /* 4342654012fSReza Sabdar * check for "we are lost" 4352654012fSReza Sabdar */ 4362654012fSReza Sabdar chk_rv = tlm_vfy_tar_checksum(tar_hdr); 4372654012fSReza Sabdar if (chk_rv == 0) { 4382654012fSReza Sabdar /* one of the end of tar file marks */ 4392654012fSReza Sabdar if (++nzerohdr >= 2) { 4402654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 4412654012fSReza Sabdar "nzerohdr %d, breaking", 4422654012fSReza Sabdar nzerohdr); 4432654012fSReza Sabdar /* end of tar file */ 4442654012fSReza Sabdar break; 4452654012fSReza Sabdar } 4462654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nzerohdr %d, continuing", 4472654012fSReza Sabdar nzerohdr); 4482654012fSReza Sabdar continue; 4492654012fSReza Sabdar } else if (chk_rv < 0) { 4502654012fSReza Sabdar nzerohdr = 0; 4512654012fSReza Sabdar /* skip this record */ 4522654012fSReza Sabdar continue; 4532654012fSReza Sabdar } 4542654012fSReza Sabdar nzerohdr = 0; 4552654012fSReza Sabdar 4562654012fSReza Sabdar /* 4572654012fSReza Sabdar * When files are spanned to the next tape, the 4582654012fSReza Sabdar * information of the acls must not be over-written 4592654012fSReza Sabdar * by the information of the LF_MULTIVOL and LF_VOLHDR 4602654012fSReza Sabdar * header, whose information is irrelevant to the file. 4612654012fSReza Sabdar * The information of the original header must be 4622654012fSReza Sabdar * kept in the 'acl'. 4632654012fSReza Sabdar */ 4642654012fSReza Sabdar if (tar_hdr->th_linkflag != LF_MULTIVOL && 4652654012fSReza Sabdar tar_hdr->th_linkflag != LF_VOLHDR) { 46686c48bbfSReza Sabdar if (tar_hdr->th_linkflag != LF_HUMONGUS) { 46786c48bbfSReza Sabdar acls->acl_attr.st_mode = 46886c48bbfSReza Sabdar oct_atoi(tar_hdr->th_mode); 46986c48bbfSReza Sabdar acls->acl_attr.st_size = 47086c48bbfSReza Sabdar oct_atoi(tar_hdr->th_size); 47186c48bbfSReza Sabdar acls->acl_attr.st_uid = 47286c48bbfSReza Sabdar oct_atoi(tar_hdr->th_uid); 47386c48bbfSReza Sabdar acls->acl_attr.st_gid = 47486c48bbfSReza Sabdar oct_atoi(tar_hdr->th_gid); 47586c48bbfSReza Sabdar acls->acl_attr.st_mtime = 47686c48bbfSReza Sabdar oct_atoi(tar_hdr->th_mtime); 47786c48bbfSReza Sabdar (void) strlcpy(acls->uname, 47886c48bbfSReza Sabdar tar_hdr->th_uname, 47986c48bbfSReza Sabdar sizeof (acls->uname)); 48086c48bbfSReza Sabdar (void) strlcpy(acls->gname, 48186c48bbfSReza Sabdar tar_hdr->th_gname, 48286c48bbfSReza Sabdar sizeof (acls->gname)); 48386c48bbfSReza Sabdar } 4842654012fSReza Sabdar file_size = oct_atoi(tar_hdr->th_size); 4852654012fSReza Sabdar acl_spot = 0; 4862654012fSReza Sabdar last_action = tar_hdr->th_linkflag; 4872654012fSReza Sabdar } 4882654012fSReza Sabdar } 4892654012fSReza Sabdar 4902654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n [%s] f [%c] s %lld m %o u %d g %d t %d", 4912654012fSReza Sabdar tar_hdr->th_name, tar_hdr->th_linkflag, 4922654012fSReza Sabdar acls->acl_attr.st_size, acls->acl_attr.st_mode, 4932654012fSReza Sabdar acls->acl_attr.st_uid, acls->acl_attr.st_gid, 4942654012fSReza Sabdar acls->acl_attr.st_mtime); 4952654012fSReza Sabdar 496b6b15642SReza Sabdar /* 497b6b15642SReza Sabdar * If the restore is running using DAR we should check for 49886c48bbfSReza Sabdar * extended attribute entries 499b6b15642SReza Sabdar */ 500b6b15642SReza Sabdar if (dar_recovered && 501b6b15642SReza Sabdar tar_hdr->th_linkflag != LF_XATTR) 502b6b15642SReza Sabdar break; 503b6b15642SReza Sabdar 504fb4eb4e8SReza Sabdar rs_create_new_bkpath(bk_path, tar_hdr->th_name, thname_buf); 505fb4eb4e8SReza Sabdar 5062654012fSReza Sabdar switch (tar_hdr->th_linkflag) { 5072654012fSReza Sabdar case LF_MULTIVOL: 5082654012fSReza Sabdar multi_volume = TRUE; 5092654012fSReza Sabdar break; 5102654012fSReza Sabdar case LF_LINK: 5112654012fSReza Sabdar is_hardlink = 1; 5122654012fSReza Sabdar hardlink_inode = 5132654012fSReza Sabdar oct_atoi(tar_hdr->th_shared.th_hlink_ino); 5142654012fSReza Sabdar 5152654012fSReza Sabdar /* 5162654012fSReza Sabdar * Check if we have restored a link with the same inode 5172654012fSReza Sabdar * If the inode is 0, we have to restore it as a 5182654012fSReza Sabdar * regular file. 5192654012fSReza Sabdar */ 5202654012fSReza Sabdar if (hardlink_inode) { 5212654012fSReza Sabdar hardlink_done = !hardlink_q_get(hardlink_q, 5222654012fSReza Sabdar hardlink_inode, 0, &hardlink_target); 5232654012fSReza Sabdar } 5242654012fSReza Sabdar 5252654012fSReza Sabdar if (hardlink_done) { 5262654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5272654012fSReza Sabdar "found hardlink, inode = %u, target = [%s]", 5282654012fSReza Sabdar hardlink_inode, 5292654012fSReza Sabdar hardlink_target? hardlink_target : "--"); 5302654012fSReza Sabdar 5312654012fSReza Sabdar /* create a hardlink to hardlink_target */ 5322654012fSReza Sabdar file_name = (*longname == 0) ? 533fb4eb4e8SReza Sabdar thname_buf : longname; 534fb4eb4e8SReza Sabdar 5352654012fSReza Sabdar if (!is_file_wanted(file_name, sels, exls, 5362654012fSReza Sabdar flags, &mchtype, &pos)) { 5372654012fSReza Sabdar nmp = NULL; 5382654012fSReza Sabdar /* 5392654012fSReza Sabdar * This means that DMA did not send us 5402654012fSReza Sabdar * the correct fh_info for the file 5412654012fSReza Sabdar * in restore list. We use the file 5422654012fSReza Sabdar * name entry in sels[] (ignore the 5432654012fSReza Sabdar * name in the tar header) as restore 5442654012fSReza Sabdar * target. 5452654012fSReza Sabdar */ 5462654012fSReza Sabdar if (DAR) { 5472654012fSReza Sabdar nmp = rs_darhl_new_name(rnp, 5482654012fSReza Sabdar name, sels, &pos, 5492654012fSReza Sabdar file_name); 5502654012fSReza Sabdar } 5512654012fSReza Sabdar } else { 5522654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, 5532654012fSReza Sabdar file_name); 5542654012fSReza Sabdar if (!nmp) { 5552654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5562654012fSReza Sabdar "can't make name for %s", 5572654012fSReza Sabdar longname); 5582654012fSReza Sabdar } 5592654012fSReza Sabdar } 5602654012fSReza Sabdar 5612654012fSReza Sabdar if (nmp) { 5622654012fSReza Sabdar if (hardlink_target) { 5632654012fSReza Sabdar erc = create_hard_link( 5642654012fSReza Sabdar hardlink_target, nmp, 5652654012fSReza Sabdar acls, job_stats); 5662654012fSReza Sabdar if (erc == 0) { 5672654012fSReza Sabdar (void) 5682654012fSReza Sabdar tlm_entry_restored( 5692654012fSReza Sabdar job_stats, 5702654012fSReza Sabdar file_name, pos); 5712654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5722654012fSReza Sabdar "restored %s -> %s", 5732654012fSReza Sabdar nmp, 5742654012fSReza Sabdar hardlink_target); 5752654012fSReza Sabdar } 5762654012fSReza Sabdar } else { 5772654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5782654012fSReza Sabdar "no target for hardlink %s", 5792654012fSReza Sabdar nmp); 5802654012fSReza Sabdar } 5812654012fSReza Sabdar 5822654012fSReza Sabdar name[0] = 0; 5832654012fSReza Sabdar is_long_name = FALSE; 5842654012fSReza Sabdar } 5852654012fSReza Sabdar 5862654012fSReza Sabdar nm_end = 0; 5872654012fSReza Sabdar longname[0] = 0; 5882654012fSReza Sabdar lnk_end = 0; 5892654012fSReza Sabdar longlink[0] = 0; 5902654012fSReza Sabdar 5912654012fSReza Sabdar break; 5922654012fSReza Sabdar } 5932654012fSReza Sabdar /* otherwise fall through, restore like a normal file */ 5942654012fSReza Sabdar /*FALLTHROUGH*/ 5952654012fSReza Sabdar case LF_OLDNORMAL: 5962654012fSReza Sabdar /* 5972654012fSReza Sabdar * check for TAR's end-of-tape method 5982654012fSReza Sabdar * of zero filled records. 5992654012fSReza Sabdar */ 6002654012fSReza Sabdar if (tar_hdr->th_name[0] == 0) { 6012654012fSReza Sabdar break; 6022654012fSReza Sabdar } 6032654012fSReza Sabdar /* 6042654012fSReza Sabdar * otherwise fall through, 6052654012fSReza Sabdar * this is an old style normal file header 6062654012fSReza Sabdar */ 6072654012fSReza Sabdar /*FALLTHROUGH*/ 6082654012fSReza Sabdar case LF_NORMAL: 6092654012fSReza Sabdar case LF_CONTIG: 6102654012fSReza Sabdar job_stats->js_files_so_far++; 6112654012fSReza Sabdar if (*hugename != 0) { 6122654012fSReza Sabdar (void) strlcpy(longname, hugename, 6132654012fSReza Sabdar TLM_MAX_PATH_NAME); 6142654012fSReza Sabdar } else if (*longname == 0) { 6152654012fSReza Sabdar if (tar_hdr->th_name[0] != '/') { 6162654012fSReza Sabdar /* 6172654012fSReza Sabdar * check for old tar format, it 6182654012fSReza Sabdar * does not have a leading "/" 6192654012fSReza Sabdar */ 6202654012fSReza Sabdar longname[0] = '/'; 6212654012fSReza Sabdar longname[1] = 0; 6222654012fSReza Sabdar (void) strlcat(longname, 6232654012fSReza Sabdar tar_hdr->th_name, 6242654012fSReza Sabdar TLM_MAX_PATH_NAME); 6252654012fSReza Sabdar } else { 6262654012fSReza Sabdar (void) strlcpy(longname, 627fb4eb4e8SReza Sabdar thname_buf, 6282654012fSReza Sabdar TLM_MAX_PATH_NAME); 6292654012fSReza Sabdar } 6302654012fSReza Sabdar } 6312654012fSReza Sabdar 6322654012fSReza Sabdar want_this_file = is_file_wanted(longname, sels, exls, 6332654012fSReza Sabdar flags, &mchtype, &pos); 6342654012fSReza Sabdar if (!want_this_file) { 6352654012fSReza Sabdar nmp = NULL; 6362654012fSReza Sabdar /* 6372654012fSReza Sabdar * This means that DMA did not send us valid 6382654012fSReza Sabdar * fh_info for the file in restore list. We 6392654012fSReza Sabdar * use the file name entry in sels[] (ignore 6402654012fSReza Sabdar * the name in the tar header) as restore 6412654012fSReza Sabdar * target. 6422654012fSReza Sabdar */ 6432654012fSReza Sabdar if (DAR && (tar_hdr->th_linkflag == LF_LINK)) { 6442654012fSReza Sabdar nmp = rs_darhl_new_name(rnp, name, 6452654012fSReza Sabdar sels, &pos, longname); 6462654012fSReza Sabdar 6472654012fSReza Sabdar if (nmp) { 6482654012fSReza Sabdar want_this_file = TRUE; 6492654012fSReza Sabdar mchtype = PM_EXACT; 6502654012fSReza Sabdar } else { 6512654012fSReza Sabdar break_flg = TRUE; 6522654012fSReza Sabdar break; 6532654012fSReza Sabdar } 6542654012fSReza Sabdar } 6552654012fSReza Sabdar } else { 6562654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, longname); 6572654012fSReza Sabdar if (!nmp) 6582654012fSReza Sabdar want_this_file = FALSE; 6592654012fSReza Sabdar } 6602654012fSReza Sabdar 6612654012fSReza Sabdar if (nmp) 6622654012fSReza Sabdar (void) strlcpy(parentlnk, nmp, strlen(nmp) + 1); 6632654012fSReza Sabdar 6642654012fSReza Sabdar /* 6652654012fSReza Sabdar * For a hardlink, even if it's not asked to be 6662654012fSReza Sabdar * restored, we restore it to a temporary location, 6672654012fSReza Sabdar * in case other links to the same file need to be 6682654012fSReza Sabdar * restored later. 6692654012fSReza Sabdar * 6702654012fSReza Sabdar * The temp files are created in tmplink_dir, with 6712654012fSReza Sabdar * names like ".tmphlrsnondar*". They are cleaned up 6722654012fSReza Sabdar * at the completion of a restore. However, if a 6732654012fSReza Sabdar * restore were interrupted, e.g. by a system reboot, 6742654012fSReza Sabdar * they would have to be cleaned up manually in order 6752654012fSReza Sabdar * for the disk space to be freed. 6762654012fSReza Sabdar * 6772654012fSReza Sabdar * If tmplink_dir is NULL, no temperorary files are 6782654012fSReza Sabdar * created during a restore. This may result in some 6792654012fSReza Sabdar * hardlinks not being restored during a partial 6802654012fSReza Sabdar * restore. 6812654012fSReza Sabdar */ 6822654012fSReza Sabdar if (is_hardlink && !DAR && !want_this_file && !nmp) { 6832654012fSReza Sabdar if (tmplink_dir) { 6842654012fSReza Sabdar (void) snprintf(name, TLM_MAX_PATH_NAME, 6852654012fSReza Sabdar "%s/%s_%d", tmplink_dir, 6862654012fSReza Sabdar hardlink_tmp_name, 6872654012fSReza Sabdar hardlink_tmp_idx); 6882654012fSReza Sabdar nmp = name; 6892654012fSReza Sabdar 6902654012fSReza Sabdar hardlink_tmp_idx++; 6912654012fSReza Sabdar hardlink_tmp_file = 1; 6922654012fSReza Sabdar want_this_file = TRUE; 6932654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 6942654012fSReza Sabdar "To restore temp hardlink file %s.", 6952654012fSReza Sabdar nmp); 6962654012fSReza Sabdar } else { 6972654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 6982654012fSReza Sabdar "No tmplink_dir specified."); 6992654012fSReza Sabdar } 7002654012fSReza Sabdar } 7012654012fSReza Sabdar 7022654012fSReza Sabdar size_left = restore_file(&fp, nmp, file_size, 7032654012fSReza Sabdar huge_size, acls, want_this_file, local_commands, 7042654012fSReza Sabdar job_stats); 7052654012fSReza Sabdar 7062654012fSReza Sabdar /* 7072654012fSReza Sabdar * In the case of non-DAR, we have to record the first 7082654012fSReza Sabdar * link for an inode that has multiple links. That's 7092654012fSReza Sabdar * the only link with data records actually backed up. 7102654012fSReza Sabdar * In this way, when we run into the other links, they 7112654012fSReza Sabdar * will be treated as links, and we won't go to look 7122654012fSReza Sabdar * for the data records to restore. This is not a 7132654012fSReza Sabdar * problem for DAR, where DMA tells the tape where 7142654012fSReza Sabdar * to locate the data records. 7152654012fSReza Sabdar */ 7162654012fSReza Sabdar if (is_hardlink && !DAR) { 7172654012fSReza Sabdar if (hardlink_q_add(hardlink_q, hardlink_inode, 7182654012fSReza Sabdar 0, nmp, hardlink_tmp_file)) 7192654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 7202654012fSReza Sabdar "failed to add (%u, %s) to HL q", 7212654012fSReza Sabdar hardlink_inode, nmp); 7222654012fSReza Sabdar } 7232654012fSReza Sabdar 7242654012fSReza Sabdar /* remove / reverse the temporary stuff */ 7252654012fSReza Sabdar if (hardlink_tmp_file) { 7262654012fSReza Sabdar nmp = NULL; 7272654012fSReza Sabdar want_this_file = FALSE; 7282654012fSReza Sabdar hardlink_tmp_file = 0; 7292654012fSReza Sabdar } 7302654012fSReza Sabdar 7312654012fSReza Sabdar /* 7322654012fSReza Sabdar * Check if it is time to set the attribute 7332654012fSReza Sabdar * of the restored directory 7342654012fSReza Sabdar */ 7352654012fSReza Sabdar while (nmp && ((bkpath = dtree_peek(stp)) != NULL)) { 7362654012fSReza Sabdar if (strstr(nmp, bkpath)) 7372654012fSReza Sabdar break; 7382654012fSReza Sabdar 7392654012fSReza Sabdar (void) dtree_pop(stp); 7402654012fSReza Sabdar } 7412654012fSReza Sabdar 7422654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "sizeleft %s %d, %lld", longname, 7432654012fSReza Sabdar size_left, huge_size); 7442654012fSReza Sabdar 7452654012fSReza Sabdar if (size_left == -TLM_STOP) { 7462654012fSReza Sabdar break_flg = TRUE; 7472654012fSReza Sabdar rv = -1; 7482654012fSReza Sabdar commands->tcs_reader = TLM_ABORT; 7492654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "restoring [%s] failed", 7502654012fSReza Sabdar longname); 7512654012fSReza Sabdar break; 7522654012fSReza Sabdar } 7532654012fSReza Sabdar 7542654012fSReza Sabdar if (want_this_file) { 7552654012fSReza Sabdar job_stats->js_bytes_total += file_size; 7562654012fSReza Sabdar job_stats->js_files_total++; 7572654012fSReza Sabdar } 7582654012fSReza Sabdar 7592654012fSReza Sabdar huge_size -= file_size; 7602654012fSReza Sabdar if (huge_size < 0) { 7612654012fSReza Sabdar huge_size = 0; 7622654012fSReza Sabdar } 7632654012fSReza Sabdar if (size_left == 0 && huge_size == 0) { 7642654012fSReza Sabdar if (PM_EXACT_OR_CHILD(mchtype)) { 7652654012fSReza Sabdar (void) tlm_entry_restored(job_stats, 7662654012fSReza Sabdar longname, pos); 7672654012fSReza Sabdar 7682654012fSReza Sabdar /* 7692654012fSReza Sabdar * Add an entry to hardlink_q to record 7702654012fSReza Sabdar * this hardlink. 7712654012fSReza Sabdar */ 7722654012fSReza Sabdar if (is_hardlink) { 7732654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 7742654012fSReza Sabdar "Restored hardlink file %s", 7752654012fSReza Sabdar nmp); 7762654012fSReza Sabdar 7772654012fSReza Sabdar if (DAR) { 7782654012fSReza Sabdar (void) hardlink_q_add( 7792654012fSReza Sabdar hardlink_q, 7802654012fSReza Sabdar hardlink_inode, 0, 7812654012fSReza Sabdar nmp, 0); 7822654012fSReza Sabdar } 7832654012fSReza Sabdar } 7842654012fSReza Sabdar } 7852654012fSReza Sabdar 7862654012fSReza Sabdar nm_end = 0; 7872654012fSReza Sabdar longname[0] = 0; 7882654012fSReza Sabdar lnk_end = 0; 7892654012fSReza Sabdar longlink[0] = 0; 7902654012fSReza Sabdar hugename[0] = 0; 7912654012fSReza Sabdar name[0] = 0; 7922654012fSReza Sabdar is_long_name = FALSE; 7932654012fSReza Sabdar } 7942654012fSReza Sabdar break; 7952654012fSReza Sabdar case LF_XATTR: 796fb4eb4e8SReza Sabdar file_name = (*longname == 0) ? thname_buf : 7972654012fSReza Sabdar longname; 7982654012fSReza Sabdar 7992654012fSReza Sabdar size_left = restore_xattr_hdr(&fp, parentlnk, 8002654012fSReza Sabdar file_name, file_size, acls, local_commands, 8012654012fSReza Sabdar job_stats); 8022654012fSReza Sabdar 8032654012fSReza Sabdar break; 8042654012fSReza Sabdar case LF_SYMLINK: 805fb4eb4e8SReza Sabdar file_name = (*longname == 0) ? thname_buf : 8062654012fSReza Sabdar longname; 8072654012fSReza Sabdar link_name = (*longlink == 0) ? 8082654012fSReza Sabdar tar_hdr->th_linkname : longlink; 8092654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "file_name[%s]", file_name); 8102654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "link_name[%s]", link_name); 8112654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 8122654012fSReza Sabdar &mchtype, &pos)) { 8132654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 8142654012fSReza Sabdar if (nmp) { 8152654012fSReza Sabdar erc = create_sym_link(nmp, link_name, 8162654012fSReza Sabdar acls, job_stats); 8172654012fSReza Sabdar if (erc == 0 && 8182654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 8192654012fSReza Sabdar (void) tlm_entry_restored( 8202654012fSReza Sabdar job_stats, file_name, pos); 8212654012fSReza Sabdar name[0] = 0; 8222654012fSReza Sabdar } 8232654012fSReza Sabdar } 8242654012fSReza Sabdar nm_end = 0; 8252654012fSReza Sabdar longname[0] = 0; 8262654012fSReza Sabdar lnk_end = 0; 8272654012fSReza Sabdar longlink[0] = 0; 8282654012fSReza Sabdar break; 8292654012fSReza Sabdar case LF_DIR: 830fb4eb4e8SReza Sabdar file_name = *longname == 0 ? thname_buf : 8312654012fSReza Sabdar longname; 8322654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 8332654012fSReza Sabdar &mchtype, &pos)) { 834c9fd6b31SReza Sabdar dir_dar = DAR; 8352654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 8362654012fSReza Sabdar if (nmp && mchtype != PM_PARENT) { 8372654012fSReza Sabdar (void) strlcpy(parentlnk, nmp, 8382654012fSReza Sabdar strlen(nmp)); 8392654012fSReza Sabdar erc = create_directory(nmp, job_stats); 8402654012fSReza Sabdar if (erc == 0 && 8412654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 8422654012fSReza Sabdar (void) tlm_entry_restored( 8432654012fSReza Sabdar job_stats, file_name, pos); 8442654012fSReza Sabdar /* 8452654012fSReza Sabdar * Check if it is time to set 8462654012fSReza Sabdar * the attribute of the restored 8472654012fSReza Sabdar * directory 8482654012fSReza Sabdar */ 8492654012fSReza Sabdar while ((bkpath = dtree_peek(stp)) 8502654012fSReza Sabdar != NULL) { 8512654012fSReza Sabdar if (strstr(nmp, bkpath)) 8522654012fSReza Sabdar break; 8532654012fSReza Sabdar (void) dtree_pop(stp); 8542654012fSReza Sabdar } 8552654012fSReza Sabdar 8562654012fSReza Sabdar (void) dtree_push(stp, nmp, acls); 8572654012fSReza Sabdar name[0] = 0; 8582654012fSReza Sabdar } 859c9fd6b31SReza Sabdar } else { 860c9fd6b31SReza Sabdar dir_dar = 0; 8612654012fSReza Sabdar } 8622654012fSReza Sabdar nm_end = 0; 8632654012fSReza Sabdar longname[0] = 0; 8642654012fSReza Sabdar lnk_end = 0; 8652654012fSReza Sabdar longlink[0] = 0; 8662654012fSReza Sabdar break; 8672654012fSReza Sabdar case LF_FIFO: 868*5181c2afSReza Sabdar case LF_BLK: 869*5181c2afSReza Sabdar case LF_CHR: 870fb4eb4e8SReza Sabdar file_name = *longname == 0 ? thname_buf : 8712654012fSReza Sabdar longname; 8722654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 8732654012fSReza Sabdar &mchtype, &pos)) { 8742654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 8752654012fSReza Sabdar if (nmp) { 876*5181c2afSReza Sabdar erc = create_special( 877*5181c2afSReza Sabdar tar_hdr->th_linkflag, nmp, acls, 878*5181c2afSReza Sabdar oct_atoi(tar_hdr->th_shared. 879*5181c2afSReza Sabdar th_dev.th_devmajor), 880*5181c2afSReza Sabdar oct_atoi(tar_hdr->th_shared. 881*5181c2afSReza Sabdar th_dev.th_devminor), job_stats); 8822654012fSReza Sabdar if (erc == 0 && 8832654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 8842654012fSReza Sabdar (void) tlm_entry_restored( 8852654012fSReza Sabdar job_stats, file_name, pos); 8862654012fSReza Sabdar name[0] = 0; 8872654012fSReza Sabdar } 8882654012fSReza Sabdar } 8892654012fSReza Sabdar nm_end = 0; 8902654012fSReza Sabdar longname[0] = 0; 8912654012fSReza Sabdar lnk_end = 0; 8922654012fSReza Sabdar longlink[0] = 0; 8932654012fSReza Sabdar break; 8942654012fSReza Sabdar case LF_LONGLINK: 895859b7745SReza Sabdar file_size = min(file_size, 896859b7745SReza Sabdar TLM_MAX_PATH_NAME - lnk_end - 1); 8972654012fSReza Sabdar file_size = max(0, file_size); 8982654012fSReza Sabdar size_left = get_long_name(lib, drv, file_size, longlink, 8992654012fSReza Sabdar &lnk_end, local_commands); 9002654012fSReza Sabdar 9012654012fSReza Sabdar if (size_left != 0) 9022654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 9032654012fSReza Sabdar "fsize %d sleft %d lnkend %d", 9042654012fSReza Sabdar file_size, size_left, lnk_end); 9052654012fSReza Sabdar break; 9062654012fSReza Sabdar case LF_LONGNAME: 907859b7745SReza Sabdar file_size = min(file_size, 908859b7745SReza Sabdar TLM_MAX_PATH_NAME - nm_end - 1); 9092654012fSReza Sabdar file_size = max(0, file_size); 9102654012fSReza Sabdar size_left = get_long_name(lib, drv, file_size, longname, 9112654012fSReza Sabdar &nm_end, local_commands); 9122654012fSReza Sabdar 9132654012fSReza Sabdar if (size_left != 0) 9142654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 9152654012fSReza Sabdar "fsize %d sleft %d nmend %d", 9162654012fSReza Sabdar file_size, size_left, nm_end); 9172654012fSReza Sabdar is_long_name = TRUE; 9182654012fSReza Sabdar break; 9192654012fSReza Sabdar case LF_ACL: 9202654012fSReza Sabdar size_left = load_acl_info(lib, drv, file_size, acls, 9212654012fSReza Sabdar &acl_spot, local_commands); 9222654012fSReza Sabdar break; 9232654012fSReza Sabdar case LF_VOLHDR: 9242654012fSReza Sabdar break; 9252654012fSReza Sabdar case LF_HUMONGUS: 9262654012fSReza Sabdar (void) memset(hugename, 0, TLM_MAX_PATH_NAME); 9272654012fSReza Sabdar (void) get_humongus_file_header(lib, drv, file_size, 9282654012fSReza Sabdar &huge_size, hugename, local_commands); 9292654012fSReza Sabdar break; 9302654012fSReza Sabdar default: 9312654012fSReza Sabdar break; 9322654012fSReza Sabdar 9332654012fSReza Sabdar } 9342654012fSReza Sabdar 9352654012fSReza Sabdar /* 9362654012fSReza Sabdar * If the restore is running using DAR we should check for 9372654012fSReza Sabdar * long file names and HUGE file sizes. 9382654012fSReza Sabdar */ 9392654012fSReza Sabdar if (DAR && tar_hdr->th_linkflag != LF_ACL && 940b6b15642SReza Sabdar tar_hdr->th_linkflag != LF_XATTR && 941c9fd6b31SReza Sabdar !huge_size && !is_long_name && !dir_dar) 942b6b15642SReza Sabdar dar_recovered = 1; 9432654012fSReza Sabdar } 9442654012fSReza Sabdar 9452654012fSReza Sabdar /* 9462654012fSReza Sabdar * tear down 9472654012fSReza Sabdar */ 9482654012fSReza Sabdar if (fp != 0) { 9492654012fSReza Sabdar (void) close(fp); 9502654012fSReza Sabdar } 9512654012fSReza Sabdar while (dtree_pop(stp) != -1) 9522654012fSReza Sabdar ; 9532654012fSReza Sabdar cstack_delete(stp); 9542654012fSReza Sabdar free(acls); 9552654012fSReza Sabdar free(longname); 9562654012fSReza Sabdar free(parentlnk); 9572654012fSReza Sabdar free(longlink); 9582654012fSReza Sabdar free(hugename); 9592654012fSReza Sabdar free(name); 960fb4eb4e8SReza Sabdar free(thname_buf); 9612654012fSReza Sabdar return (rv); 9622654012fSReza Sabdar } 9632654012fSReza Sabdar 9642654012fSReza Sabdar /* 9652654012fSReza Sabdar * Main file restore function for tar (should run as a thread) 9662654012fSReza Sabdar */ 9672654012fSReza Sabdar int 9682654012fSReza Sabdar tar_getfile(tlm_backup_restore_arg_t *argp) 9692654012fSReza Sabdar { 9702654012fSReza Sabdar tlm_job_stats_t *job_stats; 9712654012fSReza Sabdar char **sels; /* list of files desired */ 9722654012fSReza Sabdar char **exls; /* list of files not wanted */ 9732654012fSReza Sabdar char *dir; /* where to restore the files */ 9742654012fSReza Sabdar char job[TLM_MAX_BACKUP_JOB_NAME+1]; 9752654012fSReza Sabdar /* the restore job name */ 9762654012fSReza Sabdar int erc; /* error return codes */ 9772654012fSReza Sabdar int flags; 9782654012fSReza Sabdar struct rs_name_maker rn; 9792654012fSReza Sabdar tlm_commands_t *commands; 9802654012fSReza Sabdar tlm_cmd_t *local_commands; 9812654012fSReza Sabdar char *list = NULL; 9822654012fSReza Sabdar 9832654012fSReza Sabdar commands = argp->ba_commands; 9842654012fSReza Sabdar local_commands = argp->ba_cmd; 9852654012fSReza Sabdar 9862654012fSReza Sabdar flags = 0; 9872654012fSReza Sabdar 9882654012fSReza Sabdar dir = ndmp_malloc(TLM_MAX_PATH_NAME); 9892654012fSReza Sabdar if (dir == NULL) { 9902654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 9912654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 9922654012fSReza Sabdar return (-1); 9932654012fSReza Sabdar } 9942654012fSReza Sabdar 9952654012fSReza Sabdar (void) strlcpy(job, argp->ba_job, TLM_MAX_BACKUP_JOB_NAME+1); 9962654012fSReza Sabdar (void) strlcpy(dir, argp->ba_dir, TLM_MAX_PATH_NAME); 9972654012fSReza Sabdar 9982654012fSReza Sabdar flags |= RSFLG_OVR_ALWAYS; 9992654012fSReza Sabdar flags |= RSFLG_IGNORE_CASE; 10002654012fSReza Sabdar 10012654012fSReza Sabdar /* 10022654012fSReza Sabdar * do not test for "dir" having no string, since that 10032654012fSReza Sabdar * is a legal condition. Restore to origional location 10042654012fSReza Sabdar * will not have a restore directory. 10052654012fSReza Sabdar */ 10062654012fSReza Sabdar if (*job == '\0') { 10072654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No job defined"); 10082654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 10092654012fSReza Sabdar free(dir); 10102654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 10112654012fSReza Sabdar return (-1); 10122654012fSReza Sabdar } 10132654012fSReza Sabdar 10142654012fSReza Sabdar sels = argp->ba_sels; 10152654012fSReza Sabdar if (sels == NULL) { 10162654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 10172654012fSReza Sabdar free(dir); 10182654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 10192654012fSReza Sabdar return (-1); 10202654012fSReza Sabdar } 10212654012fSReza Sabdar exls = &list; 10222654012fSReza Sabdar 10232654012fSReza Sabdar tlm_log_list("selections", sels); 10242654012fSReza Sabdar tlm_log_list("exclusions", exls); 10252654012fSReza Sabdar 10262654012fSReza Sabdar if (wildcard_enabled()) 10272654012fSReza Sabdar flags |= RSFLG_MATCH_WCARD; 10282654012fSReza Sabdar 10292654012fSReza Sabdar local_commands->tc_ref++; 10302654012fSReza Sabdar commands->tcs_writer_count++; 10312654012fSReza Sabdar 10322654012fSReza Sabdar /* 10332654012fSReza Sabdar * let the launcher continue 10342654012fSReza Sabdar */ 10352654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 10362654012fSReza Sabdar 10372654012fSReza Sabdar job_stats = tlm_ref_job_stats(job); 10382654012fSReza Sabdar 10392654012fSReza Sabdar rn.rn_fp = catnames; 10402654012fSReza Sabdar rn.rn_nlp = dir; 10412654012fSReza Sabdar 10422654012fSReza Sabdar /* 10432654012fSReza Sabdar * work 10442654012fSReza Sabdar */ 10452654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "start restore job %s", job); 10462654012fSReza Sabdar erc = tar_getdir(commands, local_commands, job_stats, &rn, 1, 1, 1047fb4eb4e8SReza Sabdar sels, exls, flags, 0, NULL, NULL); 10482654012fSReza Sabdar 10492654012fSReza Sabdar /* 10502654012fSReza Sabdar * teardown 10512654012fSReza Sabdar */ 10522654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "end restore job %s", job); 10532654012fSReza Sabdar tlm_un_ref_job_stats(job); 10542654012fSReza Sabdar tlm_release_list(sels); 10552654012fSReza Sabdar tlm_release_list(exls); 10562654012fSReza Sabdar 10572654012fSReza Sabdar commands->tcs_writer_count--; 10582654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 10592654012fSReza Sabdar tlm_release_reader_writer_ipc(local_commands); 10602654012fSReza Sabdar free(dir); 10612654012fSReza Sabdar return (erc); 10622654012fSReza Sabdar } 10632654012fSReza Sabdar 10642654012fSReza Sabdar /* 10652654012fSReza Sabdar * Creates the directories all the way down to the 10662654012fSReza Sabdar * end if they dont exist 10672654012fSReza Sabdar */ 10682654012fSReza Sabdar int 10692654012fSReza Sabdar make_dirs(char *dir) 10702654012fSReza Sabdar { 10712654012fSReza Sabdar char c; 10722654012fSReza Sabdar char *cp, *end; 10732654012fSReza Sabdar struct stat64 st; 10742654012fSReza Sabdar 10752654012fSReza Sabdar cp = dir; 10762654012fSReza Sabdar cp += strspn(cp, "/"); 10772654012fSReza Sabdar end = dir + strlen(dir); 10782654012fSReza Sabdar do { 10792654012fSReza Sabdar if (*cp == '\0' || *cp == '/') { 10802654012fSReza Sabdar c = *cp; 10812654012fSReza Sabdar *cp = '\0'; 10822654012fSReza Sabdar if (lstat64(dir, &st) < 0) 10832654012fSReza Sabdar if (mkdir(dir, 0777) < 0) { 10842654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d" 10852654012fSReza Sabdar " creating directory %s", 10862654012fSReza Sabdar errno, dir); 10872654012fSReza Sabdar *cp = c; 10882654012fSReza Sabdar return (-1); 10892654012fSReza Sabdar } 10902654012fSReza Sabdar 10912654012fSReza Sabdar *cp = c; 10922654012fSReza Sabdar } 10932654012fSReza Sabdar } while (++cp <= end); 10942654012fSReza Sabdar 10952654012fSReza Sabdar return (0); 10962654012fSReza Sabdar } 10972654012fSReza Sabdar 10982654012fSReza Sabdar /* 10992654012fSReza Sabdar * Creates the directories leading to the given path 11002654012fSReza Sabdar */ 11012654012fSReza Sabdar int 11022654012fSReza Sabdar mkbasedir(char *path) 11032654012fSReza Sabdar { 11042654012fSReza Sabdar int rv; 11052654012fSReza Sabdar char *cp; 11062654012fSReza Sabdar struct stat64 st; 11072654012fSReza Sabdar 11082654012fSReza Sabdar if (!path || !*path) { 11092654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument"); 11102654012fSReza Sabdar return (-1); 11112654012fSReza Sabdar } 11122654012fSReza Sabdar 11132654012fSReza Sabdar cp = strrchr(path, '/'); 11142654012fSReza Sabdar if (cp) 11152654012fSReza Sabdar *cp = '\0'; 11162654012fSReza Sabdar rv = lstat64(path, &st); 11172654012fSReza Sabdar if (rv < 0) /* need new directories */ 11182654012fSReza Sabdar rv = make_dirs(path); 11192654012fSReza Sabdar if (cp) 11202654012fSReza Sabdar *cp = '/'; 11212654012fSReza Sabdar 11222654012fSReza Sabdar return (rv); 11232654012fSReza Sabdar } 11242654012fSReza Sabdar 11252654012fSReza Sabdar 11262654012fSReza Sabdar /* 11272654012fSReza Sabdar * read the file off the tape back onto disk 11282654012fSReza Sabdar */ 11292654012fSReza Sabdar static long 11302654012fSReza Sabdar restore_file(int *fp, 11312654012fSReza Sabdar char *real_name, 11322654012fSReza Sabdar long size, 11332654012fSReza Sabdar longlong_t huge_size, 11342654012fSReza Sabdar tlm_acls_t *acls, 11352654012fSReza Sabdar boolean_t want_this_file, 11362654012fSReza Sabdar tlm_cmd_t *local_commands, 11372654012fSReza Sabdar tlm_job_stats_t *job_stats) 11382654012fSReza Sabdar { 11392654012fSReza Sabdar struct stat64 attr; 11402654012fSReza Sabdar 11412654012fSReza Sabdar if (!real_name) { 11422654012fSReza Sabdar if (want_this_file) { 11432654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No file name but wanted!"); 11442654012fSReza Sabdar want_this_file = FALSE; 11452654012fSReza Sabdar } 11462654012fSReza Sabdar } else 11472654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new file[%s]", real_name); 11482654012fSReza Sabdar 11492654012fSReza Sabdar /* 11502654012fSReza Sabdar * OK, some FM is creeping in here ... 11512654012fSReza Sabdar * int *fp is used to keep the 11522654012fSReza Sabdar * backup file channel open through 11532654012fSReza Sabdar * the interruption of EOT and 11542654012fSReza Sabdar * processing the headers of the 11552654012fSReza Sabdar * next tape. So, if *fp is zero 11562654012fSReza Sabdar * then no file is open yet and all 11572654012fSReza Sabdar * is normal. If *fp has a number 11582654012fSReza Sabdar * then we are returning after an 11592654012fSReza Sabdar * EOT break. 11602654012fSReza Sabdar * 11612654012fSReza Sabdar * *fp is now also open for HUGE files 11622654012fSReza Sabdar * that are put back in sections. 11632654012fSReza Sabdar */ 11642654012fSReza Sabdar 11652654012fSReza Sabdar if (*fp == 0 && want_this_file) { 11662654012fSReza Sabdar int erc_stat; 11672654012fSReza Sabdar 11682654012fSReza Sabdar if (mkbasedir(real_name) < 0) 11692654012fSReza Sabdar job_stats->js_errors++; 11702654012fSReza Sabdar 11712654012fSReza Sabdar erc_stat = stat64(real_name, (struct stat64 *)&attr); 11722654012fSReza Sabdar if (erc_stat < 0) { 11732654012fSReza Sabdar /*EMPTY*/ 11742654012fSReza Sabdar /* new file */ 11752654012fSReza Sabdar } else if (acls->acl_overwrite) { 11762654012fSReza Sabdar /*EMPTY*/ 11772654012fSReza Sabdar /* take this file no matter what */ 11782654012fSReza Sabdar } else if (acls->acl_update) { 11792654012fSReza Sabdar if (attr.st_mtime < acls->acl_attr.st_mtime) { 11802654012fSReza Sabdar /*EMPTY*/ 11812654012fSReza Sabdar /* tape is newer */ 11822654012fSReza Sabdar } else { 11832654012fSReza Sabdar /* disk file is newer */ 11842654012fSReza Sabdar want_this_file = FALSE; 11852654012fSReza Sabdar } 11862654012fSReza Sabdar } else { 11872654012fSReza Sabdar /* 11882654012fSReza Sabdar * no overwrite, no update, 11892654012fSReza Sabdar * do not ever replace old files. 11902654012fSReza Sabdar */ 11912654012fSReza Sabdar want_this_file = TRUE; 11922654012fSReza Sabdar } 11932654012fSReza Sabdar if (want_this_file) { 11942654012fSReza Sabdar 1195c211fc47SReza Sabdar *fp = open(real_name, O_CREAT | O_TRUNC | O_WRONLY, 11962654012fSReza Sabdar S_IRUSR | S_IWUSR); 11972654012fSReza Sabdar if (*fp == -1) { 11982654012fSReza Sabdar NDMP_LOG(LOG_ERR, 11992654012fSReza Sabdar "Could not open %s for restore.", 12002654012fSReza Sabdar real_name); 12012654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 12022654012fSReza Sabdar "fp=%d err=%d ", *fp, errno); 12032654012fSReza Sabdar job_stats->js_errors++; 12042654012fSReza Sabdar want_this_file = FALSE; 12052654012fSReza Sabdar /* 12062654012fSReza Sabdar * we cannot return here, 12072654012fSReza Sabdar * the file is still on 12082654012fSReza Sabdar * the tape and must be 12092654012fSReza Sabdar * skipped over. 12102654012fSReza Sabdar */ 12112654012fSReza Sabdar } 12122654012fSReza Sabdar } 12132654012fSReza Sabdar (void) strlcpy(local_commands->tc_file_name, real_name, 12142654012fSReza Sabdar TLM_MAX_PATH_NAME); 12152654012fSReza Sabdar } 12162654012fSReza Sabdar 12172654012fSReza Sabdar /* 12182654012fSReza Sabdar * this is the size left in the next segment 12192654012fSReza Sabdar */ 12202654012fSReza Sabdar huge_size -= size; 12212654012fSReza Sabdar 12222654012fSReza Sabdar /* 12232654012fSReza Sabdar * work 12242654012fSReza Sabdar */ 12252654012fSReza Sabdar while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) { 12262654012fSReza Sabdar int actual_size; 12272654012fSReza Sabdar int error; 12282654012fSReza Sabdar char *rec; 12292654012fSReza Sabdar int write_size; 12302654012fSReza Sabdar 12312654012fSReza Sabdar /* 12322654012fSReza Sabdar * Use bytes_in_file field to tell reader the amount 12332654012fSReza Sabdar * of data still need to be read for this file. 12342654012fSReza Sabdar */ 12352654012fSReza Sabdar job_stats->js_bytes_in_file = size; 12362654012fSReza Sabdar 12372654012fSReza Sabdar error = 0; 12382654012fSReza Sabdar rec = get_read_buffer(size, &error, &actual_size, 12392654012fSReza Sabdar local_commands); 12402654012fSReza Sabdar if (actual_size <= 0) { 12412654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 12422654012fSReza Sabdar "RESTORE WRITER> error %d, actual_size %d", 12432654012fSReza Sabdar error, actual_size); 12442654012fSReza Sabdar 12452654012fSReza Sabdar /* no more data for this file for now */ 12462654012fSReza Sabdar job_stats->js_bytes_in_file = 0; 12472654012fSReza Sabdar 12482654012fSReza Sabdar return (size); 12492654012fSReza Sabdar } else if (error) { 12502654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 12512654012fSReza Sabdar error, local_commands->tc_file_name); 12522654012fSReza Sabdar break; 12532654012fSReza Sabdar } else { 12542654012fSReza Sabdar write_size = min(size, actual_size); 12552654012fSReza Sabdar if (want_this_file) { 12562654012fSReza Sabdar write_size = write(*fp, rec, write_size); 12572654012fSReza Sabdar } 12582654012fSReza Sabdar NS_ADD(wdisk, write_size); 12592654012fSReza Sabdar NS_INC(wfile); 12602654012fSReza Sabdar size -= write_size; 12612654012fSReza Sabdar } 12622654012fSReza Sabdar } 12632654012fSReza Sabdar 12642654012fSReza Sabdar /* no more data for this file for now */ 12652654012fSReza Sabdar job_stats->js_bytes_in_file = 0; 12662654012fSReza Sabdar 12672654012fSReza Sabdar /* 12682654012fSReza Sabdar * teardown 12692654012fSReza Sabdar */ 12702654012fSReza Sabdar if (*fp != 0 && huge_size <= 0) { 12712654012fSReza Sabdar (void) close(*fp); 12722654012fSReza Sabdar *fp = 0; 12732654012fSReza Sabdar set_acl(real_name, acls); 12742654012fSReza Sabdar } 12752654012fSReza Sabdar return (0); 12762654012fSReza Sabdar } 12772654012fSReza Sabdar 12782654012fSReza Sabdar /* 12792654012fSReza Sabdar * Set the extended attributes file attribute 12802654012fSReza Sabdar */ 12812654012fSReza Sabdar static void 12822654012fSReza Sabdar set_xattr(int fd, struct stat64 st) 12832654012fSReza Sabdar { 12842654012fSReza Sabdar struct timeval times[2]; 12852654012fSReza Sabdar 12862654012fSReza Sabdar times[0].tv_sec = st.st_atime; 12872654012fSReza Sabdar times[1].tv_sec = st.st_mtime; 12882654012fSReza Sabdar 12892654012fSReza Sabdar (void) fchmod(fd, st.st_mode); 12902654012fSReza Sabdar (void) fchown(fd, st.st_uid, st.st_gid); 12912654012fSReza Sabdar (void) futimesat(fd, ".", times); 12922654012fSReza Sabdar } 12932654012fSReza Sabdar 1294b6b15642SReza Sabdar /* 1295b6b15642SReza Sabdar * Read the system attribute file in a single buffer to write 1296b6b15642SReza Sabdar * it as a single write. A partial write to system attribute would 1297b6b15642SReza Sabdar * cause an EINVAL on write. 1298b6b15642SReza Sabdar */ 1299b6b15642SReza Sabdar static char * 1300b6b15642SReza Sabdar get_read_one_buf(char *rec, int actual_size, int size, int *error, 1301b6b15642SReza Sabdar tlm_cmd_t *lc) 1302b6b15642SReza Sabdar { 1303b6b15642SReza Sabdar char *buf, *p; 1304b6b15642SReza Sabdar int read_size; 1305b6b15642SReza Sabdar int len; 1306b6b15642SReza Sabdar 1307b6b15642SReza Sabdar if (actual_size > size) 1308b6b15642SReza Sabdar return (rec); 1309b6b15642SReza Sabdar 1310b6b15642SReza Sabdar buf = ndmp_malloc(size); 1311b6b15642SReza Sabdar if (buf == NULL) { 1312b6b15642SReza Sabdar *error = ENOMEM; 1313b6b15642SReza Sabdar return (NULL); 1314b6b15642SReza Sabdar } 1315b6b15642SReza Sabdar (void) memcpy(buf, rec, actual_size); 1316b6b15642SReza Sabdar rec = buf; 1317b6b15642SReza Sabdar buf += actual_size; 1318b6b15642SReza Sabdar while (actual_size < size) { 1319b6b15642SReza Sabdar p = get_read_buffer(size - actual_size, error, &read_size, lc); 1320b6b15642SReza Sabdar len = min(size - actual_size, read_size); 1321b6b15642SReza Sabdar (void) memcpy(buf, p, len); 1322b6b15642SReza Sabdar actual_size += len; 1323b6b15642SReza Sabdar buf += len; 1324b6b15642SReza Sabdar } 1325b6b15642SReza Sabdar return (rec); 1326b6b15642SReza Sabdar } 1327b6b15642SReza Sabdar 1328b6b15642SReza Sabdar 13292654012fSReza Sabdar /* 13302654012fSReza Sabdar * read the extended attribute header and write 13312654012fSReza Sabdar * it to the file 13322654012fSReza Sabdar */ 13332654012fSReza Sabdar static long 13342654012fSReza Sabdar restore_xattr_hdr(int *fp, 13352654012fSReza Sabdar char *name, 13362654012fSReza Sabdar char *fname, 13372654012fSReza Sabdar long size, 13382654012fSReza Sabdar tlm_acls_t *acls, 13392654012fSReza Sabdar tlm_cmd_t *local_commands, 13402654012fSReza Sabdar tlm_job_stats_t *job_stats) 13412654012fSReza Sabdar { 13422654012fSReza Sabdar tlm_tar_hdr_t *tar_hdr; 13432654012fSReza Sabdar struct xattr_hdr *xhdr; 13442654012fSReza Sabdar struct xattr_buf *xbuf; 13452654012fSReza Sabdar int namelen; 13462654012fSReza Sabdar char *xattrname; 13472654012fSReza Sabdar int actual_size; 13482654012fSReza Sabdar int error; 13492654012fSReza Sabdar 13502654012fSReza Sabdar if (!fname) { 13512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No file name but wanted!"); 13522654012fSReza Sabdar } else { 13532654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new xattr[%s]", fname); 13542654012fSReza Sabdar } 13552654012fSReza Sabdar 13562654012fSReza Sabdar error = 0; 13572654012fSReza Sabdar xhdr = (struct xattr_hdr *)get_read_buffer(size, &error, 13582654012fSReza Sabdar &actual_size, local_commands); 13597a088f03SReza Sabdar if (xhdr == NULL || error != 0) { 13602654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 13612654012fSReza Sabdar "Could not read xattr [%s:%s] for restore. ", 13622654012fSReza Sabdar name, fname); 13632654012fSReza Sabdar job_stats->js_errors++; 13642654012fSReza Sabdar return (0); 13652654012fSReza Sabdar } 13662654012fSReza Sabdar 13672654012fSReza Sabdar /* Check extended attribute header */ 13682654012fSReza Sabdar if (strcmp(xhdr->h_version, XATTR_ARCH_VERS) != 0) { 13692654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 13702654012fSReza Sabdar "Unrecognized header format [%s]", xhdr->h_version); 13712654012fSReza Sabdar return (0); 13722654012fSReza Sabdar } 13732654012fSReza Sabdar xbuf = (struct xattr_buf *)(((char *)xhdr) + sizeof (struct xattr_hdr)); 13742654012fSReza Sabdar 13752654012fSReza Sabdar (void) sscanf(xbuf->h_namesz, "%7d", &namelen); 13762654012fSReza Sabdar xattrname = xbuf->h_names + strlen(xbuf->h_names) + 1; 13772654012fSReza Sabdar 13782654012fSReza Sabdar if (*fp == 0) { 13792654012fSReza Sabdar int fd; 13802654012fSReza Sabdar 13812654012fSReza Sabdar fd = attropen(name, xattrname, O_CREAT | O_RDWR, 0755); 13822654012fSReza Sabdar if (fd == -1) { 13832654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1384b6b15642SReza Sabdar "Could not open xattr [%s:%s] for restore err=%d.", 1385b6b15642SReza Sabdar name, xattrname, errno); 13862654012fSReza Sabdar job_stats->js_errors++; 1387b6b15642SReza Sabdar return (0); 13882654012fSReza Sabdar } 13892654012fSReza Sabdar (void) strlcpy(local_commands->tc_file_name, xattrname, 13902654012fSReza Sabdar TLM_MAX_PATH_NAME); 13912654012fSReza Sabdar *fp = fd; 13922654012fSReza Sabdar } 13932654012fSReza Sabdar 13942654012fSReza Sabdar /* Get the actual extended attribute file */ 13952654012fSReza Sabdar tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(sizeof (*tar_hdr), 13962654012fSReza Sabdar &error, &actual_size, local_commands); 13977a088f03SReza Sabdar if (tar_hdr == NULL || error != 0) { 13982654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 13992654012fSReza Sabdar "Could not read xattr data [%s:%s] for restore. ", 14002654012fSReza Sabdar fname, xattrname); 14012654012fSReza Sabdar job_stats->js_errors++; 14022654012fSReza Sabdar return (0); 14032654012fSReza Sabdar } 14042654012fSReza Sabdar acls->acl_attr.st_mode = oct_atoi(tar_hdr->th_mode); 14052654012fSReza Sabdar acls->acl_attr.st_size = oct_atoi(tar_hdr->th_size); 14062654012fSReza Sabdar acls->acl_attr.st_uid = oct_atoi(tar_hdr->th_uid); 14072654012fSReza Sabdar acls->acl_attr.st_gid = oct_atoi(tar_hdr->th_gid); 14082654012fSReza Sabdar acls->acl_attr.st_mtime = oct_atoi(tar_hdr->th_mtime); 14092654012fSReza Sabdar 1410b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d", 1411b6b15642SReza Sabdar xattrname, acls->acl_attr.st_size, acls->acl_attr.st_mode, 1412b6b15642SReza Sabdar acls->acl_attr.st_uid, acls->acl_attr.st_gid); 1413b6b15642SReza Sabdar 14142654012fSReza Sabdar size = acls->acl_attr.st_size; 14152654012fSReza Sabdar while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) { 14162654012fSReza Sabdar char *rec; 14172654012fSReza Sabdar int write_size; 1418b6b15642SReza Sabdar int sysattr_write = 0; 14192654012fSReza Sabdar 14202654012fSReza Sabdar error = 0; 14212654012fSReza Sabdar rec = get_read_buffer(size, &error, &actual_size, 14222654012fSReza Sabdar local_commands); 1423b6b15642SReza Sabdar 1424b6b15642SReza Sabdar if ((actual_size < size) && sysattr_rw(xattrname)) { 1425b6b15642SReza Sabdar rec = get_read_one_buf(rec, actual_size, size, &error, 1426b6b15642SReza Sabdar local_commands); 1427b6b15642SReza Sabdar if (rec == NULL) { 1428b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 1429b6b15642SReza Sabdar error, xattrname); 1430b6b15642SReza Sabdar return (size); 1431b6b15642SReza Sabdar } 1432b6b15642SReza Sabdar actual_size = size; 1433b6b15642SReza Sabdar sysattr_write = 1; 1434b6b15642SReza Sabdar } 14352654012fSReza Sabdar if (actual_size <= 0) { 14362654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 14372654012fSReza Sabdar "RESTORE WRITER> error %d, actual_size %d", 14382654012fSReza Sabdar error, actual_size); 14392654012fSReza Sabdar 14402654012fSReza Sabdar return (size); 14412654012fSReza Sabdar } else if (error) { 14422654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 14432654012fSReza Sabdar error, local_commands->tc_file_name); 14442654012fSReza Sabdar break; 14452654012fSReza Sabdar } else { 14462654012fSReza Sabdar write_size = min(size, actual_size); 1447b6b15642SReza Sabdar if ((write_size = write(*fp, rec, write_size)) < 0) { 1448b6b15642SReza Sabdar if (sysattr_write) 1449b6b15642SReza Sabdar free(rec); 1450b6b15642SReza Sabdar 1451b6b15642SReza Sabdar break; 1452b6b15642SReza Sabdar } 1453b6b15642SReza Sabdar 14542654012fSReza Sabdar NS_ADD(wdisk, write_size); 14552654012fSReza Sabdar NS_INC(wfile); 14562654012fSReza Sabdar size -= write_size; 14572654012fSReza Sabdar } 1458b6b15642SReza Sabdar if (sysattr_write) 1459b6b15642SReza Sabdar free(rec); 14602654012fSReza Sabdar } 14612654012fSReza Sabdar 14622654012fSReza Sabdar if (*fp != 0) { 14632654012fSReza Sabdar set_xattr(*fp, acls->acl_attr); 14642654012fSReza Sabdar (void) close(*fp); 14652654012fSReza Sabdar *fp = 0; 14662654012fSReza Sabdar } 14672654012fSReza Sabdar return (0); 14682654012fSReza Sabdar } 14692654012fSReza Sabdar 14702654012fSReza Sabdar /* 14712654012fSReza Sabdar * Match the name with the list 14722654012fSReza Sabdar */ 14732654012fSReza Sabdar static int 14742654012fSReza Sabdar exact_find(char *name, char **list) 14752654012fSReza Sabdar { 14762654012fSReza Sabdar boolean_t found; 14772654012fSReza Sabdar int i; 14782654012fSReza Sabdar char *cp; 14792654012fSReza Sabdar 14802654012fSReza Sabdar found = FALSE; 14812654012fSReza Sabdar for (i = 0; *list != NULL; list++, i++) { 14822654012fSReza Sabdar cp = *list + strspn(*list, "/"); 14832654012fSReza Sabdar if (match(cp, name)) { 14842654012fSReza Sabdar found = TRUE; 14852654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "exact_find> found[%s]", cp); 14862654012fSReza Sabdar break; 14872654012fSReza Sabdar } 14882654012fSReza Sabdar } 14892654012fSReza Sabdar 14902654012fSReza Sabdar return (found); 14912654012fSReza Sabdar } 14922654012fSReza Sabdar 14932654012fSReza Sabdar /* 14942654012fSReza Sabdar * On error, return FALSE and prevent restoring(probably) unwanted data. 14952654012fSReza Sabdar */ 14962654012fSReza Sabdar static int 14972654012fSReza Sabdar is_parent(char *parent, char *child, int flags) 14982654012fSReza Sabdar { 14992654012fSReza Sabdar char tmp[TLM_MAX_PATH_NAME]; 15002654012fSReza Sabdar boolean_t rv; 15012654012fSReza Sabdar 15022654012fSReza Sabdar if (IS_SET(flags, RSFLG_MATCH_WCARD)) { 15032654012fSReza Sabdar if (!tlm_cat_path(tmp, parent, "*")) { 15042654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 15052654012fSReza Sabdar "is_parent> path too long [%s]", parent); 15062654012fSReza Sabdar rv = FALSE; 15072654012fSReza Sabdar } else 15082654012fSReza Sabdar rv = (match(tmp, child) != 0) ? TRUE : FALSE; 15092654012fSReza Sabdar } else { 15102654012fSReza Sabdar if (!tlm_cat_path(tmp, parent, "/")) { 15112654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 15122654012fSReza Sabdar "is_parent> path too long [%s]", parent); 15132654012fSReza Sabdar rv = FALSE; 15142654012fSReza Sabdar } else 15152654012fSReza Sabdar rv = (strncmp(tmp, child, strlen(tmp)) == 0) ? 15162654012fSReza Sabdar TRUE : FALSE; 15172654012fSReza Sabdar } 15182654012fSReza Sabdar 15192654012fSReza Sabdar return (rv); 15202654012fSReza Sabdar } 15212654012fSReza Sabdar 15222654012fSReza Sabdar /* 15232654012fSReza Sabdar * Used to match the filename inside the list 15242654012fSReza Sabdar */ 15252654012fSReza Sabdar static boolean_t 15262654012fSReza Sabdar strexactcmp(char *s, char *t) 15272654012fSReza Sabdar { 15282654012fSReza Sabdar return ((strcmp(s, t) == 0) ? TRUE : FALSE); 15292654012fSReza Sabdar } 15302654012fSReza Sabdar 15312654012fSReza Sabdar /* 15322654012fSReza Sabdar * Check if the file is needed to be restored 15332654012fSReza Sabdar */ 15342654012fSReza Sabdar static boolean_t 15352654012fSReza Sabdar is_file_wanted(char *name, 15362654012fSReza Sabdar char **sels, 15372654012fSReza Sabdar char **exls, 15382654012fSReza Sabdar int flags, 15392654012fSReza Sabdar int *mchtype, 15402654012fSReza Sabdar int *pos) 15412654012fSReza Sabdar { 15422654012fSReza Sabdar char *p_sel; 15432654012fSReza Sabdar char *uc_name, *retry, *namep; 15442654012fSReza Sabdar boolean_t found; 15452654012fSReza Sabdar int i; 15462654012fSReza Sabdar name_match_fp_t *cmp_fp; 15472654012fSReza Sabdar 15482654012fSReza Sabdar if (name == NULL || sels == NULL || exls == NULL) 15492654012fSReza Sabdar return (FALSE); 15502654012fSReza Sabdar 15512654012fSReza Sabdar found = FALSE; 15522654012fSReza Sabdar if (mchtype != NULL) 15532654012fSReza Sabdar *mchtype = PM_NONE; 15542654012fSReza Sabdar if (pos != NULL) 15552654012fSReza Sabdar *pos = 0; 15562654012fSReza Sabdar 15572654012fSReza Sabdar /* 15582654012fSReza Sabdar * For empty selection, restore everything 15592654012fSReza Sabdar */ 15602654012fSReza Sabdar if (*sels == NULL || **sels == '\0') { 15612654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "is_file_wanted: Restore all"); 15622654012fSReza Sabdar return (TRUE); 15632654012fSReza Sabdar } 15642654012fSReza Sabdar 15652654012fSReza Sabdar retry = ndmp_malloc(TLM_MAX_PATH_NAME); 1566fb4eb4e8SReza Sabdar if (retry == NULL) 15672654012fSReza Sabdar return (FALSE); 15682654012fSReza Sabdar 15692654012fSReza Sabdar if (IS_SET(flags, RSFLG_MATCH_WCARD)) 15702654012fSReza Sabdar cmp_fp = match; 15712654012fSReza Sabdar else 15722654012fSReza Sabdar cmp_fp = strexactcmp; 15732654012fSReza Sabdar 15742654012fSReza Sabdar namep = name + strspn(name, "/"); 1575fb4eb4e8SReza Sabdar 15762654012fSReza Sabdar if (IS_SET(flags, RSFLG_IGNORE_CASE)) { 1577fb4eb4e8SReza Sabdar uc_name = ndmp_malloc(TLM_MAX_PATH_NAME); 1578fb4eb4e8SReza Sabdar if (uc_name == NULL) { 1579fb4eb4e8SReza Sabdar free(retry); 1580fb4eb4e8SReza Sabdar return (FALSE); 1581fb4eb4e8SReza Sabdar } 15822654012fSReza Sabdar (void) strlcpy(uc_name, namep, TLM_MAX_PATH_NAME); 15832654012fSReza Sabdar (void) strupr(uc_name); 15842654012fSReza Sabdar namep = uc_name; 15852654012fSReza Sabdar } 15862654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "is_file_wanted> flg: 0x%x name: [%s]", 15872654012fSReza Sabdar flags, name); 15882654012fSReza Sabdar 15892654012fSReza Sabdar for (i = 0; *sels != NULL; sels++, i++) { 15902654012fSReza Sabdar p_sel = *sels + strspn(*sels, "/"); 15912654012fSReza Sabdar 15922654012fSReza Sabdar /* 15932654012fSReza Sabdar * Try exact match. 15942654012fSReza Sabdar */ 15952654012fSReza Sabdar if ((*cmp_fp)(p_sel, namep)) { 15962654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "match1> pos: %d [%s][%s]", 15972654012fSReza Sabdar i, p_sel, name); 15982654012fSReza Sabdar found = TRUE; 15992654012fSReza Sabdar if (mchtype != NULL) 16002654012fSReza Sabdar *mchtype = PM_EXACT; 16012654012fSReza Sabdar break; 16022654012fSReza Sabdar } 16032654012fSReza Sabdar /* 16042654012fSReza Sabdar * Try "entry/" and the current selection. The 16052654012fSReza Sabdar * current selection may be something like "<something>/". 16062654012fSReza Sabdar */ 16072654012fSReza Sabdar (void) tlm_cat_path(retry, namep, "/"); 16082654012fSReza Sabdar if ((*cmp_fp)(p_sel, retry)) { 16092654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "match2> pos %d [%s][%s]", 16102654012fSReza Sabdar i, p_sel, name); 16112654012fSReza Sabdar found = TRUE; 16122654012fSReza Sabdar if (mchtype != NULL) 16132654012fSReza Sabdar *mchtype = PM_EXACT; 16142654012fSReza Sabdar break; 16152654012fSReza Sabdar } 16162654012fSReza Sabdar /* 16172654012fSReza Sabdar * If the following check returns true it means that the 16182654012fSReza Sabdar * 'name' is an entry below the 'p_sel' hierarchy. 16192654012fSReza Sabdar */ 16202654012fSReza Sabdar if (is_parent(p_sel, namep, flags)) { 16212654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "parent1> pos %d [%s][%s]", 16222654012fSReza Sabdar i, p_sel, name); 16232654012fSReza Sabdar found = TRUE; 16242654012fSReza Sabdar if (mchtype != NULL) 16252654012fSReza Sabdar *mchtype = PM_CHILD; 16262654012fSReza Sabdar break; 16272654012fSReza Sabdar } 16282654012fSReza Sabdar /* 16292654012fSReza Sabdar * There is a special case for parent directories of a 16302654012fSReza Sabdar * selection. If 'p_sel' is something like "*d1", the 16312654012fSReza Sabdar * middle directories of the final entry can't be determined 16322654012fSReza Sabdar * until the final entry matches with 'p_sel'. At that 16332654012fSReza Sabdar * time the middle directories of the entry have been passed 16342654012fSReza Sabdar * and they can't be restored. 16352654012fSReza Sabdar */ 16362654012fSReza Sabdar if (is_parent(namep, p_sel, flags)) { 16372654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "parent2> pos %d [%s][%s]", 16382654012fSReza Sabdar i, p_sel, name); 16392654012fSReza Sabdar found = TRUE; 16402654012fSReza Sabdar if (mchtype != NULL) 16412654012fSReza Sabdar *mchtype = PM_PARENT; 16422654012fSReza Sabdar break; 16432654012fSReza Sabdar } 16442654012fSReza Sabdar } 16452654012fSReza Sabdar 16462654012fSReza Sabdar /* Check for exclusions. */ 16472654012fSReza Sabdar if (found && exact_find(namep, exls)) { 16482654012fSReza Sabdar if (mchtype != NULL) 16492654012fSReza Sabdar *mchtype = PM_NONE; 16502654012fSReza Sabdar found = FALSE; 16512654012fSReza Sabdar } 16522654012fSReza Sabdar if (found && pos != NULL) 16532654012fSReza Sabdar *pos = i; 16542654012fSReza Sabdar 1655fb4eb4e8SReza Sabdar if (IS_SET(flags, RSFLG_IGNORE_CASE)) 1656fb4eb4e8SReza Sabdar free(uc_name); 16572654012fSReza Sabdar free(retry); 16582654012fSReza Sabdar return (found); 16592654012fSReza Sabdar } 16602654012fSReza Sabdar 16612654012fSReza Sabdar /* 16622654012fSReza Sabdar * Read the specified amount data into the buffer. Detects EOT or EOF 16632654012fSReza Sabdar * during read. 16642654012fSReza Sabdar * 16652654012fSReza Sabdar * Returns the number of bytes actually read. On error returns -1. 16662654012fSReza Sabdar */ 16672654012fSReza Sabdar static int 16682654012fSReza Sabdar input_mem(int l, 16692654012fSReza Sabdar int d, 16702654012fSReza Sabdar tlm_cmd_t *lcmds, 16712654012fSReza Sabdar char *mem, 16722654012fSReza Sabdar int len) 16732654012fSReza Sabdar { 16742654012fSReza Sabdar int err; 16752654012fSReza Sabdar int toread, actual_size, rec_size; 16762654012fSReza Sabdar char *rec; 16772654012fSReza Sabdar 16782654012fSReza Sabdar if (l <= 0 || d <= 0 || !lcmds || !mem) { 16792654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument"); 16802654012fSReza Sabdar return (-1); 16812654012fSReza Sabdar } 16822654012fSReza Sabdar 16832654012fSReza Sabdar toread = len; 16842654012fSReza Sabdar while (toread > 0) { 16852654012fSReza Sabdar rec = get_read_buffer(toread, &err, &actual_size, lcmds); 16862654012fSReza Sabdar if (actual_size <= 0) { 16872654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "err %d act_size %d detected", 16882654012fSReza Sabdar err, actual_size); 16892654012fSReza Sabdar break; 16902654012fSReza Sabdar } else if (err) { 16912654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d reading data", err); 16922654012fSReza Sabdar return (-1); 16932654012fSReza Sabdar } 16942654012fSReza Sabdar rec_size = min(actual_size, toread); 16952654012fSReza Sabdar (void) memcpy(mem, rec, rec_size); 16962654012fSReza Sabdar mem += rec_size; 16972654012fSReza Sabdar toread -= rec_size; 16982654012fSReza Sabdar } 16992654012fSReza Sabdar 17002654012fSReza Sabdar return (len - toread); 17012654012fSReza Sabdar } 17022654012fSReza Sabdar 17032654012fSReza Sabdar /* 17042654012fSReza Sabdar * pick up the name and size of a HUGE file 17052654012fSReza Sabdar */ 17062654012fSReza Sabdar static int 17072654012fSReza Sabdar get_humongus_file_header(int lib, 17082654012fSReza Sabdar int drv, 17092654012fSReza Sabdar long recsize, 17102654012fSReza Sabdar longlong_t *size, 17112654012fSReza Sabdar char *name, 17122654012fSReza Sabdar tlm_cmd_t *local_commands) 17132654012fSReza Sabdar { 17142654012fSReza Sabdar char *p_record, *value; 17152654012fSReza Sabdar int rv; 17162654012fSReza Sabdar 17172654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE Record found: %d", recsize); 17182654012fSReza Sabdar 17192654012fSReza Sabdar rv = 0; 17202654012fSReza Sabdar if (recsize == 0) { 17212654012fSReza Sabdar /* 17222654012fSReza Sabdar * The humongus_file_header was written in a 17232654012fSReza Sabdar * RECORDSIZE block and the header.size field of this 17242654012fSReza Sabdar * record was 0 before this fix. For backward compatiblity 17252654012fSReza Sabdar * read only one RECORDSIZE-size block if the header.size 17262654012fSReza Sabdar * field is 0. Otherwise the header.size field should show 17272654012fSReza Sabdar * the length of the data of this header. 17282654012fSReza Sabdar */ 17292654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Old HUGE record found"); 17302654012fSReza Sabdar recsize = RECORDSIZE; 17312654012fSReza Sabdar } 17322654012fSReza Sabdar 17332654012fSReza Sabdar if (input_mem(lib, drv, local_commands, name, recsize) != recsize) { 17342654012fSReza Sabdar rv = -1; 17352654012fSReza Sabdar *size = 0; 17362654012fSReza Sabdar *name = '\0'; 17372654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error reading a HUGE file name"); 17382654012fSReza Sabdar } else { 17392654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE [%s]", name); 17402654012fSReza Sabdar 17412654012fSReza Sabdar p_record = name; 17422654012fSReza Sabdar value = parse(&p_record, " "); 17432654012fSReza Sabdar *size = atoll(value); 17442654012fSReza Sabdar /* 17452654012fSReza Sabdar * Note: Since the backed up names are not longer than 17462654012fSReza Sabdar * NAME_MAX and the buffer passed to us is 17472654012fSReza Sabdar * TLM_MAX_PATH_NAME, it should be safe to use strlcpy 17482654012fSReza Sabdar * without check on the buffer size. 17492654012fSReza Sabdar */ 17502654012fSReza Sabdar (void) strlcpy(name, p_record, TLM_MAX_PATH_NAME); 17512654012fSReza Sabdar } 17522654012fSReza Sabdar 17532654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE Record %lld [%s]", *size, name); 17542654012fSReza Sabdar 17552654012fSReza Sabdar return (rv); 17562654012fSReza Sabdar } 17572654012fSReza Sabdar 17582654012fSReza Sabdar /* 17592654012fSReza Sabdar * pick up the long name from the special tape file 17602654012fSReza Sabdar */ 17612654012fSReza Sabdar static int 17622654012fSReza Sabdar get_long_name(int lib, 17632654012fSReza Sabdar int drv, 17642654012fSReza Sabdar long recsize, 17652654012fSReza Sabdar char *name, 17662654012fSReza Sabdar long *buf_spot, 17672654012fSReza Sabdar tlm_cmd_t *local_commands) 17682654012fSReza Sabdar { 17692654012fSReza Sabdar int nread; 17702654012fSReza Sabdar 17712654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "LONGNAME Record found rs %d bs %d", recsize, 17722654012fSReza Sabdar *buf_spot); 17732654012fSReza Sabdar 17742654012fSReza Sabdar if (*buf_spot < 0) 17752654012fSReza Sabdar *buf_spot = 0; 17762654012fSReza Sabdar 17772654012fSReza Sabdar nread = input_mem(lib, drv, local_commands, name + *buf_spot, 17782654012fSReza Sabdar recsize); 17792654012fSReza Sabdar if (nread < 0) { 17802654012fSReza Sabdar nread = recsize; /* return 0 as size left */ 17812654012fSReza Sabdar name[*buf_spot] = '\0'; 17822654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Error %d reading a long file name %s.", 17832654012fSReza Sabdar nread, name); 17842654012fSReza Sabdar } else { 17852654012fSReza Sabdar *buf_spot += nread; 17862654012fSReza Sabdar name[*buf_spot] = '\0'; 17872654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "LONGNAME [%s]", name); 17882654012fSReza Sabdar } 17892654012fSReza Sabdar 17902654012fSReza Sabdar return (recsize - nread); 17912654012fSReza Sabdar } 17922654012fSReza Sabdar 17932654012fSReza Sabdar /* 17942654012fSReza Sabdar * create a new directory 17952654012fSReza Sabdar */ 17962654012fSReza Sabdar static int 17972654012fSReza Sabdar create_directory(char *dir, tlm_job_stats_t *job_stats) 17982654012fSReza Sabdar { 17992654012fSReza Sabdar struct stat64 attr; 18002654012fSReza Sabdar char *p; 18012654012fSReza Sabdar char temp; 18022654012fSReza Sabdar int erc; 18032654012fSReza Sabdar 18042654012fSReza Sabdar /* 18052654012fSReza Sabdar * Make sure all directories in this path exist, create them if 18062654012fSReza Sabdar * needed. 18072654012fSReza Sabdar */ 18082654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new dir[%s]", dir); 18092654012fSReza Sabdar 18102654012fSReza Sabdar erc = 0; 18112654012fSReza Sabdar p = &dir[1]; 18122654012fSReza Sabdar do { 18132654012fSReza Sabdar temp = *p; 18142654012fSReza Sabdar if (temp == '/' || temp == 0) { 18152654012fSReza Sabdar *p = 0; 18162654012fSReza Sabdar if (stat64(dir, &attr) < 0) { 18172654012fSReza Sabdar erc = mkdir(dir, 0777); 18182654012fSReza Sabdar if (erc < 0) { 18192654012fSReza Sabdar job_stats->js_errors++; 18202654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 18212654012fSReza Sabdar "Could not create directory %s", 18222654012fSReza Sabdar dir); 18232654012fSReza Sabdar break; 18242654012fSReza Sabdar } 18252654012fSReza Sabdar } 18262654012fSReza Sabdar *p = temp; 18272654012fSReza Sabdar } 18282654012fSReza Sabdar p++; 18292654012fSReza Sabdar } while (temp != 0); 18302654012fSReza Sabdar 18312654012fSReza Sabdar return (erc); 18322654012fSReza Sabdar } 18332654012fSReza Sabdar 18342654012fSReza Sabdar /* 18352654012fSReza Sabdar * create a new hardlink 18362654012fSReza Sabdar */ 18372654012fSReza Sabdar static int 18382654012fSReza Sabdar create_hard_link(char *name_old, char *name_new, 18392654012fSReza Sabdar tlm_acls_t *acls, tlm_job_stats_t *job_stats) 18402654012fSReza Sabdar { 18412654012fSReza Sabdar int erc; 18422654012fSReza Sabdar 18432654012fSReza Sabdar if (mkbasedir(name_new)) { 18442654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "faile to make base dir for [%s]", 18452654012fSReza Sabdar name_new); 18462654012fSReza Sabdar 18472654012fSReza Sabdar return (-1); 18482654012fSReza Sabdar } 18492654012fSReza Sabdar 18502654012fSReza Sabdar erc = link(name_old, name_new); 1851fb4eb4e8SReza Sabdar 1852fb4eb4e8SReza Sabdar /* Nothing to do if the destination already exists */ 1853fb4eb4e8SReza Sabdar if (erc && (errno == EEXIST)) 1854fb4eb4e8SReza Sabdar return (0); 1855fb4eb4e8SReza Sabdar 18562654012fSReza Sabdar if (erc) { 18572654012fSReza Sabdar job_stats->js_errors++; 18582654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d (errno %d) hardlink [%s] to [%s]", 18592654012fSReza Sabdar erc, errno, name_new, name_old); 18602654012fSReza Sabdar } else { 18612654012fSReza Sabdar set_acl(name_new, acls); 18622654012fSReza Sabdar } 18632654012fSReza Sabdar return (erc); 18642654012fSReza Sabdar } 18652654012fSReza Sabdar 18662654012fSReza Sabdar /* 18672654012fSReza Sabdar * create a new symlink 18682654012fSReza Sabdar */ 18692654012fSReza Sabdar /*ARGSUSED*/ 18702654012fSReza Sabdar static int 18712654012fSReza Sabdar create_sym_link(char *dst, char *target, tlm_acls_t *acls, 1872*5181c2afSReza Sabdar tlm_job_stats_t *job_stats) 18732654012fSReza Sabdar { 18742654012fSReza Sabdar int erc; 1875859b7745SReza Sabdar struct stat64 *st; 18762654012fSReza Sabdar 18772654012fSReza Sabdar if (mkbasedir(dst) < 0) 18782654012fSReza Sabdar return (-1); 18792654012fSReza Sabdar 1880859b7745SReza Sabdar st = &acls->acl_attr; 18812654012fSReza Sabdar erc = symlink(target, dst); 18822654012fSReza Sabdar if (erc) { 1883*5181c2afSReza Sabdar job_stats->js_errors++; 18842654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d (errno %d) softlink [%s] to [%s]", 18852654012fSReza Sabdar erc, errno, dst, target); 188686c48bbfSReza Sabdar } else { 1887859b7745SReza Sabdar st->st_mode |= S_IFLNK; 188886c48bbfSReza Sabdar set_acl(dst, acls); 18892654012fSReza Sabdar } 18902654012fSReza Sabdar 18912654012fSReza Sabdar return (erc); 18922654012fSReza Sabdar } 18932654012fSReza Sabdar 18942654012fSReza Sabdar /* 1895*5181c2afSReza Sabdar * create a new FIFO, char/block device special files 18962654012fSReza Sabdar */ 18972654012fSReza Sabdar static int 1898*5181c2afSReza Sabdar create_special(char flag, char *name, tlm_acls_t *acls, int major, int minor, 1899*5181c2afSReza Sabdar tlm_job_stats_t *job_stats) 19002654012fSReza Sabdar { 1901*5181c2afSReza Sabdar dev_t dev; 1902*5181c2afSReza Sabdar mode_t mode; 1903*5181c2afSReza Sabdar int erc; 1904*5181c2afSReza Sabdar 1905*5181c2afSReza Sabdar switch (flag) { 1906*5181c2afSReza Sabdar case LF_CHR: 1907*5181c2afSReza Sabdar mode = S_IFCHR; 1908*5181c2afSReza Sabdar dev = makedev(major, minor); 1909*5181c2afSReza Sabdar break; 1910*5181c2afSReza Sabdar case LF_BLK: 1911*5181c2afSReza Sabdar mode = S_IFBLK; 1912*5181c2afSReza Sabdar dev = makedev(major, minor); 1913*5181c2afSReza Sabdar break; 1914*5181c2afSReza Sabdar case LF_FIFO: 1915*5181c2afSReza Sabdar mode = S_IFIFO; 1916*5181c2afSReza Sabdar dev = 0; 1917*5181c2afSReza Sabdar break; 1918*5181c2afSReza Sabdar default: 1919*5181c2afSReza Sabdar NDMP_LOG(LOG_ERR, "unsupported flag %d", flag); 1920*5181c2afSReza Sabdar return (-1); 1921*5181c2afSReza Sabdar } 1922*5181c2afSReza Sabdar 1923*5181c2afSReza Sabdar /* Remove the old entry first */ 1924*5181c2afSReza Sabdar if (rmdir(name) < 0) { 1925*5181c2afSReza Sabdar if (errno == ENOTDIR) 1926*5181c2afSReza Sabdar (void) unlink(name); 1927*5181c2afSReza Sabdar } 1928*5181c2afSReza Sabdar erc = mknod(name, 0777 | mode, dev); 1929*5181c2afSReza Sabdar if (erc) { 1930*5181c2afSReza Sabdar job_stats->js_errors++; 1931*5181c2afSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d (errno %d) mknod [%s] major" 1932*5181c2afSReza Sabdar " %d minor %d", erc, errno, name, major, minor); 1933*5181c2afSReza Sabdar } else { 1934*5181c2afSReza Sabdar set_acl(name, acls); 1935*5181c2afSReza Sabdar } 1936*5181c2afSReza Sabdar return (erc); 19372654012fSReza Sabdar } 19382654012fSReza Sabdar 19392654012fSReza Sabdar /* 19402654012fSReza Sabdar * read in the ACLs for the next file 19412654012fSReza Sabdar */ 19422654012fSReza Sabdar static long 19432654012fSReza Sabdar load_acl_info(int lib, 19442654012fSReza Sabdar int drv, 19452654012fSReza Sabdar long file_size, 19462654012fSReza Sabdar tlm_acls_t *acls, 19472654012fSReza Sabdar long *acl_spot, 19482654012fSReza Sabdar tlm_cmd_t *local_commands) 19492654012fSReza Sabdar { 19502654012fSReza Sabdar char *bp; 19512654012fSReza Sabdar int nread; 19522654012fSReza Sabdar 19532654012fSReza Sabdar /* 19542654012fSReza Sabdar * If the ACL is spanned on tapes, then the acl_spot should NOT be 19552654012fSReza Sabdar * 0 on next calls to this function to read the rest of the ACL 19562654012fSReza Sabdar * on next tapes. 19572654012fSReza Sabdar */ 19582654012fSReza Sabdar if (*acl_spot == 0) { 19592654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 19602654012fSReza Sabdar } 19612654012fSReza Sabdar 19622654012fSReza Sabdar bp = ((char *)&acls->acl_info) + *acl_spot; 19632654012fSReza Sabdar nread = input_mem(lib, drv, local_commands, (void *)bp, file_size); 19642654012fSReza Sabdar if (nread < 0) { 19652654012fSReza Sabdar *acl_spot = 0; 19662654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 19672654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error reading ACL data"); 19682654012fSReza Sabdar return (0); 19692654012fSReza Sabdar } 19702654012fSReza Sabdar *acl_spot += nread; 19712654012fSReza Sabdar acls->acl_non_trivial = TRUE; 19722654012fSReza Sabdar 19732654012fSReza Sabdar return (file_size - nread); 19742654012fSReza Sabdar } 19752654012fSReza Sabdar 19762654012fSReza Sabdar static int 19772654012fSReza Sabdar ndmp_set_eprivs_least(void) 19782654012fSReza Sabdar { 19792654012fSReza Sabdar priv_set_t *priv_set; 19802654012fSReza Sabdar 19812654012fSReza Sabdar if ((priv_set = priv_allocset()) == NULL) { 19822654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Out of memory."); 19832654012fSReza Sabdar return (-1); 19842654012fSReza Sabdar } 1985634e26ecSCasper H.S. Dik 1986634e26ecSCasper H.S. Dik priv_basicset(priv_set); 1987634e26ecSCasper H.S. Dik 1988634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_PROC_AUDIT); 1989634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_PROC_SETID); 1990634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_PROC_OWNER); 1991634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_FILE_CHOWN); 1992634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF); 1993634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_FILE_DAC_READ); 1994634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_FILE_DAC_SEARCH); 1995634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE); 1996634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_FILE_OWNER); 1997634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_FILE_SETID); 1998634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_SYS_LINKDIR); 1999634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_SYS_DEVICES); 2000634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_SYS_MOUNT); 2001634e26ecSCasper H.S. Dik (void) priv_addset(priv_set, PRIV_SYS_CONFIG); 20022654012fSReza Sabdar 20032654012fSReza Sabdar if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 20042654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Additional privileges required."); 20052654012fSReza Sabdar priv_freeset(priv_set); 20062654012fSReza Sabdar return (-1); 20072654012fSReza Sabdar } 20082654012fSReza Sabdar priv_freeset(priv_set); 20092654012fSReza Sabdar return (0); 20102654012fSReza Sabdar } 20112654012fSReza Sabdar 20122654012fSReza Sabdar static int 20132654012fSReza Sabdar ndmp_set_eprivs_all(void) 20142654012fSReza Sabdar { 20152654012fSReza Sabdar priv_set_t *priv_set; 20162654012fSReza Sabdar 2017634e26ecSCasper H.S. Dik if ((priv_set = priv_allocset()) == NULL) { 2018634e26ecSCasper H.S. Dik NDMP_LOG(LOG_ERR, "Out of memory."); 20192654012fSReza Sabdar return (-1); 20202654012fSReza Sabdar } 2021634e26ecSCasper H.S. Dik 2022634e26ecSCasper H.S. Dik priv_fillset(priv_set); 2023634e26ecSCasper H.S. Dik 20242654012fSReza Sabdar if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) != 0) { 20252654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Additional privileges required."); 20262654012fSReza Sabdar return (-1); 20272654012fSReza Sabdar } 20282654012fSReza Sabdar priv_freeset(priv_set); 20292654012fSReza Sabdar return (0); 20302654012fSReza Sabdar } 20312654012fSReza Sabdar 20322654012fSReza Sabdar /* 20332654012fSReza Sabdar * Set the standard attributes of the file 20342654012fSReza Sabdar */ 20352654012fSReza Sabdar static void 2036b6b15642SReza Sabdar set_attr(char *name, tlm_acls_t *acls) 20372654012fSReza Sabdar { 20382654012fSReza Sabdar struct utimbuf tbuf; 20392654012fSReza Sabdar boolean_t priv_all = FALSE; 2040b6b15642SReza Sabdar struct stat64 *st; 2041b6b15642SReza Sabdar uid_t uid; 2042b6b15642SReza Sabdar gid_t gid; 2043b6b15642SReza Sabdar struct passwd *pwd; 2044b6b15642SReza Sabdar struct group *grp; 2045b6b15642SReza Sabdar 20462654012fSReza Sabdar 2047b6b15642SReza Sabdar if (!name || !acls) 20482654012fSReza Sabdar return; 20492654012fSReza Sabdar 2050b6b15642SReza Sabdar st = &acls->acl_attr; 2051b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "set_attr: %s uid %d gid %d uname %s gname %s " 2052b6b15642SReza Sabdar "mode %o", name, st->st_uid, st->st_gid, acls->uname, acls->gname, 2053b6b15642SReza Sabdar st->st_mode); 2054b6b15642SReza Sabdar 2055b6b15642SReza Sabdar uid = st->st_uid; 2056b6b15642SReza Sabdar if ((pwd = getpwnam(acls->uname)) != NULL) { 2057b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "set_attr: new uid %d old %d", 2058b6b15642SReza Sabdar pwd->pw_uid, uid); 2059b6b15642SReza Sabdar uid = pwd->pw_uid; 2060b6b15642SReza Sabdar } 2061b6b15642SReza Sabdar 2062b6b15642SReza Sabdar gid = st->st_gid; 2063b6b15642SReza Sabdar if ((grp = getgrnam(acls->gname)) != NULL) { 2064b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "set_attr: new gid %d old %d", 2065b6b15642SReza Sabdar grp->gr_gid, gid); 2066b6b15642SReza Sabdar gid = grp->gr_gid; 2067b6b15642SReza Sabdar } 20682654012fSReza Sabdar 206986c48bbfSReza Sabdar if (lchown(name, uid, gid)) 20702654012fSReza Sabdar NDMP_LOG(LOG_ERR, 20712654012fSReza Sabdar "Could not set uid or/and gid for file %s.", name); 20722654012fSReza Sabdar 20732654012fSReza Sabdar if ((st->st_mode & (S_ISUID | S_ISGID)) != 0) { 20742654012fSReza Sabdar /* 20752654012fSReza Sabdar * Change effective privileges to 'all' which is required to 20762654012fSReza Sabdar * change setuid bit for 'root' owned files. If fails, just 20772654012fSReza Sabdar * send error to log file and proceed. 20782654012fSReza Sabdar */ 20792654012fSReza Sabdar if (ndmp_set_eprivs_all()) { 20802654012fSReza Sabdar NDMP_LOG(LOG_ERR, 20812654012fSReza Sabdar "Could not set effective privileges to 'all'."); 20822654012fSReza Sabdar } else { 20832654012fSReza Sabdar priv_all = TRUE; 20842654012fSReza Sabdar } 20852654012fSReza Sabdar } 20862654012fSReza Sabdar 2087859b7745SReza Sabdar if (!S_ISLNK(st->st_mode)) { 2088859b7745SReza Sabdar if (chmod(name, st->st_mode)) 2089859b7745SReza Sabdar NDMP_LOG(LOG_ERR, "Could not set correct file" 2090859b7745SReza Sabdar " permission for file %s.", name); 2091859b7745SReza Sabdar 2092859b7745SReza Sabdar tbuf.modtime = st->st_mtime; 2093859b7745SReza Sabdar tbuf.actime = st->st_atime; 2094859b7745SReza Sabdar (void) utime(name, &tbuf); 2095859b7745SReza Sabdar } 20962654012fSReza Sabdar 20972654012fSReza Sabdar if (priv_all == TRUE) { 20982654012fSReza Sabdar /* 20992654012fSReza Sabdar * Give up the 'all' privileges for effective sets and go back 21002654012fSReza Sabdar * to least required privileges. If fails, just send error to 21012654012fSReza Sabdar * log file and proceed. 21022654012fSReza Sabdar */ 21032654012fSReza Sabdar if (ndmp_set_eprivs_least()) 21042654012fSReza Sabdar NDMP_LOG(LOG_ERR, 21052654012fSReza Sabdar "Could not set least required privileges."); 21062654012fSReza Sabdar } 21072654012fSReza Sabdar } 21082654012fSReza Sabdar 21092654012fSReza Sabdar /* 21102654012fSReza Sabdar * Set the ACL info for the file 21112654012fSReza Sabdar */ 21122654012fSReza Sabdar static void 21132654012fSReza Sabdar set_acl(char *name, tlm_acls_t *acls) 21142654012fSReza Sabdar { 21152654012fSReza Sabdar int erc; 21162654012fSReza Sabdar acl_t *aclp = NULL; 21172654012fSReza Sabdar 21182654012fSReza Sabdar if (name) 21192654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "set_acl: %s", name); 21202654012fSReza Sabdar if (acls != 0) { 21212654012fSReza Sabdar /* Need a place to save real modification time */ 21222654012fSReza Sabdar 2123b6b15642SReza Sabdar set_attr(name, acls); 21242654012fSReza Sabdar 21252654012fSReza Sabdar if (!acls->acl_non_trivial) { 21262654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 21272654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "set_acl: skipping trivial"); 21282654012fSReza Sabdar return; 21292654012fSReza Sabdar } 21302654012fSReza Sabdar 21312654012fSReza Sabdar erc = acl_fromtext(acls->acl_info.attr_info, &aclp); 21322654012fSReza Sabdar if (erc != 0) { 21332654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 21342654012fSReza Sabdar "TAPE RESTORE> acl_fromtext errno %d", erc); 21352654012fSReza Sabdar } 21362654012fSReza Sabdar if (aclp) { 21372654012fSReza Sabdar erc = acl_set(name, aclp); 21382654012fSReza Sabdar if (erc < 0) { 21392654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 21402654012fSReza Sabdar "TAPE RESTORE> acl_set errno %d", errno); 21412654012fSReza Sabdar } 21422654012fSReza Sabdar acl_free(aclp); 21432654012fSReza Sabdar } 21442654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 21452654012fSReza Sabdar } 21462654012fSReza Sabdar } 21472654012fSReza Sabdar 21482654012fSReza Sabdar /* 21492654012fSReza Sabdar * a wrapper to tlm_get_read_buffer so that 21502654012fSReza Sabdar * we can cleanly detect ABORT commands 21512654012fSReza Sabdar * without involving the TLM library with 21522654012fSReza Sabdar * our problems. 21532654012fSReza Sabdar */ 21542654012fSReza Sabdar static char * 21552654012fSReza Sabdar get_read_buffer(int want, 21562654012fSReza Sabdar int *error, 21572654012fSReza Sabdar int *actual_size, 21582654012fSReza Sabdar tlm_cmd_t *local_commands) 21592654012fSReza Sabdar { 21602654012fSReza Sabdar while (local_commands->tc_writer == TLM_RESTORE_RUN) { 21612654012fSReza Sabdar char *rec; 21622654012fSReza Sabdar rec = tlm_get_read_buffer(want, error, 21632654012fSReza Sabdar local_commands->tc_buffers, actual_size); 21642654012fSReza Sabdar if (rec != 0) { 21652654012fSReza Sabdar return (rec); 21662654012fSReza Sabdar } 21672654012fSReza Sabdar } 21682654012fSReza Sabdar 21692654012fSReza Sabdar /* 21702654012fSReza Sabdar * the job is ending, give Writer a buffer that will never be read ... 21712654012fSReza Sabdar * it does not matter anyhow, we are aborting. 21722654012fSReza Sabdar */ 21732654012fSReza Sabdar *actual_size = RECORDSIZE; 21742654012fSReza Sabdar return (NULL); 21752654012fSReza Sabdar } 21762654012fSReza Sabdar 21772654012fSReza Sabdar /* 21782654012fSReza Sabdar * Enable wildcard for restore options 21792654012fSReza Sabdar */ 21802654012fSReza Sabdar static boolean_t 21812654012fSReza Sabdar wildcard_enabled(void) 21822654012fSReza Sabdar { 21832654012fSReza Sabdar char *cp; 21842654012fSReza Sabdar 21852654012fSReza Sabdar cp = ndmpd_get_prop_default(NDMP_RESTORE_WILDCARD_ENABLE, "n"); 21862654012fSReza Sabdar return ((toupper(*cp) == 'Y') ? TRUE : FALSE); 21872654012fSReza Sabdar } 21882654012fSReza Sabdar 21892654012fSReza Sabdar 21902654012fSReza Sabdar /* 21912654012fSReza Sabdar * Concatenate two names 21922654012fSReza Sabdar */ 21932654012fSReza Sabdar /*ARGSUSED*/ 21942654012fSReza Sabdar static char * 21952654012fSReza Sabdar catnames(struct rs_name_maker *rnp, char *buf, int pos, char *path) 21962654012fSReza Sabdar { 21972654012fSReza Sabdar char *rv; 21982654012fSReza Sabdar 21992654012fSReza Sabdar rv = NULL; 22002654012fSReza Sabdar if (!buf) { 22012654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "buf is NULL"); 22022654012fSReza Sabdar } else if (!path) { 22032654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "path is NULL"); 22042654012fSReza Sabdar } else if (!rnp->rn_nlp) { 22052654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "rn_nlp is NULL [%s]", path); 22062654012fSReza Sabdar } else if (!tlm_cat_path(buf, rnp->rn_nlp, path)) { 22072654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", 22082654012fSReza Sabdar rnp->rn_nlp, path); 22092654012fSReza Sabdar } else 22102654012fSReza Sabdar rv = buf; 22112654012fSReza Sabdar 22122654012fSReza Sabdar return (rv); 22132654012fSReza Sabdar } 22142654012fSReza Sabdar 22152654012fSReza Sabdar 22162654012fSReza Sabdar /* 22172654012fSReza Sabdar * Create a new name path for restore 22182654012fSReza Sabdar */ 22192654012fSReza Sabdar static char * 22202654012fSReza Sabdar rs_new_name(struct rs_name_maker *rnp, char *buf, int pos, char *path) 22212654012fSReza Sabdar { 22222654012fSReza Sabdar if (!rnp || !rnp->rn_fp) 22232654012fSReza Sabdar return (NULL); 22242654012fSReza Sabdar 22252654012fSReza Sabdar return (*rnp->rn_fp)(rnp, buf, pos, path); 22262654012fSReza Sabdar } 22272654012fSReza Sabdar 2228fb4eb4e8SReza Sabdar /* 2229fb4eb4e8SReza Sabdar * Clear the extra "/" in the tar header if exists 2230fb4eb4e8SReza Sabdar */ 2231fb4eb4e8SReza Sabdar static void 2232fb4eb4e8SReza Sabdar rs_create_new_bkpath(char *bk_path, char *path, char *pbuf) 2233fb4eb4e8SReza Sabdar { 2234fb4eb4e8SReza Sabdar char *p, *slashp; 2235fb4eb4e8SReza Sabdar 2236fb4eb4e8SReza Sabdar if ((p = strstr(path, bk_path)) == NULL) { 2237fb4eb4e8SReza Sabdar (void) strlcpy(pbuf, path, TLM_MAX_PATH_NAME); 2238fb4eb4e8SReza Sabdar return; 2239fb4eb4e8SReza Sabdar } 2240fb4eb4e8SReza Sabdar if (*(p += strlen(bk_path)) == '/') 2241fb4eb4e8SReza Sabdar p++; 2242fb4eb4e8SReza Sabdar 2243fb4eb4e8SReza Sabdar slashp = bk_path + strlen(bk_path) - 1; 2244fb4eb4e8SReza Sabdar if (*slashp == '/') 2245fb4eb4e8SReza Sabdar (void) snprintf(pbuf, TLM_MAX_PATH_NAME, "%s%s", bk_path, p); 2246fb4eb4e8SReza Sabdar else 2247fb4eb4e8SReza Sabdar (void) snprintf(pbuf, TLM_MAX_PATH_NAME, "%s/%s", bk_path, p); 2248fb4eb4e8SReza Sabdar 2249fb4eb4e8SReza Sabdar NDMP_LOG(LOG_DEBUG, "old path [%s] new path [%s]", path, pbuf); 2250fb4eb4e8SReza Sabdar } 2251fb4eb4e8SReza Sabdar 2252fb4eb4e8SReza Sabdar 22532654012fSReza Sabdar /* 22542654012fSReza Sabdar * Iterate over ZFS metadata stored in the backup stream and use the callback 22552654012fSReza Sabdar * to restore it. 22562654012fSReza Sabdar */ 22572654012fSReza Sabdar int 22582654012fSReza Sabdar ndmp_iter_zfs(ndmp_context_t *nctx, int (*np_restore_property)(nvlist_t *, 22592654012fSReza Sabdar void *), void *ptr) 22602654012fSReza Sabdar { 22612654012fSReza Sabdar tlm_commands_t *cmds; 22622654012fSReza Sabdar ndmp_metadata_header_t *mhp; 226342ed7838SReza Sabdar ndmp_metadata_header_ext_t *mhpx; 22642654012fSReza Sabdar ndmp_metadata_property_t *mpp; 226542ed7838SReza Sabdar ndmp_metadata_property_ext_t *mppx; 22662654012fSReza Sabdar tlm_cmd_t *lcmd; 22672654012fSReza Sabdar int actual_size; 22682654012fSReza Sabdar nvlist_t *nvl; 22692654012fSReza Sabdar nvlist_t *valp; 22702654012fSReza Sabdar nvpair_t *nvp = NULL; 22712654012fSReza Sabdar char plname[100]; 22722654012fSReza Sabdar char *mhbuf, *pp, *tp; 22732654012fSReza Sabdar int rv, i; 22742654012fSReza Sabdar int size, lsize, sz; 22752654012fSReza Sabdar int align = RECORDSIZE - 1; 22762654012fSReza Sabdar 22772654012fSReza Sabdar if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 22782654012fSReza Sabdar return (-1); 22792654012fSReza Sabdar 22802654012fSReza Sabdar nctx->nc_plname = plname; 22812654012fSReza Sabdar if ((lcmd = cmds->tcs_command) == NULL || 22822654012fSReza Sabdar lcmd->tc_buffers == NULL) 22832654012fSReza Sabdar return (-1); 22842654012fSReza Sabdar 228542ed7838SReza Sabdar /* Default minimum bytes needed */ 22862654012fSReza Sabdar size = sizeof (ndmp_metadata_header_t) + 22872654012fSReza Sabdar ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 22882654012fSReza Sabdar size += align; 22892654012fSReza Sabdar size &= ~align; 22902654012fSReza Sabdar 22912654012fSReza Sabdar if ((mhbuf = malloc(size)) == NULL) 22922654012fSReza Sabdar return (-1); 22932654012fSReza Sabdar 22942654012fSReza Sabdar /* LINTED improper alignment */ 22952654012fSReza Sabdar while ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv, 22962654012fSReza Sabdar &actual_size, lcmd)) != NULL) { 22972654012fSReza Sabdar pp = mhbuf; 22982654012fSReza Sabdar 22992654012fSReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC, 230042ed7838SReza Sabdar sizeof (mhp->nh_magic)) != 0 && 230142ed7838SReza Sabdar strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT, 23022654012fSReza Sabdar sizeof (mhp->nh_magic)) != 0) { 23032654012fSReza Sabdar /* No more metadata */ 23042654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 230542ed7838SReza Sabdar free(mhbuf); 23062654012fSReza Sabdar return (0); 23072654012fSReza Sabdar } 23082654012fSReza Sabdar 230942ed7838SReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT, 231042ed7838SReza Sabdar sizeof (mhp->nh_magic)) == 0) { 231142ed7838SReza Sabdar mhpx = (ndmp_metadata_header_ext_t *)mhp; 231242ed7838SReza Sabdar if (mhpx->nh_total_bytes > size) { 231342ed7838SReza Sabdar if ((pp = realloc(mhbuf, mhpx->nh_total_bytes)) 231442ed7838SReza Sabdar == NULL) { 231542ed7838SReza Sabdar free(mhbuf); 231642ed7838SReza Sabdar return (-1); 231742ed7838SReza Sabdar } 231842ed7838SReza Sabdar mhbuf = pp; 231942ed7838SReza Sabdar } 232042ed7838SReza Sabdar size = mhpx->nh_total_bytes; 232142ed7838SReza Sabdar } 232242ed7838SReza Sabdar 23232654012fSReza Sabdar (void) memcpy(pp, (char *)mhp, (actual_size < size) ? 23242654012fSReza Sabdar actual_size : size); 23252654012fSReza Sabdar pp += (actual_size < size) ? actual_size : size; 23262654012fSReza Sabdar 23272654012fSReza Sabdar sz = actual_size; 23282654012fSReza Sabdar while (sz < size && 23292654012fSReza Sabdar ((tp = get_read_buffer(size - sz, &rv, &lsize, 23302654012fSReza Sabdar lcmd))) != NULL) { 233142ed7838SReza Sabdar (void) memcpy(pp, tp, lsize); 23322654012fSReza Sabdar sz += lsize; 23332654012fSReza Sabdar pp += lsize; 23342654012fSReza Sabdar } 23352654012fSReza Sabdar if (sz > size) { 23362654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, sz - size); 23372654012fSReza Sabdar } 233842ed7838SReza Sabdar 23392654012fSReza Sabdar /* LINTED improper alignment */ 23402654012fSReza Sabdar mhp = (ndmp_metadata_header_t *)mhbuf; 23412654012fSReza Sabdar 234242ed7838SReza Sabdar nvl = NULL; 234342ed7838SReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT, 234442ed7838SReza Sabdar sizeof (mhp->nh_magic)) == 0) { 234542ed7838SReza Sabdar /* New metadata format */ 234642ed7838SReza Sabdar /* LINTED improper alignment */ 234742ed7838SReza Sabdar mhpx = (ndmp_metadata_header_ext_t *)mhbuf; 234842ed7838SReza Sabdar 234942ed7838SReza Sabdar if (mhpx->nh_major > META_HDR_MAJOR_VERSION) { 235042ed7838SReza Sabdar /* Major header mismatch */ 235142ed7838SReza Sabdar NDMP_LOG(LOG_ERR, "metadata header mismatch", 235242ed7838SReza Sabdar "M%d != M%d", mhpx->nh_major, 235342ed7838SReza Sabdar META_HDR_MAJOR_VERSION); 235442ed7838SReza Sabdar free(mhbuf); 235542ed7838SReza Sabdar return (-1); 235642ed7838SReza Sabdar } 235742ed7838SReza Sabdar if (mhpx->nh_major == META_HDR_MAJOR_VERSION && 235842ed7838SReza Sabdar mhpx->nh_minor > META_HDR_MINOR_VERSION) { 235942ed7838SReza Sabdar /* Minor header mismatch */ 236042ed7838SReza Sabdar NDMP_LOG(LOG_ERR, "Warning:" 236142ed7838SReza Sabdar "metadata header mismatch m%d != m%d", 236242ed7838SReza Sabdar mhpx->nh_minor, 236342ed7838SReza Sabdar META_HDR_MINOR_VERSION); 236442ed7838SReza Sabdar continue; 236542ed7838SReza Sabdar } 23662654012fSReza Sabdar 236742ed7838SReza Sabdar nctx->nc_plversion = mhpx->nh_plversion; 236842ed7838SReza Sabdar (void) strlcpy(plname, mhpx->nh_plname, 236942ed7838SReza Sabdar sizeof (plname)); 23702654012fSReza Sabdar 237142ed7838SReza Sabdar if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 23722654012fSReza Sabdar goto nvlist_err; 237342ed7838SReza Sabdar 237442ed7838SReza Sabdar mppx = &mhpx->nh_property[0]; 237542ed7838SReza Sabdar for (i = 0; i < mhpx->nh_count && mppx; i++, mppx++) { 237642ed7838SReza Sabdar if (!*mppx->mp_name) 237742ed7838SReza Sabdar continue; 237842ed7838SReza Sabdar valp = NULL; 237942ed7838SReza Sabdar if (nvlist_alloc(&valp, 238042ed7838SReza Sabdar NV_UNIQUE_NAME, 0) != 0 || 238142ed7838SReza Sabdar nvlist_add_string(valp, "value", 238242ed7838SReza Sabdar mppx->mp_value) != 0 || 238342ed7838SReza Sabdar nvlist_add_string(valp, "source", 238442ed7838SReza Sabdar mppx->mp_source) != 0 || 238542ed7838SReza Sabdar nvlist_add_nvlist(nvl, mppx->mp_name, 238642ed7838SReza Sabdar valp) != 0) { 238742ed7838SReza Sabdar nvlist_free(valp); 238842ed7838SReza Sabdar goto nvlist_err; 238942ed7838SReza Sabdar } 239042ed7838SReza Sabdar nvlist_free(valp); 239142ed7838SReza Sabdar } 239242ed7838SReza Sabdar } else { 239342ed7838SReza Sabdar nctx->nc_plversion = mhp->nh_plversion; 239442ed7838SReza Sabdar (void) strlcpy(plname, mhp->nh_plname, 239542ed7838SReza Sabdar sizeof (plname)); 239642ed7838SReza Sabdar 239742ed7838SReza Sabdar if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 239842ed7838SReza Sabdar goto nvlist_err; 239942ed7838SReza Sabdar 240042ed7838SReza Sabdar mpp = &mhp->nh_property[0]; 240142ed7838SReza Sabdar for (i = 0; i < mhp->nh_count && mpp; i++, mpp++) { 240242ed7838SReza Sabdar if (!*mpp->mp_name) 240342ed7838SReza Sabdar continue; 240442ed7838SReza Sabdar valp = NULL; 240542ed7838SReza Sabdar if (nvlist_alloc(&valp, 240642ed7838SReza Sabdar NV_UNIQUE_NAME, 0) != 0 || 240742ed7838SReza Sabdar nvlist_add_string(valp, "value", 240842ed7838SReza Sabdar mpp->mp_value) != 0 || 240942ed7838SReza Sabdar nvlist_add_string(valp, "source", 241042ed7838SReza Sabdar mpp->mp_source) != 0 || 241142ed7838SReza Sabdar nvlist_add_nvlist(nvl, mpp->mp_name, 241242ed7838SReza Sabdar valp) != 0) { 241342ed7838SReza Sabdar nvlist_free(valp); 241442ed7838SReza Sabdar goto nvlist_err; 241542ed7838SReza Sabdar } 241642ed7838SReza Sabdar nvlist_free(valp); 241742ed7838SReza Sabdar } 24182654012fSReza Sabdar } 24192654012fSReza Sabdar 24202654012fSReza Sabdar if (np_restore_property(nvl, ptr) != 0) 24212654012fSReza Sabdar goto nvlist_err; 24222654012fSReza Sabdar 242342ed7838SReza Sabdar while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL && 242442ed7838SReza Sabdar nvpair_value_nvlist(nvp, &valp) == 0) { 242542ed7838SReza Sabdar nvlist_free(valp); 242642ed7838SReza Sabdar } 242742ed7838SReza Sabdar nvlist_free(nvl); 24282654012fSReza Sabdar } 24292654012fSReza Sabdar 243042ed7838SReza Sabdar free(mhbuf); 24312654012fSReza Sabdar return (0); 24322654012fSReza Sabdar 24332654012fSReza Sabdar nvlist_err: 24342654012fSReza Sabdar free(mhbuf); 243542ed7838SReza Sabdar 243642ed7838SReza Sabdar while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL && 243742ed7838SReza Sabdar nvpair_value_nvlist(nvp, &valp) == 0) { 243842ed7838SReza Sabdar nvlist_free(valp); 24392654012fSReza Sabdar } 244042ed7838SReza Sabdar nvlist_free(nvl); 24412654012fSReza Sabdar return (-1); 24422654012fSReza Sabdar } 24432654012fSReza Sabdar 24442654012fSReza Sabdar /* 24452654012fSReza Sabdar * Returns the version number of the plugin which created the metadata 24462654012fSReza Sabdar */ 24472654012fSReza Sabdar uint_t 24482654012fSReza Sabdar ndmp_context_get_version(ndmp_context_t *nctx) 24492654012fSReza Sabdar { 24502654012fSReza Sabdar tlm_commands_t *cmds; 24512654012fSReza Sabdar ndmp_metadata_header_t *mhp; 24522654012fSReza Sabdar tlm_cmd_t *lcmd; 24532654012fSReza Sabdar int actual_size; 24542654012fSReza Sabdar int rv; 24552654012fSReza Sabdar int size; 24562654012fSReza Sabdar int align = RECORDSIZE - 1; 24572654012fSReza Sabdar 24582654012fSReza Sabdar if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 24592654012fSReza Sabdar return (0); 24602654012fSReza Sabdar 24612654012fSReza Sabdar if ((lcmd = cmds->tcs_command) == NULL || 24622654012fSReza Sabdar lcmd->tc_buffers == NULL) 24632654012fSReza Sabdar return (0); 24642654012fSReza Sabdar 24652654012fSReza Sabdar size = sizeof (ndmp_metadata_header_t); 24662654012fSReza Sabdar size += align; 24672654012fSReza Sabdar size &= ~align; 24682654012fSReza Sabdar 24692654012fSReza Sabdar /* LINTED improper alignment */ 24702654012fSReza Sabdar if ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv, 24712654012fSReza Sabdar &actual_size, lcmd)) != NULL) { 24722654012fSReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC, 24732654012fSReza Sabdar sizeof (mhp->nh_magic)) != 0) { 24742654012fSReza Sabdar /* No more metadata */ 24752654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 24762654012fSReza Sabdar return (0); 24772654012fSReza Sabdar } 24782654012fSReza Sabdar 24792654012fSReza Sabdar nctx->nc_plversion = mhp->nh_plversion; 24802654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 24812654012fSReza Sabdar } 24822654012fSReza Sabdar 24832654012fSReza Sabdar return (nctx->nc_plversion); 24842654012fSReza Sabdar } 2485