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