1 /* 2 * Copyright 2008 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 <stdio.h> 40 #include <limits.h> 41 #include <time.h> 42 #include <sys/stat.h> 43 #include <unistd.h> 44 #include <dirent.h> 45 #include <pthread.h> 46 #include <archives.h> 47 #include <tlm.h> 48 #include <sys/fs/zfs.h> 49 #include <libzfs.h> 50 #include "tlm_proto.h" 51 52 53 static char *get_write_buffer(long size, 54 long *actual_size, 55 boolean_t zero, 56 tlm_cmd_t *); 57 static int output_acl_header(sec_attr_t *, 58 tlm_cmd_t *); 59 static int output_file_header(char *name, 60 char *link, 61 tlm_acls_t *, 62 int section, 63 tlm_cmd_t *); 64 static int output_xattr_header(char *fname, 65 char *aname, 66 int fd, 67 tlm_acls_t *, 68 int section, 69 tlm_cmd_t *); 70 71 extern libzfs_handle_t *zlibh; 72 73 74 /* 75 * output_mem 76 * 77 * Gets a IO write buffer and copies memory to the that. 78 */ 79 static void 80 output_mem(tlm_cmd_t *local_commands, char *mem, 81 int len) 82 { 83 long actual_size, rec_size; 84 char *rec; 85 86 while (len > 0) { 87 rec = get_write_buffer(len, &actual_size, 88 FALSE, local_commands); 89 rec_size = min(actual_size, len); 90 (void) memcpy(rec, mem, rec_size); 91 mem += rec_size; 92 len -= rec_size; 93 } 94 } 95 96 /* 97 * tlm_output_dir 98 * 99 * Put the directory information into the output buffers. 100 */ 101 int 102 tlm_output_dir(char *name, tlm_acls_t *tlm_acls, 103 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 104 { 105 u_longlong_t pos; 106 107 /* 108 * Send the node or path history of the directory itself. 109 */ 110 pos = tlm_get_data_offset(local_commands); 111 NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 112 (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos); 113 (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos); 114 /* fhdir_cb is handled in ndmpd_tar3.c */ 115 116 (void) output_acl_header(&tlm_acls->acl_info, 117 local_commands); 118 (void) output_file_header(name, "", tlm_acls, 0, 119 local_commands); 120 121 return (0); 122 } 123 124 /* 125 * tar_putdir 126 * 127 * Main dir backup function for tar 128 */ 129 int 130 tar_putdir(char *name, tlm_acls_t *tlm_acls, 131 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 132 { 133 int rv; 134 135 rv = tlm_output_dir(name, tlm_acls, local_commands, job_stats); 136 return (rv < 0 ? rv : 0); 137 } 138 139 /* 140 * output_acl_header 141 * 142 * output the ACL header record and data 143 */ 144 static int 145 output_acl_header(sec_attr_t *acl_info, 146 tlm_cmd_t *local_commands) 147 { 148 long actual_size; 149 tlm_tar_hdr_t *tar_hdr; 150 long acl_size; 151 152 if ((acl_info == NULL) || (*acl_info->attr_info == '\0')) 153 return (0); 154 155 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 156 &actual_size, TRUE, local_commands); 157 if (!tar_hdr) 158 return (0); 159 160 tar_hdr->th_linkflag = LF_ACL; 161 acl_info->attr_type = UFSD_ACL; 162 (void) snprintf(acl_info->attr_len, sizeof (acl_info->attr_len), 163 "%06o", strlen(acl_info->attr_info)); 164 165 acl_size = sizeof (*acl_info); 166 (void) strlcpy(tar_hdr->th_name, "UFSACL", TLM_NAME_SIZE); 167 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 168 acl_size); 169 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 170 0444); 171 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 0); 172 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 0); 173 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 174 "%011o ", 0); 175 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 176 sizeof (tar_hdr->th_magic)); 177 178 tlm_build_header_checksum(tar_hdr); 179 180 (void) output_mem(local_commands, (void *)acl_info, acl_size); 181 return (0); 182 } 183 184 /* 185 * output_humongus_header 186 * 187 * output a special header record for HUGE files 188 * output is: 1) a TAR "HUGE" header redord 189 * 2) a "file" of size, name 190 */ 191 static int 192 output_humongus_header(char *fullname, longlong_t file_size, 193 tlm_cmd_t *local_commands) 194 { 195 char *buf; 196 int len; 197 long actual_size; 198 tlm_tar_hdr_t *tar_hdr; 199 200 /* 201 * buf will contain: "%llu %s": 202 * - 20 is the maximum length of 'ulong_tlong' decimal notation. 203 * - The first '1' is for the ' ' between the "%llu" and the fullname. 204 * - The last '1' is for the null-terminator of fullname. 205 */ 206 len = 20 + 1 + strlen(fullname) + 1; 207 208 if ((buf = ndmp_malloc(sizeof (char) * len)) == NULL) 209 return (-1); 210 211 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 212 &actual_size, TRUE, local_commands); 213 if (!tar_hdr) { 214 free(buf); 215 return (0); 216 } 217 218 tar_hdr->th_linkflag = LF_HUMONGUS; 219 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 220 len); 221 tlm_build_header_checksum(tar_hdr); 222 (void) snprintf(buf, len, "%lld %s", file_size, fullname); 223 (void) output_mem(local_commands, buf, len); 224 225 free(buf); 226 return (0); 227 } 228 229 230 /* 231 * output_xattr_header 232 * 233 * output the TAR header record for extended attributes 234 */ 235 static int 236 output_xattr_header(char *fname, char *aname, int fd, 237 tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 238 { 239 struct stat64 *attr = &tlm_acls->acl_attr; 240 struct xattr_hdr *xhdr; 241 struct xattr_buf *xbuf; 242 tlm_tar_hdr_t *tar_hdr; 243 long actual_size; 244 char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 245 int hsize; 246 int comlen; 247 int namesz; 248 249 if (section_name == NULL) 250 return (-TLM_NO_SCRATCH_SPACE); 251 252 if (fstat64(fd, attr) == -1) { 253 NDMP_LOG(LOG_DEBUG, "output_file_header stat failed."); 254 free(section_name); 255 return (-TLM_OPEN_ERR); 256 } 257 258 /* 259 * if the file has to go out in sections, 260 * we must mung the name. 261 */ 262 if (section == 0) { 263 (void) snprintf(section_name, TLM_MAX_PATH_NAME, 264 "/dev/null/%s.hdr", aname); 265 } else { 266 (void) snprintf(section_name, 267 TLM_MAX_PATH_NAME, "%s.%03d", aname, section); 268 } 269 namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */ 270 hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 271 comlen = namesz + sizeof (struct xattr_buf); 272 273 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 274 &actual_size, TRUE, local_commands); 275 if (!tar_hdr) { 276 free(section_name); 277 return (0); 278 } 279 280 (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 281 282 tar_hdr->th_linkflag = LF_XATTR; 283 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 284 hsize); 285 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 286 attr->st_mode & 07777); 287 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 288 attr->st_uid); 289 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 290 attr->st_gid); 291 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 292 attr->st_mtime); 293 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 294 sizeof (tar_hdr->th_magic)); 295 296 tlm_build_header_checksum(tar_hdr); 297 298 xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE, 299 &actual_size, TRUE, local_commands); 300 if (!xhdr) { 301 free(section_name); 302 return (0); 303 } 304 305 (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s", 306 XATTR_ARCH_VERS); 307 (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d", 308 sizeof (xhdr->h_size) - 1, hsize); 309 (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len), 310 "%0*d", sizeof (xhdr->h_component_len) - 1, comlen); 311 (void) snprintf(xhdr->h_link_component_len, 312 sizeof (xhdr->h_link_component_len), "%0*d", 313 sizeof (xhdr->h_link_component_len) - 1, 0); 314 315 xbuf = (struct xattr_buf *)(((caddr_t)xhdr) + 316 sizeof (struct xattr_hdr)); 317 (void) snprintf(xbuf->h_namesz, sizeof (xbuf->h_namesz), "%0*d", 318 sizeof (xbuf->h_namesz) - 1, namesz); 319 320 /* No support for links in extended attributes */ 321 xbuf->h_typeflag = LF_NORMAL; 322 323 (void) strlcpy(xbuf->h_names, fname, TLM_NAME_SIZE); 324 (void) strlcpy(&xbuf->h_names[strlen(fname) + 1], aname, 325 TLM_NAME_SIZE); 326 327 free(section_name); 328 return (0); 329 } 330 331 332 /* 333 * output_file_header 334 * 335 * output the TAR header record 336 */ 337 static int 338 output_file_header(char *name, char *link, 339 tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands) 340 { 341 static longlong_t file_count = 0; 342 struct stat64 *attr = &tlm_acls->acl_attr; 343 tlm_tar_hdr_t *tar_hdr; 344 long actual_size; 345 boolean_t long_name = FALSE; 346 boolean_t long_link = FALSE; 347 char *section_name = ndmp_malloc(TLM_MAX_PATH_NAME); 348 int nmlen, lnklen; 349 350 if (section_name == NULL) 351 return (-TLM_NO_SCRATCH_SPACE); 352 353 /* 354 * if the file has to go out in sections, 355 * we must mung the name. 356 */ 357 if (section == 0) { 358 (void) strlcpy(section_name, name, TLM_MAX_PATH_NAME); 359 } else { 360 (void) snprintf(section_name, 361 TLM_MAX_PATH_NAME, "%s.%03d", name, section); 362 } 363 364 nmlen = strlen(section_name); 365 if (nmlen >= NAMSIZ) { 366 /* 367 * file name is too big, it must go out 368 * in its own data file 369 */ 370 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 371 &actual_size, TRUE, local_commands); 372 if (!tar_hdr) { 373 free(section_name); 374 return (0); 375 } 376 (void) snprintf(tar_hdr->th_name, 377 sizeof (tar_hdr->th_name), 378 "%s%08qd.fil", 379 LONGNAME_PREFIX, 380 file_count++); 381 382 tar_hdr->th_linkflag = LF_LONGNAME; 383 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 384 "%011o ", nmlen); 385 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 386 "%06o ", attr->st_mode & 07777); 387 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 388 "%06o ", attr->st_uid); 389 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 390 "%06o ", attr->st_gid); 391 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 392 "%011o ", attr->st_mtime); 393 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 394 sizeof (tar_hdr->th_magic)); 395 396 tlm_build_header_checksum(tar_hdr); 397 398 (void) output_mem(local_commands, 399 (void *)section_name, nmlen); 400 long_name = TRUE; 401 } 402 403 lnklen = strlen(link); 404 if (lnklen >= NAMSIZ) { 405 /* 406 * link name is too big, it must go out 407 * in its own data file 408 */ 409 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 410 &actual_size, TRUE, local_commands); 411 if (!tar_hdr) { 412 free(section_name); 413 return (0); 414 } 415 (void) snprintf(tar_hdr->th_linkname, 416 sizeof (tar_hdr->th_name), 417 "%s%08qd.slk", 418 LONGNAME_PREFIX, 419 file_count++); 420 421 tar_hdr->th_linkflag = LF_LONGLINK; 422 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), 423 "%011o ", lnklen); 424 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), 425 "%06o ", attr->st_mode & 07777); 426 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), 427 "%06o ", attr->st_uid); 428 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), 429 "%06o ", attr->st_gid); 430 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), 431 "%011o ", attr->st_mtime); 432 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 433 sizeof (tar_hdr->th_magic)); 434 435 tlm_build_header_checksum(tar_hdr); 436 437 (void) output_mem(local_commands, (void *)link, 438 lnklen); 439 long_link = TRUE; 440 } 441 tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE, 442 &actual_size, TRUE, local_commands); 443 if (!tar_hdr) { 444 free(section_name); 445 return (0); 446 } 447 if (long_name) { 448 (void) snprintf(tar_hdr->th_name, 449 sizeof (tar_hdr->th_name), 450 "%s%08qd.fil", 451 LONGNAME_PREFIX, 452 file_count++); 453 } else { 454 (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE); 455 } 456 457 NDMP_LOG(LOG_DEBUG, "long_link: %s [%s]", long_link ? "TRUE" : "FALSE", 458 link); 459 460 if (long_link) { 461 (void) snprintf(tar_hdr->th_linkname, 462 sizeof (tar_hdr->th_name), 463 "%s%08qd.slk", 464 LONGNAME_PREFIX, 465 file_count++); 466 } else { 467 (void) strlcpy(tar_hdr->th_linkname, link, TLM_NAME_SIZE); 468 } 469 if (S_ISDIR(attr->st_mode)) { 470 tar_hdr->th_linkflag = LF_DIR; 471 } else if (S_ISFIFO(attr->st_mode)) { 472 tar_hdr->th_linkflag = LF_FIFO; 473 } else if (attr->st_nlink > 1) { 474 /* mark file with hardlink LF_LINK */ 475 tar_hdr->th_linkflag = LF_LINK; 476 (void) snprintf(tar_hdr->th_shared.th_hlink_ino, 477 sizeof (tar_hdr->th_shared.th_hlink_ino), 478 "%011o ", attr->st_ino); 479 } else { 480 tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL : LF_SYMLINK; 481 NDMP_LOG(LOG_DEBUG, "linkflag: '%c'", tar_hdr->th_linkflag); 482 } 483 (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ", 484 (long)attr->st_size); 485 (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ", 486 attr->st_mode & 07777); 487 (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ", 488 attr->st_uid); 489 (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ", 490 attr->st_gid); 491 (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ", 492 attr->st_mtime); 493 (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC, 494 sizeof (tar_hdr->th_magic)); 495 496 tlm_build_header_checksum(tar_hdr); 497 if (long_name || long_link) { 498 if (file_count > 99999990) { 499 file_count = 0; 500 } 501 } 502 free(section_name); 503 return (0); 504 } 505 506 507 /* 508 * tlm_readlink 509 * 510 * Read where the softlink points to. Read the link in the checkpointed 511 * path if the backup is being done on a checkpointed file system. 512 */ 513 static int 514 tlm_readlink(char *nm, char *snap, char *buf, int bufsize) 515 { 516 int len; 517 518 if ((len = readlink(snap, buf, bufsize)) >= 0) { 519 /* 520 * realink(2) doesn't null terminate the link name. We must 521 * do it here. 522 */ 523 buf[len] = '\0'; 524 } else { 525 NDMP_LOG(LOG_DEBUG, "Error %d reading softlink of [%s]", 526 errno, nm); 527 buf[0] = '\0'; 528 529 /* Backup the link if the destination missing */ 530 if (errno == ENOENT) 531 return (0); 532 533 } 534 535 return (len); 536 } 537 538 539 /* 540 * tlm_output_xattr 541 * 542 * Put this file into the output buffers. 543 */ 544 /*ARGSUSED*/ 545 longlong_t 546 tlm_output_xattr(char *dir, char *name, char *chkdir, 547 tlm_acls_t *tlm_acls, tlm_commands_t *commands, 548 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats) 549 { 550 char *fullname; /* directory + name */ 551 char *snapname; /* snapshot name */ 552 int section; /* section of a huge file */ 553 int fd; 554 longlong_t seek_spot = 0; /* location in the file */ 555 /* for Multi Volume record */ 556 u_longlong_t pos; 557 DIR *dp; 558 struct dirent *dtp; 559 char *attrname; 560 char *fnamep; 561 int rv = 0; 562 563 if (S_ISLNK(tlm_acls->acl_attr.st_mode)) 564 return (TLM_NO_SOURCE_FILE); 565 566 fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 567 if (fullname == NULL) { 568 free(fullname); 569 return (-TLM_NO_SCRATCH_SPACE); 570 } 571 572 if (!tlm_cat_path(fullname, dir, name)) { 573 NDMP_LOG(LOG_DEBUG, "Path too long."); 574 free(fullname); 575 return (-TLM_NO_SCRATCH_SPACE); 576 } 577 578 if (pathconf(fullname, _PC_XATTR_EXISTS) != 1) { 579 free(fullname); 580 return (0); 581 } 582 583 attrname = ndmp_malloc(TLM_MAX_PATH_NAME); 584 snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 585 if (attrname == NULL || snapname == NULL) { 586 rv = -TLM_NO_SCRATCH_SPACE; 587 goto err_out; 588 } 589 590 if (!tlm_cat_path(snapname, chkdir, name)) { 591 NDMP_LOG(LOG_DEBUG, "Path too long."); 592 rv = -TLM_NO_SCRATCH_SPACE; 593 goto err_out; 594 } 595 596 fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 597 598 /* 599 * Open the file for reading. 600 */ 601 fd = open(fnamep, O_RDONLY | O_XATTR); 602 if (fd == -1) { 603 NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname); 604 rv = TLM_NO_SOURCE_FILE; 605 goto err_out; 606 } 607 608 pos = tlm_get_data_offset(local_commands); 609 NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 610 611 section = 0; 612 613 dp = (DIR *)fdopendir(fd); 614 if (dp == NULL) { 615 NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname); 616 (void) close(fd); 617 rv = TLM_NO_SOURCE_FILE; 618 goto err_out; 619 } 620 621 (void) output_acl_header(&tlm_acls->acl_info, 622 local_commands); 623 624 while ((dtp = readdir(dp)) != NULL) { 625 int section_size; 626 627 if (*dtp->d_name == '.') 628 continue; 629 630 (void) close(fd); 631 fd = attropen(fnamep, dtp->d_name, O_RDONLY); 632 if (fd == -1) { 633 NDMP_LOG(LOG_DEBUG, 634 "problem(%d) opening xattr file [%s]", errno, 635 fullname); 636 goto tear_down; 637 } 638 639 (void) output_xattr_header(fullname, dtp->d_name, fd, 640 tlm_acls, section, local_commands); 641 (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s", 642 dtp->d_name); 643 (void) output_file_header(attrname, "", tlm_acls, 0, 644 local_commands); 645 646 section_size = (long)llmin(tlm_acls->acl_attr.st_size, 647 (longlong_t)TLM_MAX_TAR_IMAGE); 648 649 /* We only can read upto one section extended attribute */ 650 while (section_size > 0) { 651 char *buf; 652 long actual_size; 653 int read_size; 654 655 /* 656 * check for Abort commands 657 */ 658 if (commands->tcs_reader != TLM_BACKUP_RUN) { 659 local_commands->tc_writer = TLM_ABORT; 660 goto tear_down; 661 } 662 663 local_commands->tc_buffers->tbs_buffer[ 664 local_commands->tc_buffers->tbs_buffer_in]. 665 tb_file_size = section_size; 666 local_commands->tc_buffers->tbs_buffer[ 667 local_commands->tc_buffers->tbs_buffer_in]. 668 tb_seek_spot = seek_spot; 669 670 buf = get_write_buffer(section_size, 671 &actual_size, FALSE, local_commands); 672 if (!buf) 673 goto tear_down; 674 675 /* 676 * check for Abort commands 677 */ 678 if (commands->tcs_reader != TLM_BACKUP_RUN) { 679 local_commands->tc_writer = TLM_ABORT; 680 goto tear_down; 681 } 682 683 read_size = min(section_size, actual_size); 684 actual_size = read(fd, buf, read_size); 685 NS_ADD(rdisk, actual_size); 686 NS_INC(rfile); 687 688 if (actual_size == -1) { 689 NDMP_LOG(LOG_DEBUG, 690 "problem(%d) reading file [%s][%s]", 691 errno, fullname, snapname); 692 goto tear_down; 693 } 694 seek_spot += actual_size; 695 section_size -= actual_size; 696 } 697 } 698 699 tear_down: 700 local_commands->tc_buffers->tbs_buffer[ 701 local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 702 703 (void) closedir(dp); 704 (void) close(fd); 705 706 err_out: 707 free(fullname); 708 free(attrname); 709 free(snapname); 710 return (rv); 711 } 712 713 714 /* 715 * tlm_output_file 716 * 717 * Put this file into the output buffers. 718 */ 719 longlong_t 720 tlm_output_file(char *dir, char *name, char *chkdir, 721 tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands, 722 tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q) 723 { 724 char *fullname; /* directory + name */ 725 char *snapname; /* snapshot name */ 726 char *linkname; /* where this file points */ 727 int section = 0; /* section of a huge file */ 728 int fd; 729 longlong_t real_size; /* the origional file size */ 730 longlong_t file_size; /* real size of this file */ 731 longlong_t seek_spot = 0; /* location in the file */ 732 /* for Multi Volume record */ 733 u_longlong_t pos; 734 char *fnamep; 735 736 /* Indicate whether a file with the same inode has been backed up. */ 737 int hardlink_done = 0; 738 739 /* 740 * If a file with the same inode has been backed up, hardlink_pos holds 741 * the tape offset of the data record. 742 */ 743 u_longlong_t hardlink_pos = 0; 744 745 if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) { 746 NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name); 747 return (-TLM_NO_SCRATCH_SPACE); 748 } 749 750 fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 751 linkname = ndmp_malloc(TLM_MAX_PATH_NAME); 752 snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 753 if (fullname == NULL || linkname == NULL || snapname == NULL) { 754 real_size = -TLM_NO_SCRATCH_SPACE; 755 goto err_out; 756 } 757 if (!tlm_cat_path(fullname, dir, name) || 758 !tlm_cat_path(snapname, chkdir, name)) { 759 NDMP_LOG(LOG_DEBUG, "Path too long."); 760 real_size = -TLM_NO_SCRATCH_SPACE; 761 goto err_out; 762 } 763 764 pos = tlm_get_data_offset(local_commands); 765 NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 766 767 if (S_ISLNK(tlm_acls->acl_attr.st_mode)) { 768 file_size = tlm_readlink(fullname, snapname, linkname, 769 TLM_MAX_PATH_NAME-1); 770 if (file_size < 0) { 771 real_size = -ENOENT; 772 goto err_out; 773 } 774 775 /* 776 * Since soft links can not be read(2), we should only 777 * backup the file header. 778 */ 779 (void) output_file_header(fullname, 780 linkname, 781 tlm_acls, 782 section, 783 local_commands); 784 785 (void) tlm_log_fhnode(job_stats, dir, name, 786 &tlm_acls->acl_attr, pos); 787 (void) tlm_log_fhpath_name(job_stats, fullname, 788 &tlm_acls->acl_attr, pos); 789 790 free(fullname); 791 free(linkname); 792 free(snapname); 793 return (0); 794 } 795 796 fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 797 798 /* 799 * For hardlink, only read the data if no other link 800 * belonging to the same inode has been backed up. 801 */ 802 if (tlm_acls->acl_attr.st_nlink > 1) { 803 hardlink_done = !hardlink_q_get(hardlink_q, 804 tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL); 805 } 806 807 if (!hardlink_done) { 808 /* 809 * Open the file for reading. 810 */ 811 fd = open(fnamep, O_RDONLY); 812 if (fd == -1) { 813 NDMP_LOG(LOG_DEBUG, 814 "BACKUP> Can't open file [%s] err(%d)", 815 fullname, errno); 816 real_size = -TLM_NO_SOURCE_FILE; 817 goto err_out; 818 } 819 } else { 820 NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %u, pos = %10lld ", 821 tlm_acls->acl_attr.st_ino, hardlink_pos); 822 823 fd = -1; 824 } 825 826 linkname[0] = 0; 827 828 real_size = tlm_acls->acl_attr.st_size; 829 (void) output_acl_header(&tlm_acls->acl_info, 830 local_commands); 831 832 /* 833 * section = 0: file is small enough for TAR 834 * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks 835 * and the file name gets munged 836 */ 837 file_size = real_size; 838 if (file_size > TLM_MAX_TAR_IMAGE) { 839 if (output_humongus_header(fullname, file_size, 840 local_commands) < 0) { 841 (void) close(fd); 842 real_size = -TLM_NO_SCRATCH_SPACE; 843 goto err_out; 844 } 845 section = 1; 846 } else { 847 section = 0; 848 } 849 850 /* 851 * For hardlink, if other link belonging to the same inode 852 * has been backed up, only backup an empty record. 853 */ 854 if (hardlink_done) 855 file_size = 0; 856 857 /* 858 * work 859 */ 860 if (file_size == 0) { 861 (void) output_file_header(fullname, 862 linkname, 863 tlm_acls, 864 section, 865 local_commands); 866 /* 867 * this can fall right through since zero size files 868 * will be skipped by the WHILE loop anyway 869 */ 870 } 871 872 while (file_size > 0) { 873 int section_size = llmin(file_size, 874 (longlong_t)TLM_MAX_TAR_IMAGE); 875 876 tlm_acls->acl_attr.st_size = (longlong_t)section_size; 877 (void) output_file_header(fullname, 878 linkname, 879 tlm_acls, 880 section, 881 local_commands); 882 while (section_size > 0) { 883 char *buf; 884 long actual_size; 885 int read_size; 886 887 /* 888 * check for Abort commands 889 */ 890 if (commands->tcs_reader != TLM_BACKUP_RUN) { 891 local_commands->tc_writer = TLM_ABORT; 892 goto tear_down; 893 } 894 895 local_commands->tc_buffers->tbs_buffer[ 896 local_commands->tc_buffers->tbs_buffer_in]. 897 tb_file_size = section_size; 898 local_commands->tc_buffers->tbs_buffer[ 899 local_commands->tc_buffers->tbs_buffer_in]. 900 tb_seek_spot = seek_spot; 901 902 buf = get_write_buffer(section_size, 903 &actual_size, FALSE, local_commands); 904 if (!buf) 905 goto tear_down; 906 907 /* 908 * check for Abort commands 909 */ 910 if (commands->tcs_reader != TLM_BACKUP_RUN) { 911 local_commands->tc_writer = TLM_ABORT; 912 goto tear_down; 913 } 914 915 read_size = min(section_size, actual_size); 916 actual_size = read(fd, buf, read_size); 917 NS_ADD(rdisk, actual_size); 918 NS_INC(rfile); 919 920 if (actual_size == 0) 921 break; 922 923 if (actual_size == -1) { 924 NDMP_LOG(LOG_DEBUG, 925 "problem(%d) reading file [%s][%s]", 926 errno, fullname, snapname); 927 goto tear_down; 928 } 929 seek_spot += actual_size; 930 file_size -= actual_size; 931 section_size -= actual_size; 932 } 933 section++; 934 } 935 936 /* 937 * If data belonging to this hardlink has been backed up, add the link 938 * to hardlink queue. 939 */ 940 if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) { 941 (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino, 942 pos, NULL, 0); 943 NDMP_LOG(LOG_DEBUG, 944 "backed up hardlink file %s, inode = %u, pos = %10lld ", 945 fullname, tlm_acls->acl_attr.st_ino, pos); 946 } 947 948 /* 949 * For hardlink, if other link belonging to the same inode has been 950 * backed up, send the offset of the data records for that link. 951 */ 952 if (hardlink_done) { 953 (void) tlm_log_fhnode(job_stats, dir, name, 954 &tlm_acls->acl_attr, hardlink_pos); 955 NDMP_LOG(LOG_DEBUG, 956 "backed up hardlink link %s, inode = %u, pos = %10lld ", 957 fullname, tlm_acls->acl_attr.st_ino, hardlink_pos); 958 } else { 959 (void) tlm_log_fhnode(job_stats, dir, name, 960 &tlm_acls->acl_attr, pos); 961 } 962 963 (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr, 964 pos); 965 966 tear_down: 967 local_commands->tc_buffers->tbs_buffer[ 968 local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 969 970 (void) close(fd); 971 972 err_out: 973 free(fullname); 974 free(linkname); 975 free(snapname); 976 return (real_size); 977 } 978 979 /* 980 * tar_putfile 981 * 982 * Main file backup function for tar 983 */ 984 int 985 tar_putfile(char *dir, char *name, char *chkdir, 986 tlm_acls_t *tlm_acls, tlm_commands_t *commands, 987 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats, 988 struct hardlink_q *hardlink_q) 989 { 990 int rv; 991 992 rv = tlm_output_file(dir, name, chkdir, tlm_acls, commands, 993 local_commands, job_stats, hardlink_q); 994 if (rv < 0) 995 return (rv); 996 997 rv = tlm_output_xattr(dir, name, chkdir, tlm_acls, commands, 998 local_commands, job_stats); 999 1000 return (rv < 0 ? rv : 0); 1001 } 1002 1003 /* 1004 * get_write_buffer 1005 * 1006 * a wrapper to tlm_get_write_buffer so that 1007 * we can cleanly detect ABORT commands 1008 * without involving the TLM library with 1009 * our problems. 1010 */ 1011 static char * 1012 get_write_buffer(long size, long *actual_size, 1013 boolean_t zero, tlm_cmd_t *local_commands) 1014 { 1015 while (local_commands->tc_reader == TLM_BACKUP_RUN) { 1016 char *rec = tlm_get_write_buffer(size, actual_size, 1017 local_commands->tc_buffers, zero); 1018 if (rec != 0) { 1019 return (rec); 1020 } 1021 } 1022 return (NULL); 1023 } 1024 1025 #define NDMP_MORE_RECORDS 2 1026 1027 /* 1028 * write_tar_eof 1029 * 1030 * This function is initially written for NDMP support. It appends 1031 * two tar headers to the tar file, and also N more empty buffers 1032 * to make sure that the two tar headers will be read as a part of 1033 * a mover record and don't get locked because of EOM on the mover 1034 * side. 1035 */ 1036 void 1037 write_tar_eof(tlm_cmd_t *local_commands) 1038 { 1039 int i; 1040 long actual_size; 1041 tlm_buffers_t *bufs; 1042 1043 /* 1044 * output 2 zero filled records, 1045 * TAR wants this. 1046 */ 1047 (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 1048 &actual_size, TRUE, local_commands); 1049 (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 1050 &actual_size, TRUE, local_commands); 1051 1052 /* 1053 * NDMP: Clear the rest of the buffer and write two more buffers 1054 * to the tape. 1055 */ 1056 bufs = local_commands->tc_buffers; 1057 (void) get_write_buffer(bufs->tbs_data_transfer_size, 1058 &actual_size, TRUE, local_commands); 1059 1060 for (i = 0; i < NDMP_MORE_RECORDS && 1061 local_commands->tc_reader == TLM_BACKUP_RUN; i++) { 1062 /* 1063 * We don't need the return value of get_write_buffer(), 1064 * since it's already zeroed out if the buffer is returned. 1065 */ 1066 (void) get_write_buffer(bufs->tbs_data_transfer_size, 1067 &actual_size, TRUE, local_commands); 1068 } 1069 1070 bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE; 1071 tlm_buffer_release_in_buf(bufs); 1072 } 1073 1074 /* 1075 * Callback to backup each ZFS property 1076 */ 1077 static int 1078 zfs_put_prop_cb(int prop, void *pp) 1079 { 1080 ndmp_metadata_header_t *mhp; 1081 ndmp_metadata_property_t *mpp; 1082 char buf[ZFS_MAXNAMELEN]; 1083 char sbuf[ZFS_MAXNAMELEN]; 1084 zprop_source_t stype; 1085 1086 if (pp == NULL) 1087 return (ZPROP_INVAL); 1088 1089 mhp = (ndmp_metadata_header_t *)pp; 1090 mpp = &mhp->nh_property[mhp->nh_count++]; 1091 1092 (void) strlcpy(mpp->mp_name, zfs_prop_to_name(prop), NAME_MAX); 1093 (void) zfs_prop_get(mhp->nh_handle, 1094 prop, buf, sizeof (buf), &stype, sbuf, sizeof (sbuf), FALSE); 1095 (void) strlcpy(mpp->mp_value, buf, NAME_MAX); 1096 if (stype == ZPROP_SRC_LOCAL) 1097 (void) strlcpy(mpp->mp_source, mhp->nh_dataset, NAME_MAX); 1098 else 1099 (void) strlcpy(mpp->mp_source, sbuf, NAME_MAX); 1100 1101 return (ZPROP_CONT); 1102 } 1103 1104 1105 /* 1106 * Notifies ndmpd that the metadata associated with the given ZFS dataset 1107 * should be backed up. 1108 */ 1109 int 1110 ndmp_include_zfs(ndmp_context_t *nctx, const char *dataset) 1111 { 1112 tlm_commands_t *cmds; 1113 ndmp_metadata_header_t *mhp; 1114 ndmp_metadata_property_t *mpp; 1115 tlm_cmd_t *lcmd; 1116 long actual_size; 1117 nvlist_t *uprops, *ulist; 1118 const char *pname; 1119 nvpair_t *elp; 1120 char *sval, *ssrc; 1121 char *wbuf, *pp, *tp; 1122 long size, lsize, sz; 1123 int align = RECORDSIZE - 1; 1124 1125 if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 1126 return (-1); 1127 1128 if ((lcmd = cmds->tcs_command) == NULL || 1129 lcmd->tc_buffers == NULL) 1130 return (-1); 1131 1132 size = sizeof (ndmp_metadata_header_t) + 1133 ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 1134 size += align; 1135 size &= ~align; 1136 1137 if ((mhp = malloc(size)) == NULL) 1138 return (-1); 1139 (void) memset(mhp, 0, size); 1140 1141 mhp->nh_plversion = nctx->nc_plversion; 1142 (void) strlcpy(mhp->nh_plname, nctx->nc_plname, 1143 sizeof (mhp->nh_plname)); 1144 (void) strlcpy(mhp->nh_magic, ZFS_META_MAGIC, sizeof (mhp->nh_magic)); 1145 (void) strlcpy(mhp->nh_dataset, dataset, sizeof (mhp->nh_dataset)); 1146 1147 if ((mhp->nh_handle = zfs_open(zlibh, dataset, 1148 ZFS_TYPE_DATASET)) == NULL) { 1149 free(mhp); 1150 return (ZPROP_INVAL); 1151 } 1152 1153 /* Get all the ZFS properties */ 1154 (void) zprop_iter(zfs_put_prop_cb, mhp, TRUE, TRUE, 1155 ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET); 1156 1157 /* Get user properties */ 1158 uprops = zfs_get_user_props(mhp->nh_handle); 1159 1160 elp = nvlist_next_nvpair(uprops, NULL); 1161 1162 while (elp != NULL) { 1163 mpp = &mhp->nh_property[mhp->nh_count]; 1164 if (nvpair_value_nvlist(elp, &ulist) != 0 || 1165 nvlist_lookup_string(ulist, ZPROP_VALUE, &sval) != 0 || 1166 nvlist_lookup_string(ulist, ZPROP_SOURCE, &ssrc) != 0) { 1167 zfs_close(mhp->nh_handle); 1168 free(mhp); 1169 return (-1); 1170 } 1171 if ((pname = nvpair_name(elp)) != NULL) 1172 (void) strlcpy(mpp->mp_name, pname, NAME_MAX); 1173 1174 (void) strlcpy(mpp->mp_value, sval, NAME_MAX); 1175 (void) strlcpy(mpp->mp_source, ssrc, NAME_MAX); 1176 mhp->nh_count++; 1177 elp = nvlist_next_nvpair(uprops, elp); 1178 } 1179 1180 zfs_close(mhp->nh_handle); 1181 1182 if ((wbuf = get_write_buffer(size, &actual_size, TRUE, 1183 lcmd)) != NULL) { 1184 pp = (char *)mhp; 1185 1186 (void) memcpy(wbuf, pp, (actual_size < size) ? 1187 actual_size : size); 1188 pp += (actual_size < size) ? actual_size : size; 1189 1190 sz = actual_size; 1191 while (sz < size && 1192 ((tp = get_write_buffer(size - sz, &lsize, 1193 TRUE, lcmd))) != NULL) { 1194 (void) memcpy(tp, pp, size - sz); 1195 sz += lsize; 1196 pp += lsize; 1197 } 1198 if (sz > size) { 1199 tlm_unget_write_buffer(lcmd->tc_buffers, sz - size); 1200 } 1201 } 1202 1203 free(mhp); 1204 return (0); 1205 } 1206