12654012fSReza Sabdar /* 2b6b15642SReza Sabdar * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 32654012fSReza Sabdar * Use is subject to license terms. 42654012fSReza Sabdar */ 52654012fSReza Sabdar 62654012fSReza Sabdar /* 72654012fSReza Sabdar * BSD 3 Clause License 82654012fSReza Sabdar * 92654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 102654012fSReza Sabdar * 112654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 122654012fSReza Sabdar * modification, are permitted provided that the following conditions 132654012fSReza Sabdar * are met: 142654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 152654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 162654012fSReza Sabdar * 172654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 182654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 192654012fSReza Sabdar * the documentation and/or other materials provided with the 202654012fSReza Sabdar * distribution. 212654012fSReza Sabdar * 222654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 232654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 242654012fSReza Sabdar * products derived from this software without specific prior written 252654012fSReza Sabdar * permission. 262654012fSReza Sabdar * 272654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 282654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 292654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 302654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 312654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 322654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 332654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 342654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 352654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 362654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 372654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 382654012fSReza Sabdar */ 392654012fSReza Sabdar #include <stdlib.h> 402654012fSReza Sabdar #include <ctype.h> 412654012fSReza Sabdar #include <stdio.h> 422654012fSReza Sabdar #include <limits.h> 432654012fSReza Sabdar #include <string.h> 442654012fSReza Sabdar #include <time.h> 452654012fSReza Sabdar #include <sys/types.h> 462654012fSReza Sabdar #include <sys/acl.h> 472654012fSReza Sabdar #include <utime.h> 482654012fSReza Sabdar #include <unistd.h> 492654012fSReza Sabdar #include <pthread.h> 502654012fSReza Sabdar #include <archives.h> 512654012fSReza Sabdar #include <priv.h> 522654012fSReza Sabdar #include <tlm.h> 532654012fSReza Sabdar #include <libzfs.h> 54b6b15642SReza Sabdar #include <pwd.h> 55b6b15642SReza Sabdar #include <grp.h> 562654012fSReza Sabdar #include <ndmpd_prop.h> 572654012fSReza Sabdar #include "tlm_proto.h" 582654012fSReza Sabdar 592654012fSReza Sabdar 602654012fSReza Sabdar #define PM_EXACT_OR_CHILD(m) ((m) == PM_EXACT || (m) == PM_CHILD) 612654012fSReza Sabdar 622654012fSReza Sabdar typedef boolean_t name_match_fp_t(char *s, char *t); 632654012fSReza Sabdar 642654012fSReza Sabdar static void set_acl(char *name, 652654012fSReza Sabdar tlm_acls_t *acls); 662654012fSReza Sabdar static long restore_file(int *fp, 672654012fSReza Sabdar char *real_name, 682654012fSReza Sabdar long size, 692654012fSReza Sabdar longlong_t huge_size, 702654012fSReza Sabdar tlm_acls_t *, 712654012fSReza Sabdar boolean_t want_this_file, 722654012fSReza Sabdar tlm_cmd_t *, 732654012fSReza Sabdar tlm_job_stats_t *); 742654012fSReza Sabdar static long restore_xattr_hdr(int *fp, 752654012fSReza Sabdar char *name, 762654012fSReza Sabdar char *fname, 772654012fSReza Sabdar long size, 782654012fSReza Sabdar tlm_acls_t *acls, 792654012fSReza Sabdar tlm_cmd_t *local_commands, 802654012fSReza Sabdar tlm_job_stats_t *job_stats); 812654012fSReza Sabdar static int get_long_name(int lib, 822654012fSReza Sabdar int drv, 832654012fSReza Sabdar long recsize, 842654012fSReza Sabdar char *name, 852654012fSReza Sabdar long *buf_spot, 862654012fSReza Sabdar tlm_cmd_t *local_commands); 872654012fSReza Sabdar static int get_humongus_file_header(int lib, 882654012fSReza Sabdar int drv, 892654012fSReza Sabdar long recsize, 902654012fSReza Sabdar longlong_t *size, 912654012fSReza Sabdar char *name, 922654012fSReza Sabdar tlm_cmd_t *); 932654012fSReza Sabdar static int create_directory(char *dir, 942654012fSReza Sabdar tlm_job_stats_t *); 952654012fSReza Sabdar static int create_hard_link(char *name, 962654012fSReza Sabdar char *link, 972654012fSReza Sabdar tlm_acls_t *, 982654012fSReza Sabdar tlm_job_stats_t *); 992654012fSReza Sabdar static int create_sym_link(char *dst, 1002654012fSReza Sabdar char *target, 1012654012fSReza Sabdar tlm_acls_t *, 1022654012fSReza Sabdar tlm_job_stats_t *); 1032654012fSReza Sabdar static int create_fifo(char *name, 1042654012fSReza Sabdar tlm_acls_t *); 1052654012fSReza Sabdar static long load_acl_info(int lib, 1062654012fSReza Sabdar int drv, 1072654012fSReza Sabdar long size, 1082654012fSReza Sabdar tlm_acls_t *, 1092654012fSReza Sabdar long *acl_spot, 1102654012fSReza Sabdar tlm_cmd_t *); 1112654012fSReza Sabdar static char *get_read_buffer(int want, 1122654012fSReza Sabdar int *error, 1132654012fSReza Sabdar int *actual_size, 1142654012fSReza Sabdar tlm_cmd_t *); 1152654012fSReza Sabdar static boolean_t wildcard_enabled(void); 1162654012fSReza Sabdar static boolean_t is_file_wanted(char *name, 1172654012fSReza Sabdar char **sels, 1182654012fSReza Sabdar char **exls, 1192654012fSReza Sabdar int flags, 1202654012fSReza Sabdar int *mchtype, 1212654012fSReza Sabdar int *pos); 1222654012fSReza Sabdar static char *catnames(struct rs_name_maker *rnp, 1232654012fSReza Sabdar char *buf, 1242654012fSReza Sabdar int pos, 1252654012fSReza Sabdar char *path); 1262654012fSReza Sabdar 1272654012fSReza Sabdar static char *rs_new_name(struct rs_name_maker *rnp, 1282654012fSReza Sabdar char *real_name, 1292654012fSReza Sabdar int pos, 1302654012fSReza Sabdar char *path); 1312654012fSReza Sabdar 1322654012fSReza Sabdar typedef struct stack_ent { 1332654012fSReza Sabdar char *se_name; 1342654012fSReza Sabdar tlm_acls_t se_acls; 1352654012fSReza Sabdar } stack_ent_t; 1362654012fSReza Sabdar 1372654012fSReza Sabdar 1382654012fSReza Sabdar /* 1392654012fSReza Sabdar * dtree_push 1402654012fSReza Sabdar */ 1412654012fSReza Sabdar int 1422654012fSReza Sabdar dtree_push(cstack_t *stp, char *nmp, tlm_acls_t *acls) 1432654012fSReza Sabdar { 1442654012fSReza Sabdar int len; 1452654012fSReza Sabdar stack_ent_t *sp; 1462654012fSReza Sabdar 1472654012fSReza Sabdar sp = ndmp_malloc(sizeof (stack_ent_t)); 1482654012fSReza Sabdar if (!sp || !nmp || !acls) { 1492654012fSReza Sabdar free(sp); 1502654012fSReza Sabdar return (-1); 1512654012fSReza Sabdar } 1522654012fSReza Sabdar 1532654012fSReza Sabdar len = strlen(nmp) + 1; 1542654012fSReza Sabdar sp->se_name = ndmp_malloc(len); 1552654012fSReza Sabdar if (!sp->se_name) { 1562654012fSReza Sabdar free(sp); 1572654012fSReza Sabdar return (-1); 1582654012fSReza Sabdar } 1592654012fSReza Sabdar 1602654012fSReza Sabdar (void) strlcpy(sp->se_name, nmp, len); 1612654012fSReza Sabdar (void) memcpy(&sp->se_acls, acls, sizeof (*acls)); 162*86c48bbfSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 1632654012fSReza Sabdar 1642654012fSReza Sabdar return (cstack_push(stp, (void *)sp, sizeof (*sp))); 1652654012fSReza Sabdar } 1662654012fSReza Sabdar 1672654012fSReza Sabdar /* 1682654012fSReza Sabdar * dtree_pop 1692654012fSReza Sabdar */ 1702654012fSReza Sabdar int 1712654012fSReza Sabdar dtree_pop(cstack_t *stp) 1722654012fSReza Sabdar { 1732654012fSReza Sabdar int err; 1742654012fSReza Sabdar stack_ent_t *sp; 1752654012fSReza Sabdar 1762654012fSReza Sabdar err = cstack_pop(stp, (void **)&sp, (void *)NULL); 1772654012fSReza Sabdar if (err) 1782654012fSReza Sabdar return (-1); 1792654012fSReza Sabdar 1802654012fSReza Sabdar set_acl(sp->se_name, &sp->se_acls); 1812654012fSReza Sabdar 1822654012fSReza Sabdar free(sp->se_name); 1832654012fSReza Sabdar free(sp); 1842654012fSReza Sabdar return (err); 1852654012fSReza Sabdar } 1862654012fSReza Sabdar 1872654012fSReza Sabdar 1882654012fSReza Sabdar /* 1892654012fSReza Sabdar * dtree_peek 1902654012fSReza Sabdar */ 1912654012fSReza Sabdar char * 1922654012fSReza Sabdar dtree_peek(cstack_t *stp) 1932654012fSReza Sabdar { 1942654012fSReza Sabdar int err; 1952654012fSReza Sabdar stack_ent_t *sp; 1962654012fSReza Sabdar 1972654012fSReza Sabdar err = cstack_top(stp, (void **)&sp, (void *)NULL); 1982654012fSReza Sabdar if (err) 1992654012fSReza Sabdar return (NULL); 2002654012fSReza Sabdar 2012654012fSReza Sabdar return (sp->se_name); 2022654012fSReza Sabdar } 2032654012fSReza Sabdar 2042654012fSReza Sabdar /* 2052654012fSReza Sabdar * NBU and EBS may not send us the correct file list containing hardlinks 2062654012fSReza Sabdar * during a DAR restore, e.g. they appear always send the first name 2072654012fSReza Sabdar * associated with an inode, even if other link names were 2082654012fSReza Sabdar * selected for the restore. As a workaround, we use the file name entry 2092654012fSReza Sabdar * in sels[] (ignore the name in the tar header) as restore target. 2102654012fSReza Sabdar */ 2112654012fSReza Sabdar static char * 2122654012fSReza Sabdar rs_darhl_new_name(struct rs_name_maker *rnp, char *name, char **sels, int *pos, 2132654012fSReza Sabdar char *longname) 2142654012fSReza Sabdar { 2152654012fSReza Sabdar int x; 2162654012fSReza Sabdar 2172654012fSReza Sabdar for (x = 0; sels[x] != NULL; x++) { 2182654012fSReza Sabdar if (strcmp(sels[x], " ")) { 2192654012fSReza Sabdar *pos = x; 2202654012fSReza Sabdar (void) strlcpy(longname, sels[x], TLM_MAX_PATH_NAME); 2212654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 2222654012fSReza Sabdar "to replace hardlink name [%s], pos [%d]", 2232654012fSReza Sabdar longname, *pos); 2242654012fSReza Sabdar 2252654012fSReza Sabdar return (rs_new_name(rnp, name, *pos, longname)); 2262654012fSReza Sabdar } 2272654012fSReza Sabdar } 2282654012fSReza Sabdar 2292654012fSReza Sabdar return (NULL); 2302654012fSReza Sabdar } 2312654012fSReza Sabdar 2322654012fSReza Sabdar 2332654012fSReza Sabdar /* 2342654012fSReza Sabdar * Main dir restore funciton for tar 2352654012fSReza Sabdar */ 2362654012fSReza Sabdar int 2372654012fSReza Sabdar tar_getdir(tlm_commands_t *commands, 2382654012fSReza Sabdar tlm_cmd_t *local_commands, 2392654012fSReza Sabdar tlm_job_stats_t *job_stats, 2402654012fSReza Sabdar struct rs_name_maker *rnp, 2412654012fSReza Sabdar int lib, 2422654012fSReza Sabdar int drv, 2432654012fSReza Sabdar char **sels, /* what to get off the tape */ 2442654012fSReza Sabdar char **exls, /* what to leave behind */ 2452654012fSReza Sabdar int flags, 2462654012fSReza Sabdar int DAR, struct hardlink_q *hardlink_q) 2472654012fSReza Sabdar { 2482654012fSReza Sabdar int fp = 0; /* file being restored ... */ 2492654012fSReza Sabdar /* ...need to preserve across volume changes */ 2502654012fSReza Sabdar tlm_acls_t *acls; /* file access info */ 2512654012fSReza Sabdar char *longname; 2522654012fSReza Sabdar boolean_t is_long_name = FALSE; 2532654012fSReza Sabdar char *longlink; 2542654012fSReza Sabdar char *hugename; 2552654012fSReza Sabdar longlong_t huge_size = 0; /* size of a HUGE file */ 2562654012fSReza Sabdar long acl_spot; /* any ACL info on the next volume */ 2572654012fSReza Sabdar long file_size; /* size of file to restore */ 2582654012fSReza Sabdar long size_left = 0; /* need this after volume change */ 2592654012fSReza Sabdar int last_action = 0; /* what we are doing at EOT */ 2602654012fSReza Sabdar boolean_t multi_volume = FALSE; /* is this a multi-volume switch ? */ 2612654012fSReza Sabdar int chk_rv; /* scratch area */ 2622654012fSReza Sabdar 2632654012fSReza Sabdar int mchtype, pos; 2642654012fSReza Sabdar /* 2652654012fSReza Sabdar * if an exact match is found for 2662654012fSReza Sabdar * restore and its position in the 2672654012fSReza Sabdar * selections list 2682654012fSReza Sabdar */ 2692654012fSReza Sabdar int nzerohdr; /* the number of empty tar headers */ 2702654012fSReza Sabdar boolean_t break_flg; /* exit the while loop */ 2712654012fSReza Sabdar int rv; 2722654012fSReza Sabdar long nm_end, lnk_end; 2732654012fSReza Sabdar char *name, *nmp; 2742654012fSReza Sabdar cstack_t *stp; 2752654012fSReza Sabdar char *bkpath; 2762654012fSReza Sabdar char *parentlnk; 2772654012fSReza Sabdar /* 2782654012fSReza Sabdar * The directory where temporary files may be created during a partial 2792654012fSReza Sabdar * non-DAR restore of hardlinks. It is intended to be initialized by 2802654012fSReza Sabdar * an environment variable that can be set by user. 2812654012fSReza Sabdar * 2822654012fSReza Sabdar * It is not initialized for now. We keep it here for future use. 2832654012fSReza Sabdar */ 2842654012fSReza Sabdar char *tmplink_dir = NULL; 285b6b15642SReza Sabdar int dar_recovered = 0; 2862654012fSReza Sabdar 2872654012fSReza Sabdar /* 2882654012fSReza Sabdar * startup 2892654012fSReza Sabdar */ 2902654012fSReza Sabdar 2912654012fSReza Sabdar longname = ndmp_malloc(TLM_MAX_PATH_NAME); 2922654012fSReza Sabdar longlink = ndmp_malloc(TLM_MAX_PATH_NAME); 2932654012fSReza Sabdar hugename = ndmp_malloc(TLM_MAX_PATH_NAME); 2942654012fSReza Sabdar parentlnk = ndmp_malloc(TLM_MAX_PATH_NAME); 2952654012fSReza Sabdar name = ndmp_malloc(TLM_MAX_PATH_NAME); 2962654012fSReza Sabdar acls = ndmp_malloc(sizeof (tlm_acls_t)); 2972654012fSReza Sabdar stp = cstack_new(); 2982654012fSReza Sabdar if (longname == NULL || longlink == NULL || hugename == NULL || 2992654012fSReza Sabdar name == NULL || acls == NULL || stp == NULL || parentlnk == NULL) { 3002654012fSReza Sabdar cstack_delete(stp); 3012654012fSReza Sabdar free(longname); 3022654012fSReza Sabdar free(longlink); 3032654012fSReza Sabdar free(hugename); 3042654012fSReza Sabdar free(parentlnk); 3052654012fSReza Sabdar free(name); 3062654012fSReza Sabdar free(acls); 3072654012fSReza Sabdar return (-TLM_NO_SCRATCH_SPACE); 3082654012fSReza Sabdar } 3092654012fSReza Sabdar 3102654012fSReza Sabdar acl_spot = 0; 3112654012fSReza Sabdar *hugename = '\0'; 3122654012fSReza Sabdar *parentlnk = '\0'; 3132654012fSReza Sabdar nm_end = 0; 3142654012fSReza Sabdar *longname = '\0'; 3152654012fSReza Sabdar lnk_end = 0; 3162654012fSReza Sabdar *longlink = '\0'; 3172654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 3182654012fSReza Sabdar if (IS_SET(flags, RSFLG_OVR_ALWAYS)) { 3192654012fSReza Sabdar acls->acl_overwrite = TRUE; 3202654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_ALWAYS"); 3212654012fSReza Sabdar } else if (IS_SET(flags, RSFLG_OVR_UPDATE)) { 3222654012fSReza Sabdar acls->acl_update = TRUE; 3232654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_UPDATE"); 3242654012fSReza Sabdar } 3252654012fSReza Sabdar 3262654012fSReza Sabdar /* 3272654012fSReza Sabdar * work 3282654012fSReza Sabdar */ 3292654012fSReza Sabdar rv = 0; 3302654012fSReza Sabdar nzerohdr = 0; 3312654012fSReza Sabdar break_flg = FALSE; 3322654012fSReza Sabdar while (commands->tcs_writer != TLM_ABORT && 3332654012fSReza Sabdar local_commands->tc_writer != TLM_STOP) { 3342654012fSReza Sabdar tlm_tar_hdr_t fake_tar_hdr; 3352654012fSReza Sabdar char *file_name; 3362654012fSReza Sabdar char *link_name; 3372654012fSReza Sabdar int erc; 3382654012fSReza Sabdar int actual_size; 3392654012fSReza Sabdar boolean_t want_this_file; 3402654012fSReza Sabdar int want = sizeof (tlm_tar_hdr_t); 3412654012fSReza Sabdar tlm_tar_hdr_t *tar_hdr; 3422654012fSReza Sabdar 3432654012fSReza Sabdar /* The inode of an LF_LINK type. */ 3442654012fSReza Sabdar unsigned long hardlink_inode = 0; 3452654012fSReza Sabdar 3462654012fSReza Sabdar /* 3472654012fSReza Sabdar * Indicate whether a file with the same inode has been 3482654012fSReza Sabdar * restored. 3492654012fSReza Sabdar */ 3502654012fSReza Sabdar int hardlink_done = 0; 3512654012fSReza Sabdar 3522654012fSReza Sabdar /* The path of the restored hardlink file */ 3532654012fSReza Sabdar char *hardlink_target = NULL; 3542654012fSReza Sabdar int is_hardlink = 0; 3552654012fSReza Sabdar 3562654012fSReza Sabdar /* 3572654012fSReza Sabdar * Whether a temporary file should be created for restoring 3582654012fSReza Sabdar * hardlink. 3592654012fSReza Sabdar */ 3602654012fSReza Sabdar int hardlink_tmp_file = 0; 3612654012fSReza Sabdar char *hardlink_tmp_name = ".tmphlrsnondar"; 3622654012fSReza Sabdar 3632654012fSReza Sabdar /* used to make up hardlink_tmp_name */ 3642654012fSReza Sabdar static int hardlink_tmp_idx = 0; 3652654012fSReza Sabdar 3662654012fSReza Sabdar if (break_flg) { 3672654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 3682654012fSReza Sabdar "Exiting writer thread drive %d", drv); 3692654012fSReza Sabdar break; 3702654012fSReza Sabdar } 3712654012fSReza Sabdar 3722654012fSReza Sabdar if (multi_volume) { 3732654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "multi_volume %c %d", 3742654012fSReza Sabdar last_action, size_left); 3752654012fSReza Sabdar 3762654012fSReza Sabdar /* 3772654012fSReza Sabdar * the previous volume is out of data 3782654012fSReza Sabdar * and is back in the rack, a new tape 3792654012fSReza Sabdar * is loaded and ready to read. 3802654012fSReza Sabdar * 3812654012fSReza Sabdar * We need to pick up where we left off. 3822654012fSReza Sabdar */ 3832654012fSReza Sabdar (void) memset(&fake_tar_hdr, 0, sizeof (fake_tar_hdr)); 3842654012fSReza Sabdar file_size = size_left; 3852654012fSReza Sabdar tar_hdr = &fake_tar_hdr; 3862654012fSReza Sabdar tar_hdr->th_linkflag = last_action; 3872654012fSReza Sabdar 3882654012fSReza Sabdar multi_volume = FALSE; 3892654012fSReza Sabdar last_action = 0; 3902654012fSReza Sabdar } else { 3912654012fSReza Sabdar tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(want, 3922654012fSReza Sabdar &erc, &actual_size, local_commands); 3937bc22e45SReza Sabdar 3947bc22e45SReza Sabdar if (tar_hdr == NULL) { 3957bc22e45SReza Sabdar rv = -1; 3967bc22e45SReza Sabdar continue; 3977bc22e45SReza Sabdar } 3987bc22e45SReza Sabdar 3992654012fSReza Sabdar /* 4002654012fSReza Sabdar * we can ignore read errors here because 4012654012fSReza Sabdar * 1) they are logged by Restore Reader 4022654012fSReza Sabdar * 2) we are not doing anything important here 4032654012fSReza Sabdar * just looking for the next work record. 4042654012fSReza Sabdar */ 4052654012fSReza Sabdar if (actual_size < want) { 4062654012fSReza Sabdar /* 4072654012fSReza Sabdar * EOF hits here 4082654012fSReza Sabdar * 4092654012fSReza Sabdar * wait for another buffer to come along 4102654012fSReza Sabdar * or until the Reader thread tells us 4112654012fSReza Sabdar * that no more tapes will be loaded ... 4122654012fSReza Sabdar * time to stop. 4132654012fSReza Sabdar */ 4142654012fSReza Sabdar continue; 4152654012fSReza Sabdar } 4162654012fSReza Sabdar 4172654012fSReza Sabdar /* 4182654012fSReza Sabdar * check for "we are lost" 4192654012fSReza Sabdar */ 4202654012fSReza Sabdar chk_rv = tlm_vfy_tar_checksum(tar_hdr); 4212654012fSReza Sabdar if (chk_rv == 0) { 4222654012fSReza Sabdar /* one of the end of tar file marks */ 4232654012fSReza Sabdar if (++nzerohdr >= 2) { 4242654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 4252654012fSReza Sabdar "nzerohdr %d, breaking", 4262654012fSReza Sabdar nzerohdr); 4272654012fSReza Sabdar /* end of tar file */ 4282654012fSReza Sabdar break; 4292654012fSReza Sabdar } 4302654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nzerohdr %d, continuing", 4312654012fSReza Sabdar nzerohdr); 4322654012fSReza Sabdar continue; 4332654012fSReza Sabdar } else if (chk_rv < 0) { 4342654012fSReza Sabdar nzerohdr = 0; 4352654012fSReza Sabdar /* skip this record */ 4362654012fSReza Sabdar continue; 4372654012fSReza Sabdar } 4382654012fSReza Sabdar nzerohdr = 0; 4392654012fSReza Sabdar 4402654012fSReza Sabdar /* 4412654012fSReza Sabdar * When files are spanned to the next tape, the 4422654012fSReza Sabdar * information of the acls must not be over-written 4432654012fSReza Sabdar * by the information of the LF_MULTIVOL and LF_VOLHDR 4442654012fSReza Sabdar * header, whose information is irrelevant to the file. 4452654012fSReza Sabdar * The information of the original header must be 4462654012fSReza Sabdar * kept in the 'acl'. 4472654012fSReza Sabdar */ 4482654012fSReza Sabdar if (tar_hdr->th_linkflag != LF_MULTIVOL && 4492654012fSReza Sabdar tar_hdr->th_linkflag != LF_VOLHDR) { 450*86c48bbfSReza Sabdar if (tar_hdr->th_linkflag != LF_HUMONGUS) { 451*86c48bbfSReza Sabdar acls->acl_attr.st_mode = 452*86c48bbfSReza Sabdar oct_atoi(tar_hdr->th_mode); 453*86c48bbfSReza Sabdar acls->acl_attr.st_size = 454*86c48bbfSReza Sabdar oct_atoi(tar_hdr->th_size); 455*86c48bbfSReza Sabdar acls->acl_attr.st_uid = 456*86c48bbfSReza Sabdar oct_atoi(tar_hdr->th_uid); 457*86c48bbfSReza Sabdar acls->acl_attr.st_gid = 458*86c48bbfSReza Sabdar oct_atoi(tar_hdr->th_gid); 459*86c48bbfSReza Sabdar acls->acl_attr.st_mtime = 460*86c48bbfSReza Sabdar oct_atoi(tar_hdr->th_mtime); 461*86c48bbfSReza Sabdar (void) strlcpy(acls->uname, 462*86c48bbfSReza Sabdar tar_hdr->th_uname, 463*86c48bbfSReza Sabdar sizeof (acls->uname)); 464*86c48bbfSReza Sabdar (void) strlcpy(acls->gname, 465*86c48bbfSReza Sabdar tar_hdr->th_gname, 466*86c48bbfSReza Sabdar sizeof (acls->gname)); 467*86c48bbfSReza Sabdar } 4682654012fSReza Sabdar file_size = oct_atoi(tar_hdr->th_size); 4692654012fSReza Sabdar acl_spot = 0; 4702654012fSReza Sabdar last_action = tar_hdr->th_linkflag; 4712654012fSReza Sabdar } 4722654012fSReza Sabdar } 4732654012fSReza Sabdar 4742654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "n [%s] f [%c] s %lld m %o u %d g %d t %d", 4752654012fSReza Sabdar tar_hdr->th_name, tar_hdr->th_linkflag, 4762654012fSReza Sabdar acls->acl_attr.st_size, acls->acl_attr.st_mode, 4772654012fSReza Sabdar acls->acl_attr.st_uid, acls->acl_attr.st_gid, 4782654012fSReza Sabdar acls->acl_attr.st_mtime); 4792654012fSReza Sabdar 480b6b15642SReza Sabdar /* 481b6b15642SReza Sabdar * If the restore is running using DAR we should check for 482*86c48bbfSReza Sabdar * extended attribute entries 483b6b15642SReza Sabdar */ 484b6b15642SReza Sabdar if (dar_recovered && 485b6b15642SReza Sabdar tar_hdr->th_linkflag != LF_XATTR) 486b6b15642SReza Sabdar break; 487b6b15642SReza Sabdar 4882654012fSReza Sabdar switch (tar_hdr->th_linkflag) { 4892654012fSReza Sabdar case LF_MULTIVOL: 4902654012fSReza Sabdar multi_volume = TRUE; 4912654012fSReza Sabdar break; 4922654012fSReza Sabdar case LF_LINK: 4932654012fSReza Sabdar is_hardlink = 1; 4942654012fSReza Sabdar hardlink_inode = 4952654012fSReza Sabdar oct_atoi(tar_hdr->th_shared.th_hlink_ino); 4962654012fSReza Sabdar 4972654012fSReza Sabdar /* 4982654012fSReza Sabdar * Check if we have restored a link with the same inode 4992654012fSReza Sabdar * If the inode is 0, we have to restore it as a 5002654012fSReza Sabdar * regular file. 5012654012fSReza Sabdar */ 5022654012fSReza Sabdar if (hardlink_inode) { 5032654012fSReza Sabdar hardlink_done = !hardlink_q_get(hardlink_q, 5042654012fSReza Sabdar hardlink_inode, 0, &hardlink_target); 5052654012fSReza Sabdar } 5062654012fSReza Sabdar 5072654012fSReza Sabdar if (hardlink_done) { 5082654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5092654012fSReza Sabdar "found hardlink, inode = %u, target = [%s]", 5102654012fSReza Sabdar hardlink_inode, 5112654012fSReza Sabdar hardlink_target? hardlink_target : "--"); 5122654012fSReza Sabdar 5132654012fSReza Sabdar /* create a hardlink to hardlink_target */ 5142654012fSReza Sabdar file_name = (*longname == 0) ? 5152654012fSReza Sabdar tar_hdr->th_name : longname; 5162654012fSReza Sabdar if (!is_file_wanted(file_name, sels, exls, 5172654012fSReza Sabdar flags, &mchtype, &pos)) { 5182654012fSReza Sabdar nmp = NULL; 5192654012fSReza Sabdar /* 5202654012fSReza Sabdar * This means that DMA did not send us 5212654012fSReza Sabdar * the correct fh_info for the file 5222654012fSReza Sabdar * in restore list. We use the file 5232654012fSReza Sabdar * name entry in sels[] (ignore the 5242654012fSReza Sabdar * name in the tar header) as restore 5252654012fSReza Sabdar * target. 5262654012fSReza Sabdar */ 5272654012fSReza Sabdar if (DAR) { 5282654012fSReza Sabdar nmp = rs_darhl_new_name(rnp, 5292654012fSReza Sabdar name, sels, &pos, 5302654012fSReza Sabdar file_name); 5312654012fSReza Sabdar } 5322654012fSReza Sabdar } else { 5332654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, 5342654012fSReza Sabdar file_name); 5352654012fSReza Sabdar if (!nmp) { 5362654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5372654012fSReza Sabdar "can't make name for %s", 5382654012fSReza Sabdar longname); 5392654012fSReza Sabdar } 5402654012fSReza Sabdar } 5412654012fSReza Sabdar 5422654012fSReza Sabdar if (nmp) { 5432654012fSReza Sabdar if (hardlink_target) { 5442654012fSReza Sabdar erc = create_hard_link( 5452654012fSReza Sabdar hardlink_target, nmp, 5462654012fSReza Sabdar acls, job_stats); 5472654012fSReza Sabdar if (erc == 0) { 5482654012fSReza Sabdar (void) 5492654012fSReza Sabdar tlm_entry_restored( 5502654012fSReza Sabdar job_stats, 5512654012fSReza Sabdar file_name, pos); 5522654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5532654012fSReza Sabdar "restored %s -> %s", 5542654012fSReza Sabdar nmp, 5552654012fSReza Sabdar hardlink_target); 5562654012fSReza Sabdar } 5572654012fSReza Sabdar } else { 5582654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5592654012fSReza Sabdar "no target for hardlink %s", 5602654012fSReza Sabdar nmp); 5612654012fSReza Sabdar } 5622654012fSReza Sabdar 5632654012fSReza Sabdar name[0] = 0; 5642654012fSReza Sabdar is_long_name = FALSE; 5652654012fSReza Sabdar } 5662654012fSReza Sabdar 5672654012fSReza Sabdar nm_end = 0; 5682654012fSReza Sabdar longname[0] = 0; 5692654012fSReza Sabdar lnk_end = 0; 5702654012fSReza Sabdar longlink[0] = 0; 5712654012fSReza Sabdar 5722654012fSReza Sabdar break; 5732654012fSReza Sabdar } 5742654012fSReza Sabdar /* otherwise fall through, restore like a normal file */ 5752654012fSReza Sabdar /*FALLTHROUGH*/ 5762654012fSReza Sabdar case LF_OLDNORMAL: 5772654012fSReza Sabdar /* 5782654012fSReza Sabdar * check for TAR's end-of-tape method 5792654012fSReza Sabdar * of zero filled records. 5802654012fSReza Sabdar */ 5812654012fSReza Sabdar if (tar_hdr->th_name[0] == 0) { 5822654012fSReza Sabdar break; 5832654012fSReza Sabdar } 5842654012fSReza Sabdar /* 5852654012fSReza Sabdar * otherwise fall through, 5862654012fSReza Sabdar * this is an old style normal file header 5872654012fSReza Sabdar */ 5882654012fSReza Sabdar /*FALLTHROUGH*/ 5892654012fSReza Sabdar case LF_NORMAL: 5902654012fSReza Sabdar case LF_CONTIG: 5912654012fSReza Sabdar job_stats->js_files_so_far++; 5922654012fSReza Sabdar if (*hugename != 0) { 5932654012fSReza Sabdar (void) strlcpy(longname, hugename, 5942654012fSReza Sabdar TLM_MAX_PATH_NAME); 5952654012fSReza Sabdar } else if (*longname == 0) { 5962654012fSReza Sabdar if (tar_hdr->th_name[0] != '/') { 5972654012fSReza Sabdar /* 5982654012fSReza Sabdar * check for old tar format, it 5992654012fSReza Sabdar * does not have a leading "/" 6002654012fSReza Sabdar */ 6012654012fSReza Sabdar longname[0] = '/'; 6022654012fSReza Sabdar longname[1] = 0; 6032654012fSReza Sabdar (void) strlcat(longname, 6042654012fSReza Sabdar tar_hdr->th_name, 6052654012fSReza Sabdar TLM_MAX_PATH_NAME); 6062654012fSReza Sabdar } else { 6072654012fSReza Sabdar (void) strlcpy(longname, 6082654012fSReza Sabdar tar_hdr->th_name, 6092654012fSReza Sabdar TLM_MAX_PATH_NAME); 6102654012fSReza Sabdar } 6112654012fSReza Sabdar } 6122654012fSReza Sabdar 6132654012fSReza Sabdar want_this_file = is_file_wanted(longname, sels, exls, 6142654012fSReza Sabdar flags, &mchtype, &pos); 6152654012fSReza Sabdar if (!want_this_file) { 6162654012fSReza Sabdar nmp = NULL; 6172654012fSReza Sabdar /* 6182654012fSReza Sabdar * This means that DMA did not send us valid 6192654012fSReza Sabdar * fh_info for the file in restore list. We 6202654012fSReza Sabdar * use the file name entry in sels[] (ignore 6212654012fSReza Sabdar * the name in the tar header) as restore 6222654012fSReza Sabdar * target. 6232654012fSReza Sabdar */ 6242654012fSReza Sabdar if (DAR && (tar_hdr->th_linkflag == LF_LINK)) { 6252654012fSReza Sabdar nmp = rs_darhl_new_name(rnp, name, 6262654012fSReza Sabdar sels, &pos, longname); 6272654012fSReza Sabdar 6282654012fSReza Sabdar if (nmp) { 6292654012fSReza Sabdar want_this_file = TRUE; 6302654012fSReza Sabdar mchtype = PM_EXACT; 6312654012fSReza Sabdar } else { 6322654012fSReza Sabdar break_flg = TRUE; 6332654012fSReza Sabdar break; 6342654012fSReza Sabdar } 6352654012fSReza Sabdar } 6362654012fSReza Sabdar } else { 6372654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, longname); 6382654012fSReza Sabdar if (!nmp) 6392654012fSReza Sabdar want_this_file = FALSE; 6402654012fSReza Sabdar } 6412654012fSReza Sabdar 6422654012fSReza Sabdar if (nmp) 6432654012fSReza Sabdar (void) strlcpy(parentlnk, nmp, strlen(nmp) + 1); 6442654012fSReza Sabdar 6452654012fSReza Sabdar /* 6462654012fSReza Sabdar * For a hardlink, even if it's not asked to be 6472654012fSReza Sabdar * restored, we restore it to a temporary location, 6482654012fSReza Sabdar * in case other links to the same file need to be 6492654012fSReza Sabdar * restored later. 6502654012fSReza Sabdar * 6512654012fSReza Sabdar * The temp files are created in tmplink_dir, with 6522654012fSReza Sabdar * names like ".tmphlrsnondar*". They are cleaned up 6532654012fSReza Sabdar * at the completion of a restore. However, if a 6542654012fSReza Sabdar * restore were interrupted, e.g. by a system reboot, 6552654012fSReza Sabdar * they would have to be cleaned up manually in order 6562654012fSReza Sabdar * for the disk space to be freed. 6572654012fSReza Sabdar * 6582654012fSReza Sabdar * If tmplink_dir is NULL, no temperorary files are 6592654012fSReza Sabdar * created during a restore. This may result in some 6602654012fSReza Sabdar * hardlinks not being restored during a partial 6612654012fSReza Sabdar * restore. 6622654012fSReza Sabdar */ 6632654012fSReza Sabdar if (is_hardlink && !DAR && !want_this_file && !nmp) { 6642654012fSReza Sabdar if (tmplink_dir) { 6652654012fSReza Sabdar (void) snprintf(name, TLM_MAX_PATH_NAME, 6662654012fSReza Sabdar "%s/%s_%d", tmplink_dir, 6672654012fSReza Sabdar hardlink_tmp_name, 6682654012fSReza Sabdar hardlink_tmp_idx); 6692654012fSReza Sabdar nmp = name; 6702654012fSReza Sabdar 6712654012fSReza Sabdar hardlink_tmp_idx++; 6722654012fSReza Sabdar hardlink_tmp_file = 1; 6732654012fSReza Sabdar want_this_file = TRUE; 6742654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 6752654012fSReza Sabdar "To restore temp hardlink file %s.", 6762654012fSReza Sabdar nmp); 6772654012fSReza Sabdar } else { 6782654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 6792654012fSReza Sabdar "No tmplink_dir specified."); 6802654012fSReza Sabdar } 6812654012fSReza Sabdar } 6822654012fSReza Sabdar 6832654012fSReza Sabdar size_left = restore_file(&fp, nmp, file_size, 6842654012fSReza Sabdar huge_size, acls, want_this_file, local_commands, 6852654012fSReza Sabdar job_stats); 6862654012fSReza Sabdar 6872654012fSReza Sabdar /* 6882654012fSReza Sabdar * In the case of non-DAR, we have to record the first 6892654012fSReza Sabdar * link for an inode that has multiple links. That's 6902654012fSReza Sabdar * the only link with data records actually backed up. 6912654012fSReza Sabdar * In this way, when we run into the other links, they 6922654012fSReza Sabdar * will be treated as links, and we won't go to look 6932654012fSReza Sabdar * for the data records to restore. This is not a 6942654012fSReza Sabdar * problem for DAR, where DMA tells the tape where 6952654012fSReza Sabdar * to locate the data records. 6962654012fSReza Sabdar */ 6972654012fSReza Sabdar if (is_hardlink && !DAR) { 6982654012fSReza Sabdar if (hardlink_q_add(hardlink_q, hardlink_inode, 6992654012fSReza Sabdar 0, nmp, hardlink_tmp_file)) 7002654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 7012654012fSReza Sabdar "failed to add (%u, %s) to HL q", 7022654012fSReza Sabdar hardlink_inode, nmp); 7032654012fSReza Sabdar } 7042654012fSReza Sabdar 7052654012fSReza Sabdar /* remove / reverse the temporary stuff */ 7062654012fSReza Sabdar if (hardlink_tmp_file) { 7072654012fSReza Sabdar nmp = NULL; 7082654012fSReza Sabdar want_this_file = FALSE; 7092654012fSReza Sabdar hardlink_tmp_file = 0; 7102654012fSReza Sabdar } 7112654012fSReza Sabdar 7122654012fSReza Sabdar /* 7132654012fSReza Sabdar * Check if it is time to set the attribute 7142654012fSReza Sabdar * of the restored directory 7152654012fSReza Sabdar */ 7162654012fSReza Sabdar while (nmp && ((bkpath = dtree_peek(stp)) != NULL)) { 7172654012fSReza Sabdar if (strstr(nmp, bkpath)) 7182654012fSReza Sabdar break; 7192654012fSReza Sabdar 7202654012fSReza Sabdar (void) dtree_pop(stp); 7212654012fSReza Sabdar } 7222654012fSReza Sabdar 7232654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "sizeleft %s %d, %lld", longname, 7242654012fSReza Sabdar size_left, huge_size); 7252654012fSReza Sabdar 7262654012fSReza Sabdar if (size_left == -TLM_STOP) { 7272654012fSReza Sabdar break_flg = TRUE; 7282654012fSReza Sabdar rv = -1; 7292654012fSReza Sabdar commands->tcs_reader = TLM_ABORT; 7302654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "restoring [%s] failed", 7312654012fSReza Sabdar longname); 7322654012fSReza Sabdar break; 7332654012fSReza Sabdar } 7342654012fSReza Sabdar 7352654012fSReza Sabdar if (want_this_file) { 7362654012fSReza Sabdar job_stats->js_bytes_total += file_size; 7372654012fSReza Sabdar job_stats->js_files_total++; 7382654012fSReza Sabdar } 7392654012fSReza Sabdar 7402654012fSReza Sabdar huge_size -= file_size; 7412654012fSReza Sabdar if (huge_size < 0) { 7422654012fSReza Sabdar huge_size = 0; 7432654012fSReza Sabdar } 7442654012fSReza Sabdar if (size_left == 0 && huge_size == 0) { 7452654012fSReza Sabdar if (PM_EXACT_OR_CHILD(mchtype)) { 7462654012fSReza Sabdar (void) tlm_entry_restored(job_stats, 7472654012fSReza Sabdar longname, pos); 7482654012fSReza Sabdar 7492654012fSReza Sabdar /* 7502654012fSReza Sabdar * Add an entry to hardlink_q to record 7512654012fSReza Sabdar * this hardlink. 7522654012fSReza Sabdar */ 7532654012fSReza Sabdar if (is_hardlink) { 7542654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 7552654012fSReza Sabdar "Restored hardlink file %s", 7562654012fSReza Sabdar nmp); 7572654012fSReza Sabdar 7582654012fSReza Sabdar if (DAR) { 7592654012fSReza Sabdar (void) hardlink_q_add( 7602654012fSReza Sabdar hardlink_q, 7612654012fSReza Sabdar hardlink_inode, 0, 7622654012fSReza Sabdar nmp, 0); 7632654012fSReza Sabdar } 7642654012fSReza Sabdar } 7652654012fSReza Sabdar } 7662654012fSReza Sabdar 7672654012fSReza Sabdar nm_end = 0; 7682654012fSReza Sabdar longname[0] = 0; 7692654012fSReza Sabdar lnk_end = 0; 7702654012fSReza Sabdar longlink[0] = 0; 7712654012fSReza Sabdar hugename[0] = 0; 7722654012fSReza Sabdar name[0] = 0; 7732654012fSReza Sabdar is_long_name = FALSE; 7742654012fSReza Sabdar } 7752654012fSReza Sabdar break; 7762654012fSReza Sabdar case LF_XATTR: 7772654012fSReza Sabdar file_name = (*longname == 0) ? tar_hdr->th_name : 7782654012fSReza Sabdar longname; 7792654012fSReza Sabdar 7802654012fSReza Sabdar size_left = restore_xattr_hdr(&fp, parentlnk, 7812654012fSReza Sabdar file_name, file_size, acls, local_commands, 7822654012fSReza Sabdar job_stats); 7832654012fSReza Sabdar 7842654012fSReza Sabdar break; 7852654012fSReza Sabdar case LF_SYMLINK: 7862654012fSReza Sabdar file_name = (*longname == 0) ? tar_hdr->th_name : 7872654012fSReza Sabdar longname; 7882654012fSReza Sabdar link_name = (*longlink == 0) ? 7892654012fSReza Sabdar tar_hdr->th_linkname : longlink; 7902654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "file_name[%s]", file_name); 7912654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "link_name[%s]", link_name); 7922654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 7932654012fSReza Sabdar &mchtype, &pos)) { 7942654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 7952654012fSReza Sabdar if (nmp) { 7962654012fSReza Sabdar erc = create_sym_link(nmp, link_name, 7972654012fSReza Sabdar acls, job_stats); 7982654012fSReza Sabdar if (erc == 0 && 7992654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 8002654012fSReza Sabdar (void) tlm_entry_restored( 8012654012fSReza Sabdar job_stats, file_name, pos); 8022654012fSReza Sabdar name[0] = 0; 8032654012fSReza Sabdar } 8042654012fSReza Sabdar } 8052654012fSReza Sabdar nm_end = 0; 8062654012fSReza Sabdar longname[0] = 0; 8072654012fSReza Sabdar lnk_end = 0; 8082654012fSReza Sabdar longlink[0] = 0; 8092654012fSReza Sabdar break; 8102654012fSReza Sabdar case LF_DIR: 8112654012fSReza Sabdar file_name = *longname == 0 ? tar_hdr->th_name : 8122654012fSReza Sabdar longname; 8132654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 8142654012fSReza Sabdar &mchtype, &pos)) { 8152654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 8162654012fSReza Sabdar if (nmp && mchtype != PM_PARENT) { 8172654012fSReza Sabdar (void) strlcpy(parentlnk, nmp, 8182654012fSReza Sabdar strlen(nmp)); 8192654012fSReza Sabdar erc = create_directory(nmp, job_stats); 8202654012fSReza Sabdar if (erc == 0 && 8212654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 8222654012fSReza Sabdar (void) tlm_entry_restored( 8232654012fSReza Sabdar job_stats, file_name, pos); 8242654012fSReza Sabdar /* 8252654012fSReza Sabdar * Check if it is time to set 8262654012fSReza Sabdar * the attribute of the restored 8272654012fSReza Sabdar * directory 8282654012fSReza Sabdar */ 8292654012fSReza Sabdar while ((bkpath = dtree_peek(stp)) 8302654012fSReza Sabdar != NULL) { 8312654012fSReza Sabdar if (strstr(nmp, bkpath)) 8322654012fSReza Sabdar break; 8332654012fSReza Sabdar (void) dtree_pop(stp); 8342654012fSReza Sabdar } 8352654012fSReza Sabdar 8362654012fSReza Sabdar (void) dtree_push(stp, nmp, acls); 8372654012fSReza Sabdar name[0] = 0; 8382654012fSReza Sabdar } 8392654012fSReza Sabdar } 8402654012fSReza Sabdar nm_end = 0; 8412654012fSReza Sabdar longname[0] = 0; 8422654012fSReza Sabdar lnk_end = 0; 8432654012fSReza Sabdar longlink[0] = 0; 8442654012fSReza Sabdar break; 8452654012fSReza Sabdar case LF_FIFO: 8462654012fSReza Sabdar file_name = *longname == 0 ? tar_hdr->th_name : 8472654012fSReza Sabdar longname; 8482654012fSReza Sabdar if (is_file_wanted(file_name, sels, exls, flags, 8492654012fSReza Sabdar &mchtype, &pos)) { 8502654012fSReza Sabdar nmp = rs_new_name(rnp, name, pos, file_name); 8512654012fSReza Sabdar if (nmp) { 8522654012fSReza Sabdar erc = create_fifo(nmp, acls); 8532654012fSReza Sabdar if (erc == 0 && 8542654012fSReza Sabdar PM_EXACT_OR_CHILD(mchtype)) 8552654012fSReza Sabdar (void) tlm_entry_restored( 8562654012fSReza Sabdar job_stats, file_name, pos); 8572654012fSReza Sabdar name[0] = 0; 8582654012fSReza Sabdar } 8592654012fSReza Sabdar } 8602654012fSReza Sabdar nm_end = 0; 8612654012fSReza Sabdar longname[0] = 0; 8622654012fSReza Sabdar lnk_end = 0; 8632654012fSReza Sabdar longlink[0] = 0; 8642654012fSReza Sabdar break; 8652654012fSReza Sabdar case LF_LONGLINK: 8662654012fSReza Sabdar file_size = min(file_size, TLM_MAX_PATH_NAME - lnk_end); 8672654012fSReza Sabdar file_size = max(0, file_size); 8682654012fSReza Sabdar size_left = get_long_name(lib, drv, file_size, longlink, 8692654012fSReza Sabdar &lnk_end, local_commands); 8702654012fSReza Sabdar 8712654012fSReza Sabdar if (size_left != 0) 8722654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 8732654012fSReza Sabdar "fsize %d sleft %d lnkend %d", 8742654012fSReza Sabdar file_size, size_left, lnk_end); 8752654012fSReza Sabdar break; 8762654012fSReza Sabdar case LF_LONGNAME: 8772654012fSReza Sabdar file_size = min(file_size, TLM_MAX_PATH_NAME - nm_end); 8782654012fSReza Sabdar file_size = max(0, file_size); 8792654012fSReza Sabdar size_left = get_long_name(lib, drv, file_size, longname, 8802654012fSReza Sabdar &nm_end, local_commands); 8812654012fSReza Sabdar 8822654012fSReza Sabdar if (size_left != 0) 8832654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 8842654012fSReza Sabdar "fsize %d sleft %d nmend %d", 8852654012fSReza Sabdar file_size, size_left, nm_end); 8862654012fSReza Sabdar is_long_name = TRUE; 8872654012fSReza Sabdar break; 8882654012fSReza Sabdar case LF_ACL: 8892654012fSReza Sabdar size_left = load_acl_info(lib, drv, file_size, acls, 8902654012fSReza Sabdar &acl_spot, local_commands); 8912654012fSReza Sabdar break; 8922654012fSReza Sabdar case LF_VOLHDR: 8932654012fSReza Sabdar break; 8942654012fSReza Sabdar case LF_HUMONGUS: 8952654012fSReza Sabdar (void) memset(hugename, 0, TLM_MAX_PATH_NAME); 8962654012fSReza Sabdar (void) get_humongus_file_header(lib, drv, file_size, 8972654012fSReza Sabdar &huge_size, hugename, local_commands); 8982654012fSReza Sabdar break; 8992654012fSReza Sabdar default: 9002654012fSReza Sabdar break; 9012654012fSReza Sabdar 9022654012fSReza Sabdar } 9032654012fSReza Sabdar 9042654012fSReza Sabdar /* 9052654012fSReza Sabdar * If the restore is running using DAR we should check for 9062654012fSReza Sabdar * long file names and HUGE file sizes. 9072654012fSReza Sabdar */ 9082654012fSReza Sabdar if (DAR && tar_hdr->th_linkflag != LF_ACL && 909b6b15642SReza Sabdar tar_hdr->th_linkflag != LF_XATTR && 9102654012fSReza Sabdar !huge_size && !is_long_name) 911b6b15642SReza Sabdar dar_recovered = 1; 9122654012fSReza Sabdar } 9132654012fSReza Sabdar 9142654012fSReza Sabdar /* 9152654012fSReza Sabdar * tear down 9162654012fSReza Sabdar */ 9172654012fSReza Sabdar if (fp != 0) { 9182654012fSReza Sabdar (void) close(fp); 9192654012fSReza Sabdar } 9202654012fSReza Sabdar while (dtree_pop(stp) != -1) 9212654012fSReza Sabdar ; 9222654012fSReza Sabdar cstack_delete(stp); 9232654012fSReza Sabdar free(acls); 9242654012fSReza Sabdar free(longname); 9252654012fSReza Sabdar free(parentlnk); 9262654012fSReza Sabdar free(longlink); 9272654012fSReza Sabdar free(hugename); 9282654012fSReza Sabdar free(name); 9292654012fSReza Sabdar return (rv); 9302654012fSReza Sabdar } 9312654012fSReza Sabdar 9322654012fSReza Sabdar /* 9332654012fSReza Sabdar * Main file restore function for tar (should run as a thread) 9342654012fSReza Sabdar */ 9352654012fSReza Sabdar int 9362654012fSReza Sabdar tar_getfile(tlm_backup_restore_arg_t *argp) 9372654012fSReza Sabdar { 9382654012fSReza Sabdar tlm_job_stats_t *job_stats; 9392654012fSReza Sabdar char **sels; /* list of files desired */ 9402654012fSReza Sabdar char **exls; /* list of files not wanted */ 9412654012fSReza Sabdar char *dir; /* where to restore the files */ 9422654012fSReza Sabdar char job[TLM_MAX_BACKUP_JOB_NAME+1]; 9432654012fSReza Sabdar /* the restore job name */ 9442654012fSReza Sabdar int erc; /* error return codes */ 9452654012fSReza Sabdar int flags; 9462654012fSReza Sabdar struct rs_name_maker rn; 9472654012fSReza Sabdar tlm_commands_t *commands; 9482654012fSReza Sabdar tlm_cmd_t *local_commands; 9492654012fSReza Sabdar char *list = NULL; 9502654012fSReza Sabdar 9512654012fSReza Sabdar commands = argp->ba_commands; 9522654012fSReza Sabdar local_commands = argp->ba_cmd; 9532654012fSReza Sabdar 9542654012fSReza Sabdar flags = 0; 9552654012fSReza Sabdar 9562654012fSReza Sabdar dir = ndmp_malloc(TLM_MAX_PATH_NAME); 9572654012fSReza Sabdar if (dir == NULL) { 9582654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 9592654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 9602654012fSReza Sabdar return (-1); 9612654012fSReza Sabdar } 9622654012fSReza Sabdar 9632654012fSReza Sabdar (void) strlcpy(job, argp->ba_job, TLM_MAX_BACKUP_JOB_NAME+1); 9642654012fSReza Sabdar (void) strlcpy(dir, argp->ba_dir, TLM_MAX_PATH_NAME); 9652654012fSReza Sabdar 9662654012fSReza Sabdar flags |= RSFLG_OVR_ALWAYS; 9672654012fSReza Sabdar flags |= RSFLG_IGNORE_CASE; 9682654012fSReza Sabdar 9692654012fSReza Sabdar /* 9702654012fSReza Sabdar * do not test for "dir" having no string, since that 9712654012fSReza Sabdar * is a legal condition. Restore to origional location 9722654012fSReza Sabdar * will not have a restore directory. 9732654012fSReza Sabdar */ 9742654012fSReza Sabdar if (*job == '\0') { 9752654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No job defined"); 9762654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 9772654012fSReza Sabdar free(dir); 9782654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 9792654012fSReza Sabdar return (-1); 9802654012fSReza Sabdar } 9812654012fSReza Sabdar 9822654012fSReza Sabdar sels = argp->ba_sels; 9832654012fSReza Sabdar if (sels == NULL) { 9842654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 9852654012fSReza Sabdar free(dir); 9862654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 9872654012fSReza Sabdar return (-1); 9882654012fSReza Sabdar } 9892654012fSReza Sabdar exls = &list; 9902654012fSReza Sabdar 9912654012fSReza Sabdar tlm_log_list("selections", sels); 9922654012fSReza Sabdar tlm_log_list("exclusions", exls); 9932654012fSReza Sabdar 9942654012fSReza Sabdar if (wildcard_enabled()) 9952654012fSReza Sabdar flags |= RSFLG_MATCH_WCARD; 9962654012fSReza Sabdar 9972654012fSReza Sabdar local_commands->tc_ref++; 9982654012fSReza Sabdar commands->tcs_writer_count++; 9992654012fSReza Sabdar 10002654012fSReza Sabdar /* 10012654012fSReza Sabdar * let the launcher continue 10022654012fSReza Sabdar */ 10032654012fSReza Sabdar (void) pthread_barrier_wait(&argp->ba_barrier); 10042654012fSReza Sabdar 10052654012fSReza Sabdar job_stats = tlm_ref_job_stats(job); 10062654012fSReza Sabdar 10072654012fSReza Sabdar rn.rn_fp = catnames; 10082654012fSReza Sabdar rn.rn_nlp = dir; 10092654012fSReza Sabdar 10102654012fSReza Sabdar /* 10112654012fSReza Sabdar * work 10122654012fSReza Sabdar */ 10132654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "start restore job %s", job); 10142654012fSReza Sabdar erc = tar_getdir(commands, local_commands, job_stats, &rn, 1, 1, 10152654012fSReza Sabdar sels, exls, flags, 0, NULL); 10162654012fSReza Sabdar 10172654012fSReza Sabdar /* 10182654012fSReza Sabdar * teardown 10192654012fSReza Sabdar */ 10202654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "end restore job %s", job); 10212654012fSReza Sabdar tlm_un_ref_job_stats(job); 10222654012fSReza Sabdar tlm_release_list(sels); 10232654012fSReza Sabdar tlm_release_list(exls); 10242654012fSReza Sabdar 10252654012fSReza Sabdar commands->tcs_writer_count--; 10262654012fSReza Sabdar local_commands->tc_reader = TLM_STOP; 10272654012fSReza Sabdar tlm_release_reader_writer_ipc(local_commands); 10282654012fSReza Sabdar free(dir); 10292654012fSReza Sabdar return (erc); 10302654012fSReza Sabdar } 10312654012fSReza Sabdar 10322654012fSReza Sabdar /* 10332654012fSReza Sabdar * Creates the directories all the way down to the 10342654012fSReza Sabdar * end if they dont exist 10352654012fSReza Sabdar */ 10362654012fSReza Sabdar int 10372654012fSReza Sabdar make_dirs(char *dir) 10382654012fSReza Sabdar { 10392654012fSReza Sabdar char c; 10402654012fSReza Sabdar char *cp, *end; 10412654012fSReza Sabdar struct stat64 st; 10422654012fSReza Sabdar 10432654012fSReza Sabdar cp = dir; 10442654012fSReza Sabdar cp += strspn(cp, "/"); 10452654012fSReza Sabdar end = dir + strlen(dir); 10462654012fSReza Sabdar do { 10472654012fSReza Sabdar if (*cp == '\0' || *cp == '/') { 10482654012fSReza Sabdar c = *cp; 10492654012fSReza Sabdar *cp = '\0'; 10502654012fSReza Sabdar if (lstat64(dir, &st) < 0) 10512654012fSReza Sabdar if (mkdir(dir, 0777) < 0) { 10522654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d" 10532654012fSReza Sabdar " creating directory %s", 10542654012fSReza Sabdar errno, dir); 10552654012fSReza Sabdar *cp = c; 10562654012fSReza Sabdar return (-1); 10572654012fSReza Sabdar } 10582654012fSReza Sabdar 10592654012fSReza Sabdar *cp = c; 10602654012fSReza Sabdar } 10612654012fSReza Sabdar } while (++cp <= end); 10622654012fSReza Sabdar 10632654012fSReza Sabdar return (0); 10642654012fSReza Sabdar } 10652654012fSReza Sabdar 10662654012fSReza Sabdar /* 10672654012fSReza Sabdar * Creates the directories leading to the given path 10682654012fSReza Sabdar */ 10692654012fSReza Sabdar int 10702654012fSReza Sabdar mkbasedir(char *path) 10712654012fSReza Sabdar { 10722654012fSReza Sabdar int rv; 10732654012fSReza Sabdar char *cp; 10742654012fSReza Sabdar struct stat64 st; 10752654012fSReza Sabdar 10762654012fSReza Sabdar if (!path || !*path) { 10772654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument"); 10782654012fSReza Sabdar return (-1); 10792654012fSReza Sabdar } 10802654012fSReza Sabdar 10812654012fSReza Sabdar cp = strrchr(path, '/'); 10822654012fSReza Sabdar if (cp) 10832654012fSReza Sabdar *cp = '\0'; 10842654012fSReza Sabdar rv = lstat64(path, &st); 10852654012fSReza Sabdar if (rv < 0) /* need new directories */ 10862654012fSReza Sabdar rv = make_dirs(path); 10872654012fSReza Sabdar if (cp) 10882654012fSReza Sabdar *cp = '/'; 10892654012fSReza Sabdar 10902654012fSReza Sabdar return (rv); 10912654012fSReza Sabdar } 10922654012fSReza Sabdar 10932654012fSReza Sabdar 10942654012fSReza Sabdar /* 10952654012fSReza Sabdar * read the file off the tape back onto disk 10962654012fSReza Sabdar */ 10972654012fSReza Sabdar static long 10982654012fSReza Sabdar restore_file(int *fp, 10992654012fSReza Sabdar char *real_name, 11002654012fSReza Sabdar long size, 11012654012fSReza Sabdar longlong_t huge_size, 11022654012fSReza Sabdar tlm_acls_t *acls, 11032654012fSReza Sabdar boolean_t want_this_file, 11042654012fSReza Sabdar tlm_cmd_t *local_commands, 11052654012fSReza Sabdar tlm_job_stats_t *job_stats) 11062654012fSReza Sabdar { 11072654012fSReza Sabdar struct stat64 attr; 11082654012fSReza Sabdar 11092654012fSReza Sabdar if (!real_name) { 11102654012fSReza Sabdar if (want_this_file) { 11112654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No file name but wanted!"); 11122654012fSReza Sabdar want_this_file = FALSE; 11132654012fSReza Sabdar } 11142654012fSReza Sabdar } else 11152654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new file[%s]", real_name); 11162654012fSReza Sabdar 11172654012fSReza Sabdar /* 11182654012fSReza Sabdar * OK, some FM is creeping in here ... 11192654012fSReza Sabdar * int *fp is used to keep the 11202654012fSReza Sabdar * backup file channel open through 11212654012fSReza Sabdar * the interruption of EOT and 11222654012fSReza Sabdar * processing the headers of the 11232654012fSReza Sabdar * next tape. So, if *fp is zero 11242654012fSReza Sabdar * then no file is open yet and all 11252654012fSReza Sabdar * is normal. If *fp has a number 11262654012fSReza Sabdar * then we are returning after an 11272654012fSReza Sabdar * EOT break. 11282654012fSReza Sabdar * 11292654012fSReza Sabdar * *fp is now also open for HUGE files 11302654012fSReza Sabdar * that are put back in sections. 11312654012fSReza Sabdar */ 11322654012fSReza Sabdar 11332654012fSReza Sabdar if (*fp == 0 && want_this_file) { 11342654012fSReza Sabdar int erc_stat; 11352654012fSReza Sabdar 11362654012fSReza Sabdar if (mkbasedir(real_name) < 0) 11372654012fSReza Sabdar job_stats->js_errors++; 11382654012fSReza Sabdar 11392654012fSReza Sabdar erc_stat = stat64(real_name, (struct stat64 *)&attr); 11402654012fSReza Sabdar if (erc_stat < 0) { 11412654012fSReza Sabdar /*EMPTY*/ 11422654012fSReza Sabdar /* new file */ 11432654012fSReza Sabdar } else if (acls->acl_overwrite) { 11442654012fSReza Sabdar /*EMPTY*/ 11452654012fSReza Sabdar /* take this file no matter what */ 11462654012fSReza Sabdar } else if (acls->acl_update) { 11472654012fSReza Sabdar if (attr.st_mtime < acls->acl_attr.st_mtime) { 11482654012fSReza Sabdar /*EMPTY*/ 11492654012fSReza Sabdar /* tape is newer */ 11502654012fSReza Sabdar } else { 11512654012fSReza Sabdar /* disk file is newer */ 11522654012fSReza Sabdar want_this_file = FALSE; 11532654012fSReza Sabdar } 11542654012fSReza Sabdar } else { 11552654012fSReza Sabdar /* 11562654012fSReza Sabdar * no overwrite, no update, 11572654012fSReza Sabdar * do not ever replace old files. 11582654012fSReza Sabdar */ 11592654012fSReza Sabdar want_this_file = TRUE; 11602654012fSReza Sabdar } 11612654012fSReza Sabdar if (want_this_file) { 11622654012fSReza Sabdar 11632654012fSReza Sabdar *fp = open(real_name, O_CREAT | O_WRONLY, 11642654012fSReza Sabdar S_IRUSR | S_IWUSR); 11652654012fSReza Sabdar if (*fp == -1) { 11662654012fSReza Sabdar NDMP_LOG(LOG_ERR, 11672654012fSReza Sabdar "Could not open %s for restore.", 11682654012fSReza Sabdar real_name); 11692654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 11702654012fSReza Sabdar "fp=%d err=%d ", *fp, errno); 11712654012fSReza Sabdar job_stats->js_errors++; 11722654012fSReza Sabdar want_this_file = FALSE; 11732654012fSReza Sabdar /* 11742654012fSReza Sabdar * we cannot return here, 11752654012fSReza Sabdar * the file is still on 11762654012fSReza Sabdar * the tape and must be 11772654012fSReza Sabdar * skipped over. 11782654012fSReza Sabdar */ 11792654012fSReza Sabdar } 11802654012fSReza Sabdar } 11812654012fSReza Sabdar (void) strlcpy(local_commands->tc_file_name, real_name, 11822654012fSReza Sabdar TLM_MAX_PATH_NAME); 11832654012fSReza Sabdar } 11842654012fSReza Sabdar 11852654012fSReza Sabdar /* 11862654012fSReza Sabdar * this is the size left in the next segment 11872654012fSReza Sabdar */ 11882654012fSReza Sabdar huge_size -= size; 11892654012fSReza Sabdar 11902654012fSReza Sabdar /* 11912654012fSReza Sabdar * work 11922654012fSReza Sabdar */ 11932654012fSReza Sabdar while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) { 11942654012fSReza Sabdar int actual_size; 11952654012fSReza Sabdar int error; 11962654012fSReza Sabdar char *rec; 11972654012fSReza Sabdar int write_size; 11982654012fSReza Sabdar 11992654012fSReza Sabdar /* 12002654012fSReza Sabdar * Use bytes_in_file field to tell reader the amount 12012654012fSReza Sabdar * of data still need to be read for this file. 12022654012fSReza Sabdar */ 12032654012fSReza Sabdar job_stats->js_bytes_in_file = size; 12042654012fSReza Sabdar 12052654012fSReza Sabdar error = 0; 12062654012fSReza Sabdar rec = get_read_buffer(size, &error, &actual_size, 12072654012fSReza Sabdar local_commands); 12082654012fSReza Sabdar if (actual_size <= 0) { 12092654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 12102654012fSReza Sabdar "RESTORE WRITER> error %d, actual_size %d", 12112654012fSReza Sabdar error, actual_size); 12122654012fSReza Sabdar 12132654012fSReza Sabdar /* no more data for this file for now */ 12142654012fSReza Sabdar job_stats->js_bytes_in_file = 0; 12152654012fSReza Sabdar 12162654012fSReza Sabdar return (size); 12172654012fSReza Sabdar } else if (error) { 12182654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 12192654012fSReza Sabdar error, local_commands->tc_file_name); 12202654012fSReza Sabdar break; 12212654012fSReza Sabdar } else { 12222654012fSReza Sabdar write_size = min(size, actual_size); 12232654012fSReza Sabdar if (want_this_file) { 12242654012fSReza Sabdar write_size = write(*fp, rec, write_size); 12252654012fSReza Sabdar } 12262654012fSReza Sabdar NS_ADD(wdisk, write_size); 12272654012fSReza Sabdar NS_INC(wfile); 12282654012fSReza Sabdar size -= write_size; 12292654012fSReza Sabdar } 12302654012fSReza Sabdar } 12312654012fSReza Sabdar 12322654012fSReza Sabdar /* no more data for this file for now */ 12332654012fSReza Sabdar job_stats->js_bytes_in_file = 0; 12342654012fSReza Sabdar 12352654012fSReza Sabdar /* 12362654012fSReza Sabdar * teardown 12372654012fSReza Sabdar */ 12382654012fSReza Sabdar if (*fp != 0 && huge_size <= 0) { 12392654012fSReza Sabdar (void) close(*fp); 12402654012fSReza Sabdar *fp = 0; 12412654012fSReza Sabdar set_acl(real_name, acls); 12422654012fSReza Sabdar } 12432654012fSReza Sabdar return (0); 12442654012fSReza Sabdar } 12452654012fSReza Sabdar 12462654012fSReza Sabdar /* 12472654012fSReza Sabdar * Set the extended attributes file attribute 12482654012fSReza Sabdar */ 12492654012fSReza Sabdar static void 12502654012fSReza Sabdar set_xattr(int fd, struct stat64 st) 12512654012fSReza Sabdar { 12522654012fSReza Sabdar struct timeval times[2]; 12532654012fSReza Sabdar 12542654012fSReza Sabdar times[0].tv_sec = st.st_atime; 12552654012fSReza Sabdar times[1].tv_sec = st.st_mtime; 12562654012fSReza Sabdar 12572654012fSReza Sabdar (void) fchmod(fd, st.st_mode); 12582654012fSReza Sabdar (void) fchown(fd, st.st_uid, st.st_gid); 12592654012fSReza Sabdar (void) futimesat(fd, ".", times); 12602654012fSReza Sabdar } 12612654012fSReza Sabdar 1262b6b15642SReza Sabdar /* 1263b6b15642SReza Sabdar * Read the system attribute file in a single buffer to write 1264b6b15642SReza Sabdar * it as a single write. A partial write to system attribute would 1265b6b15642SReza Sabdar * cause an EINVAL on write. 1266b6b15642SReza Sabdar */ 1267b6b15642SReza Sabdar static char * 1268b6b15642SReza Sabdar get_read_one_buf(char *rec, int actual_size, int size, int *error, 1269b6b15642SReza Sabdar tlm_cmd_t *lc) 1270b6b15642SReza Sabdar { 1271b6b15642SReza Sabdar char *buf, *p; 1272b6b15642SReza Sabdar int read_size; 1273b6b15642SReza Sabdar int len; 1274b6b15642SReza Sabdar 1275b6b15642SReza Sabdar if (actual_size > size) 1276b6b15642SReza Sabdar return (rec); 1277b6b15642SReza Sabdar 1278b6b15642SReza Sabdar buf = ndmp_malloc(size); 1279b6b15642SReza Sabdar if (buf == NULL) { 1280b6b15642SReza Sabdar *error = ENOMEM; 1281b6b15642SReza Sabdar return (NULL); 1282b6b15642SReza Sabdar } 1283b6b15642SReza Sabdar (void) memcpy(buf, rec, actual_size); 1284b6b15642SReza Sabdar rec = buf; 1285b6b15642SReza Sabdar buf += actual_size; 1286b6b15642SReza Sabdar while (actual_size < size) { 1287b6b15642SReza Sabdar p = get_read_buffer(size - actual_size, error, &read_size, lc); 1288b6b15642SReza Sabdar len = min(size - actual_size, read_size); 1289b6b15642SReza Sabdar (void) memcpy(buf, p, len); 1290b6b15642SReza Sabdar actual_size += len; 1291b6b15642SReza Sabdar buf += len; 1292b6b15642SReza Sabdar } 1293b6b15642SReza Sabdar return (rec); 1294b6b15642SReza Sabdar } 1295b6b15642SReza Sabdar 1296b6b15642SReza Sabdar 12972654012fSReza Sabdar /* 12982654012fSReza Sabdar * read the extended attribute header and write 12992654012fSReza Sabdar * it to the file 13002654012fSReza Sabdar */ 13012654012fSReza Sabdar static long 13022654012fSReza Sabdar restore_xattr_hdr(int *fp, 13032654012fSReza Sabdar char *name, 13042654012fSReza Sabdar char *fname, 13052654012fSReza Sabdar long size, 13062654012fSReza Sabdar tlm_acls_t *acls, 13072654012fSReza Sabdar tlm_cmd_t *local_commands, 13082654012fSReza Sabdar tlm_job_stats_t *job_stats) 13092654012fSReza Sabdar { 13102654012fSReza Sabdar tlm_tar_hdr_t *tar_hdr; 13112654012fSReza Sabdar struct xattr_hdr *xhdr; 13122654012fSReza Sabdar struct xattr_buf *xbuf; 13132654012fSReza Sabdar int namelen; 13142654012fSReza Sabdar char *xattrname; 13152654012fSReza Sabdar int actual_size; 13162654012fSReza Sabdar int error; 13172654012fSReza Sabdar 13182654012fSReza Sabdar if (!fname) { 13192654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No file name but wanted!"); 13202654012fSReza Sabdar } else { 13212654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new xattr[%s]", fname); 13222654012fSReza Sabdar } 13232654012fSReza Sabdar 13242654012fSReza Sabdar error = 0; 13252654012fSReza Sabdar xhdr = (struct xattr_hdr *)get_read_buffer(size, &error, 13262654012fSReza Sabdar &actual_size, local_commands); 13272654012fSReza Sabdar if (error) { 13282654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 13292654012fSReza Sabdar "Could not read xattr [%s:%s] for restore. ", 13302654012fSReza Sabdar name, fname); 13312654012fSReza Sabdar job_stats->js_errors++; 13322654012fSReza Sabdar return (0); 13332654012fSReza Sabdar } 13342654012fSReza Sabdar 13352654012fSReza Sabdar /* Check extended attribute header */ 13362654012fSReza Sabdar if (strcmp(xhdr->h_version, XATTR_ARCH_VERS) != 0) { 13372654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 13382654012fSReza Sabdar "Unrecognized header format [%s]", xhdr->h_version); 13392654012fSReza Sabdar return (0); 13402654012fSReza Sabdar } 13412654012fSReza Sabdar xbuf = (struct xattr_buf *)(((char *)xhdr) + sizeof (struct xattr_hdr)); 13422654012fSReza Sabdar 13432654012fSReza Sabdar (void) sscanf(xbuf->h_namesz, "%7d", &namelen); 13442654012fSReza Sabdar xattrname = xbuf->h_names + strlen(xbuf->h_names) + 1; 13452654012fSReza Sabdar 13462654012fSReza Sabdar if (*fp == 0) { 13472654012fSReza Sabdar int fd; 13482654012fSReza Sabdar 13492654012fSReza Sabdar fd = attropen(name, xattrname, O_CREAT | O_RDWR, 0755); 13502654012fSReza Sabdar if (fd == -1) { 13512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 1352b6b15642SReza Sabdar "Could not open xattr [%s:%s] for restore err=%d.", 1353b6b15642SReza Sabdar name, xattrname, errno); 13542654012fSReza Sabdar job_stats->js_errors++; 1355b6b15642SReza Sabdar return (0); 13562654012fSReza Sabdar } 13572654012fSReza Sabdar (void) strlcpy(local_commands->tc_file_name, xattrname, 13582654012fSReza Sabdar TLM_MAX_PATH_NAME); 13592654012fSReza Sabdar *fp = fd; 13602654012fSReza Sabdar } 13612654012fSReza Sabdar 13622654012fSReza Sabdar /* Get the actual extended attribute file */ 13632654012fSReza Sabdar tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(sizeof (*tar_hdr), 13642654012fSReza Sabdar &error, &actual_size, local_commands); 13652654012fSReza Sabdar if (error) { 13662654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 13672654012fSReza Sabdar "Could not read xattr data [%s:%s] for restore. ", 13682654012fSReza Sabdar fname, xattrname); 13692654012fSReza Sabdar job_stats->js_errors++; 13702654012fSReza Sabdar return (0); 13712654012fSReza Sabdar } 13722654012fSReza Sabdar acls->acl_attr.st_mode = oct_atoi(tar_hdr->th_mode); 13732654012fSReza Sabdar acls->acl_attr.st_size = oct_atoi(tar_hdr->th_size); 13742654012fSReza Sabdar acls->acl_attr.st_uid = oct_atoi(tar_hdr->th_uid); 13752654012fSReza Sabdar acls->acl_attr.st_gid = oct_atoi(tar_hdr->th_gid); 13762654012fSReza Sabdar acls->acl_attr.st_mtime = oct_atoi(tar_hdr->th_mtime); 13772654012fSReza Sabdar 1378b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d", 1379b6b15642SReza Sabdar xattrname, acls->acl_attr.st_size, acls->acl_attr.st_mode, 1380b6b15642SReza Sabdar acls->acl_attr.st_uid, acls->acl_attr.st_gid); 1381b6b15642SReza Sabdar 13822654012fSReza Sabdar size = acls->acl_attr.st_size; 13832654012fSReza Sabdar while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) { 13842654012fSReza Sabdar char *rec; 13852654012fSReza Sabdar int write_size; 1386b6b15642SReza Sabdar int sysattr_write = 0; 13872654012fSReza Sabdar 13882654012fSReza Sabdar error = 0; 13892654012fSReza Sabdar rec = get_read_buffer(size, &error, &actual_size, 13902654012fSReza Sabdar local_commands); 1391b6b15642SReza Sabdar 1392b6b15642SReza Sabdar if ((actual_size < size) && sysattr_rw(xattrname)) { 1393b6b15642SReza Sabdar rec = get_read_one_buf(rec, actual_size, size, &error, 1394b6b15642SReza Sabdar local_commands); 1395b6b15642SReza Sabdar if (rec == NULL) { 1396b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 1397b6b15642SReza Sabdar error, xattrname); 1398b6b15642SReza Sabdar return (size); 1399b6b15642SReza Sabdar } 1400b6b15642SReza Sabdar actual_size = size; 1401b6b15642SReza Sabdar sysattr_write = 1; 1402b6b15642SReza Sabdar } 14032654012fSReza Sabdar if (actual_size <= 0) { 14042654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 14052654012fSReza Sabdar "RESTORE WRITER> error %d, actual_size %d", 14062654012fSReza Sabdar error, actual_size); 14072654012fSReza Sabdar 14082654012fSReza Sabdar return (size); 14092654012fSReza Sabdar } else if (error) { 14102654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]", 14112654012fSReza Sabdar error, local_commands->tc_file_name); 14122654012fSReza Sabdar break; 14132654012fSReza Sabdar } else { 14142654012fSReza Sabdar write_size = min(size, actual_size); 1415b6b15642SReza Sabdar if ((write_size = write(*fp, rec, write_size)) < 0) { 1416b6b15642SReza Sabdar if (sysattr_write) 1417b6b15642SReza Sabdar free(rec); 1418b6b15642SReza Sabdar 1419b6b15642SReza Sabdar break; 1420b6b15642SReza Sabdar } 1421b6b15642SReza Sabdar 14222654012fSReza Sabdar NS_ADD(wdisk, write_size); 14232654012fSReza Sabdar NS_INC(wfile); 14242654012fSReza Sabdar size -= write_size; 14252654012fSReza Sabdar } 1426b6b15642SReza Sabdar if (sysattr_write) 1427b6b15642SReza Sabdar free(rec); 14282654012fSReza Sabdar } 14292654012fSReza Sabdar 14302654012fSReza Sabdar if (*fp != 0) { 14312654012fSReza Sabdar set_xattr(*fp, acls->acl_attr); 14322654012fSReza Sabdar (void) close(*fp); 14332654012fSReza Sabdar *fp = 0; 14342654012fSReza Sabdar } 14352654012fSReza Sabdar return (0); 14362654012fSReza Sabdar } 14372654012fSReza Sabdar 14382654012fSReza Sabdar /* 14392654012fSReza Sabdar * Match the name with the list 14402654012fSReza Sabdar */ 14412654012fSReza Sabdar static int 14422654012fSReza Sabdar exact_find(char *name, char **list) 14432654012fSReza Sabdar { 14442654012fSReza Sabdar boolean_t found; 14452654012fSReza Sabdar int i; 14462654012fSReza Sabdar char *cp; 14472654012fSReza Sabdar 14482654012fSReza Sabdar found = FALSE; 14492654012fSReza Sabdar for (i = 0; *list != NULL; list++, i++) { 14502654012fSReza Sabdar cp = *list + strspn(*list, "/"); 14512654012fSReza Sabdar if (match(cp, name)) { 14522654012fSReza Sabdar found = TRUE; 14532654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "exact_find> found[%s]", cp); 14542654012fSReza Sabdar break; 14552654012fSReza Sabdar } 14562654012fSReza Sabdar } 14572654012fSReza Sabdar 14582654012fSReza Sabdar return (found); 14592654012fSReza Sabdar } 14602654012fSReza Sabdar 14612654012fSReza Sabdar /* 14622654012fSReza Sabdar * On error, return FALSE and prevent restoring(probably) unwanted data. 14632654012fSReza Sabdar */ 14642654012fSReza Sabdar static int 14652654012fSReza Sabdar is_parent(char *parent, char *child, int flags) 14662654012fSReza Sabdar { 14672654012fSReza Sabdar char tmp[TLM_MAX_PATH_NAME]; 14682654012fSReza Sabdar boolean_t rv; 14692654012fSReza Sabdar 14702654012fSReza Sabdar if (IS_SET(flags, RSFLG_MATCH_WCARD)) { 14712654012fSReza Sabdar if (!tlm_cat_path(tmp, parent, "*")) { 14722654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 14732654012fSReza Sabdar "is_parent> path too long [%s]", parent); 14742654012fSReza Sabdar rv = FALSE; 14752654012fSReza Sabdar } else 14762654012fSReza Sabdar rv = (match(tmp, child) != 0) ? TRUE : FALSE; 14772654012fSReza Sabdar } else { 14782654012fSReza Sabdar if (!tlm_cat_path(tmp, parent, "/")) { 14792654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 14802654012fSReza Sabdar "is_parent> path too long [%s]", parent); 14812654012fSReza Sabdar rv = FALSE; 14822654012fSReza Sabdar } else 14832654012fSReza Sabdar rv = (strncmp(tmp, child, strlen(tmp)) == 0) ? 14842654012fSReza Sabdar TRUE : FALSE; 14852654012fSReza Sabdar } 14862654012fSReza Sabdar 14872654012fSReza Sabdar return (rv); 14882654012fSReza Sabdar } 14892654012fSReza Sabdar 14902654012fSReza Sabdar /* 14912654012fSReza Sabdar * Used to match the filename inside the list 14922654012fSReza Sabdar */ 14932654012fSReza Sabdar static boolean_t 14942654012fSReza Sabdar strexactcmp(char *s, char *t) 14952654012fSReza Sabdar { 14962654012fSReza Sabdar return ((strcmp(s, t) == 0) ? TRUE : FALSE); 14972654012fSReza Sabdar } 14982654012fSReza Sabdar 14992654012fSReza Sabdar /* 15002654012fSReza Sabdar * Check if the file is needed to be restored 15012654012fSReza Sabdar */ 15022654012fSReza Sabdar static boolean_t 15032654012fSReza Sabdar is_file_wanted(char *name, 15042654012fSReza Sabdar char **sels, 15052654012fSReza Sabdar char **exls, 15062654012fSReza Sabdar int flags, 15072654012fSReza Sabdar int *mchtype, 15082654012fSReza Sabdar int *pos) 15092654012fSReza Sabdar { 15102654012fSReza Sabdar char *p_sel; 15112654012fSReza Sabdar char *uc_name, *retry, *namep; 15122654012fSReza Sabdar boolean_t found; 15132654012fSReza Sabdar int i; 15142654012fSReza Sabdar name_match_fp_t *cmp_fp; 15152654012fSReza Sabdar 15162654012fSReza Sabdar if (name == NULL || sels == NULL || exls == NULL) 15172654012fSReza Sabdar return (FALSE); 15182654012fSReza Sabdar 15192654012fSReza Sabdar found = FALSE; 15202654012fSReza Sabdar if (mchtype != NULL) 15212654012fSReza Sabdar *mchtype = PM_NONE; 15222654012fSReza Sabdar if (pos != NULL) 15232654012fSReza Sabdar *pos = 0; 15242654012fSReza Sabdar 15252654012fSReza Sabdar /* 15262654012fSReza Sabdar * For empty selection, restore everything 15272654012fSReza Sabdar */ 15282654012fSReza Sabdar if (*sels == NULL || **sels == '\0') { 15292654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "is_file_wanted: Restore all"); 15302654012fSReza Sabdar return (TRUE); 15312654012fSReza Sabdar } 15322654012fSReza Sabdar 15332654012fSReza Sabdar uc_name = ndmp_malloc(TLM_MAX_PATH_NAME); 15342654012fSReza Sabdar retry = ndmp_malloc(TLM_MAX_PATH_NAME); 15352654012fSReza Sabdar if (uc_name == NULL || retry == NULL) { 15362654012fSReza Sabdar free(uc_name); 15372654012fSReza Sabdar free(retry); 15382654012fSReza Sabdar return (FALSE); 15392654012fSReza Sabdar } 15402654012fSReza Sabdar 15412654012fSReza Sabdar if (IS_SET(flags, RSFLG_MATCH_WCARD)) 15422654012fSReza Sabdar cmp_fp = match; 15432654012fSReza Sabdar else 15442654012fSReza Sabdar cmp_fp = strexactcmp; 15452654012fSReza Sabdar 15462654012fSReza Sabdar namep = name + strspn(name, "/"); 15472654012fSReza Sabdar if (IS_SET(flags, RSFLG_IGNORE_CASE)) { 15482654012fSReza Sabdar (void) strlcpy(uc_name, namep, TLM_MAX_PATH_NAME); 15492654012fSReza Sabdar (void) strupr(uc_name); 15502654012fSReza Sabdar namep = uc_name; 15512654012fSReza Sabdar } 15522654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "is_file_wanted> flg: 0x%x name: [%s]", 15532654012fSReza Sabdar flags, name); 15542654012fSReza Sabdar 15552654012fSReza Sabdar for (i = 0; *sels != NULL; sels++, i++) { 15562654012fSReza Sabdar p_sel = *sels + strspn(*sels, "/"); 15572654012fSReza Sabdar 15582654012fSReza Sabdar /* 15592654012fSReza Sabdar * Try exact match. 15602654012fSReza Sabdar */ 15612654012fSReza Sabdar if ((*cmp_fp)(p_sel, namep)) { 15622654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "match1> pos: %d [%s][%s]", 15632654012fSReza Sabdar i, p_sel, name); 15642654012fSReza Sabdar found = TRUE; 15652654012fSReza Sabdar if (mchtype != NULL) 15662654012fSReza Sabdar *mchtype = PM_EXACT; 15672654012fSReza Sabdar break; 15682654012fSReza Sabdar } 15692654012fSReza Sabdar /* 15702654012fSReza Sabdar * Try "entry/" and the current selection. The 15712654012fSReza Sabdar * current selection may be something like "<something>/". 15722654012fSReza Sabdar */ 15732654012fSReza Sabdar (void) tlm_cat_path(retry, namep, "/"); 15742654012fSReza Sabdar if ((*cmp_fp)(p_sel, retry)) { 15752654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "match2> pos %d [%s][%s]", 15762654012fSReza Sabdar i, p_sel, name); 15772654012fSReza Sabdar found = TRUE; 15782654012fSReza Sabdar if (mchtype != NULL) 15792654012fSReza Sabdar *mchtype = PM_EXACT; 15802654012fSReza Sabdar break; 15812654012fSReza Sabdar } 15822654012fSReza Sabdar /* 15832654012fSReza Sabdar * If the following check returns true it means that the 15842654012fSReza Sabdar * 'name' is an entry below the 'p_sel' hierarchy. 15852654012fSReza Sabdar */ 15862654012fSReza Sabdar if (is_parent(p_sel, namep, flags)) { 15872654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "parent1> pos %d [%s][%s]", 15882654012fSReza Sabdar i, p_sel, name); 15892654012fSReza Sabdar found = TRUE; 15902654012fSReza Sabdar if (mchtype != NULL) 15912654012fSReza Sabdar *mchtype = PM_CHILD; 15922654012fSReza Sabdar break; 15932654012fSReza Sabdar } 15942654012fSReza Sabdar 15952654012fSReza Sabdar /* 15962654012fSReza Sabdar * There is a special case for parent directories of a 15972654012fSReza Sabdar * selection. If 'p_sel' is something like "*d1", the 15982654012fSReza Sabdar * middle directories of the final entry can't be determined 15992654012fSReza Sabdar * until the final entry matches with 'p_sel'. At that 16002654012fSReza Sabdar * time the middle directories of the entry have been passed 16012654012fSReza Sabdar * and they can't be restored. 16022654012fSReza Sabdar */ 16032654012fSReza Sabdar if (is_parent(namep, p_sel, flags)) { 16042654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "parent2> pos %d [%s][%s]", 16052654012fSReza Sabdar i, p_sel, name); 16062654012fSReza Sabdar found = TRUE; 16072654012fSReza Sabdar if (mchtype != NULL) 16082654012fSReza Sabdar *mchtype = PM_PARENT; 16092654012fSReza Sabdar break; 16102654012fSReza Sabdar } 16112654012fSReza Sabdar } 16122654012fSReza Sabdar 16132654012fSReza Sabdar /* Check for exclusions. */ 16142654012fSReza Sabdar if (found && exact_find(namep, exls)) { 16152654012fSReza Sabdar if (mchtype != NULL) 16162654012fSReza Sabdar *mchtype = PM_NONE; 16172654012fSReza Sabdar found = FALSE; 16182654012fSReza Sabdar } 16192654012fSReza Sabdar if (found && pos != NULL) 16202654012fSReza Sabdar *pos = i; 16212654012fSReza Sabdar 16222654012fSReza Sabdar free(uc_name); 16232654012fSReza Sabdar free(retry); 16242654012fSReza Sabdar return (found); 16252654012fSReza Sabdar } 16262654012fSReza Sabdar 16272654012fSReza Sabdar /* 16282654012fSReza Sabdar * Read the specified amount data into the buffer. Detects EOT or EOF 16292654012fSReza Sabdar * during read. 16302654012fSReza Sabdar * 16312654012fSReza Sabdar * Returns the number of bytes actually read. On error returns -1. 16322654012fSReza Sabdar */ 16332654012fSReza Sabdar static int 16342654012fSReza Sabdar input_mem(int l, 16352654012fSReza Sabdar int d, 16362654012fSReza Sabdar tlm_cmd_t *lcmds, 16372654012fSReza Sabdar char *mem, 16382654012fSReza Sabdar int len) 16392654012fSReza Sabdar { 16402654012fSReza Sabdar int err; 16412654012fSReza Sabdar int toread, actual_size, rec_size; 16422654012fSReza Sabdar char *rec; 16432654012fSReza Sabdar 16442654012fSReza Sabdar if (l <= 0 || d <= 0 || !lcmds || !mem) { 16452654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument"); 16462654012fSReza Sabdar return (-1); 16472654012fSReza Sabdar } 16482654012fSReza Sabdar 16492654012fSReza Sabdar toread = len; 16502654012fSReza Sabdar while (toread > 0) { 16512654012fSReza Sabdar rec = get_read_buffer(toread, &err, &actual_size, lcmds); 16522654012fSReza Sabdar if (actual_size <= 0) { 16532654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "err %d act_size %d detected", 16542654012fSReza Sabdar err, actual_size); 16552654012fSReza Sabdar break; 16562654012fSReza Sabdar } else if (err) { 16572654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d reading data", err); 16582654012fSReza Sabdar return (-1); 16592654012fSReza Sabdar } 16602654012fSReza Sabdar rec_size = min(actual_size, toread); 16612654012fSReza Sabdar (void) memcpy(mem, rec, rec_size); 16622654012fSReza Sabdar mem += rec_size; 16632654012fSReza Sabdar toread -= rec_size; 16642654012fSReza Sabdar } 16652654012fSReza Sabdar 16662654012fSReza Sabdar return (len - toread); 16672654012fSReza Sabdar } 16682654012fSReza Sabdar 16692654012fSReza Sabdar /* 16702654012fSReza Sabdar * pick up the name and size of a HUGE file 16712654012fSReza Sabdar */ 16722654012fSReza Sabdar static int 16732654012fSReza Sabdar get_humongus_file_header(int lib, 16742654012fSReza Sabdar int drv, 16752654012fSReza Sabdar long recsize, 16762654012fSReza Sabdar longlong_t *size, 16772654012fSReza Sabdar char *name, 16782654012fSReza Sabdar tlm_cmd_t *local_commands) 16792654012fSReza Sabdar { 16802654012fSReza Sabdar char *p_record, *value; 16812654012fSReza Sabdar int rv; 16822654012fSReza Sabdar 16832654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE Record found: %d", recsize); 16842654012fSReza Sabdar 16852654012fSReza Sabdar rv = 0; 16862654012fSReza Sabdar if (recsize == 0) { 16872654012fSReza Sabdar /* 16882654012fSReza Sabdar * The humongus_file_header was written in a 16892654012fSReza Sabdar * RECORDSIZE block and the header.size field of this 16902654012fSReza Sabdar * record was 0 before this fix. For backward compatiblity 16912654012fSReza Sabdar * read only one RECORDSIZE-size block if the header.size 16922654012fSReza Sabdar * field is 0. Otherwise the header.size field should show 16932654012fSReza Sabdar * the length of the data of this header. 16942654012fSReza Sabdar */ 16952654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Old HUGE record found"); 16962654012fSReza Sabdar recsize = RECORDSIZE; 16972654012fSReza Sabdar } 16982654012fSReza Sabdar 16992654012fSReza Sabdar if (input_mem(lib, drv, local_commands, name, recsize) != recsize) { 17002654012fSReza Sabdar rv = -1; 17012654012fSReza Sabdar *size = 0; 17022654012fSReza Sabdar *name = '\0'; 17032654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error reading a HUGE file name"); 17042654012fSReza Sabdar } else { 17052654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE [%s]", name); 17062654012fSReza Sabdar 17072654012fSReza Sabdar p_record = name; 17082654012fSReza Sabdar value = parse(&p_record, " "); 17092654012fSReza Sabdar *size = atoll(value); 17102654012fSReza Sabdar /* 17112654012fSReza Sabdar * Note: Since the backed up names are not longer than 17122654012fSReza Sabdar * NAME_MAX and the buffer passed to us is 17132654012fSReza Sabdar * TLM_MAX_PATH_NAME, it should be safe to use strlcpy 17142654012fSReza Sabdar * without check on the buffer size. 17152654012fSReza Sabdar */ 17162654012fSReza Sabdar (void) strlcpy(name, p_record, TLM_MAX_PATH_NAME); 17172654012fSReza Sabdar } 17182654012fSReza Sabdar 17192654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "HUGE Record %lld [%s]", *size, name); 17202654012fSReza Sabdar 17212654012fSReza Sabdar return (rv); 17222654012fSReza Sabdar } 17232654012fSReza Sabdar 17242654012fSReza Sabdar /* 17252654012fSReza Sabdar * pick up the long name from the special tape file 17262654012fSReza Sabdar */ 17272654012fSReza Sabdar static int 17282654012fSReza Sabdar get_long_name(int lib, 17292654012fSReza Sabdar int drv, 17302654012fSReza Sabdar long recsize, 17312654012fSReza Sabdar char *name, 17322654012fSReza Sabdar long *buf_spot, 17332654012fSReza Sabdar tlm_cmd_t *local_commands) 17342654012fSReza Sabdar { 17352654012fSReza Sabdar int nread; 17362654012fSReza Sabdar 17372654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "LONGNAME Record found rs %d bs %d", recsize, 17382654012fSReza Sabdar *buf_spot); 17392654012fSReza Sabdar 17402654012fSReza Sabdar if (*buf_spot < 0) 17412654012fSReza Sabdar *buf_spot = 0; 17422654012fSReza Sabdar 17432654012fSReza Sabdar nread = input_mem(lib, drv, local_commands, name + *buf_spot, 17442654012fSReza Sabdar recsize); 17452654012fSReza Sabdar if (nread < 0) { 17462654012fSReza Sabdar nread = recsize; /* return 0 as size left */ 17472654012fSReza Sabdar name[*buf_spot] = '\0'; 17482654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Error %d reading a long file name %s.", 17492654012fSReza Sabdar nread, name); 17502654012fSReza Sabdar } else { 17512654012fSReza Sabdar *buf_spot += nread; 17522654012fSReza Sabdar name[*buf_spot] = '\0'; 17532654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "LONGNAME [%s]", name); 17542654012fSReza Sabdar } 17552654012fSReza Sabdar 17562654012fSReza Sabdar return (recsize - nread); 17572654012fSReza Sabdar } 17582654012fSReza Sabdar 17592654012fSReza Sabdar /* 17602654012fSReza Sabdar * create a new directory 17612654012fSReza Sabdar */ 17622654012fSReza Sabdar static int 17632654012fSReza Sabdar create_directory(char *dir, tlm_job_stats_t *job_stats) 17642654012fSReza Sabdar { 17652654012fSReza Sabdar struct stat64 attr; 17662654012fSReza Sabdar char *p; 17672654012fSReza Sabdar char temp; 17682654012fSReza Sabdar int erc; 17692654012fSReza Sabdar 17702654012fSReza Sabdar /* 17712654012fSReza Sabdar * Make sure all directories in this path exist, create them if 17722654012fSReza Sabdar * needed. 17732654012fSReza Sabdar */ 17742654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "new dir[%s]", dir); 17752654012fSReza Sabdar 17762654012fSReza Sabdar erc = 0; 17772654012fSReza Sabdar p = &dir[1]; 17782654012fSReza Sabdar do { 17792654012fSReza Sabdar temp = *p; 17802654012fSReza Sabdar if (temp == '/' || temp == 0) { 17812654012fSReza Sabdar *p = 0; 17822654012fSReza Sabdar if (stat64(dir, &attr) < 0) { 17832654012fSReza Sabdar erc = mkdir(dir, 0777); 17842654012fSReza Sabdar if (erc < 0) { 17852654012fSReza Sabdar job_stats->js_errors++; 17862654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 17872654012fSReza Sabdar "Could not create directory %s", 17882654012fSReza Sabdar dir); 17892654012fSReza Sabdar break; 17902654012fSReza Sabdar } 17912654012fSReza Sabdar } 17922654012fSReza Sabdar *p = temp; 17932654012fSReza Sabdar } 17942654012fSReza Sabdar p++; 17952654012fSReza Sabdar } while (temp != 0); 17962654012fSReza Sabdar 17972654012fSReza Sabdar return (erc); 17982654012fSReza Sabdar } 17992654012fSReza Sabdar 18002654012fSReza Sabdar /* 18012654012fSReza Sabdar * create a new hardlink 18022654012fSReza Sabdar */ 18032654012fSReza Sabdar static int 18042654012fSReza Sabdar create_hard_link(char *name_old, char *name_new, 18052654012fSReza Sabdar tlm_acls_t *acls, tlm_job_stats_t *job_stats) 18062654012fSReza Sabdar { 18072654012fSReza Sabdar int erc; 18082654012fSReza Sabdar 18092654012fSReza Sabdar if (mkbasedir(name_new)) { 18102654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "faile to make base dir for [%s]", 18112654012fSReza Sabdar name_new); 18122654012fSReza Sabdar 18132654012fSReza Sabdar return (-1); 18142654012fSReza Sabdar } 18152654012fSReza Sabdar 18162654012fSReza Sabdar erc = link(name_old, name_new); 18172654012fSReza Sabdar if (erc) { 18182654012fSReza Sabdar job_stats->js_errors++; 18192654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d (errno %d) hardlink [%s] to [%s]", 18202654012fSReza Sabdar erc, errno, name_new, name_old); 18212654012fSReza Sabdar } else { 18222654012fSReza Sabdar set_acl(name_new, acls); 18232654012fSReza Sabdar } 18242654012fSReza Sabdar return (erc); 18252654012fSReza Sabdar } 18262654012fSReza Sabdar 18272654012fSReza Sabdar /* 18282654012fSReza Sabdar * create a new symlink 18292654012fSReza Sabdar */ 18302654012fSReza Sabdar /*ARGSUSED*/ 18312654012fSReza Sabdar static int 18322654012fSReza Sabdar create_sym_link(char *dst, char *target, tlm_acls_t *acls, 18332654012fSReza Sabdar tlm_job_stats_t *job_satats) 18342654012fSReza Sabdar { 18352654012fSReza Sabdar int erc; 18362654012fSReza Sabdar 18372654012fSReza Sabdar if (mkbasedir(dst) < 0) 18382654012fSReza Sabdar return (-1); 18392654012fSReza Sabdar 18402654012fSReza Sabdar erc = symlink(target, dst); 18412654012fSReza Sabdar if (erc) { 18422654012fSReza Sabdar job_satats->js_errors++; 18432654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error %d (errno %d) softlink [%s] to [%s]", 18442654012fSReza Sabdar erc, errno, dst, target); 1845*86c48bbfSReza Sabdar } else { 1846*86c48bbfSReza Sabdar set_acl(dst, acls); 18472654012fSReza Sabdar } 18482654012fSReza Sabdar 18492654012fSReza Sabdar return (erc); 18502654012fSReza Sabdar } 18512654012fSReza Sabdar 18522654012fSReza Sabdar /* 18532654012fSReza Sabdar * create a new FIFO 18542654012fSReza Sabdar */ 18552654012fSReza Sabdar static int 18562654012fSReza Sabdar create_fifo(char *name, tlm_acls_t *acls) 18572654012fSReza Sabdar { 18582654012fSReza Sabdar (void) mknod(name, 0777 + S_IFIFO, 0); 18592654012fSReza Sabdar set_acl(name, acls); 18602654012fSReza Sabdar return (0); 18612654012fSReza Sabdar } 18622654012fSReza Sabdar 18632654012fSReza Sabdar /* 18642654012fSReza Sabdar * read in the ACLs for the next file 18652654012fSReza Sabdar */ 18662654012fSReza Sabdar static long 18672654012fSReza Sabdar load_acl_info(int lib, 18682654012fSReza Sabdar int drv, 18692654012fSReza Sabdar long file_size, 18702654012fSReza Sabdar tlm_acls_t *acls, 18712654012fSReza Sabdar long *acl_spot, 18722654012fSReza Sabdar tlm_cmd_t *local_commands) 18732654012fSReza Sabdar { 18742654012fSReza Sabdar char *bp; 18752654012fSReza Sabdar int nread; 18762654012fSReza Sabdar 18772654012fSReza Sabdar /* 18782654012fSReza Sabdar * If the ACL is spanned on tapes, then the acl_spot should NOT be 18792654012fSReza Sabdar * 0 on next calls to this function to read the rest of the ACL 18802654012fSReza Sabdar * on next tapes. 18812654012fSReza Sabdar */ 18822654012fSReza Sabdar if (*acl_spot == 0) { 18832654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 18842654012fSReza Sabdar } 18852654012fSReza Sabdar 18862654012fSReza Sabdar bp = ((char *)&acls->acl_info) + *acl_spot; 18872654012fSReza Sabdar nread = input_mem(lib, drv, local_commands, (void *)bp, file_size); 18882654012fSReza Sabdar if (nread < 0) { 18892654012fSReza Sabdar *acl_spot = 0; 18902654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 18912654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Error reading ACL data"); 18922654012fSReza Sabdar return (0); 18932654012fSReza Sabdar } 18942654012fSReza Sabdar *acl_spot += nread; 18952654012fSReza Sabdar acls->acl_non_trivial = TRUE; 18962654012fSReza Sabdar 18972654012fSReza Sabdar return (file_size - nread); 18982654012fSReza Sabdar } 18992654012fSReza Sabdar 19002654012fSReza Sabdar static int 19012654012fSReza Sabdar ndmp_set_eprivs_least(void) 19022654012fSReza Sabdar { 19032654012fSReza Sabdar priv_set_t *priv_set; 19042654012fSReza Sabdar 19052654012fSReza Sabdar if ((priv_set = priv_allocset()) == NULL) { 19062654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Out of memory."); 19072654012fSReza Sabdar return (-1); 19082654012fSReza Sabdar } 19092654012fSReza Sabdar priv_emptyset(priv_set); 19102654012fSReza Sabdar (void) priv_addset(priv_set, "basic"); 19112654012fSReza Sabdar (void) priv_addset(priv_set, "proc_audit"); 19122654012fSReza Sabdar (void) priv_addset(priv_set, "proc_setid"); 19132654012fSReza Sabdar (void) priv_addset(priv_set, "proc_owner"); 19142654012fSReza Sabdar (void) priv_addset(priv_set, "file_chown"); 19152654012fSReza Sabdar (void) priv_addset(priv_set, "file_chown_self"); 19162654012fSReza Sabdar (void) priv_addset(priv_set, "file_dac_read"); 19172654012fSReza Sabdar (void) priv_addset(priv_set, "file_dac_search"); 19182654012fSReza Sabdar (void) priv_addset(priv_set, "file_dac_write"); 19192654012fSReza Sabdar (void) priv_addset(priv_set, "file_owner"); 19202654012fSReza Sabdar (void) priv_addset(priv_set, "file_setid"); 19212654012fSReza Sabdar (void) priv_addset(priv_set, "sys_linkdir"); 19222654012fSReza Sabdar (void) priv_addset(priv_set, "sys_devices"); 19232654012fSReza Sabdar (void) priv_addset(priv_set, "sys_mount"); 19242654012fSReza Sabdar (void) priv_addset(priv_set, "sys_config"); 19252654012fSReza Sabdar 19262654012fSReza Sabdar if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) { 19272654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Additional privileges required."); 19282654012fSReza Sabdar priv_freeset(priv_set); 19292654012fSReza Sabdar return (-1); 19302654012fSReza Sabdar } 19312654012fSReza Sabdar priv_freeset(priv_set); 19322654012fSReza Sabdar return (0); 19332654012fSReza Sabdar } 19342654012fSReza Sabdar 19352654012fSReza Sabdar static int 19362654012fSReza Sabdar ndmp_set_eprivs_all(void) 19372654012fSReza Sabdar { 19382654012fSReza Sabdar priv_set_t *priv_set; 19392654012fSReza Sabdar 19402654012fSReza Sabdar if ((priv_set = priv_str_to_set("all", ",", NULL)) == NULL) { 19412654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Could not set privileges to 'all'."); 19422654012fSReza Sabdar return (-1); 19432654012fSReza Sabdar } 19442654012fSReza Sabdar if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) != 0) { 19452654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Additional privileges required."); 19462654012fSReza Sabdar return (-1); 19472654012fSReza Sabdar } 19482654012fSReza Sabdar priv_freeset(priv_set); 19492654012fSReza Sabdar return (0); 19502654012fSReza Sabdar } 19512654012fSReza Sabdar 19522654012fSReza Sabdar /* 19532654012fSReza Sabdar * Set the standard attributes of the file 19542654012fSReza Sabdar */ 19552654012fSReza Sabdar static void 1956b6b15642SReza Sabdar set_attr(char *name, tlm_acls_t *acls) 19572654012fSReza Sabdar { 19582654012fSReza Sabdar struct utimbuf tbuf; 19592654012fSReza Sabdar boolean_t priv_all = FALSE; 1960b6b15642SReza Sabdar struct stat64 *st; 1961b6b15642SReza Sabdar uid_t uid; 1962b6b15642SReza Sabdar gid_t gid; 1963b6b15642SReza Sabdar struct passwd *pwd; 1964b6b15642SReza Sabdar struct group *grp; 1965b6b15642SReza Sabdar 19662654012fSReza Sabdar 1967b6b15642SReza Sabdar if (!name || !acls) 19682654012fSReza Sabdar return; 19692654012fSReza Sabdar 1970b6b15642SReza Sabdar st = &acls->acl_attr; 1971b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "set_attr: %s uid %d gid %d uname %s gname %s " 1972b6b15642SReza Sabdar "mode %o", name, st->st_uid, st->st_gid, acls->uname, acls->gname, 1973b6b15642SReza Sabdar st->st_mode); 1974b6b15642SReza Sabdar 1975b6b15642SReza Sabdar uid = st->st_uid; 1976b6b15642SReza Sabdar if ((pwd = getpwnam(acls->uname)) != NULL) { 1977b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "set_attr: new uid %d old %d", 1978b6b15642SReza Sabdar pwd->pw_uid, uid); 1979b6b15642SReza Sabdar uid = pwd->pw_uid; 1980b6b15642SReza Sabdar } 1981b6b15642SReza Sabdar 1982b6b15642SReza Sabdar gid = st->st_gid; 1983b6b15642SReza Sabdar if ((grp = getgrnam(acls->gname)) != NULL) { 1984b6b15642SReza Sabdar NDMP_LOG(LOG_DEBUG, "set_attr: new gid %d old %d", 1985b6b15642SReza Sabdar grp->gr_gid, gid); 1986b6b15642SReza Sabdar gid = grp->gr_gid; 1987b6b15642SReza Sabdar } 19882654012fSReza Sabdar 1989*86c48bbfSReza Sabdar if (lchown(name, uid, gid)) 19902654012fSReza Sabdar NDMP_LOG(LOG_ERR, 19912654012fSReza Sabdar "Could not set uid or/and gid for file %s.", name); 19922654012fSReza Sabdar 19932654012fSReza Sabdar if ((st->st_mode & (S_ISUID | S_ISGID)) != 0) { 19942654012fSReza Sabdar /* 19952654012fSReza Sabdar * Change effective privileges to 'all' which is required to 19962654012fSReza Sabdar * change setuid bit for 'root' owned files. If fails, just 19972654012fSReza Sabdar * send error to log file and proceed. 19982654012fSReza Sabdar */ 19992654012fSReza Sabdar if (ndmp_set_eprivs_all()) { 20002654012fSReza Sabdar NDMP_LOG(LOG_ERR, 20012654012fSReza Sabdar "Could not set effective privileges to 'all'."); 20022654012fSReza Sabdar } else { 20032654012fSReza Sabdar priv_all = TRUE; 20042654012fSReza Sabdar } 20052654012fSReza Sabdar } 20062654012fSReza Sabdar 20072654012fSReza Sabdar if (chmod(name, st->st_mode)) 20082654012fSReza Sabdar NDMP_LOG(LOG_ERR, 20092654012fSReza Sabdar "Could not set correct file permission for file %s.", name); 20102654012fSReza Sabdar 20112654012fSReza Sabdar if (priv_all == TRUE) { 20122654012fSReza Sabdar /* 20132654012fSReza Sabdar * Give up the 'all' privileges for effective sets and go back 20142654012fSReza Sabdar * to least required privileges. If fails, just send error to 20152654012fSReza Sabdar * log file and proceed. 20162654012fSReza Sabdar */ 20172654012fSReza Sabdar if (ndmp_set_eprivs_least()) 20182654012fSReza Sabdar NDMP_LOG(LOG_ERR, 20192654012fSReza Sabdar "Could not set least required privileges."); 20202654012fSReza Sabdar } 20212654012fSReza Sabdar 20222654012fSReza Sabdar tbuf.modtime = st->st_mtime; 20232654012fSReza Sabdar tbuf.actime = st->st_atime; 20242654012fSReza Sabdar (void) utime(name, &tbuf); 20252654012fSReza Sabdar } 20262654012fSReza Sabdar 20272654012fSReza Sabdar /* 20282654012fSReza Sabdar * Set the ACL info for the file 20292654012fSReza Sabdar */ 20302654012fSReza Sabdar static void 20312654012fSReza Sabdar set_acl(char *name, tlm_acls_t *acls) 20322654012fSReza Sabdar { 20332654012fSReza Sabdar int erc; 20342654012fSReza Sabdar acl_t *aclp = NULL; 20352654012fSReza Sabdar 20362654012fSReza Sabdar if (name) 20372654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "set_acl: %s", name); 20382654012fSReza Sabdar if (acls != 0) { 20392654012fSReza Sabdar /* Need a place to save real modification time */ 20402654012fSReza Sabdar 2041b6b15642SReza Sabdar set_attr(name, acls); 20422654012fSReza Sabdar 20432654012fSReza Sabdar if (!acls->acl_non_trivial) { 20442654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 20452654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "set_acl: skipping trivial"); 20462654012fSReza Sabdar return; 20472654012fSReza Sabdar } 20482654012fSReza Sabdar 20492654012fSReza Sabdar erc = acl_fromtext(acls->acl_info.attr_info, &aclp); 20502654012fSReza Sabdar if (erc != 0) { 20512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 20522654012fSReza Sabdar "TAPE RESTORE> acl_fromtext errno %d", erc); 20532654012fSReza Sabdar } 20542654012fSReza Sabdar if (aclp) { 20552654012fSReza Sabdar erc = acl_set(name, aclp); 20562654012fSReza Sabdar if (erc < 0) { 20572654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 20582654012fSReza Sabdar "TAPE RESTORE> acl_set errno %d", errno); 20592654012fSReza Sabdar } 20602654012fSReza Sabdar acl_free(aclp); 20612654012fSReza Sabdar } 20622654012fSReza Sabdar (void) memset(acls, 0, sizeof (tlm_acls_t)); 20632654012fSReza Sabdar } 20642654012fSReza Sabdar } 20652654012fSReza Sabdar 20662654012fSReza Sabdar /* 20672654012fSReza Sabdar * a wrapper to tlm_get_read_buffer so that 20682654012fSReza Sabdar * we can cleanly detect ABORT commands 20692654012fSReza Sabdar * without involving the TLM library with 20702654012fSReza Sabdar * our problems. 20712654012fSReza Sabdar */ 20722654012fSReza Sabdar static char * 20732654012fSReza Sabdar get_read_buffer(int want, 20742654012fSReza Sabdar int *error, 20752654012fSReza Sabdar int *actual_size, 20762654012fSReza Sabdar tlm_cmd_t *local_commands) 20772654012fSReza Sabdar { 20782654012fSReza Sabdar while (local_commands->tc_writer == TLM_RESTORE_RUN) { 20792654012fSReza Sabdar char *rec; 20802654012fSReza Sabdar rec = tlm_get_read_buffer(want, error, 20812654012fSReza Sabdar local_commands->tc_buffers, actual_size); 20822654012fSReza Sabdar if (rec != 0) { 20832654012fSReza Sabdar return (rec); 20842654012fSReza Sabdar } 20852654012fSReza Sabdar } 20862654012fSReza Sabdar 20872654012fSReza Sabdar /* 20882654012fSReza Sabdar * the job is ending, give Writer a buffer that will never be read ... 20892654012fSReza Sabdar * it does not matter anyhow, we are aborting. 20902654012fSReza Sabdar */ 20912654012fSReza Sabdar *actual_size = RECORDSIZE; 20922654012fSReza Sabdar return (NULL); 20932654012fSReza Sabdar } 20942654012fSReza Sabdar 20952654012fSReza Sabdar /* 20962654012fSReza Sabdar * Enable wildcard for restore options 20972654012fSReza Sabdar */ 20982654012fSReza Sabdar static boolean_t 20992654012fSReza Sabdar wildcard_enabled(void) 21002654012fSReza Sabdar { 21012654012fSReza Sabdar char *cp; 21022654012fSReza Sabdar 21032654012fSReza Sabdar cp = ndmpd_get_prop_default(NDMP_RESTORE_WILDCARD_ENABLE, "n"); 21042654012fSReza Sabdar return ((toupper(*cp) == 'Y') ? TRUE : FALSE); 21052654012fSReza Sabdar } 21062654012fSReza Sabdar 21072654012fSReza Sabdar 21082654012fSReza Sabdar /* 21092654012fSReza Sabdar * Concatenate two names 21102654012fSReza Sabdar */ 21112654012fSReza Sabdar /*ARGSUSED*/ 21122654012fSReza Sabdar static char * 21132654012fSReza Sabdar catnames(struct rs_name_maker *rnp, char *buf, int pos, char *path) 21142654012fSReza Sabdar { 21152654012fSReza Sabdar char *rv; 21162654012fSReza Sabdar 21172654012fSReza Sabdar rv = NULL; 21182654012fSReza Sabdar if (!buf) { 21192654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "buf is NULL"); 21202654012fSReza Sabdar } else if (!path) { 21212654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "path is NULL"); 21222654012fSReza Sabdar } else if (!rnp->rn_nlp) { 21232654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "rn_nlp is NULL [%s]", path); 21242654012fSReza Sabdar } else if (!tlm_cat_path(buf, rnp->rn_nlp, path)) { 21252654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", 21262654012fSReza Sabdar rnp->rn_nlp, path); 21272654012fSReza Sabdar } else 21282654012fSReza Sabdar rv = buf; 21292654012fSReza Sabdar 21302654012fSReza Sabdar return (rv); 21312654012fSReza Sabdar } 21322654012fSReza Sabdar 21332654012fSReza Sabdar 21342654012fSReza Sabdar /* 21352654012fSReza Sabdar * Create a new name path for restore 21362654012fSReza Sabdar */ 21372654012fSReza Sabdar static char * 21382654012fSReza Sabdar rs_new_name(struct rs_name_maker *rnp, char *buf, int pos, char *path) 21392654012fSReza Sabdar { 21402654012fSReza Sabdar if (!rnp || !rnp->rn_fp) 21412654012fSReza Sabdar return (NULL); 21422654012fSReza Sabdar 21432654012fSReza Sabdar return (*rnp->rn_fp)(rnp, buf, pos, path); 21442654012fSReza Sabdar } 21452654012fSReza Sabdar 21462654012fSReza Sabdar /* 21472654012fSReza Sabdar * Iterate over ZFS metadata stored in the backup stream and use the callback 21482654012fSReza Sabdar * to restore it. 21492654012fSReza Sabdar */ 21502654012fSReza Sabdar int 21512654012fSReza Sabdar ndmp_iter_zfs(ndmp_context_t *nctx, int (*np_restore_property)(nvlist_t *, 21522654012fSReza Sabdar void *), void *ptr) 21532654012fSReza Sabdar { 21542654012fSReza Sabdar tlm_commands_t *cmds; 21552654012fSReza Sabdar ndmp_metadata_header_t *mhp; 21562654012fSReza Sabdar ndmp_metadata_property_t *mpp; 21572654012fSReza Sabdar tlm_cmd_t *lcmd; 21582654012fSReza Sabdar int actual_size; 21592654012fSReza Sabdar nvlist_t *nvl; 21602654012fSReza Sabdar nvlist_t *nvl_head; 21612654012fSReza Sabdar nvlist_t *valp; 21622654012fSReza Sabdar nvpair_t *nvp = NULL; 21632654012fSReza Sabdar nvpair_t *nvph = NULL; 21642654012fSReza Sabdar char plname[100]; 21652654012fSReza Sabdar char *mhbuf, *pp, *tp; 21662654012fSReza Sabdar int rv, i; 21672654012fSReza Sabdar int size, lsize, sz; 21682654012fSReza Sabdar int align = RECORDSIZE - 1; 21692654012fSReza Sabdar 21702654012fSReza Sabdar if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 21712654012fSReza Sabdar return (-1); 21722654012fSReza Sabdar 21732654012fSReza Sabdar nctx->nc_plname = plname; 21742654012fSReza Sabdar if ((lcmd = cmds->tcs_command) == NULL || 21752654012fSReza Sabdar lcmd->tc_buffers == NULL) 21762654012fSReza Sabdar return (-1); 21772654012fSReza Sabdar 21782654012fSReza Sabdar size = sizeof (ndmp_metadata_header_t) + 21792654012fSReza Sabdar ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 21802654012fSReza Sabdar size += align; 21812654012fSReza Sabdar size &= ~align; 21822654012fSReza Sabdar 21832654012fSReza Sabdar /* For nvlist cleanup */ 21842654012fSReza Sabdar if (nvlist_alloc(&nvl_head, NV_UNIQUE_NAME, 0) != 0) 21852654012fSReza Sabdar return (-1); 21862654012fSReza Sabdar 21872654012fSReza Sabdar if ((mhbuf = malloc(size)) == NULL) 21882654012fSReza Sabdar return (-1); 21892654012fSReza Sabdar 21902654012fSReza Sabdar /* LINTED improper alignment */ 21912654012fSReza Sabdar while ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv, 21922654012fSReza Sabdar &actual_size, lcmd)) != NULL) { 21932654012fSReza Sabdar pp = mhbuf; 21942654012fSReza Sabdar 21952654012fSReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC, 21962654012fSReza Sabdar sizeof (mhp->nh_magic)) != 0) { 21972654012fSReza Sabdar /* No more metadata */ 21982654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 21992654012fSReza Sabdar nvlist_free(nvl_head); 22002654012fSReza Sabdar return (0); 22012654012fSReza Sabdar } 22022654012fSReza Sabdar 22032654012fSReza Sabdar (void) memcpy(pp, (char *)mhp, (actual_size < size) ? 22042654012fSReza Sabdar actual_size : size); 22052654012fSReza Sabdar pp += (actual_size < size) ? actual_size : size; 22062654012fSReza Sabdar 22072654012fSReza Sabdar sz = actual_size; 22082654012fSReza Sabdar while (sz < size && 22092654012fSReza Sabdar ((tp = get_read_buffer(size - sz, &rv, &lsize, 22102654012fSReza Sabdar lcmd))) != NULL) { 22112654012fSReza Sabdar (void) memcpy(pp, tp, size - sz); 22122654012fSReza Sabdar sz += lsize; 22132654012fSReza Sabdar pp += lsize; 22142654012fSReza Sabdar } 22152654012fSReza Sabdar if (sz > size) { 22162654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, sz - size); 22172654012fSReza Sabdar } 22182654012fSReza Sabdar /* LINTED improper alignment */ 22192654012fSReza Sabdar mhp = (ndmp_metadata_header_t *)mhbuf; 22202654012fSReza Sabdar 22212654012fSReza Sabdar nctx->nc_plversion = mhp->nh_plversion; 22222654012fSReza Sabdar (void) strlcpy(plname, mhp->nh_plname, sizeof (plname)); 22232654012fSReza Sabdar 22242654012fSReza Sabdar if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 22252654012fSReza Sabdar goto nvlist_err; 22262654012fSReza Sabdar 22272654012fSReza Sabdar mpp = &mhp->nh_property[0]; 22282654012fSReza Sabdar for (i = 0; i < mhp->nh_count && mpp; i++) { 22292654012fSReza Sabdar if (nvlist_alloc(&valp, NV_UNIQUE_NAME, 0) != 0 || 22302654012fSReza Sabdar nvlist_add_string(valp, "value", 22312654012fSReza Sabdar mpp->mp_value) != 0 || 22322654012fSReza Sabdar nvlist_add_string(valp, "source", 22332654012fSReza Sabdar mpp->mp_source) != 0 || 22342654012fSReza Sabdar nvlist_add_nvlist(nvl, mpp->mp_name, valp) != 0) 22352654012fSReza Sabdar goto nvlist_err; 22362654012fSReza Sabdar mpp++; 22372654012fSReza Sabdar } 22382654012fSReza Sabdar 22392654012fSReza Sabdar if (np_restore_property(nvl, ptr) != 0) 22402654012fSReza Sabdar goto nvlist_err; 22412654012fSReza Sabdar 22422654012fSReza Sabdar (void) nvlist_add_nvlist(nvl_head, "_", nvl); 22432654012fSReza Sabdar } 22442654012fSReza Sabdar free(mhbuf); 22452654012fSReza Sabdar 22462654012fSReza Sabdar nvlist_free(nvl_head); 22472654012fSReza Sabdar return (0); 22482654012fSReza Sabdar 22492654012fSReza Sabdar nvlist_err: 22502654012fSReza Sabdar free(mhbuf); 22512654012fSReza Sabdar while ((nvph = nvlist_next_nvpair(nvl_head, nvph)) != NULL && 22522654012fSReza Sabdar nvpair_value_nvlist(nvph, &nvl) == 0) { 22532654012fSReza Sabdar while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL && 22542654012fSReza Sabdar nvpair_value_nvlist(nvp, &valp) == 0) { 22552654012fSReza Sabdar nvlist_free(valp); 22562654012fSReza Sabdar } 22572654012fSReza Sabdar nvlist_free(nvl); 22582654012fSReza Sabdar } 22592654012fSReza Sabdar nvlist_free(nvl_head); 22602654012fSReza Sabdar return (-1); 22612654012fSReza Sabdar } 22622654012fSReza Sabdar 22632654012fSReza Sabdar /* 22642654012fSReza Sabdar * Returns the version number of the plugin which created the metadata 22652654012fSReza Sabdar */ 22662654012fSReza Sabdar uint_t 22672654012fSReza Sabdar ndmp_context_get_version(ndmp_context_t *nctx) 22682654012fSReza Sabdar { 22692654012fSReza Sabdar tlm_commands_t *cmds; 22702654012fSReza Sabdar ndmp_metadata_header_t *mhp; 22712654012fSReza Sabdar tlm_cmd_t *lcmd; 22722654012fSReza Sabdar int actual_size; 22732654012fSReza Sabdar int rv; 22742654012fSReza Sabdar int size; 22752654012fSReza Sabdar int align = RECORDSIZE - 1; 22762654012fSReza Sabdar 22772654012fSReza Sabdar if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 22782654012fSReza Sabdar return (0); 22792654012fSReza Sabdar 22802654012fSReza Sabdar if ((lcmd = cmds->tcs_command) == NULL || 22812654012fSReza Sabdar lcmd->tc_buffers == NULL) 22822654012fSReza Sabdar return (0); 22832654012fSReza Sabdar 22842654012fSReza Sabdar size = sizeof (ndmp_metadata_header_t); 22852654012fSReza Sabdar size += align; 22862654012fSReza Sabdar size &= ~align; 22872654012fSReza Sabdar 22882654012fSReza Sabdar /* LINTED improper alignment */ 22892654012fSReza Sabdar if ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv, 22902654012fSReza Sabdar &actual_size, lcmd)) != NULL) { 22912654012fSReza Sabdar if (strncmp(mhp->nh_magic, ZFS_META_MAGIC, 22922654012fSReza Sabdar sizeof (mhp->nh_magic)) != 0) { 22932654012fSReza Sabdar /* No more metadata */ 22942654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 22952654012fSReza Sabdar return (0); 22962654012fSReza Sabdar } 22972654012fSReza Sabdar 22982654012fSReza Sabdar nctx->nc_plversion = mhp->nh_plversion; 22992654012fSReza Sabdar tlm_unget_read_buffer(lcmd->tc_buffers, actual_size); 23002654012fSReza Sabdar } 23012654012fSReza Sabdar 23022654012fSReza Sabdar return (nctx->nc_plversion); 23032654012fSReza Sabdar } 2304