1*2654012fSReza Sabdar /* 2*2654012fSReza Sabdar * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3*2654012fSReza Sabdar * Use is subject to license terms. 4*2654012fSReza Sabdar */ 5*2654012fSReza Sabdar 6*2654012fSReza Sabdar /* 7*2654012fSReza Sabdar * BSD 3 Clause License 8*2654012fSReza Sabdar * 9*2654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 10*2654012fSReza Sabdar * 11*2654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 12*2654012fSReza Sabdar * modification, are permitted provided that the following conditions 13*2654012fSReza Sabdar * are met: 14*2654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 15*2654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 16*2654012fSReza Sabdar * 17*2654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 18*2654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 19*2654012fSReza Sabdar * the documentation and/or other materials provided with the 20*2654012fSReza Sabdar * distribution. 21*2654012fSReza Sabdar * 22*2654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 23*2654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 24*2654012fSReza Sabdar * products derived from this software without specific prior written 25*2654012fSReza Sabdar * permission. 26*2654012fSReza Sabdar * 27*2654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28*2654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29*2654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30*2654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 31*2654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32*2654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33*2654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34*2654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35*2654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36*2654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37*2654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 38*2654012fSReza Sabdar */ 39*2654012fSReza Sabdar #include <stdlib.h> 40*2654012fSReza Sabdar #include <ctype.h> 41*2654012fSReza Sabdar #include <stdio.h> 42*2654012fSReza Sabdar #include <limits.h> 43*2654012fSReza Sabdar #include <string.h> 44*2654012fSReza Sabdar #include <time.h> 45*2654012fSReza Sabdar #include <sys/types.h> 46*2654012fSReza Sabdar #include <sys/acl.h> 47*2654012fSReza Sabdar #include <utime.h> 48*2654012fSReza Sabdar #include <unistd.h> 49*2654012fSReza Sabdar #include <pthread.h> 50*2654012fSReza Sabdar #include <archives.h> 51*2654012fSReza Sabdar #include <priv.h> 52*2654012fSReza Sabdar #include <tlm.h> 53*2654012fSReza Sabdar #include <libzfs.h> 54*2654012fSReza Sabdar #include <ndmpd_prop.h> 55*2654012fSReza Sabdar #include "tlm_proto.h" 56*2654012fSReza Sabdar 57*2654012fSReza Sabdar 58*2654012fSReza Sabdar #define PM_EXACT_OR_CHILD(m) ((m) == PM_EXACT || (m) == PM_CHILD) 59*2654012fSReza Sabdar 60*2654012fSReza Sabdar typedef boolean_t name_match_fp_t(char *s, char *t); 61*2654012fSReza Sabdar 62*2654012fSReza Sabdar static void set_acl(char *name, 63*2654012fSReza Sabdar tlm_acls_t *acls); 64*2654012fSReza Sabdar static long restore_file(int *fp, 65*2654012fSReza Sabdar char *real_name, 66*2654012fSReza Sabdar long size, 67*2654012fSReza Sabdar longlong_t huge_size, 68*2654012fSReza Sabdar tlm_acls_t *, 69*2654012fSReza Sabdar boolean_t want_this_file, 70*2654012fSReza Sabdar tlm_cmd_t *, 71*2654012fSReza Sabdar tlm_job_stats_t *); 72*2654012fSReza Sabdar static long restore_xattr_hdr(int *fp, 73*2654012fSReza Sabdar char *name, 74*2654012fSReza Sabdar char *fname, 75*2654012fSReza Sabdar long size, 76*2654012fSReza Sabdar tlm_acls_t *acls, 77*2654012fSReza Sabdar tlm_cmd_t *local_commands, 78*2654012fSReza Sabdar tlm_job_stats_t *job_stats); 79*2654012fSReza Sabdar static int get_long_name(int lib, 80*2654012fSReza Sabdar int drv, 81*2654012fSReza Sabdar long recsize, 82*2654012fSReza Sabdar char *name, 83*2654012fSReza Sabdar long *buf_spot, 84*2654012fSReza Sabdar tlm_cmd_t *local_commands); 85*2654012fSReza Sabdar static int get_humongus_file_header(int lib, 86*2654012fSReza Sabdar int drv, 87*2654012fSReza Sabdar long recsize, 88*2654012fSReza Sabdar longlong_t *size, 89*2654012fSReza Sabdar char *name, 90*2654012fSReza Sabdar tlm_cmd_t *); 91*2654012fSReza Sabdar static int create_directory(char *dir, 92*2654012fSReza Sabdar tlm_job_stats_t *); 93*2654012fSReza Sabdar static int create_hard_link(char *name, 94*2654012fSReza Sabdar char *link, 95*2654012fSReza Sabdar tlm_acls_t *, 96*2654012fSReza Sabdar tlm_job_stats_t *); 97*2654012fSReza Sabdar static int create_sym_link(char *dst, 98*2654012fSReza Sabdar char *target, 99*2654012fSReza Sabdar tlm_acls_t *, 100*2654012fSReza Sabdar tlm_job_stats_t *); 101*2654012fSReza Sabdar static int create_fifo(char *name, 102*2654012fSReza Sabdar tlm_acls_t *); 103*2654012fSReza Sabdar static long load_acl_info(int lib, 104*2654012fSReza Sabdar int drv, 105*2654012fSReza Sabdar long size, 106*2654012fSReza Sabdar tlm_acls_t *, 107*2654012fSReza Sabdar long *acl_spot, 108*2654012fSReza Sabdar tlm_cmd_t *); 109*2654012fSReza Sabdar static char *get_read_buffer(int want, 110*2654012fSReza Sabdar int *error, 111*2654012fSReza Sabdar int *actual_size, 112*2654012fSReza Sabdar tlm_cmd_t *); 113*2654012fSReza Sabdar static boolean_t wildcard_enabled(void); 114*2654012fSReza Sabdar static boolean_t is_file_wanted(char *name, 115*2654012fSReza Sabdar char **sels, 116*2654012fSReza Sabdar char **exls, 117*2654012fSReza Sabdar int flags, 118*2654012fSReza Sabdar int *mchtype, 119*2654012fSReza Sabdar int *pos); 120*2654012fSReza Sabdar static char *catnames(struct rs_name_maker *rnp, 121*2654012fSReza Sabdar char *buf, 122*2654012fSReza Sabdar int pos, 123*2654012fSReza Sabdar char *path); 124*2654012fSReza Sabdar 125*2654012fSReza Sabdar static char *rs_new_name(struct rs_name_maker *rnp, 126*2654012fSReza Sabdar char *real_name, 127*2654012fSReza Sabdar int pos, 128*2654012fSReza Sabdar char *path); 129*2654012fSReza Sabdar 130*2654012fSReza Sabdar typedef struct stack_ent { 131*2654012fSReza Sabdar char *se_name; 132*2654012fSReza Sabdar tlm_acls_t se_acls; 133*2654012fSReza Sabdar } stack_ent_t; 134*2654012fSReza Sabdar 135*2654012fSReza Sabdar 136*2654012fSReza Sabdar /* 137*2654012fSReza Sabdar * dtree_push 138*2654012fSReza Sabdar */ 139*2654012fSReza Sabdar int 140*2654012fSReza Sabdar dtree_push(cstack_t *stp, char *nmp, tlm_acls_t *acls) 141*2654012fSReza Sabdar { 142*2654012fSReza Sabdar int len; 143*2654012fSReza Sabdar stack_ent_t *sp; 144*2654012fSReza Sabdar 145*2654012fSReza Sabdar sp = ndmp_malloc(sizeof (stack_ent_t)); 146*2654012fSReza Sabdar if (!sp || !nmp || !acls) { 147*2654012fSReza Sabdar free(sp); 148*2654012fSReza Sabdar return (-1); 149*2654012fSReza Sabdar } 150*2654012fSReza Sabdar 151*2654012fSReza Sabdar len = strlen(nmp) + 1; 152*2654012fSReza Sabdar sp->se_name = ndmp_malloc(len); 153*2654012fSReza Sabdar if (!sp->se_name) { 154*2654012fSReza Sabdar free(sp); 155*2654012fSReza Sabdar return (-1); 156*2654012fSReza Sabdar } 157*2654012fSReza Sabdar 158*2654012fSReza Sabdar (void) strlcpy(sp->se_name, nmp, len); 159*2654012fSReza Sabdar (void) memcpy(&sp->se_acls, acls, sizeof (*acls)); 160*2654012fSReza Sabdar 161*2654012fSReza Sabdar return (cstack_push(stp, (void *)sp, sizeof (*sp))); 162*2654012fSReza Sabdar } 163*2654012fSReza Sabdar 164*2654012fSReza Sabdar /* 165*2654012fSReza Sabdar * dtree_pop 166*2654012fSReza Sabdar */ 167*2654012fSReza Sabdar int 168*2654012fSReza Sabdar dtree_pop(cstack_t *stp) 169*2654012fSReza Sabdar { 170*2654012fSReza Sabdar int err; 171*2654012fSReza Sabdar stack_ent_t *sp; 172*2654012fSReza Sabdar 173*2654012fSReza Sabdar err = cstack_pop(stp, (void **)&sp, (void *)NULL); 174*2654012fSReza Sabdar if (err) 175*2654012fSReza Sabdar return (-1); 176*2654012fSReza Sabdar 177*2654012fSReza Sabdar set_acl(sp->se_name, &sp->se_acls); 178*2654012fSReza Sabdar 179*2654012fSReza Sabdar free(sp->se_name); 180*2654012fSReza Sabdar free(sp); 181*2654012fSReza Sabdar return (err); 182*2654012fSReza Sabdar } 183*2654012fSReza Sabdar 184*2654012fSReza Sabdar 185*2654012fSReza Sabdar /* 186*2654012fSReza Sabdar * dtree_peek 187*2654012fSReza Sabdar */ 188*2654012fSReza Sabdar char * 189*2654012fSReza Sabdar dtree_peek(cstack_t *stp) 190*2654012fSReza Sabdar { 191*2654012fSReza Sabdar int err; 192*2654012fSReza Sabdar stack_ent_t *sp; 193*2654012fSReza Sabdar 194*2654012fSReza Sabdar err = cstack_top(stp, (void **)&sp, (void *)NULL); 195*2654012fSReza Sabdar if (err) 196*2654012fSReza Sabdar return (NULL); 197*2654012fSReza Sabdar 198*2654012fSReza Sabdar return (sp->se_name); 199*2654012fSReza Sabdar } 200*2654012fSReza Sabdar 201*2654012fSReza Sabdar /* 202*2654012fSReza Sabdar * NBU and EBS may not send us the correct file list containing hardlinks 203*2654012fSReza Sabdar * during a DAR restore, e.g. they appear always send the first name 204*2654012fSReza Sabdar * associated with an inode, even if other link names were 205*2654012fSReza Sabdar * selected for the restore. As a workaround, we use the file name entry 206*2654012fSReza Sabdar * in sels[] (ignore the name in the tar header) as restore target. 207*2654012fSReza Sabdar */ 208*2654012fSReza Sabdar static char * 209*2654012fSReza Sabdar rs_darhl_new_name(struct rs_name_maker *rnp, char *name, char **sels, int *pos, 210*2654012fSReza Sabdar char *longname) 211*2654012fSReza Sabdar { 212*2654012fSReza Sabdar int x; 213*2654012fSReza Sabdar 214*2654012fSReza Sabdar for (x = 0; sels[x] != NULL; x++) { 215*2654012fSReza Sabdar if (strcmp(sels[x], " ")) { 216*2654012fSReza Sabdar *pos = x; 217*2654012fSReza Sabdar (void) strlcpy(longname, sels[x], TLM_MAX_PATH_NAME); 218*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 219*2654012fSReza Sabdar "to replace hardlink name [%s], pos [%d]", 220*2654012fSReza Sabdar longname, *pos); 221*2654012fSReza Sabdar 222*2654012fSReza Sabdar return (rs_new_name(rnp, name, *pos, longname)); 223*2654012fSReza Sabdar } 224*2654012fSReza Sabdar } 225*2654012fSReza Sabdar 226*2654012fSReza Sabdar return (NULL); 227*2654012fSReza Sabdar } 228*2654012fSReza Sabdar 229*2654012fSReza Sabdar 230*2654012fSReza Sabdar /* 231*2654012fSReza Sabdar * Main dir restore funciton for tar 232*2654012fSReza Sabdar */ 233*2654012fSReza Sabdar int 234*2654012fSReza Sabdar tar_getdir(tlm_commands_t *commands, 235*2654012fSReza Sabdar tlm_cmd_t *local_commands, 236*2654012fSReza Sabdar tlm_job_stats_t *job_stats, 237*2654012fSReza Sabdar struct rs_name_maker *rnp, 238*2654012fSReza Sabdar int lib, 239*2654012fSReza Sabdar int drv, 240*2654012fSReza Sabdar char **sels, /* what to get off the tape */ 241*2654012fSReza Sabdar char **exls, /* what to leave behind */ 242*2654012fSReza Sabdar int flags, 243*2654012fSReza Sabdar int DAR, struct hardlink_q *hardlink_q) 244*2654012fSReza Sabdar { 245*2654012fSReza Sabdar int fp = 0; /* file being restored ... */ 246*2654012fSReza Sabdar /* ...need to preserve across volume changes */ 247*2654012fSReza Sabdar tlm_acls_t *acls; /* file access info */ 248*2654012fSReza Sabdar char *longname; 249*2654012fSReza Sabdar boolean_t is_long_name = FALSE; 250*2654012fSReza Sabdar char *longlink; 251*2654012fSReza Sabdar char *hugename; 252*2654012fSReza Sabdar longlong_t huge_size = 0; /* size of a HUGE file */ 253*2654012fSReza Sabdar long acl_spot; /* any ACL info on the next volume */ 254*2654012fSReza Sabdar long file_size; /* size of file to restore */ 255*2654012fSReza Sabdar long size_left = 0; /* need this after volume change */ 256*2654012fSReza Sabdar int last_action = 0; /* what we are doing at EOT */ 257*2654012fSReza Sabdar boolean_t multi_volume = FALSE; /* is this a multi-volume switch ? */ 258*2654012fSReza Sabdar int chk_rv; /* scratch area */ 259*2654012fSReza Sabdar 260*2654012fSReza Sabdar int mchtype, pos; 261*2654012fSReza Sabdar /* 262*2654012fSReza Sabdar * if an exact match is found for 263*2654012fSReza Sabdar * restore and its position in the 264*2654012fSReza Sabdar * selections list 265*2654012fSReza Sabdar */ 266*2654012fSReza Sabdar int nzerohdr; /* the number of empty tar headers */ 267*2654012fSReza Sabdar boolean_t break_flg; /* exit the while loop */ 268*2654012fSReza Sabdar int rv; 269*2654012fSReza Sabdar long nm_end, lnk_end; 270*2654012fSReza Sabdar char *name, *nmp; 271*2654012fSReza Sabdar cstack_t *stp; 272*2654012fSReza Sabdar char *bkpath; 273*2654012fSReza Sabdar char *parentlnk; 274*2654012fSReza Sabdar /* 275*2654012fSReza Sabdar * The directory where temporary files may be created during a partial 276*2654012fSReza Sabdar * non-DAR restore of hardlinks. It is intended to be initialized by 277*2654012fSReza Sabdar * an environment variable that can be set by user. 278*2654012fSReza Sabdar * 279*2654012fSReza Sabdar * It is not initialized for now. We keep it here for future use. 280*2654012fSReza Sabdar */ 281*2654012fSReza Sabdar char *tmplink_dir = NULL; 282*2654012fSReza Sabdar 283*2654012fSReza Sabdar /* 284*2654012fSReza Sabdar * startup 285*2654012fSReza Sabdar */ 286*2654012fSReza Sabdar 287*2654012fSReza Sabdar longname = ndmp_malloc(TLM_MAX_PATH_NAME); 288*2654012fSReza Sabdar longlink = ndmp_malloc(TLM_MAX_PATH_NAME); 289*2654012fSReza Sabdar hugename = ndmp_malloc(TLM_MAX_PATH_NAME); 290*2654012fSReza Sabdar parentlnk = ndmp_malloc(TLM_MAX_PATH_NAME); 291*2654012fSReza Sabdar name = ndmp_malloc(TLM_MAX_PATH_NAME); 292*2654012fSReza Sabdar acls = ndmp_malloc(sizeof (tlm_acls_t)); 293*2654012fSReza Sabdar stp = cstack_new(); 294*2654012fSReza Sabdar if (longname == NULL || longlink == NULL || hugename == NULL || 295*2654012fSReza Sabdar name == NULL || acls == NULL || stp == NULL || parentlnk == NULL) { 296*2654012fSReza Sabdar cstack_delete(stp); 297*2654012fSReza Sabdar free(longname); 298*2654012fSReza Sabdar free(longlink); 299*2654012fSReza Sabdar free(hugename); 300*2654012fSReza Sabdar free(parentlnk); 301*2654012fSReza Sabdar free(name); 302*2654012fSReza Sabdar free(acls); 303*2654012fSReza Sabdar return (-TLM_NO_SCRATCH_SPACE); 304*2654012fSReza Sabdar } 305*2654012fSReza Sabdar 306*2654012fSReza Sabdar acl_spot = 0; 307*2654012fSReza Sabdar *hugename = '\0'; 308*2654012fSReza Sabdar *parentlnk = '\0'; 309*2654012fSReza Sabdar nm_end = 0; 310*2654012fSReza Sabdar *longname = '\0'; 311*2654012fSReza Sabdar lnk_end = 0; 312*2654012fSReza Sabdar *longlink = '\0'; 313*2654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 314*2654012fSReza Sabdar if (IS_SET(flags, RSFLG_OVR_ALWAYS)) { 315*2654012fSReza Sabdar acls->acl_overwrite = TRUE; 316*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_ALWAYS"); 317*2654012fSReza Sabdar } else if (IS_SET(flags, RSFLG_OVR_UPDATE)) { 318*2654012fSReza Sabdar acls->acl_update = TRUE; 319*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_UPDATE"); 320*2654012fSReza Sabdar } 321*2654012fSReza Sabdar 322*2654012fSReza Sabdar /* 323*2654012fSReza Sabdar * work 324*2654012fSReza Sabdar */ 325*2654012fSReza Sabdar rv = 0; 326*2654012fSReza Sabdar nzerohdr = 0; 327*2654012fSReza Sabdar break_flg = FALSE; 328*2654012fSReza Sabdar while (commands->tcs_writer != TLM_ABORT && 329*2654012fSReza Sabdar local_commands->tc_writer != TLM_STOP) { 330*2654012fSReza Sabdar tlm_tar_hdr_t fake_tar_hdr; 331*2654012fSReza Sabdar char *file_name; 332*2654012fSReza Sabdar char *link_name; 333*2654012fSReza Sabdar int erc; 334*2654012fSReza Sabdar int actual_size; 335*2654012fSReza Sabdar boolean_t want_this_file; 336*2654012fSReza Sabdar int want = sizeof (tlm_tar_hdr_t); 337*2654012fSReza Sabdar tlm_tar_hdr_t *tar_hdr; 338*2654012fSReza Sabdar 339*2654012fSReza Sabdar /* The inode of an LF_LINK type. */ 340*2654012fSReza Sabdar unsigned long hardlink_inode = 0; 341*2654012fSReza Sabdar 342*2654012fSReza Sabdar /* 343*2654012fSReza Sabdar * Indicate whether a file with the same inode has been 344*2654012fSReza Sabdar * restored. 345*2654012fSReza Sabdar */ 346*2654012fSReza Sabdar int hardlink_done = 0; 347*2654012fSReza Sabdar 348*2654012fSReza Sabdar /* The path of the restored hardlink file */ 349*2654012fSReza Sabdar char *hardlink_target = NULL; 350*2654012fSReza Sabdar int is_hardlink = 0; 351*2654012fSReza Sabdar 352*2654012fSReza Sabdar /* 353*2654012fSReza Sabdar * Whether a temporary file should be created for restoring 354*2654012fSReza Sabdar * hardlink. 355*2654012fSReza Sabdar */ 356*2654012fSReza Sabdar int hardlink_tmp_file = 0; 357*2654012fSReza Sabdar char *hardlink_tmp_name = ".tmphlrsnondar"; 358*2654012fSReza Sabdar 359*2654012fSReza Sabdar /* used to make up hardlink_tmp_name */ 360*2654012fSReza Sabdar static int hardlink_tmp_idx = 0; 361*2654012fSReza Sabdar 362*2654012fSReza Sabdar if (break_flg) { 363*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 364*2654012fSReza Sabdar "Exiting writer thread drive %d", drv); 365*2654012fSReza Sabdar break; 366*2654012fSReza Sabdar } 367*2654012fSReza Sabdar 368*2654012fSReza Sabdar if (multi_volume) { 369*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "multi_volume %c %d", 370*2654012fSReza Sabdar last_action, size_left); 371*2654012fSReza Sabdar 372*2654012fSReza Sabdar /* 373*2654012fSReza Sabdar * the previous volume is out of data 374*2654012fSReza Sabdar * and is back in the rack, a new tape 375*2654012fSReza Sabdar * is loaded and ready to read. 376*2654012fSReza Sabdar * 377*2654012fSReza Sabdar * We need to pick up where we left off. 378*2654012fSReza Sabdar */ 379*2654012fSReza Sabdar (void) memset(&fake_tar_hdr, 0, sizeof (fake_tar_hdr)); 380*2654012fSReza Sabdar file_size = size_left; 381*2654012fSReza Sabdar tar_hdr = &fake_tar_hdr; 382*2654012fSReza Sabdar tar_hdr->th_linkflag = last_action; 383*2654012fSReza Sabdar 384*2654012fSReza Sabdar multi_volume = FALSE; 385*2654012fSReza Sabdar last_action = 0; 386*2654012fSReza Sabdar } else { 387*2654012fSReza Sabdar tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(want, 388*2654012fSReza Sabdar &erc, &actual_size, local_commands); 389*2654012fSReza Sabdar /* 390*2654012fSReza Sabdar * we can ignore read errors here because 391*2654012fSReza Sabdar * 1) they are logged by Restore Reader 392*2654012fSReza Sabdar * 2) we are not doing anything important here 393*2654012fSReza Sabdar * just looking for the next work record. 394*2654012fSReza Sabdar */ 395*2654012fSReza Sabdar if (actual_size < want) { 396*2654012fSReza Sabdar /* 397*2654012fSReza Sabdar * EOF hits here 398*2654012fSReza Sabdar * 399*2654012fSReza Sabdar * wait for another buffer to come along 400*2654012fSReza Sabdar * or until the Reader thread tells us 401*2654012fSReza Sabdar * that no more tapes will be loaded ... 402*2654012fSReza Sabdar * time to stop. 403*2654012fSReza Sabdar */ 404*2654012fSReza Sabdar continue; 405*2654012fSReza Sabdar } 406*2654012fSReza Sabdar 407*2654012fSReza Sabdar /* 408*2654012fSReza Sabdar * check for "we are lost" 409*2654012fSReza Sabdar */ 410*2654012fSReza Sabdar chk_rv = tlm_vfy_tar_checksum(tar_hdr); 411*2654012fSReza Sabdar if (chk_rv == 0) { 412*2654012fSReza Sabdar /* one of the end of tar file marks */ 413*2654012fSReza Sabdar if (++nzerohdr >= 2) { 414*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 415*2654012fSReza Sabdar "nzerohdr %d, breaking", 416*2654012fSReza Sabdar nzerohdr); 417*2654012fSReza Sabdar /* end of tar file */ 418*2654012fSReza Sabdar break; 419*2654012fSReza Sabdar } 420*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nzerohdr %d, continuing", 421*2654012fSReza Sabdar nzerohdr); 422*2654012fSReza Sabdar continue; 423*2654012fSReza Sabdar } else if (chk_rv < 0) { 424*2654012fSReza Sabdar nzerohdr = 0; 425*2654012fSReza Sabdar /* skip this record */ 426*2654012fSReza Sabdar continue; 427*2654012fSReza Sabdar } 428*2654012fSReza Sabdar nzerohdr = 0; 429*2654012fSReza Sabdar 430*2654012fSReza Sabdar /* 431*2654012fSReza Sabdar * When files are spanned to the next tape, the 432*2654012fSReza Sabdar * information of the acls must not be over-written 433*2654012fSReza Sabdar * by the information of the LF_MULTIVOL and LF_VOLHDR 434*2654012fSReza Sabdar * header, whose information is irrelevant to the file. 435*2654012fSReza Sabdar * The information of the original header must be 436*2654012fSReza Sabdar * kept in the 'acl'. 437*2654012fSReza Sabdar */ 438*2654012fSReza Sabdar if (tar_hdr->th_linkflag != LF_MULTIVOL && 439*2654012fSReza Sabdar tar_hdr->th_linkflag != LF_VOLHDR) { 440*2654012fSReza Sabdar acls->acl_attr.st_mode = 441*2654012fSReza Sabdar oct_atoi(tar_hdr->th_mode); 442*2654012fSReza Sabdar acls->acl_attr.st_size = 443*2654012fSReza Sabdar oct_atoi(tar_hdr->th_size); 444*2654012fSReza Sabdar acls->acl_attr.st_uid = 445*2654012fSReza Sabdar oct_atoi(tar_hdr->th_uid); 446*2654012fSReza Sabdar acls->acl_attr.st_gid = 447*2654012fSReza Sabdar oct_atoi(tar_hdr->th_gid); 448*2654012fSReza Sabdar acls->acl_attr.st_mtime = 449*2654012fSReza Sabdar oct_atoi(tar_hdr->th_mtime); 450*2654012fSReza Sabdar file_size = oct_atoi(tar_hdr->th_size); 451*2654012fSReza Sabdar acl_spot = 0; 452*2654012fSReza Sabdar last_action = tar_hdr->th_linkflag; 453*2654012fSReza Sabdar } 454*2654012fSReza Sabdar } 455*2654012fSReza Sabdar 456*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n [%s] f [%c] s %lld m %o u %d g %d t %d", 457*2654012fSReza Sabdar tar_hdr->th_name, tar_hdr->th_linkflag, 458*2654012fSReza Sabdar acls->acl_attr.st_size, acls->acl_attr.st_mode, 459*2654012fSReza Sabdar acls->acl_attr.st_uid, acls->acl_attr.st_gid, 460*2654012fSReza Sabdar acls->acl_attr.st_mtime); 461*2654012fSReza Sabdar 462*2654012fSReza Sabdar switch (tar_hdr->th_linkflag) { 463*2654012fSReza Sabdar case LF_MULTIVOL: 464*2654012fSReza Sabdar multi_volume = TRUE; 465*2654012fSReza Sabdar break; 466*2654012fSReza Sabdar case LF_LINK: 467*2654012fSReza Sabdar is_hardlink = 1; 468*2654012fSReza Sabdar hardlink_inode = 469*2654012fSReza Sabdar oct_atoi(tar_hdr->th_shared.th_hlink_ino); 470*2654012fSReza Sabdar 471*2654012fSReza Sabdar /* 472*2654012fSReza Sabdar * Check if we have restored a link with the same inode 473*2654012fSReza Sabdar * If the inode is 0, we have to restore it as a 474*2654012fSReza Sabdar * regular file. 475*2654012fSReza Sabdar */ 476*2654012fSReza Sabdar if (hardlink_inode) { 477*2654012fSReza Sabdar hardlink_done = !hardlink_q_get(hardlink_q, 478*2654012fSReza Sabdar hardlink_inode, 0, &hardlink_target); 479*2654012fSReza Sabdar } 480*2654012fSReza Sabdar 481*2654012fSReza Sabdar if (hardlink_done) { 482*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 483*2654012fSReza Sabdar "found hardlink, inode = %u, target = [%s]", 484*2654012fSReza Sabdar hardlink_inode, 485*2654012fSReza Sabdar hardlink_target? hardlink_target : "--"); 486*2654012fSReza Sabdar 487*2654012fSReza Sabdar /* create a hardlink to hardlink_target */ 488*2654012fSReza Sabdar file_name = (*longname == 0) ? 489*2654012fSReza Sabdar tar_hdr->th_name : longname; 490*2654012fSReza Sabdar if (!is_file_wanted(file_name, sels, exls, 491*2654012fSReza Sabdar flags, &mchtype, &pos)) { 492*2654012fSReza Sabdar nmp = NULL; 493*2654012fSReza Sabdar /* 494*2654012fSReza Sabdar * This means that DMA did not send us 495*2654012fSReza Sabdar * the correct fh_info for the file 496*2654012fSReza Sabdar * in restore list. We use the file 497*2654012fSReza Sabdar * name entry in sels[] (ignore the 498*2654012fSReza Sabdar * name in the tar header) as restore 499*2654012fSReza Sabdar * target. 500*2654012fSReza Sabdar */ 501*2654012fSReza Sabdar if (DAR) { 502*2654012fSReza Sabdar nmp = rs_darhl_new_name(rnp, 503*2654012fSReza Sabdar name, sels, &pos, 504*2654012fSReza Sabdar file_name); 505*2654012fSReza Sabdar } 506*2654012fSReza Sabdar } else { 507*2654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, 508*2654012fSReza Sabdar file_name); 509*2654012fSReza Sabdar if (!nmp) { 510*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 511*2654012fSReza Sabdar "can't make name for %s", 512*2654012fSReza Sabdar longname); 513*2654012fSReza Sabdar } 514*2654012fSReza Sabdar } 515*2654012fSReza Sabdar 516*2654012fSReza Sabdar if (nmp) { 517*2654012fSReza Sabdar if (hardlink_target) { 518*2654012fSReza Sabdar erc = create_hard_link( 519*2654012fSReza Sabdar hardlink_target, nmp, 520*2654012fSReza Sabdar acls, job_stats); 521*2654012fSReza Sabdar if (erc == 0) { 522*2654012fSReza Sabdar (void) 523*2654012fSReza Sabdar tlm_entry_restored( 524*2654012fSReza Sabdar job_stats, 525*2654012fSReza Sabdar file_name, pos); 526*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 527*2654012fSReza Sabdar "restored %s -> %s", 528*2654012fSReza Sabdar nmp, 529*2654012fSReza Sabdar hardlink_target); 530*2654012fSReza Sabdar } 531*2654012fSReza Sabdar } else { 532*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 533*2654012fSReza Sabdar "no target for hardlink %s", 534*2654012fSReza Sabdar nmp); 535*2654012fSReza Sabdar } 536*2654012fSReza Sabdar 537*2654012fSReza Sabdar name[0] = 0; 538*2654012fSReza Sabdar is_long_name = FALSE; 539*2654012fSReza Sabdar } 540*2654012fSReza Sabdar 541*2654012fSReza Sabdar nm_end = 0; 542*2654012fSReza Sabdar longname[0] = 0; 543*2654012fSReza Sabdar lnk_end = 0; 544*2654012fSReza Sabdar longlink[0] = 0; 545*2654012fSReza Sabdar 546*2654012fSReza Sabdar break; 547*2654012fSReza Sabdar } 548*2654012fSReza Sabdar /* otherwise fall through, restore like a normal file */ 549*2654012fSReza Sabdar /*FALLTHROUGH*/ 550*2654012fSReza Sabdar case LF_OLDNORMAL: 551*2654012fSReza Sabdar /* 552*2654012fSReza Sabdar * check for TAR's end-of-tape method 553*2654012fSReza Sabdar * of zero filled records. 554*2654012fSReza Sabdar */ 555*2654012fSReza Sabdar if (tar_hdr->th_name[0] == 0) { 556*2654012fSReza Sabdar break; 557*2654012fSReza Sabdar } 558*2654012fSReza Sabdar /* 559*2654012fSReza Sabdar * otherwise fall through, 560*2654012fSReza Sabdar * this is an old style normal file header 561*2654012fSReza Sabdar */ 562*2654012fSReza Sabdar /*FALLTHROUGH*/ 563*2654012fSReza Sabdar case LF_NORMAL: 564*2654012fSReza Sabdar case LF_CONTIG: 565*2654012fSReza Sabdar job_stats->js_files_so_far++; 566*2654012fSReza Sabdar if (*hugename != 0) { 567*2654012fSReza Sabdar (void) strlcpy(longname, hugename, 568*2654012fSReza Sabdar TLM_MAX_PATH_NAME); 569*2654012fSReza Sabdar } else if (*longname == 0) { 570*2654012fSReza Sabdar if (tar_hdr->th_name[0] != '/') { 571*2654012fSReza Sabdar /* 572*2654012fSReza Sabdar * check for old tar format, it 573*2654012fSReza Sabdar * does not have a leading "/" 574*2654012fSReza Sabdar */ 575*2654012fSReza Sabdar longname[0] = '/'; 576*2654012fSReza Sabdar longname[1] = 0; 577*2654012fSReza Sabdar (void) strlcat(longname, 578*2654012fSReza Sabdar tar_hdr->th_name, 579*2654012fSReza Sabdar TLM_MAX_PATH_NAME); 580*2654012fSReza Sabdar } else { 581*2654012fSReza Sabdar (void) strlcpy(longname, 582*2654012fSReza Sabdar tar_hdr->th_name, 583*2654012fSReza Sabdar TLM_MAX_PATH_NAME); 584*2654012fSReza Sabdar } 585*2654012fSReza Sabdar } 586*2654012fSReza Sabdar 587*2654012fSReza Sabdar want_this_file = is_file_wanted(longname, sels, exls, 588*2654012fSReza Sabdar flags, &mchtype, &pos); 589*2654012fSReza Sabdar if (!want_this_file) { 590*2654012fSReza Sabdar nmp = NULL; 591*2654012fSReza Sabdar /* 592*2654012fSReza Sabdar * This means that DMA did not send us valid 593*2654012fSReza Sabdar * fh_info for the file in restore list. We 594*2654012fSReza Sabdar * use the file name entry in sels[] (ignore 595*2654012fSReza Sabdar * the name in the tar header) as restore 596*2654012fSReza Sabdar * target. 597*2654012fSReza Sabdar */ 598*2654012fSReza Sabdar if (DAR && (tar_hdr->th_linkflag == LF_LINK)) { 599*2654012fSReza Sabdar nmp = rs_darhl_new_name(rnp, name, 600*2654012fSReza Sabdar sels, &pos, longname); 601*2654012fSReza Sabdar 602*2654012fSReza Sabdar if (nmp) { 603*2654012fSReza Sabdar want_this_file = TRUE; 604*2654012fSReza Sabdar mchtype = PM_EXACT; 605*2654012fSReza Sabdar } else { 606*2654012fSReza Sabdar break_flg = TRUE; 607*2654012fSReza Sabdar break; 608*2654012fSReza Sabdar } 609*2654012fSReza Sabdar } 610*2654012fSReza Sabdar } else { 611*2654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, longname); 612*2654012fSReza Sabdar if (!nmp) 613*2654012fSReza Sabdar want_this_file = FALSE; 614*2654012fSReza Sabdar } 615*2654012fSReza Sabdar 616*2654012fSReza Sabdar if (nmp) 617*2654012fSReza Sabdar (void) strlcpy(parentlnk, nmp, strlen(nmp) + 1); 618*2654012fSReza Sabdar 619*2654012fSReza Sabdar /* 620*2654012fSReza Sabdar * For a hardlink, even if it's not asked to be 621*2654012fSReza Sabdar * restored, we restore it to a temporary location, 622*2654012fSReza Sabdar * in case other links to the same file need to be 623*2654012fSReza Sabdar * restored later. 624*2654012fSReza Sabdar * 625*2654012fSReza Sabdar * The temp files are created in tmplink_dir, with 626*2654012fSReza Sabdar * names like ".tmphlrsnondar*". They are cleaned up 627*2654012fSReza Sabdar * at the completion of a restore. However, if a 628*2654012fSReza Sabdar * restore were interrupted, e.g. by a system reboot, 629*2654012fSReza Sabdar * they would have to be cleaned up manually in order 630*2654012fSReza Sabdar * for the disk space to be freed. 631*2654012fSReza Sabdar * 632*2654012fSReza Sabdar * If tmplink_dir is NULL, no temperorary files are 633*2654012fSReza Sabdar * created during a restore. This may result in some 634*2654012fSReza Sabdar * hardlinks not being restored during a partial 635*2654012fSReza Sabdar * restore. 636*2654012fSReza Sabdar */ 637*2654012fSReza Sabdar if (is_hardlink && !DAR && !want_this_file && !nmp) { 638*2654012fSReza Sabdar if (tmplink_dir) { 639*2654012fSReza Sabdar (void) snprintf(name, TLM_MAX_PATH_NAME, 640*2654012fSReza Sabdar "%s/%s_%d", tmplink_dir, 641*2654012fSReza Sabdar hardlink_tmp_name, 642*2654012fSReza Sabdar hardlink_tmp_idx); 643*2654012fSReza Sabdar nmp = name; 644*2654012fSReza Sabdar 645*2654012fSReza Sabdar hardlink_tmp_idx++; 646*2654012fSReza Sabdar hardlink_tmp_file = 1; 647*2654012fSReza Sabdar want_this_file = TRUE; 648*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 649*2654012fSReza Sabdar "To restore temp hardlink file %s.", 650*2654012fSReza Sabdar nmp); 651*2654012fSReza Sabdar } else { 652*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 653*2654012fSReza Sabdar "No tmplink_dir specified."); 654*2654012fSReza Sabdar } 655*2654012fSReza Sabdar } 656*2654012fSReza Sabdar 657*2654012fSReza Sabdar size_left = restore_file(&fp, nmp, file_size, 658*2654012fSReza Sabdar huge_size, acls, want_this_file, local_commands, 659*2654012fSReza Sabdar job_stats); 660*2654012fSReza Sabdar 661*2654012fSReza Sabdar /* 662*2654012fSReza Sabdar * In the case of non-DAR, we have to record the first 663*2654012fSReza Sabdar * link for an inode that has multiple links. That's 664*2654012fSReza Sabdar * the only link with data records actually backed up. 665*2654012fSReza Sabdar * In this way, when we run into the other links, they 666*2654012fSReza Sabdar * will be treated as links, and we won't go to look 667*2654012fSReza Sabdar * for the data records to restore. This is not a 668*2654012fSReza Sabdar * problem for DAR, where DMA tells the tape where 669*2654012fSReza Sabdar * to locate the data records. 670*2654012fSReza Sabdar */ 671*2654012fSReza Sabdar if (is_hardlink && !DAR) { 672*2654012fSReza Sabdar if (hardlink_q_add(hardlink_q, hardlink_inode, 673*2654012fSReza Sabdar 0, nmp, hardlink_tmp_file)) 674*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 675*2654012fSReza Sabdar "failed to add (%u, %s) to HL q", 676*2654012fSReza Sabdar hardlink_inode, nmp); 677*2654012fSReza Sabdar } 678*2654012fSReza Sabdar 679*2654012fSReza Sabdar /* remove / reverse the temporary stuff */ 680*2654012fSReza Sabdar if (hardlink_tmp_file) { 681*2654012fSReza Sabdar nmp = NULL; 682*2654012fSReza Sabdar want_this_file = FALSE; 683*2654012fSReza Sabdar hardlink_tmp_file = 0; 684*2654012fSReza Sabdar } 685*2654012fSReza Sabdar 686*2654012fSReza Sabdar /* 687*2654012fSReza Sabdar * Check if it is time to set the attribute 688*2654012fSReza Sabdar * of the restored directory 689*2654012fSReza Sabdar */ 690*2654012fSReza Sabdar while (nmp && ((bkpath = dtree_peek(stp)) != NULL)) { 691*2654012fSReza Sabdar if (strstr(nmp, bkpath)) 692*2654012fSReza Sabdar break; 693*2654012fSReza Sabdar 694*2654012fSReza Sabdar (void) dtree_pop(stp); 695*2654012fSReza Sabdar } 696*2654012fSReza Sabdar 697*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "sizeleft %s %d, %lld", longname, 698*2654012fSReza Sabdar size_left, huge_size); 699*2654012fSReza Sabdar 700*2654012fSReza Sabdar if (size_left == -TLM_STOP) { 701*2654012fSReza Sabdar break_flg = TRUE; 702*2654012fSReza Sabdar rv = -1; 703*2654012fSReza Sabdar commands->tcs_reader = TLM_ABORT; 704*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "restoring [%s] failed", 705*2654012fSReza Sabdar longname); 706*2654012fSReza Sabdar break; 707*2654012fSReza Sabdar } 708*2654012fSReza Sabdar 709*2654012fSReza Sabdar if (want_this_file) { 710*2654012fSReza Sabdar job_stats->js_bytes_total += file_size; 711*2654012fSReza Sabdar job_stats->js_files_total++; 712*2654012fSReza Sabdar } 713*2654012fSReza Sabdar 714*2654012fSReza Sabdar huge_size -= file_size; 715*2654012fSReza Sabdar if (huge_size < 0) { 716*2654012fSReza Sabdar huge_size = 0; 717*2654012fSReza Sabdar } 718*2654012fSReza Sabdar if (size_left == 0 && huge_size == 0) { 719*2654012fSReza Sabdar if (PM_EXACT_OR_CHILD(mchtype)) { 720*2654012fSReza Sabdar (void) tlm_entry_restored(job_stats, 721*2654012fSReza Sabdar longname, pos); 722*2654012fSReza Sabdar 723*2654012fSReza Sabdar /* 724*2654012fSReza Sabdar * Add an entry to hardlink_q to record 725*2654012fSReza Sabdar * this hardlink. 726*2654012fSReza Sabdar */ 727*2654012fSReza Sabdar if (is_hardlink) { 728*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 729*2654012fSReza Sabdar "Restored hardlink file %s", 730*2654012fSReza Sabdar nmp); 731*2654012fSReza Sabdar 732*2654012fSReza Sabdar if (DAR) { 733*2654012fSReza Sabdar (void) hardlink_q_add( 734*2654012fSReza Sabdar hardlink_q, 735*2654012fSReza Sabdar hardlink_inode, 0, 736*2654012fSReza Sabdar nmp, 0); 737*2654012fSReza Sabdar } 738*2654012fSReza Sabdar } 739*2654012fSReza Sabdar } 740*2654012fSReza Sabdar 741*2654012fSReza Sabdar nm_end = 0; 742*2654012fSReza Sabdar longname[0] = 0; 743*2654012fSReza Sabdar lnk_end = 0; 744*2654012fSReza Sabdar longlink[0] = 0; 745*2654012fSReza Sabdar hugename[0] = 0; 746*2654012fSReza Sabdar name[0] = 0; 747*2654012fSReza Sabdar is_long_name = FALSE; 748*2654012fSReza Sabdar } 749*2654012fSReza Sabdar break; 750*2654012fSReza Sabdar case LF_XATTR: 751*2654012fSReza Sabdar file_name = (*longname == 0) ? tar_hdr->th_name : 752*2654012fSReza Sabdar longname; 753*2654012fSReza Sabdar 754*2654012fSReza Sabdar size_left = restore_xattr_hdr(&fp, parentlnk, 755*2654012fSReza Sabdar file_name, file_size, acls, local_commands, 756*2654012fSReza Sabdar job_stats); 757*2654012fSReza Sabdar 758*2654012fSReza Sabdar break; 759*2654012fSReza Sabdar case LF_SYMLINK: 760*2654012fSReza Sabdar file_name = (*longname == 0) ? tar_hdr->th_name : 761*2654012fSReza Sabdar longname; 762*2654012fSReza Sabdar link_name = (*longlink == 0) ? 763*2654012fSReza Sabdar tar_hdr->th_linkname : longlink; 764*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "file_name[%s]", file_name); 765*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "link_name[%s]", link_name); 766*2654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 767*2654012fSReza Sabdar &mchtype, &pos)) { 768*2654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 769*2654012fSReza Sabdar if (nmp) { 770*2654012fSReza Sabdar erc = create_sym_link(nmp, link_name, 771*2654012fSReza Sabdar acls, job_stats); 772*2654012fSReza Sabdar if (erc == 0 && 773*2654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 774*2654012fSReza Sabdar (void) tlm_entry_restored( 775*2654012fSReza Sabdar job_stats, file_name, pos); 776*2654012fSReza Sabdar name[0] = 0; 777*2654012fSReza Sabdar } 778*2654012fSReza Sabdar } 779*2654012fSReza Sabdar nm_end = 0; 780*2654012fSReza Sabdar longname[0] = 0; 781*2654012fSReza Sabdar lnk_end = 0; 782*2654012fSReza Sabdar longlink[0] = 0; 783*2654012fSReza Sabdar break; 784*2654012fSReza Sabdar case LF_DIR: 785*2654012fSReza Sabdar file_name = *longname == 0 ? tar_hdr->th_name : 786*2654012fSReza Sabdar longname; 787*2654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 788*2654012fSReza Sabdar &mchtype, &pos)) { 789*2654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 790*2654012fSReza Sabdar if (nmp && mchtype != PM_PARENT) { 791*2654012fSReza Sabdar (void) strlcpy(parentlnk, nmp, 792*2654012fSReza Sabdar strlen(nmp)); 793*2654012fSReza Sabdar erc = create_directory(nmp, job_stats); 794*2654012fSReza Sabdar if (erc == 0 && 795*2654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 796*2654012fSReza Sabdar (void) tlm_entry_restored( 797*2654012fSReza Sabdar job_stats, file_name, pos); 798*2654012fSReza Sabdar /* 799*2654012fSReza Sabdar * Check if it is time to set 800*2654012fSReza Sabdar * the attribute of the restored 801*2654012fSReza Sabdar * directory 802*2654012fSReza Sabdar */ 803*2654012fSReza Sabdar while ((bkpath = dtree_peek(stp)) 804*2654012fSReza Sabdar != NULL) { 805*2654012fSReza Sabdar if (strstr(nmp, bkpath)) 806*2654012fSReza Sabdar break; 807*2654012fSReza Sabdar (void) dtree_pop(stp); 808*2654012fSReza Sabdar } 809*2654012fSReza Sabdar 810*2654012fSReza Sabdar (void) dtree_push(stp, nmp, acls); 811*2654012fSReza Sabdar name[0] = 0; 812*2654012fSReza Sabdar } 813*2654012fSReza Sabdar } 814*2654012fSReza Sabdar nm_end = 0; 815*2654012fSReza Sabdar longname[0] = 0; 816*2654012fSReza Sabdar lnk_end = 0; 817*2654012fSReza Sabdar longlink[0] = 0; 818*2654012fSReza Sabdar break; 819*2654012fSReza Sabdar case LF_FIFO: 820*2654012fSReza Sabdar file_name = *longname == 0 ? tar_hdr->th_name : 821*2654012fSReza Sabdar longname; 822*2654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 823*2654012fSReza Sabdar &mchtype, &pos)) { 824*2654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 825*2654012fSReza Sabdar if (nmp) { 826*2654012fSReza Sabdar erc = create_fifo(nmp, acls); 827*2654012fSReza Sabdar if (erc == 0 && 828*2654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 829*2654012fSReza Sabdar (void) tlm_entry_restored( 830*2654012fSReza Sabdar job_stats, file_name, pos); 831*2654012fSReza Sabdar name[0] = 0; 832*2654012fSReza Sabdar } 833*2654012fSReza Sabdar } 834*2654012fSReza Sabdar nm_end = 0; 835*2654012fSReza Sabdar longname[0] = 0; 836*2654012fSReza Sabdar lnk_end = 0; 837*2654012fSReza Sabdar longlink[0] = 0; 838*2654012fSReza Sabdar break; 839*2654012fSReza Sabdar case LF_LONGLINK: 840*2654012fSReza Sabdar file_size = min(file_size, TLM_MAX_PATH_NAME - lnk_end); 841*2654012fSReza Sabdar file_size = max(0, file_size); 842*2654012fSReza Sabdar size_left = get_long_name(lib, drv, file_size, longlink, 843*2654012fSReza Sabdar &lnk_end, local_commands); 844*2654012fSReza Sabdar 845*2654012fSReza Sabdar if (size_left != 0) 846*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 847*2654012fSReza Sabdar "fsize %d sleft %d lnkend %d", 848*2654012fSReza Sabdar file_size, size_left, lnk_end); 849*2654012fSReza Sabdar break; 850*2654012fSReza Sabdar case LF_LONGNAME: 851*2654012fSReza Sabdar file_size = min(file_size, TLM_MAX_PATH_NAME - nm_end); 852*2654012fSReza Sabdar file_size = max(0, file_size); 853*2654012fSReza Sabdar size_left = get_long_name(lib, drv, file_size, longname, 854*2654012fSReza Sabdar &nm_end, local_commands); 855*2654012fSReza Sabdar 856*2654012fSReza Sabdar if (size_left != 0) 857*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 858*2654012fSReza Sabdar "fsize %d sleft %d nmend %d", 859*2654012fSReza Sabdar file_size, size_left, nm_end); 860*2654012fSReza Sabdar is_long_name = TRUE; 861*2654012fSReza Sabdar break; 862*2654012fSReza Sabdar case LF_ACL: 863*2654012fSReza Sabdar size_left = load_acl_info(lib, drv, file_size, acls, 864*2654012fSReza Sabdar &acl_spot, local_commands); 865*2654012fSReza Sabdar break; 866*2654012fSReza Sabdar case LF_VOLHDR: 867*2654012fSReza Sabdar break; 868*2654012fSReza Sabdar case LF_HUMONGUS: 869*2654012fSReza Sabdar (void) memset(hugename, 0, TLM_MAX_PATH_NAME); 870*2654012fSReza Sabdar (void) get_humongus_file_header(lib, drv, file_size, 871*2654012fSReza Sabdar &huge_size, hugename, local_commands); 872*2654012fSReza Sabdar break; 873*2654012fSReza Sabdar default: 874*2654012fSReza Sabdar break; 875*2654012fSReza Sabdar 876*2654012fSReza Sabdar } 877*2654012fSReza Sabdar 878*2654012fSReza Sabdar /* 879*2654012fSReza Sabdar * If the restore is running using DAR we should check for 880*2654012fSReza Sabdar * long file names and HUGE file sizes. 881*2654012fSReza Sabdar */ 882*2654012fSReza Sabdar if (DAR && tar_hdr->th_linkflag != LF_ACL && 883*2654012fSReza Sabdar !huge_size && !is_long_name) 884*2654012fSReza Sabdar break; 885*2654012fSReza Sabdar } 886*2654012fSReza Sabdar 887*2654012fSReza Sabdar /* 888*2654012fSReza Sabdar * tear down 889*2654012fSReza Sabdar */ 890*2654012fSReza Sabdar if (fp != 0) { 891*2654012fSReza Sabdar (void) close(fp); 892*2654012fSReza Sabdar } 893*2654012fSReza Sabdar while (dtree_pop(stp) != -1) 894*2654012fSReza Sabdar ; 895*2654012fSReza Sabdar cstack_delete(stp); 896*2654012fSReza Sabdar free(acls); 897*2654012fSReza Sabdar free(longname); 898*2654012fSReza Sabdar free(parentlnk); 899*2654012fSReza Sabdar free(longlink); 900*2654012fSReza Sabdar free(hugename); 901*2654012fSReza Sabdar free(name); 902*2654012fSReza Sabdar return (rv); 903*2654012fSReza Sabdar } 904*2654012fSReza Sabdar 905*2654012fSReza Sabdar /* 906*2654012fSReza Sabdar * Main file restore function for tar (should run as a thread) 907*2654012fSReza Sabdar */ 908*2654012fSReza Sabdar int 909*2654012fSReza Sabdar tar_getfile(tlm_backup_restore_arg_t *argp) 910*2654012fSReza Sabdar { 911*2654012fSReza Sabdar tlm_job_stats_t *job_stats; 912*2654012fSReza Sabdar char **sels; /* list of files desired */ 913*2654012fSReza Sabdar char **exls; /* list of files not wanted */ 914*2654012fSReza Sabdar char *dir; /* where to restore the files */ 915*2654012fSReza Sabdar char job[TLM_MAX_BACKUP_JOB_NAME+1]; 916*2654012fSReza Sabdar /* the restore job name */ 917*2654012fSReza Sabdar int erc; /* error return codes */ 918*2654012fSReza Sabdar int flags; 919*2654012fSReza Sabdar struct rs_name_maker rn; 920*2654012fSReza Sabdar tlm_commands_t *commands; 921*2654012fSReza Sabdar tlm_cmd_t *local_commands; 922*2654012fSReza Sabdar char *list = NULL; 923*2654012fSReza Sabdar 924*2654012fSReza Sabdar commands = argp->ba_commands; 925*2654012fSReza Sabdar local_commands = argp->ba_cmd; 926*2654012fSReza Sabdar 927*2654012fSReza Sabdar flags = 0; 928*2654012fSReza Sabdar 929*2654012fSReza Sabdar dir = ndmp_malloc(TLM_MAX_PATH_NAME); 930*2654012fSReza Sabdar if (dir == NULL) { 931*2654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 932*2654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 933*2654012fSReza Sabdar return (-1); 934*2654012fSReza Sabdar } 935*2654012fSReza Sabdar 936*2654012fSReza Sabdar (void) strlcpy(job, argp->ba_job, TLM_MAX_BACKUP_JOB_NAME+1); 937*2654012fSReza Sabdar (void) strlcpy(dir, argp->ba_dir, TLM_MAX_PATH_NAME); 938*2654012fSReza Sabdar 939*2654012fSReza Sabdar flags |= RSFLG_OVR_ALWAYS; 940*2654012fSReza Sabdar flags |= RSFLG_IGNORE_CASE; 941*2654012fSReza Sabdar 942*2654012fSReza Sabdar /* 943*2654012fSReza Sabdar * do not test for "dir" having no string, since that 944*2654012fSReza Sabdar * is a legal condition. Restore to origional location 945*2654012fSReza Sabdar * will not have a restore directory. 946*2654012fSReza Sabdar */ 947*2654012fSReza Sabdar if (*job == '\0') { 948*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No job defined"); 949*2654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 950*2654012fSReza Sabdar free(dir); 951*2654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 952*2654012fSReza Sabdar return (-1); 953*2654012fSReza Sabdar } 954*2654012fSReza Sabdar 955*2654012fSReza Sabdar sels = argp->ba_sels; 956*2654012fSReza Sabdar if (sels == NULL) { 957*2654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 958*2654012fSReza Sabdar free(dir); 959*2654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 960*2654012fSReza Sabdar return (-1); 961*2654012fSReza Sabdar } 962*2654012fSReza Sabdar exls = &list; 963*2654012fSReza Sabdar 964*2654012fSReza Sabdar tlm_log_list("selections", sels); 965*2654012fSReza Sabdar tlm_log_list("exclusions", exls); 966*2654012fSReza Sabdar 967*2654012fSReza Sabdar if (wildcard_enabled()) 968*2654012fSReza Sabdar flags |= RSFLG_MATCH_WCARD; 969*2654012fSReza Sabdar 970*2654012fSReza Sabdar local_commands->tc_ref++; 971*2654012fSReza Sabdar commands->tcs_writer_count++; 972*2654012fSReza Sabdar 973*2654012fSReza Sabdar /* 974*2654012fSReza Sabdar * let the launcher continue 975*2654012fSReza Sabdar */ 976*2654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 977*2654012fSReza Sabdar 978*2654012fSReza Sabdar job_stats = tlm_ref_job_stats(job); 979*2654012fSReza Sabdar 980*2654012fSReza Sabdar rn.rn_fp = catnames; 981*2654012fSReza Sabdar rn.rn_nlp = dir; 982*2654012fSReza Sabdar 983*2654012fSReza Sabdar /* 984*2654012fSReza Sabdar * work 985*2654012fSReza Sabdar */ 986*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "start restore job %s", job); 987*2654012fSReza Sabdar erc = tar_getdir(commands, local_commands, job_stats, &rn, 1, 1, 988*2654012fSReza Sabdar sels, exls, flags, 0, NULL); 989*2654012fSReza Sabdar 990*2654012fSReza Sabdar /* 991*2654012fSReza Sabdar * teardown 992*2654012fSReza Sabdar */ 993*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "end restore job %s", job); 994*2654012fSReza Sabdar tlm_un_ref_job_stats(job); 995*2654012fSReza Sabdar tlm_release_list(sels); 996*2654012fSReza Sabdar tlm_release_list(exls); 997*2654012fSReza Sabdar 998*2654012fSReza Sabdar commands->tcs_writer_count--; 999*2654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 1000*2654012fSReza Sabdar tlm_release_reader_writer_ipc(local_commands); 1001*2654012fSReza Sabdar free(dir); 1002*2654012fSReza Sabdar return (erc); 1003*2654012fSReza Sabdar } 1004*2654012fSReza Sabdar 1005*2654012fSReza Sabdar /* 1006*2654012fSReza Sabdar * Creates the directories all the way down to the 1007*2654012fSReza Sabdar * end if they dont exist 1008*2654012fSReza Sabdar */ 1009*2654012fSReza Sabdar int 1010*2654012fSReza Sabdar make_dirs(char *dir) 1011*2654012fSReza Sabdar { 1012*2654012fSReza Sabdar char c; 1013*2654012fSReza Sabdar char *cp, *end; 1014*2654012fSReza Sabdar struct stat64 st; 1015*2654012fSReza Sabdar 1016*2654012fSReza Sabdar cp = dir; 1017*2654012fSReza Sabdar cp += strspn(cp, "/"); 1018*2654012fSReza Sabdar end = dir + strlen(dir); 1019*2654012fSReza Sabdar do { 1020*2654012fSReza Sabdar if (*cp == '\0' || *cp == '/') { 1021*2654012fSReza Sabdar c = *cp; 1022*2654012fSReza Sabdar *cp = '\0'; 1023*2654012fSReza Sabdar if (lstat64(dir, &st) < 0) 1024*2654012fSReza Sabdar if (mkdir(dir, 0777) < 0) { 1025*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d" 1026*2654012fSReza Sabdar " creating directory %s", 1027*2654012fSReza Sabdar errno, dir); 1028*2654012fSReza Sabdar *cp = c; 1029*2654012fSReza Sabdar return (-1); 1030*2654012fSReza Sabdar } 1031*2654012fSReza Sabdar 1032*2654012fSReza Sabdar *cp = c; 1033*2654012fSReza Sabdar } 1034*2654012fSReza Sabdar } while (++cp <= end); 1035*2654012fSReza Sabdar 1036*2654012fSReza Sabdar return (0); 1037*2654012fSReza Sabdar } 1038*2654012fSReza Sabdar 1039*2654012fSReza Sabdar /* 1040*2654012fSReza Sabdar * Creates the directories leading to the given path 1041*2654012fSReza Sabdar */ 1042*2654012fSReza Sabdar int 1043*2654012fSReza Sabdar mkbasedir(char *path) 1044*2654012fSReza Sabdar { 1045*2654012fSReza Sabdar int rv; 1046*2654012fSReza Sabdar char *cp; 1047*2654012fSReza Sabdar struct stat64 st; 1048*2654012fSReza Sabdar 1049*2654012fSReza Sabdar if (!path || !*path) { 1050*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument"); 1051*2654012fSReza Sabdar return (-1); 1052*2654012fSReza Sabdar } 1053*2654012fSReza Sabdar 1054*2654012fSReza Sabdar cp = strrchr(path, '/'); 1055*2654012fSReza Sabdar if (cp) 1056*2654012fSReza Sabdar *cp = '\0'; 1057*2654012fSReza Sabdar rv = lstat64(path, &st); 1058*2654012fSReza Sabdar if (rv < 0) /* need new directories */ 1059*2654012fSReza Sabdar rv = make_dirs(path); 1060*2654012fSReza Sabdar if (cp) 1061*2654012fSReza Sabdar *cp = '/'; 1062*2654012fSReza Sabdar 1063*2654012fSReza Sabdar return (rv); 1064*2654012fSReza Sabdar } 1065*2654012fSReza Sabdar 1066*2654012fSReza Sabdar 1067*2654012fSReza Sabdar /* 1068*2654012fSReza Sabdar * read the file off the tape back onto disk 1069*2654012fSReza Sabdar */ 1070*2654012fSReza Sabdar static long 1071*2654012fSReza Sabdar restore_file(int *fp, 1072*2654012fSReza Sabdar char *real_name, 1073*2654012fSReza Sabdar long size, 1074*2654012fSReza Sabdar longlong_t huge_size, 1075*2654012fSReza Sabdar tlm_acls_t *acls, 1076*2654012fSReza Sabdar boolean_t want_this_file, 1077*2654012fSReza Sabdar tlm_cmd_t *local_commands, 1078*2654012fSReza Sabdar tlm_job_stats_t *job_stats) 1079*2654012fSReza Sabdar { 1080*2654012fSReza Sabdar struct stat64 attr; 1081*2654012fSReza Sabdar 1082*2654012fSReza Sabdar if (!real_name) { 1083*2654012fSReza Sabdar if (want_this_file) { 1084*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No file name but wanted!"); 1085*2654012fSReza Sabdar want_this_file = FALSE; 1086*2654012fSReza Sabdar } 1087*2654012fSReza Sabdar } else 1088*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new file[%s]", real_name); 1089*2654012fSReza Sabdar 1090*2654012fSReza Sabdar /* 1091*2654012fSReza Sabdar * OK, some FM is creeping in here ... 1092*2654012fSReza Sabdar * int *fp is used to keep the 1093*2654012fSReza Sabdar * backup file channel open through 1094*2654012fSReza Sabdar * the interruption of EOT and 1095*2654012fSReza Sabdar * processing the headers of the 1096*2654012fSReza Sabdar * next tape. So, if *fp is zero 1097*2654012fSReza Sabdar * then no file is open yet and all 1098*2654012fSReza Sabdar * is normal. If *fp has a number 1099*2654012fSReza Sabdar * then we are returning after an 1100*2654012fSReza Sabdar * EOT break. 1101*2654012fSReza Sabdar * 1102*2654012fSReza Sabdar * *fp is now also open for HUGE files 1103*2654012fSReza Sabdar * that are put back in sections. 1104*2654012fSReza Sabdar */ 1105*2654012fSReza Sabdar 1106*2654012fSReza Sabdar if (*fp == 0 && want_this_file) { 1107*2654012fSReza Sabdar int erc_stat; 1108*2654012fSReza Sabdar 1109*2654012fSReza Sabdar if (mkbasedir(real_name) < 0) 1110*2654012fSReza Sabdar job_stats->js_errors++; 1111*2654012fSReza Sabdar 1112*2654012fSReza Sabdar erc_stat = stat64(real_name, (struct stat64 *)&attr); 1113*2654012fSReza Sabdar if (erc_stat < 0) { 1114*2654012fSReza Sabdar /*EMPTY*/ 1115*2654012fSReza Sabdar /* new file */ 1116*2654012fSReza Sabdar } else if (acls->acl_overwrite) { 1117*2654012fSReza Sabdar /*EMPTY*/ 1118*2654012fSReza Sabdar /* take this file no matter what */ 1119*2654012fSReza Sabdar } else if (acls->acl_update) { 1120*2654012fSReza Sabdar if (attr.st_mtime < acls->acl_attr.st_mtime) { 1121*2654012fSReza Sabdar /*EMPTY*/ 1122*2654012fSReza Sabdar /* tape is newer */ 1123*2654012fSReza Sabdar } else { 1124*2654012fSReza Sabdar /* disk file is newer */ 1125*2654012fSReza Sabdar want_this_file = FALSE; 1126*2654012fSReza Sabdar } 1127*2654012fSReza Sabdar } else { 1128*2654012fSReza Sabdar /* 1129*2654012fSReza Sabdar * no overwrite, no update, 1130*2654012fSReza Sabdar * do not ever replace old files. 1131*2654012fSReza Sabdar */ 1132*2654012fSReza Sabdar want_this_file = TRUE; 1133*2654012fSReza Sabdar } 1134*2654012fSReza Sabdar if (want_this_file) { 1135*2654012fSReza Sabdar 1136*2654012fSReza Sabdar *fp = open(real_name, O_CREAT | O_WRONLY, 1137*2654012fSReza Sabdar S_IRUSR | S_IWUSR); 1138*2654012fSReza Sabdar if (*fp == -1) { 1139*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, 1140*2654012fSReza Sabdar "Could not open %s for restore.", 1141*2654012fSReza Sabdar real_name); 1142*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1143*2654012fSReza Sabdar "fp=%d err=%d ", *fp, errno); 1144*2654012fSReza Sabdar job_stats->js_errors++; 1145*2654012fSReza Sabdar want_this_file = FALSE; 1146*2654012fSReza Sabdar /* 1147*2654012fSReza Sabdar * we cannot return here, 1148*2654012fSReza Sabdar * the file is still on 1149*2654012fSReza Sabdar * the tape and must be 1150*2654012fSReza Sabdar * skipped over. 1151*2654012fSReza Sabdar */ 1152*2654012fSReza Sabdar } 1153*2654012fSReza Sabdar } 1154*2654012fSReza Sabdar (void) strlcpy(local_commands->tc_file_name, real_name, 1155*2654012fSReza Sabdar TLM_MAX_PATH_NAME); 1156*2654012fSReza Sabdar } 1157*2654012fSReza Sabdar 1158*2654012fSReza Sabdar /* 1159*2654012fSReza Sabdar * this is the size left in the next segment 1160*2654012fSReza Sabdar */ 1161*2654012fSReza Sabdar huge_size -= size; 1162*2654012fSReza Sabdar 1163*2654012fSReza Sabdar /* 1164*2654012fSReza Sabdar * work 1165*2654012fSReza Sabdar */ 1166*2654012fSReza Sabdar while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) { 1167*2654012fSReza Sabdar int actual_size; 1168*2654012fSReza Sabdar int error; 1169*2654012fSReza Sabdar char *rec; 1170*2654012fSReza Sabdar int write_size; 1171*2654012fSReza Sabdar 1172*2654012fSReza Sabdar /* 1173*2654012fSReza Sabdar * Use bytes_in_file field to tell reader the amount 1174*2654012fSReza Sabdar * of data still need to be read for this file. 1175*2654012fSReza Sabdar */ 1176*2654012fSReza Sabdar job_stats->js_bytes_in_file = size; 1177*2654012fSReza Sabdar 1178*2654012fSReza Sabdar error = 0; 1179*2654012fSReza Sabdar rec = get_read_buffer(size, &error, &actual_size, 1180*2654012fSReza Sabdar local_commands); 1181*2654012fSReza Sabdar if (actual_size <= 0) { 1182*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1183*2654012fSReza Sabdar "RESTORE WRITER> error %d, actual_size %d", 1184*2654012fSReza Sabdar error, actual_size); 1185*2654012fSReza Sabdar 1186*2654012fSReza Sabdar /* no more data for this file for now */ 1187*2654012fSReza Sabdar job_stats->js_bytes_in_file = 0; 1188*2654012fSReza Sabdar 1189*2654012fSReza Sabdar return (size); 1190*2654012fSReza Sabdar } else if (error) { 1191*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 1192*2654012fSReza Sabdar error, local_commands->tc_file_name); 1193*2654012fSReza Sabdar break; 1194*2654012fSReza Sabdar } else { 1195*2654012fSReza Sabdar write_size = min(size, actual_size); 1196*2654012fSReza Sabdar if (want_this_file) { 1197*2654012fSReza Sabdar write_size = write(*fp, rec, write_size); 1198*2654012fSReza Sabdar } 1199*2654012fSReza Sabdar NS_ADD(wdisk, write_size); 1200*2654012fSReza Sabdar NS_INC(wfile); 1201*2654012fSReza Sabdar size -= write_size; 1202*2654012fSReza Sabdar } 1203*2654012fSReza Sabdar } 1204*2654012fSReza Sabdar 1205*2654012fSReza Sabdar /* no more data for this file for now */ 1206*2654012fSReza Sabdar job_stats->js_bytes_in_file = 0; 1207*2654012fSReza Sabdar 1208*2654012fSReza Sabdar /* 1209*2654012fSReza Sabdar * teardown 1210*2654012fSReza Sabdar */ 1211*2654012fSReza Sabdar if (*fp != 0 && huge_size <= 0) { 1212*2654012fSReza Sabdar (void) close(*fp); 1213*2654012fSReza Sabdar *fp = 0; 1214*2654012fSReza Sabdar set_acl(real_name, acls); 1215*2654012fSReza Sabdar } 1216*2654012fSReza Sabdar return (0); 1217*2654012fSReza Sabdar } 1218*2654012fSReza Sabdar 1219*2654012fSReza Sabdar /* 1220*2654012fSReza Sabdar * Set the extended attributes file attribute 1221*2654012fSReza Sabdar */ 1222*2654012fSReza Sabdar static void 1223*2654012fSReza Sabdar set_xattr(int fd, struct stat64 st) 1224*2654012fSReza Sabdar { 1225*2654012fSReza Sabdar struct timeval times[2]; 1226*2654012fSReza Sabdar 1227*2654012fSReza Sabdar times[0].tv_sec = st.st_atime; 1228*2654012fSReza Sabdar times[1].tv_sec = st.st_mtime; 1229*2654012fSReza Sabdar 1230*2654012fSReza Sabdar (void) fchmod(fd, st.st_mode); 1231*2654012fSReza Sabdar (void) fchown(fd, st.st_uid, st.st_gid); 1232*2654012fSReza Sabdar (void) futimesat(fd, ".", times); 1233*2654012fSReza Sabdar } 1234*2654012fSReza Sabdar 1235*2654012fSReza Sabdar /* 1236*2654012fSReza Sabdar * read the extended attribute header and write 1237*2654012fSReza Sabdar * it to the file 1238*2654012fSReza Sabdar */ 1239*2654012fSReza Sabdar static long 1240*2654012fSReza Sabdar restore_xattr_hdr(int *fp, 1241*2654012fSReza Sabdar char *name, 1242*2654012fSReza Sabdar char *fname, 1243*2654012fSReza Sabdar long size, 1244*2654012fSReza Sabdar tlm_acls_t *acls, 1245*2654012fSReza Sabdar tlm_cmd_t *local_commands, 1246*2654012fSReza Sabdar tlm_job_stats_t *job_stats) 1247*2654012fSReza Sabdar { 1248*2654012fSReza Sabdar tlm_tar_hdr_t *tar_hdr; 1249*2654012fSReza Sabdar struct xattr_hdr *xhdr; 1250*2654012fSReza Sabdar struct xattr_buf *xbuf; 1251*2654012fSReza Sabdar int namelen; 1252*2654012fSReza Sabdar char *xattrname; 1253*2654012fSReza Sabdar int actual_size; 1254*2654012fSReza Sabdar int error; 1255*2654012fSReza Sabdar 1256*2654012fSReza Sabdar if (!fname) { 1257*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No file name but wanted!"); 1258*2654012fSReza Sabdar } else { 1259*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new xattr[%s]", fname); 1260*2654012fSReza Sabdar } 1261*2654012fSReza Sabdar 1262*2654012fSReza Sabdar error = 0; 1263*2654012fSReza Sabdar xhdr = (struct xattr_hdr *)get_read_buffer(size, &error, 1264*2654012fSReza Sabdar &actual_size, local_commands); 1265*2654012fSReza Sabdar if (error) { 1266*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1267*2654012fSReza Sabdar "Could not read xattr [%s:%s] for restore. ", 1268*2654012fSReza Sabdar name, fname); 1269*2654012fSReza Sabdar job_stats->js_errors++; 1270*2654012fSReza Sabdar return (0); 1271*2654012fSReza Sabdar } 1272*2654012fSReza Sabdar 1273*2654012fSReza Sabdar /* Check extended attribute header */ 1274*2654012fSReza Sabdar if (strcmp(xhdr->h_version, XATTR_ARCH_VERS) != 0) { 1275*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1276*2654012fSReza Sabdar "Unrecognized header format [%s]", xhdr->h_version); 1277*2654012fSReza Sabdar return (0); 1278*2654012fSReza Sabdar } 1279*2654012fSReza Sabdar xbuf = (struct xattr_buf *)(((char *)xhdr) + sizeof (struct xattr_hdr)); 1280*2654012fSReza Sabdar 1281*2654012fSReza Sabdar (void) sscanf(xbuf->h_namesz, "%7d", &namelen); 1282*2654012fSReza Sabdar xattrname = xbuf->h_names + strlen(xbuf->h_names) + 1; 1283*2654012fSReza Sabdar 1284*2654012fSReza Sabdar if (*fp == 0) { 1285*2654012fSReza Sabdar int fd; 1286*2654012fSReza Sabdar 1287*2654012fSReza Sabdar fd = attropen(name, xattrname, O_CREAT | O_RDWR, 0755); 1288*2654012fSReza Sabdar if (fd == -1) { 1289*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1290*2654012fSReza Sabdar "Could not open xattr [%s:%s] for restore.", 1291*2654012fSReza Sabdar name, xattrname); 1292*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "err=%d ", errno); 1293*2654012fSReza Sabdar job_stats->js_errors++; 1294*2654012fSReza Sabdar } 1295*2654012fSReza Sabdar (void) strlcpy(local_commands->tc_file_name, xattrname, 1296*2654012fSReza Sabdar TLM_MAX_PATH_NAME); 1297*2654012fSReza Sabdar *fp = fd; 1298*2654012fSReza Sabdar } 1299*2654012fSReza Sabdar 1300*2654012fSReza Sabdar /* Get the actual extended attribute file */ 1301*2654012fSReza Sabdar tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(sizeof (*tar_hdr), 1302*2654012fSReza Sabdar &error, &actual_size, local_commands); 1303*2654012fSReza Sabdar if (error) { 1304*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1305*2654012fSReza Sabdar "Could not read xattr data [%s:%s] for restore. ", 1306*2654012fSReza Sabdar fname, xattrname); 1307*2654012fSReza Sabdar job_stats->js_errors++; 1308*2654012fSReza Sabdar return (0); 1309*2654012fSReza Sabdar } 1310*2654012fSReza Sabdar acls->acl_attr.st_mode = oct_atoi(tar_hdr->th_mode); 1311*2654012fSReza Sabdar acls->acl_attr.st_size = oct_atoi(tar_hdr->th_size); 1312*2654012fSReza Sabdar acls->acl_attr.st_uid = oct_atoi(tar_hdr->th_uid); 1313*2654012fSReza Sabdar acls->acl_attr.st_gid = oct_atoi(tar_hdr->th_gid); 1314*2654012fSReza Sabdar acls->acl_attr.st_mtime = oct_atoi(tar_hdr->th_mtime); 1315*2654012fSReza Sabdar 1316*2654012fSReza Sabdar size = acls->acl_attr.st_size; 1317*2654012fSReza Sabdar while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) { 1318*2654012fSReza Sabdar char *rec; 1319*2654012fSReza Sabdar int write_size; 1320*2654012fSReza Sabdar 1321*2654012fSReza Sabdar error = 0; 1322*2654012fSReza Sabdar rec = get_read_buffer(size, &error, &actual_size, 1323*2654012fSReza Sabdar local_commands); 1324*2654012fSReza Sabdar if (actual_size <= 0) { 1325*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1326*2654012fSReza Sabdar "RESTORE WRITER> error %d, actual_size %d", 1327*2654012fSReza Sabdar error, actual_size); 1328*2654012fSReza Sabdar 1329*2654012fSReza Sabdar return (size); 1330*2654012fSReza Sabdar } else if (error) { 1331*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 1332*2654012fSReza Sabdar error, local_commands->tc_file_name); 1333*2654012fSReza Sabdar break; 1334*2654012fSReza Sabdar } else { 1335*2654012fSReza Sabdar write_size = min(size, actual_size); 1336*2654012fSReza Sabdar write_size = write(*fp, rec, write_size); 1337*2654012fSReza Sabdar NS_ADD(wdisk, write_size); 1338*2654012fSReza Sabdar NS_INC(wfile); 1339*2654012fSReza Sabdar size -= write_size; 1340*2654012fSReza Sabdar } 1341*2654012fSReza Sabdar } 1342*2654012fSReza Sabdar 1343*2654012fSReza Sabdar if (*fp != 0) { 1344*2654012fSReza Sabdar set_xattr(*fp, acls->acl_attr); 1345*2654012fSReza Sabdar (void) close(*fp); 1346*2654012fSReza Sabdar *fp = 0; 1347*2654012fSReza Sabdar } 1348*2654012fSReza Sabdar return (0); 1349*2654012fSReza Sabdar } 1350*2654012fSReza Sabdar 1351*2654012fSReza Sabdar /* 1352*2654012fSReza Sabdar * Match the name with the list 1353*2654012fSReza Sabdar */ 1354*2654012fSReza Sabdar static int 1355*2654012fSReza Sabdar exact_find(char *name, char **list) 1356*2654012fSReza Sabdar { 1357*2654012fSReza Sabdar boolean_t found; 1358*2654012fSReza Sabdar int i; 1359*2654012fSReza Sabdar char *cp; 1360*2654012fSReza Sabdar 1361*2654012fSReza Sabdar found = FALSE; 1362*2654012fSReza Sabdar for (i = 0; *list != NULL; list++, i++) { 1363*2654012fSReza Sabdar cp = *list + strspn(*list, "/"); 1364*2654012fSReza Sabdar if (match(cp, name)) { 1365*2654012fSReza Sabdar found = TRUE; 1366*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "exact_find> found[%s]", cp); 1367*2654012fSReza Sabdar break; 1368*2654012fSReza Sabdar } 1369*2654012fSReza Sabdar } 1370*2654012fSReza Sabdar 1371*2654012fSReza Sabdar return (found); 1372*2654012fSReza Sabdar } 1373*2654012fSReza Sabdar 1374*2654012fSReza Sabdar /* 1375*2654012fSReza Sabdar * On error, return FALSE and prevent restoring(probably) unwanted data. 1376*2654012fSReza Sabdar */ 1377*2654012fSReza Sabdar static int 1378*2654012fSReza Sabdar is_parent(char *parent, char *child, int flags) 1379*2654012fSReza Sabdar { 1380*2654012fSReza Sabdar char tmp[TLM_MAX_PATH_NAME]; 1381*2654012fSReza Sabdar boolean_t rv; 1382*2654012fSReza Sabdar 1383*2654012fSReza Sabdar if (IS_SET(flags, RSFLG_MATCH_WCARD)) { 1384*2654012fSReza Sabdar if (!tlm_cat_path(tmp, parent, "*")) { 1385*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1386*2654012fSReza Sabdar "is_parent> path too long [%s]", parent); 1387*2654012fSReza Sabdar rv = FALSE; 1388*2654012fSReza Sabdar } else 1389*2654012fSReza Sabdar rv = (match(tmp, child) != 0) ? TRUE : FALSE; 1390*2654012fSReza Sabdar } else { 1391*2654012fSReza Sabdar if (!tlm_cat_path(tmp, parent, "/")) { 1392*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1393*2654012fSReza Sabdar "is_parent> path too long [%s]", parent); 1394*2654012fSReza Sabdar rv = FALSE; 1395*2654012fSReza Sabdar } else 1396*2654012fSReza Sabdar rv = (strncmp(tmp, child, strlen(tmp)) == 0) ? 1397*2654012fSReza Sabdar TRUE : FALSE; 1398*2654012fSReza Sabdar } 1399*2654012fSReza Sabdar 1400*2654012fSReza Sabdar return (rv); 1401*2654012fSReza Sabdar } 1402*2654012fSReza Sabdar 1403*2654012fSReza Sabdar /* 1404*2654012fSReza Sabdar * Used to match the filename inside the list 1405*2654012fSReza Sabdar */ 1406*2654012fSReza Sabdar static boolean_t 1407*2654012fSReza Sabdar strexactcmp(char *s, char *t) 1408*2654012fSReza Sabdar { 1409*2654012fSReza Sabdar return ((strcmp(s, t) == 0) ? TRUE : FALSE); 1410*2654012fSReza Sabdar } 1411*2654012fSReza Sabdar 1412*2654012fSReza Sabdar /* 1413*2654012fSReza Sabdar * Check if the file is needed to be restored 1414*2654012fSReza Sabdar */ 1415*2654012fSReza Sabdar static boolean_t 1416*2654012fSReza Sabdar is_file_wanted(char *name, 1417*2654012fSReza Sabdar char **sels, 1418*2654012fSReza Sabdar char **exls, 1419*2654012fSReza Sabdar int flags, 1420*2654012fSReza Sabdar int *mchtype, 1421*2654012fSReza Sabdar int *pos) 1422*2654012fSReza Sabdar { 1423*2654012fSReza Sabdar char *p_sel; 1424*2654012fSReza Sabdar char *uc_name, *retry, *namep; 1425*2654012fSReza Sabdar boolean_t found; 1426*2654012fSReza Sabdar int i; 1427*2654012fSReza Sabdar name_match_fp_t *cmp_fp; 1428*2654012fSReza Sabdar 1429*2654012fSReza Sabdar if (name == NULL || sels == NULL || exls == NULL) 1430*2654012fSReza Sabdar return (FALSE); 1431*2654012fSReza Sabdar 1432*2654012fSReza Sabdar found = FALSE; 1433*2654012fSReza Sabdar if (mchtype != NULL) 1434*2654012fSReza Sabdar *mchtype = PM_NONE; 1435*2654012fSReza Sabdar if (pos != NULL) 1436*2654012fSReza Sabdar *pos = 0; 1437*2654012fSReza Sabdar 1438*2654012fSReza Sabdar /* 1439*2654012fSReza Sabdar * For empty selection, restore everything 1440*2654012fSReza Sabdar */ 1441*2654012fSReza Sabdar if (*sels == NULL || **sels == '\0') { 1442*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "is_file_wanted: Restore all"); 1443*2654012fSReza Sabdar return (TRUE); 1444*2654012fSReza Sabdar } 1445*2654012fSReza Sabdar 1446*2654012fSReza Sabdar uc_name = ndmp_malloc(TLM_MAX_PATH_NAME); 1447*2654012fSReza Sabdar retry = ndmp_malloc(TLM_MAX_PATH_NAME); 1448*2654012fSReza Sabdar if (uc_name == NULL || retry == NULL) { 1449*2654012fSReza Sabdar free(uc_name); 1450*2654012fSReza Sabdar free(retry); 1451*2654012fSReza Sabdar return (FALSE); 1452*2654012fSReza Sabdar } 1453*2654012fSReza Sabdar 1454*2654012fSReza Sabdar if (IS_SET(flags, RSFLG_MATCH_WCARD)) 1455*2654012fSReza Sabdar cmp_fp = match; 1456*2654012fSReza Sabdar else 1457*2654012fSReza Sabdar cmp_fp = strexactcmp; 1458*2654012fSReza Sabdar 1459*2654012fSReza Sabdar namep = name + strspn(name, "/"); 1460*2654012fSReza Sabdar if (IS_SET(flags, RSFLG_IGNORE_CASE)) { 1461*2654012fSReza Sabdar (void) strlcpy(uc_name, namep, TLM_MAX_PATH_NAME); 1462*2654012fSReza Sabdar (void) strupr(uc_name); 1463*2654012fSReza Sabdar namep = uc_name; 1464*2654012fSReza Sabdar } 1465*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "is_file_wanted> flg: 0x%x name: [%s]", 1466*2654012fSReza Sabdar flags, name); 1467*2654012fSReza Sabdar 1468*2654012fSReza Sabdar for (i = 0; *sels != NULL; sels++, i++) { 1469*2654012fSReza Sabdar p_sel = *sels + strspn(*sels, "/"); 1470*2654012fSReza Sabdar 1471*2654012fSReza Sabdar /* 1472*2654012fSReza Sabdar * Try exact match. 1473*2654012fSReza Sabdar */ 1474*2654012fSReza Sabdar if ((*cmp_fp)(p_sel, namep)) { 1475*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "match1> pos: %d [%s][%s]", 1476*2654012fSReza Sabdar i, p_sel, name); 1477*2654012fSReza Sabdar found = TRUE; 1478*2654012fSReza Sabdar if (mchtype != NULL) 1479*2654012fSReza Sabdar *mchtype = PM_EXACT; 1480*2654012fSReza Sabdar break; 1481*2654012fSReza Sabdar } 1482*2654012fSReza Sabdar /* 1483*2654012fSReza Sabdar * Try "entry/" and the current selection. The 1484*2654012fSReza Sabdar * current selection may be something like "<something>/". 1485*2654012fSReza Sabdar */ 1486*2654012fSReza Sabdar (void) tlm_cat_path(retry, namep, "/"); 1487*2654012fSReza Sabdar if ((*cmp_fp)(p_sel, retry)) { 1488*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "match2> pos %d [%s][%s]", 1489*2654012fSReza Sabdar i, p_sel, name); 1490*2654012fSReza Sabdar found = TRUE; 1491*2654012fSReza Sabdar if (mchtype != NULL) 1492*2654012fSReza Sabdar *mchtype = PM_EXACT; 1493*2654012fSReza Sabdar break; 1494*2654012fSReza Sabdar } 1495*2654012fSReza Sabdar /* 1496*2654012fSReza Sabdar * If the following check returns true it means that the 1497*2654012fSReza Sabdar * 'name' is an entry below the 'p_sel' hierarchy. 1498*2654012fSReza Sabdar */ 1499*2654012fSReza Sabdar if (is_parent(p_sel, namep, flags)) { 1500*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "parent1> pos %d [%s][%s]", 1501*2654012fSReza Sabdar i, p_sel, name); 1502*2654012fSReza Sabdar found = TRUE; 1503*2654012fSReza Sabdar if (mchtype != NULL) 1504*2654012fSReza Sabdar *mchtype = PM_CHILD; 1505*2654012fSReza Sabdar break; 1506*2654012fSReza Sabdar } 1507*2654012fSReza Sabdar 1508*2654012fSReza Sabdar /* 1509*2654012fSReza Sabdar * There is a special case for parent directories of a 1510*2654012fSReza Sabdar * selection. If 'p_sel' is something like "*d1", the 1511*2654012fSReza Sabdar * middle directories of the final entry can't be determined 1512*2654012fSReza Sabdar * until the final entry matches with 'p_sel'. At that 1513*2654012fSReza Sabdar * time the middle directories of the entry have been passed 1514*2654012fSReza Sabdar * and they can't be restored. 1515*2654012fSReza Sabdar */ 1516*2654012fSReza Sabdar if (is_parent(namep, p_sel, flags)) { 1517*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "parent2> pos %d [%s][%s]", 1518*2654012fSReza Sabdar i, p_sel, name); 1519*2654012fSReza Sabdar found = TRUE; 1520*2654012fSReza Sabdar if (mchtype != NULL) 1521*2654012fSReza Sabdar *mchtype = PM_PARENT; 1522*2654012fSReza Sabdar break; 1523*2654012fSReza Sabdar } 1524*2654012fSReza Sabdar } 1525*2654012fSReza Sabdar 1526*2654012fSReza Sabdar /* Check for exclusions. */ 1527*2654012fSReza Sabdar if (found && exact_find(namep, exls)) { 1528*2654012fSReza Sabdar if (mchtype != NULL) 1529*2654012fSReza Sabdar *mchtype = PM_NONE; 1530*2654012fSReza Sabdar found = FALSE; 1531*2654012fSReza Sabdar } 1532*2654012fSReza Sabdar if (found && pos != NULL) 1533*2654012fSReza Sabdar *pos = i; 1534*2654012fSReza Sabdar 1535*2654012fSReza Sabdar free(uc_name); 1536*2654012fSReza Sabdar free(retry); 1537*2654012fSReza Sabdar return (found); 1538*2654012fSReza Sabdar } 1539*2654012fSReza Sabdar 1540*2654012fSReza Sabdar /* 1541*2654012fSReza Sabdar * Read the specified amount data into the buffer. Detects EOT or EOF 1542*2654012fSReza Sabdar * during read. 1543*2654012fSReza Sabdar * 1544*2654012fSReza Sabdar * Returns the number of bytes actually read. On error returns -1. 1545*2654012fSReza Sabdar */ 1546*2654012fSReza Sabdar static int 1547*2654012fSReza Sabdar input_mem(int l, 1548*2654012fSReza Sabdar int d, 1549*2654012fSReza Sabdar tlm_cmd_t *lcmds, 1550*2654012fSReza Sabdar char *mem, 1551*2654012fSReza Sabdar int len) 1552*2654012fSReza Sabdar { 1553*2654012fSReza Sabdar int err; 1554*2654012fSReza Sabdar int toread, actual_size, rec_size; 1555*2654012fSReza Sabdar char *rec; 1556*2654012fSReza Sabdar 1557*2654012fSReza Sabdar if (l <= 0 || d <= 0 || !lcmds || !mem) { 1558*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument"); 1559*2654012fSReza Sabdar return (-1); 1560*2654012fSReza Sabdar } 1561*2654012fSReza Sabdar 1562*2654012fSReza Sabdar toread = len; 1563*2654012fSReza Sabdar while (toread > 0) { 1564*2654012fSReza Sabdar rec = get_read_buffer(toread, &err, &actual_size, lcmds); 1565*2654012fSReza Sabdar if (actual_size <= 0) { 1566*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "err %d act_size %d detected", 1567*2654012fSReza Sabdar err, actual_size); 1568*2654012fSReza Sabdar break; 1569*2654012fSReza Sabdar } else if (err) { 1570*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d reading data", err); 1571*2654012fSReza Sabdar return (-1); 1572*2654012fSReza Sabdar } 1573*2654012fSReza Sabdar rec_size = min(actual_size, toread); 1574*2654012fSReza Sabdar (void) memcpy(mem, rec, rec_size); 1575*2654012fSReza Sabdar mem += rec_size; 1576*2654012fSReza Sabdar toread -= rec_size; 1577*2654012fSReza Sabdar } 1578*2654012fSReza Sabdar 1579*2654012fSReza Sabdar return (len - toread); 1580*2654012fSReza Sabdar } 1581*2654012fSReza Sabdar 1582*2654012fSReza Sabdar /* 1583*2654012fSReza Sabdar * pick up the name and size of a HUGE file 1584*2654012fSReza Sabdar */ 1585*2654012fSReza Sabdar static int 1586*2654012fSReza Sabdar get_humongus_file_header(int lib, 1587*2654012fSReza Sabdar int drv, 1588*2654012fSReza Sabdar long recsize, 1589*2654012fSReza Sabdar longlong_t *size, 1590*2654012fSReza Sabdar char *name, 1591*2654012fSReza Sabdar tlm_cmd_t *local_commands) 1592*2654012fSReza Sabdar { 1593*2654012fSReza Sabdar char *p_record, *value; 1594*2654012fSReza Sabdar int rv; 1595*2654012fSReza Sabdar 1596*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE Record found: %d", recsize); 1597*2654012fSReza Sabdar 1598*2654012fSReza Sabdar rv = 0; 1599*2654012fSReza Sabdar if (recsize == 0) { 1600*2654012fSReza Sabdar /* 1601*2654012fSReza Sabdar * The humongus_file_header was written in a 1602*2654012fSReza Sabdar * RECORDSIZE block and the header.size field of this 1603*2654012fSReza Sabdar * record was 0 before this fix. For backward compatiblity 1604*2654012fSReza Sabdar * read only one RECORDSIZE-size block if the header.size 1605*2654012fSReza Sabdar * field is 0. Otherwise the header.size field should show 1606*2654012fSReza Sabdar * the length of the data of this header. 1607*2654012fSReza Sabdar */ 1608*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Old HUGE record found"); 1609*2654012fSReza Sabdar recsize = RECORDSIZE; 1610*2654012fSReza Sabdar } 1611*2654012fSReza Sabdar 1612*2654012fSReza Sabdar if (input_mem(lib, drv, local_commands, name, recsize) != recsize) { 1613*2654012fSReza Sabdar rv = -1; 1614*2654012fSReza Sabdar *size = 0; 1615*2654012fSReza Sabdar *name = '\0'; 1616*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error reading a HUGE file name"); 1617*2654012fSReza Sabdar } else { 1618*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE [%s]", name); 1619*2654012fSReza Sabdar 1620*2654012fSReza Sabdar p_record = name; 1621*2654012fSReza Sabdar value = parse(&p_record, " "); 1622*2654012fSReza Sabdar *size = atoll(value); 1623*2654012fSReza Sabdar /* 1624*2654012fSReza Sabdar * Note: Since the backed up names are not longer than 1625*2654012fSReza Sabdar * NAME_MAX and the buffer passed to us is 1626*2654012fSReza Sabdar * TLM_MAX_PATH_NAME, it should be safe to use strlcpy 1627*2654012fSReza Sabdar * without check on the buffer size. 1628*2654012fSReza Sabdar */ 1629*2654012fSReza Sabdar (void) strlcpy(name, p_record, TLM_MAX_PATH_NAME); 1630*2654012fSReza Sabdar } 1631*2654012fSReza Sabdar 1632*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE Record %lld [%s]", *size, name); 1633*2654012fSReza Sabdar 1634*2654012fSReza Sabdar return (rv); 1635*2654012fSReza Sabdar } 1636*2654012fSReza Sabdar 1637*2654012fSReza Sabdar /* 1638*2654012fSReza Sabdar * pick up the long name from the special tape file 1639*2654012fSReza Sabdar */ 1640*2654012fSReza Sabdar static int 1641*2654012fSReza Sabdar get_long_name(int lib, 1642*2654012fSReza Sabdar int drv, 1643*2654012fSReza Sabdar long recsize, 1644*2654012fSReza Sabdar char *name, 1645*2654012fSReza Sabdar long *buf_spot, 1646*2654012fSReza Sabdar tlm_cmd_t *local_commands) 1647*2654012fSReza Sabdar { 1648*2654012fSReza Sabdar int nread; 1649*2654012fSReza Sabdar 1650*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "LONGNAME Record found rs %d bs %d", recsize, 1651*2654012fSReza Sabdar *buf_spot); 1652*2654012fSReza Sabdar 1653*2654012fSReza Sabdar if (*buf_spot < 0) 1654*2654012fSReza Sabdar *buf_spot = 0; 1655*2654012fSReza Sabdar 1656*2654012fSReza Sabdar nread = input_mem(lib, drv, local_commands, name + *buf_spot, 1657*2654012fSReza Sabdar recsize); 1658*2654012fSReza Sabdar if (nread < 0) { 1659*2654012fSReza Sabdar nread = recsize; /* return 0 as size left */ 1660*2654012fSReza Sabdar name[*buf_spot] = '\0'; 1661*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Error %d reading a long file name %s.", 1662*2654012fSReza Sabdar nread, name); 1663*2654012fSReza Sabdar } else { 1664*2654012fSReza Sabdar *buf_spot += nread; 1665*2654012fSReza Sabdar name[*buf_spot] = '\0'; 1666*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "LONGNAME [%s]", name); 1667*2654012fSReza Sabdar } 1668*2654012fSReza Sabdar 1669*2654012fSReza Sabdar return (recsize - nread); 1670*2654012fSReza Sabdar } 1671*2654012fSReza Sabdar 1672*2654012fSReza Sabdar /* 1673*2654012fSReza Sabdar * create a new directory 1674*2654012fSReza Sabdar */ 1675*2654012fSReza Sabdar static int 1676*2654012fSReza Sabdar create_directory(char *dir, tlm_job_stats_t *job_stats) 1677*2654012fSReza Sabdar { 1678*2654012fSReza Sabdar struct stat64 attr; 1679*2654012fSReza Sabdar char *p; 1680*2654012fSReza Sabdar char temp; 1681*2654012fSReza Sabdar int erc; 1682*2654012fSReza Sabdar 1683*2654012fSReza Sabdar /* 1684*2654012fSReza Sabdar * Make sure all directories in this path exist, create them if 1685*2654012fSReza Sabdar * needed. 1686*2654012fSReza Sabdar */ 1687*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new dir[%s]", dir); 1688*2654012fSReza Sabdar 1689*2654012fSReza Sabdar erc = 0; 1690*2654012fSReza Sabdar p = &dir[1]; 1691*2654012fSReza Sabdar do { 1692*2654012fSReza Sabdar temp = *p; 1693*2654012fSReza Sabdar if (temp == '/' || temp == 0) { 1694*2654012fSReza Sabdar *p = 0; 1695*2654012fSReza Sabdar if (stat64(dir, &attr) < 0) { 1696*2654012fSReza Sabdar erc = mkdir(dir, 0777); 1697*2654012fSReza Sabdar if (erc < 0) { 1698*2654012fSReza Sabdar job_stats->js_errors++; 1699*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1700*2654012fSReza Sabdar "Could not create directory %s", 1701*2654012fSReza Sabdar dir); 1702*2654012fSReza Sabdar break; 1703*2654012fSReza Sabdar } 1704*2654012fSReza Sabdar } 1705*2654012fSReza Sabdar *p = temp; 1706*2654012fSReza Sabdar } 1707*2654012fSReza Sabdar p++; 1708*2654012fSReza Sabdar } while (temp != 0); 1709*2654012fSReza Sabdar 1710*2654012fSReza Sabdar return (erc); 1711*2654012fSReza Sabdar } 1712*2654012fSReza Sabdar 1713*2654012fSReza Sabdar /* 1714*2654012fSReza Sabdar * create a new hardlink 1715*2654012fSReza Sabdar */ 1716*2654012fSReza Sabdar static int 1717*2654012fSReza Sabdar create_hard_link(char *name_old, char *name_new, 1718*2654012fSReza Sabdar tlm_acls_t *acls, tlm_job_stats_t *job_stats) 1719*2654012fSReza Sabdar { 1720*2654012fSReza Sabdar int erc; 1721*2654012fSReza Sabdar 1722*2654012fSReza Sabdar if (mkbasedir(name_new)) { 1723*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "faile to make base dir for [%s]", 1724*2654012fSReza Sabdar name_new); 1725*2654012fSReza Sabdar 1726*2654012fSReza Sabdar return (-1); 1727*2654012fSReza Sabdar } 1728*2654012fSReza Sabdar 1729*2654012fSReza Sabdar erc = link(name_old, name_new); 1730*2654012fSReza Sabdar if (erc) { 1731*2654012fSReza Sabdar job_stats->js_errors++; 1732*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d (errno %d) hardlink [%s] to [%s]", 1733*2654012fSReza Sabdar erc, errno, name_new, name_old); 1734*2654012fSReza Sabdar } else { 1735*2654012fSReza Sabdar set_acl(name_new, acls); 1736*2654012fSReza Sabdar } 1737*2654012fSReza Sabdar return (erc); 1738*2654012fSReza Sabdar } 1739*2654012fSReza Sabdar 1740*2654012fSReza Sabdar /* 1741*2654012fSReza Sabdar * create a new symlink 1742*2654012fSReza Sabdar */ 1743*2654012fSReza Sabdar /*ARGSUSED*/ 1744*2654012fSReza Sabdar static int 1745*2654012fSReza Sabdar create_sym_link(char *dst, char *target, tlm_acls_t *acls, 1746*2654012fSReza Sabdar tlm_job_stats_t *job_satats) 1747*2654012fSReza Sabdar { 1748*2654012fSReza Sabdar int erc; 1749*2654012fSReza Sabdar 1750*2654012fSReza Sabdar if (mkbasedir(dst) < 0) 1751*2654012fSReza Sabdar return (-1); 1752*2654012fSReza Sabdar 1753*2654012fSReza Sabdar erc = symlink(target, dst); 1754*2654012fSReza Sabdar if (erc) { 1755*2654012fSReza Sabdar job_satats->js_errors++; 1756*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d (errno %d) softlink [%s] to [%s]", 1757*2654012fSReza Sabdar erc, errno, dst, target); 1758*2654012fSReza Sabdar } 1759*2654012fSReza Sabdar 1760*2654012fSReza Sabdar return (erc); 1761*2654012fSReza Sabdar } 1762*2654012fSReza Sabdar 1763*2654012fSReza Sabdar /* 1764*2654012fSReza Sabdar * create a new FIFO 1765*2654012fSReza Sabdar */ 1766*2654012fSReza Sabdar static int 1767*2654012fSReza Sabdar create_fifo(char *name, tlm_acls_t *acls) 1768*2654012fSReza Sabdar { 1769*2654012fSReza Sabdar (void) mknod(name, 0777 + S_IFIFO, 0); 1770*2654012fSReza Sabdar set_acl(name, acls); 1771*2654012fSReza Sabdar return (0); 1772*2654012fSReza Sabdar } 1773*2654012fSReza Sabdar 1774*2654012fSReza Sabdar /* 1775*2654012fSReza Sabdar * read in the ACLs for the next file 1776*2654012fSReza Sabdar */ 1777*2654012fSReza Sabdar static long 1778*2654012fSReza Sabdar load_acl_info(int lib, 1779*2654012fSReza Sabdar int drv, 1780*2654012fSReza Sabdar long file_size, 1781*2654012fSReza Sabdar tlm_acls_t *acls, 1782*2654012fSReza Sabdar long *acl_spot, 1783*2654012fSReza Sabdar tlm_cmd_t *local_commands) 1784*2654012fSReza Sabdar { 1785*2654012fSReza Sabdar char *bp; 1786*2654012fSReza Sabdar int nread; 1787*2654012fSReza Sabdar 1788*2654012fSReza Sabdar /* 1789*2654012fSReza Sabdar * If the ACL is spanned on tapes, then the acl_spot should NOT be 1790*2654012fSReza Sabdar * 0 on next calls to this function to read the rest of the ACL 1791*2654012fSReza Sabdar * on next tapes. 1792*2654012fSReza Sabdar */ 1793*2654012fSReza Sabdar if (*acl_spot == 0) { 1794*2654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 1795*2654012fSReza Sabdar } 1796*2654012fSReza Sabdar 1797*2654012fSReza Sabdar bp = ((char *)&acls->acl_info) + *acl_spot; 1798*2654012fSReza Sabdar nread = input_mem(lib, drv, local_commands, (void *)bp, file_size); 1799*2654012fSReza Sabdar if (nread < 0) { 1800*2654012fSReza Sabdar *acl_spot = 0; 1801*2654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 1802*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error reading ACL data"); 1803*2654012fSReza Sabdar return (0); 1804*2654012fSReza Sabdar } 1805*2654012fSReza Sabdar *acl_spot += nread; 1806*2654012fSReza Sabdar acls->acl_non_trivial = TRUE; 1807*2654012fSReza Sabdar 1808*2654012fSReza Sabdar return (file_size - nread); 1809*2654012fSReza Sabdar } 1810*2654012fSReza Sabdar 1811*2654012fSReza Sabdar static int 1812*2654012fSReza Sabdar ndmp_set_eprivs_least(void) 1813*2654012fSReza Sabdar { 1814*2654012fSReza Sabdar priv_set_t *priv_set; 1815*2654012fSReza Sabdar 1816*2654012fSReza Sabdar if ((priv_set = priv_allocset()) == NULL) { 1817*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Out of memory."); 1818*2654012fSReza Sabdar return (-1); 1819*2654012fSReza Sabdar } 1820*2654012fSReza Sabdar priv_emptyset(priv_set); 1821*2654012fSReza Sabdar (void) priv_addset(priv_set, "basic"); 1822*2654012fSReza Sabdar (void) priv_addset(priv_set, "proc_audit"); 1823*2654012fSReza Sabdar (void) priv_addset(priv_set, "proc_setid"); 1824*2654012fSReza Sabdar (void) priv_addset(priv_set, "proc_owner"); 1825*2654012fSReza Sabdar (void) priv_addset(priv_set, "file_chown"); 1826*2654012fSReza Sabdar (void) priv_addset(priv_set, "file_chown_self"); 1827*2654012fSReza Sabdar (void) priv_addset(priv_set, "file_dac_read"); 1828*2654012fSReza Sabdar (void) priv_addset(priv_set, "file_dac_search"); 1829*2654012fSReza Sabdar (void) priv_addset(priv_set, "file_dac_write"); 1830*2654012fSReza Sabdar (void) priv_addset(priv_set, "file_owner"); 1831*2654012fSReza Sabdar (void) priv_addset(priv_set, "file_setid"); 1832*2654012fSReza Sabdar (void) priv_addset(priv_set, "sys_linkdir"); 1833*2654012fSReza Sabdar (void) priv_addset(priv_set, "sys_devices"); 1834*2654012fSReza Sabdar (void) priv_addset(priv_set, "sys_mount"); 1835*2654012fSReza Sabdar (void) priv_addset(priv_set, "sys_config"); 1836*2654012fSReza Sabdar 1837*2654012fSReza Sabdar if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 1838*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Additional privileges required."); 1839*2654012fSReza Sabdar priv_freeset(priv_set); 1840*2654012fSReza Sabdar return (-1); 1841*2654012fSReza Sabdar } 1842*2654012fSReza Sabdar priv_freeset(priv_set); 1843*2654012fSReza Sabdar return (0); 1844*2654012fSReza Sabdar } 1845*2654012fSReza Sabdar 1846*2654012fSReza Sabdar static int 1847*2654012fSReza Sabdar ndmp_set_eprivs_all(void) 1848*2654012fSReza Sabdar { 1849*2654012fSReza Sabdar priv_set_t *priv_set; 1850*2654012fSReza Sabdar 1851*2654012fSReza Sabdar if ((priv_set = priv_str_to_set("all", ",", NULL)) == NULL) { 1852*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Could not set privileges to 'all'."); 1853*2654012fSReza Sabdar return (-1); 1854*2654012fSReza Sabdar } 1855*2654012fSReza Sabdar if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) != 0) { 1856*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Additional privileges required."); 1857*2654012fSReza Sabdar return (-1); 1858*2654012fSReza Sabdar } 1859*2654012fSReza Sabdar priv_freeset(priv_set); 1860*2654012fSReza Sabdar return (0); 1861*2654012fSReza Sabdar } 1862*2654012fSReza Sabdar 1863*2654012fSReza Sabdar /* 1864*2654012fSReza Sabdar * Set the standard attributes of the file 1865*2654012fSReza Sabdar */ 1866*2654012fSReza Sabdar static void 1867*2654012fSReza Sabdar set_attr(char *name, struct stat64 *st) 1868*2654012fSReza Sabdar { 1869*2654012fSReza Sabdar struct utimbuf tbuf; 1870*2654012fSReza Sabdar boolean_t priv_all = FALSE; 1871*2654012fSReza Sabdar 1872*2654012fSReza Sabdar if (!name || !st) 1873*2654012fSReza Sabdar return; 1874*2654012fSReza Sabdar 1875*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "set_attr: %s uid %d gid %d mode %o", name, 1876*2654012fSReza Sabdar st->st_uid, st->st_gid, st->st_mode); 1877*2654012fSReza Sabdar 1878*2654012fSReza Sabdar if (chown(name, st->st_uid, st->st_gid)) 1879*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, 1880*2654012fSReza Sabdar "Could not set uid or/and gid for file %s.", name); 1881*2654012fSReza Sabdar 1882*2654012fSReza Sabdar if ((st->st_mode & (S_ISUID | S_ISGID)) != 0) { 1883*2654012fSReza Sabdar /* 1884*2654012fSReza Sabdar * Change effective privileges to 'all' which is required to 1885*2654012fSReza Sabdar * change setuid bit for 'root' owned files. If fails, just 1886*2654012fSReza Sabdar * send error to log file and proceed. 1887*2654012fSReza Sabdar */ 1888*2654012fSReza Sabdar if (ndmp_set_eprivs_all()) { 1889*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, 1890*2654012fSReza Sabdar "Could not set effective privileges to 'all'."); 1891*2654012fSReza Sabdar } else { 1892*2654012fSReza Sabdar priv_all = TRUE; 1893*2654012fSReza Sabdar } 1894*2654012fSReza Sabdar } 1895*2654012fSReza Sabdar 1896*2654012fSReza Sabdar if (chmod(name, st->st_mode)) 1897*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, 1898*2654012fSReza Sabdar "Could not set correct file permission for file %s.", name); 1899*2654012fSReza Sabdar 1900*2654012fSReza Sabdar if (priv_all == TRUE) { 1901*2654012fSReza Sabdar /* 1902*2654012fSReza Sabdar * Give up the 'all' privileges for effective sets and go back 1903*2654012fSReza Sabdar * to least required privileges. If fails, just send error to 1904*2654012fSReza Sabdar * log file and proceed. 1905*2654012fSReza Sabdar */ 1906*2654012fSReza Sabdar if (ndmp_set_eprivs_least()) 1907*2654012fSReza Sabdar NDMP_LOG(LOG_ERR, 1908*2654012fSReza Sabdar "Could not set least required privileges."); 1909*2654012fSReza Sabdar } 1910*2654012fSReza Sabdar 1911*2654012fSReza Sabdar tbuf.modtime = st->st_mtime; 1912*2654012fSReza Sabdar tbuf.actime = st->st_atime; 1913*2654012fSReza Sabdar (void) utime(name, &tbuf); 1914*2654012fSReza Sabdar } 1915*2654012fSReza Sabdar 1916*2654012fSReza Sabdar /* 1917*2654012fSReza Sabdar * Set the ACL info for the file 1918*2654012fSReza Sabdar */ 1919*2654012fSReza Sabdar static void 1920*2654012fSReza Sabdar set_acl(char *name, tlm_acls_t *acls) 1921*2654012fSReza Sabdar { 1922*2654012fSReza Sabdar int erc; 1923*2654012fSReza Sabdar acl_t *aclp = NULL; 1924*2654012fSReza Sabdar 1925*2654012fSReza Sabdar if (name) 1926*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "set_acl: %s", name); 1927*2654012fSReza Sabdar if (acls != 0) { 1928*2654012fSReza Sabdar /* Need a place to save real modification time */ 1929*2654012fSReza Sabdar 1930*2654012fSReza Sabdar set_attr(name, &acls->acl_attr); 1931*2654012fSReza Sabdar 1932*2654012fSReza Sabdar if (!acls->acl_non_trivial) { 1933*2654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 1934*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "set_acl: skipping trivial"); 1935*2654012fSReza Sabdar return; 1936*2654012fSReza Sabdar } 1937*2654012fSReza Sabdar 1938*2654012fSReza Sabdar erc = acl_fromtext(acls->acl_info.attr_info, &aclp); 1939*2654012fSReza Sabdar if (erc != 0) { 1940*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1941*2654012fSReza Sabdar "TAPE RESTORE> acl_fromtext errno %d", erc); 1942*2654012fSReza Sabdar } 1943*2654012fSReza Sabdar if (aclp) { 1944*2654012fSReza Sabdar erc = acl_set(name, aclp); 1945*2654012fSReza Sabdar if (erc < 0) { 1946*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1947*2654012fSReza Sabdar "TAPE RESTORE> acl_set errno %d", errno); 1948*2654012fSReza Sabdar } 1949*2654012fSReza Sabdar acl_free(aclp); 1950*2654012fSReza Sabdar } 1951*2654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 1952*2654012fSReza Sabdar } 1953*2654012fSReza Sabdar } 1954*2654012fSReza Sabdar 1955*2654012fSReza Sabdar /* 1956*2654012fSReza Sabdar * a wrapper to tlm_get_read_buffer so that 1957*2654012fSReza Sabdar * we can cleanly detect ABORT commands 1958*2654012fSReza Sabdar * without involving the TLM library with 1959*2654012fSReza Sabdar * our problems. 1960*2654012fSReza Sabdar */ 1961*2654012fSReza Sabdar static char * 1962*2654012fSReza Sabdar get_read_buffer(int want, 1963*2654012fSReza Sabdar int *error, 1964*2654012fSReza Sabdar int *actual_size, 1965*2654012fSReza Sabdar tlm_cmd_t *local_commands) 1966*2654012fSReza Sabdar { 1967*2654012fSReza Sabdar while (local_commands->tc_writer == TLM_RESTORE_RUN) { 1968*2654012fSReza Sabdar char *rec; 1969*2654012fSReza Sabdar rec = tlm_get_read_buffer(want, error, 1970*2654012fSReza Sabdar local_commands->tc_buffers, actual_size); 1971*2654012fSReza Sabdar if (rec != 0) { 1972*2654012fSReza Sabdar return (rec); 1973*2654012fSReza Sabdar } 1974*2654012fSReza Sabdar } 1975*2654012fSReza Sabdar 1976*2654012fSReza Sabdar /* 1977*2654012fSReza Sabdar * the job is ending, give Writer a buffer that will never be read ... 1978*2654012fSReza Sabdar * it does not matter anyhow, we are aborting. 1979*2654012fSReza Sabdar */ 1980*2654012fSReza Sabdar *actual_size = RECORDSIZE; 1981*2654012fSReza Sabdar return (NULL); 1982*2654012fSReza Sabdar } 1983*2654012fSReza Sabdar 1984*2654012fSReza Sabdar /* 1985*2654012fSReza Sabdar * Enable wildcard for restore options 1986*2654012fSReza Sabdar */ 1987*2654012fSReza Sabdar static boolean_t 1988*2654012fSReza Sabdar wildcard_enabled(void) 1989*2654012fSReza Sabdar { 1990*2654012fSReza Sabdar char *cp; 1991*2654012fSReza Sabdar 1992*2654012fSReza Sabdar cp = ndmpd_get_prop_default(NDMP_RESTORE_WILDCARD_ENABLE, "n"); 1993*2654012fSReza Sabdar return ((toupper(*cp) == 'Y') ? TRUE : FALSE); 1994*2654012fSReza Sabdar } 1995*2654012fSReza Sabdar 1996*2654012fSReza Sabdar 1997*2654012fSReza Sabdar /* 1998*2654012fSReza Sabdar * Concatenate two names 1999*2654012fSReza Sabdar */ 2000*2654012fSReza Sabdar /*ARGSUSED*/ 2001*2654012fSReza Sabdar static char * 2002*2654012fSReza Sabdar catnames(struct rs_name_maker *rnp, char *buf, int pos, char *path) 2003*2654012fSReza Sabdar { 2004*2654012fSReza Sabdar char *rv; 2005*2654012fSReza Sabdar 2006*2654012fSReza Sabdar rv = NULL; 2007*2654012fSReza Sabdar if (!buf) { 2008*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "buf is NULL"); 2009*2654012fSReza Sabdar } else if (!path) { 2010*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "path is NULL"); 2011*2654012fSReza Sabdar } else if (!rnp->rn_nlp) { 2012*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "rn_nlp is NULL [%s]", path); 2013*2654012fSReza Sabdar } else if (!tlm_cat_path(buf, rnp->rn_nlp, path)) { 2014*2654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", 2015*2654012fSReza Sabdar rnp->rn_nlp, path); 2016*2654012fSReza Sabdar } else 2017*2654012fSReza Sabdar rv = buf; 2018*2654012fSReza Sabdar 2019*2654012fSReza Sabdar return (rv); 2020*2654012fSReza Sabdar } 2021*2654012fSReza Sabdar 2022*2654012fSReza Sabdar 2023*2654012fSReza Sabdar /* 2024*2654012fSReza Sabdar * Create a new name path for restore 2025*2654012fSReza Sabdar */ 2026*2654012fSReza Sabdar static char * 2027*2654012fSReza Sabdar rs_new_name(struct rs_name_maker *rnp, char *buf, int pos, char *path) 2028*2654012fSReza Sabdar { 2029*2654012fSReza Sabdar if (!rnp || !rnp->rn_fp) 2030*2654012fSReza Sabdar return (NULL); 2031*2654012fSReza Sabdar 2032*2654012fSReza Sabdar return (*rnp->rn_fp)(rnp, buf, pos, path); 2033*2654012fSReza Sabdar } 2034*2654012fSReza Sabdar 2035*2654012fSReza Sabdar /* 2036*2654012fSReza Sabdar * Iterate over ZFS metadata stored in the backup stream and use the callback 2037*2654012fSReza Sabdar * to restore it. 2038*2654012fSReza Sabdar */ 2039*2654012fSReza Sabdar int 2040*2654012fSReza Sabdar ndmp_iter_zfs(ndmp_context_t *nctx, int (*np_restore_property)(nvlist_t *, 2041*2654012fSReza Sabdar void *), void *ptr) 2042*2654012fSReza Sabdar { 2043*2654012fSReza Sabdar tlm_commands_t *cmds; 2044*2654012fSReza Sabdar ndmp_metadata_header_t *mhp; 2045*2654012fSReza Sabdar ndmp_metadata_property_t *mpp; 2046*2654012fSReza Sabdar tlm_cmd_t *lcmd; 2047*2654012fSReza Sabdar int actual_size; 2048*2654012fSReza Sabdar nvlist_t *nvl; 2049*2654012fSReza Sabdar nvlist_t *nvl_head; 2050*2654012fSReza Sabdar nvlist_t *valp; 2051*2654012fSReza Sabdar nvpair_t *nvp = NULL; 2052*2654012fSReza Sabdar nvpair_t *nvph = NULL; 2053*2654012fSReza Sabdar char plname[100]; 2054*2654012fSReza Sabdar char *mhbuf, *pp, *tp; 2055*2654012fSReza Sabdar int rv, i; 2056*2654012fSReza Sabdar int size, lsize, sz; 2057*2654012fSReza Sabdar int align = RECORDSIZE - 1; 2058*2654012fSReza Sabdar 2059*2654012fSReza Sabdar if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 2060*2654012fSReza Sabdar return (-1); 2061*2654012fSReza Sabdar 2062*2654012fSReza Sabdar nctx->nc_plname = plname; 2063*2654012fSReza Sabdar if ((lcmd = cmds->tcs_command) == NULL || 2064*2654012fSReza Sabdar lcmd->tc_buffers == NULL) 2065*2654012fSReza Sabdar return (-1); 2066*2654012fSReza Sabdar 2067*2654012fSReza Sabdar size = sizeof (ndmp_metadata_header_t) + 2068*2654012fSReza Sabdar ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 2069*2654012fSReza Sabdar size += align; 2070*2654012fSReza Sabdar size &= ~align; 2071*2654012fSReza Sabdar 2072*2654012fSReza Sabdar /* For nvlist cleanup */ 2073*2654012fSReza Sabdar if (nvlist_alloc(&nvl_head, NV_UNIQUE_NAME, 0) != 0) 2074*2654012fSReza Sabdar return (-1); 2075*2654012fSReza Sabdar 2076*2654012fSReza Sabdar if ((mhbuf = malloc(size)) == NULL) 2077*2654012fSReza Sabdar return (-1); 2078*2654012fSReza Sabdar 2079*2654012fSReza Sabdar /* LINTED improper alignment */ 2080*2654012fSReza Sabdar while ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv, 2081*2654012fSReza Sabdar &actual_size, lcmd)) != NULL) { 2082*2654012fSReza Sabdar pp = mhbuf; 2083*2654012fSReza Sabdar 2084*2654012fSReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC, 2085*2654012fSReza Sabdar sizeof (mhp->nh_magic)) != 0) { 2086*2654012fSReza Sabdar /* No more metadata */ 2087*2654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 2088*2654012fSReza Sabdar nvlist_free(nvl_head); 2089*2654012fSReza Sabdar return (0); 2090*2654012fSReza Sabdar } 2091*2654012fSReza Sabdar 2092*2654012fSReza Sabdar (void) memcpy(pp, (char *)mhp, (actual_size < size) ? 2093*2654012fSReza Sabdar actual_size : size); 2094*2654012fSReza Sabdar pp += (actual_size < size) ? actual_size : size; 2095*2654012fSReza Sabdar 2096*2654012fSReza Sabdar sz = actual_size; 2097*2654012fSReza Sabdar while (sz < size && 2098*2654012fSReza Sabdar ((tp = get_read_buffer(size - sz, &rv, &lsize, 2099*2654012fSReza Sabdar lcmd))) != NULL) { 2100*2654012fSReza Sabdar (void) memcpy(pp, tp, size - sz); 2101*2654012fSReza Sabdar sz += lsize; 2102*2654012fSReza Sabdar pp += lsize; 2103*2654012fSReza Sabdar } 2104*2654012fSReza Sabdar if (sz > size) { 2105*2654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, sz - size); 2106*2654012fSReza Sabdar } 2107*2654012fSReza Sabdar /* LINTED improper alignment */ 2108*2654012fSReza Sabdar mhp = (ndmp_metadata_header_t *)mhbuf; 2109*2654012fSReza Sabdar 2110*2654012fSReza Sabdar nctx->nc_plversion = mhp->nh_plversion; 2111*2654012fSReza Sabdar (void) strlcpy(plname, mhp->nh_plname, sizeof (plname)); 2112*2654012fSReza Sabdar 2113*2654012fSReza Sabdar if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 2114*2654012fSReza Sabdar goto nvlist_err; 2115*2654012fSReza Sabdar 2116*2654012fSReza Sabdar mpp = &mhp->nh_property[0]; 2117*2654012fSReza Sabdar for (i = 0; i < mhp->nh_count && mpp; i++) { 2118*2654012fSReza Sabdar if (nvlist_alloc(&valp, NV_UNIQUE_NAME, 0) != 0 || 2119*2654012fSReza Sabdar nvlist_add_string(valp, "value", 2120*2654012fSReza Sabdar mpp->mp_value) != 0 || 2121*2654012fSReza Sabdar nvlist_add_string(valp, "source", 2122*2654012fSReza Sabdar mpp->mp_source) != 0 || 2123*2654012fSReza Sabdar nvlist_add_nvlist(nvl, mpp->mp_name, valp) != 0) 2124*2654012fSReza Sabdar goto nvlist_err; 2125*2654012fSReza Sabdar mpp++; 2126*2654012fSReza Sabdar } 2127*2654012fSReza Sabdar 2128*2654012fSReza Sabdar if (np_restore_property(nvl, ptr) != 0) 2129*2654012fSReza Sabdar goto nvlist_err; 2130*2654012fSReza Sabdar 2131*2654012fSReza Sabdar (void) nvlist_add_nvlist(nvl_head, "_", nvl); 2132*2654012fSReza Sabdar } 2133*2654012fSReza Sabdar free(mhbuf); 2134*2654012fSReza Sabdar 2135*2654012fSReza Sabdar nvlist_free(nvl_head); 2136*2654012fSReza Sabdar return (0); 2137*2654012fSReza Sabdar 2138*2654012fSReza Sabdar nvlist_err: 2139*2654012fSReza Sabdar free(mhbuf); 2140*2654012fSReza Sabdar while ((nvph = nvlist_next_nvpair(nvl_head, nvph)) != NULL && 2141*2654012fSReza Sabdar nvpair_value_nvlist(nvph, &nvl) == 0) { 2142*2654012fSReza Sabdar while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL && 2143*2654012fSReza Sabdar nvpair_value_nvlist(nvp, &valp) == 0) { 2144*2654012fSReza Sabdar nvlist_free(valp); 2145*2654012fSReza Sabdar } 2146*2654012fSReza Sabdar nvlist_free(nvl); 2147*2654012fSReza Sabdar } 2148*2654012fSReza Sabdar nvlist_free(nvl_head); 2149*2654012fSReza Sabdar return (-1); 2150*2654012fSReza Sabdar } 2151*2654012fSReza Sabdar 2152*2654012fSReza Sabdar /* 2153*2654012fSReza Sabdar * Returns the version number of the plugin which created the metadata 2154*2654012fSReza Sabdar */ 2155*2654012fSReza Sabdar uint_t 2156*2654012fSReza Sabdar ndmp_context_get_version(ndmp_context_t *nctx) 2157*2654012fSReza Sabdar { 2158*2654012fSReza Sabdar tlm_commands_t *cmds; 2159*2654012fSReza Sabdar ndmp_metadata_header_t *mhp; 2160*2654012fSReza Sabdar tlm_cmd_t *lcmd; 2161*2654012fSReza Sabdar int actual_size; 2162*2654012fSReza Sabdar int rv; 2163*2654012fSReza Sabdar int size; 2164*2654012fSReza Sabdar int align = RECORDSIZE - 1; 2165*2654012fSReza Sabdar 2166*2654012fSReza Sabdar if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 2167*2654012fSReza Sabdar return (0); 2168*2654012fSReza Sabdar 2169*2654012fSReza Sabdar if ((lcmd = cmds->tcs_command) == NULL || 2170*2654012fSReza Sabdar lcmd->tc_buffers == NULL) 2171*2654012fSReza Sabdar return (0); 2172*2654012fSReza Sabdar 2173*2654012fSReza Sabdar size = sizeof (ndmp_metadata_header_t); 2174*2654012fSReza Sabdar size += align; 2175*2654012fSReza Sabdar size &= ~align; 2176*2654012fSReza Sabdar 2177*2654012fSReza Sabdar /* LINTED improper alignment */ 2178*2654012fSReza Sabdar if ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv, 2179*2654012fSReza Sabdar &actual_size, lcmd)) != NULL) { 2180*2654012fSReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC, 2181*2654012fSReza Sabdar sizeof (mhp->nh_magic)) != 0) { 2182*2654012fSReza Sabdar /* No more metadata */ 2183*2654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 2184*2654012fSReza Sabdar return (0); 2185*2654012fSReza Sabdar } 2186*2654012fSReza Sabdar 2187*2654012fSReza Sabdar nctx->nc_plversion = mhp->nh_plversion; 2188*2654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 2189*2654012fSReza Sabdar } 2190*2654012fSReza Sabdar 2191*2654012fSReza Sabdar return (nctx->nc_plversion); 2192*2654012fSReza Sabdar } 2193