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