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