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