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