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 S_ISFIFO(tlm_acls->acl_attr.st_mode)) { 632 return (TLM_NO_SOURCE_FILE); 633 } 634 635 fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 636 if (fullname == NULL) { 637 free(fullname); 638 return (-TLM_NO_SCRATCH_SPACE); 639 } 640 641 if (!tlm_cat_path(fullname, dir, name)) { 642 NDMP_LOG(LOG_DEBUG, "Path too long."); 643 free(fullname); 644 return (-TLM_NO_SCRATCH_SPACE); 645 } 646 647 if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 && 648 sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) { 649 free(fullname); 650 return (0); 651 } 652 653 attrname = ndmp_malloc(TLM_MAX_PATH_NAME); 654 snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 655 if (attrname == NULL || snapname == NULL) { 656 rv = -TLM_NO_SCRATCH_SPACE; 657 goto err_out; 658 } 659 660 if (!tlm_cat_path(snapname, chkdir, name)) { 661 NDMP_LOG(LOG_DEBUG, "Path too long."); 662 rv = -TLM_NO_SCRATCH_SPACE; 663 goto err_out; 664 } 665 666 fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 667 668 /* 669 * Open the file for reading. 670 */ 671 fd = attropen(fnamep, ".", O_RDONLY); 672 if (fd == -1) { 673 NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s][%s]", 674 fullname, fnamep); 675 rv = TLM_NO_SOURCE_FILE; 676 goto err_out; 677 } 678 679 pos = tlm_get_data_offset(local_commands); 680 NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 681 682 section = 0; 683 684 dp = (DIR *)fdopendir(fd); 685 if (dp == NULL) { 686 NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname); 687 (void) close(fd); 688 rv = TLM_NO_SOURCE_FILE; 689 goto err_out; 690 } 691 692 while ((dtp = readdir(dp)) != NULL) { 693 int section_size; 694 695 if (*dtp->d_name == '.') 696 continue; 697 698 if (sysattr_rdonly(dtp->d_name)) 699 continue; 700 701 afd = attropen(fnamep, dtp->d_name, O_RDONLY); 702 if (afd == -1) { 703 NDMP_LOG(LOG_DEBUG, 704 "problem(%d) opening xattr file [%s][%s]", errno, 705 fullname, fnamep); 706 goto tear_down; 707 } 708 709 (void) output_xattr_header(fullname, dtp->d_name, afd, 710 tlm_acls, section, local_commands); 711 (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s", 712 dtp->d_name); 713 (void) output_file_header(attrname, "", tlm_acls, 0, 714 local_commands); 715 716 section_size = (long)llmin(tlm_acls->acl_attr.st_size, 717 (longlong_t)TLM_MAX_TAR_IMAGE); 718 719 /* We only can read upto one section extended attribute */ 720 while (section_size > 0) { 721 char *buf; 722 long actual_size; 723 int read_size; 724 int sysattr_read = 0; 725 char *rec; 726 int size; 727 728 /* 729 * check for Abort commands 730 */ 731 if (commands->tcs_reader != TLM_BACKUP_RUN) { 732 local_commands->tc_writer = TLM_ABORT; 733 goto tear_down; 734 } 735 736 local_commands->tc_buffers->tbs_buffer[ 737 local_commands->tc_buffers->tbs_buffer_in]. 738 tb_file_size = section_size; 739 local_commands->tc_buffers->tbs_buffer[ 740 local_commands->tc_buffers->tbs_buffer_in]. 741 tb_seek_spot = seek_spot; 742 743 buf = get_write_buffer(section_size, 744 &actual_size, FALSE, local_commands); 745 if (!buf) 746 goto tear_down; 747 748 if ((actual_size < section_size) && 749 sysattr_rw(dtp->d_name)) { 750 rec = buf; 751 buf = ndmp_malloc(section_size); 752 if (!buf) 753 goto tear_down; 754 size = actual_size; 755 actual_size = section_size; 756 sysattr_read = 1; 757 } 758 759 /* 760 * check for Abort commands 761 */ 762 if (commands->tcs_reader != TLM_BACKUP_RUN) { 763 local_commands->tc_writer = TLM_ABORT; 764 goto tear_down; 765 } 766 767 read_size = min(section_size, actual_size); 768 if ((actual_size = read(afd, buf, read_size)) < 0) 769 break; 770 771 if (sysattr_read) { 772 if (get_write_one_buf(buf, rec, read_size, 773 size, local_commands) == 0) { 774 free(buf); 775 goto tear_down; 776 } 777 free(buf); 778 } 779 780 781 NS_ADD(rdisk, actual_size); 782 NS_INC(rfile); 783 784 if (actual_size == -1) { 785 NDMP_LOG(LOG_DEBUG, 786 "problem(%d) reading file [%s][%s]", 787 errno, fullname, snapname); 788 goto tear_down; 789 } 790 seek_spot += actual_size; 791 section_size -= actual_size; 792 } 793 (void) close(afd); 794 afd = -1; 795 } 796 797 tear_down: 798 local_commands->tc_buffers->tbs_buffer[ 799 local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 800 801 if (afd > 0) 802 (void) close(afd); 803 804 /* closedir closes fd too */ 805 (void) closedir(dp); 806 807 err_out: 808 free(fullname); 809 free(attrname); 810 free(snapname); 811 return (rv); 812 } 813 814 815 /* 816 * tlm_output_file 817 * 818 * Put this file into the output buffers. 819 */ 820 longlong_t 821 tlm_output_file(char *dir, char *name, char *chkdir, 822 tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands, 823 tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q) 824 { 825 char *fullname; /* directory + name */ 826 char *snapname; /* snapshot name */ 827 char *linkname; /* where this file points */ 828 int section = 0; /* section of a huge file */ 829 int fd; 830 longlong_t real_size; /* the origional file size */ 831 longlong_t file_size; /* real size of this file */ 832 longlong_t seek_spot = 0; /* location in the file */ 833 /* for Multi Volume record */ 834 u_longlong_t pos; 835 char *fnamep; 836 837 /* Indicate whether a file with the same inode has been backed up. */ 838 int hardlink_done = 0; 839 840 /* 841 * If a file with the same inode has been backed up, hardlink_pos holds 842 * the tape offset of the data record. 843 */ 844 u_longlong_t hardlink_pos = 0; 845 846 if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) { 847 NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name); 848 return (-TLM_NO_SCRATCH_SPACE); 849 } 850 851 fullname = ndmp_malloc(TLM_MAX_PATH_NAME); 852 linkname = ndmp_malloc(TLM_MAX_PATH_NAME); 853 snapname = ndmp_malloc(TLM_MAX_PATH_NAME); 854 if (fullname == NULL || linkname == NULL || snapname == NULL) { 855 real_size = -TLM_NO_SCRATCH_SPACE; 856 goto err_out; 857 } 858 if (!tlm_cat_path(fullname, dir, name) || 859 !tlm_cat_path(snapname, chkdir, name)) { 860 NDMP_LOG(LOG_DEBUG, "Path too long."); 861 real_size = -TLM_NO_SCRATCH_SPACE; 862 goto err_out; 863 } 864 865 pos = tlm_get_data_offset(local_commands); 866 NDMP_LOG(LOG_DEBUG, "pos: %10lld [%s]", pos, name); 867 868 if (S_ISLNK(tlm_acls->acl_attr.st_mode) || 869 S_ISFIFO(tlm_acls->acl_attr.st_mode)) { 870 if (S_ISLNK(tlm_acls->acl_attr.st_mode)) { 871 file_size = tlm_readlink(fullname, snapname, linkname, 872 TLM_MAX_PATH_NAME-1); 873 if (file_size < 0) { 874 real_size = -ENOENT; 875 goto err_out; 876 } 877 } 878 879 /* 880 * Since soft links can not be read(2), we should only 881 * backup the file header. 882 */ 883 (void) output_file_header(fullname, 884 linkname, 885 tlm_acls, 886 section, 887 local_commands); 888 889 (void) tlm_log_fhnode(job_stats, dir, name, 890 &tlm_acls->acl_attr, pos); 891 (void) tlm_log_fhpath_name(job_stats, fullname, 892 &tlm_acls->acl_attr, pos); 893 894 free(fullname); 895 free(linkname); 896 free(snapname); 897 return (0); 898 } 899 900 fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname; 901 902 /* 903 * For hardlink, only read the data if no other link 904 * belonging to the same inode has been backed up. 905 */ 906 if (tlm_acls->acl_attr.st_nlink > 1) { 907 hardlink_done = !hardlink_q_get(hardlink_q, 908 tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL); 909 } 910 911 if (!hardlink_done) { 912 /* 913 * Open the file for reading. 914 */ 915 fd = open(fnamep, O_RDONLY); 916 if (fd == -1) { 917 NDMP_LOG(LOG_DEBUG, 918 "BACKUP> Can't open file [%s][%s] err(%d)", 919 fullname, fnamep, errno); 920 real_size = -TLM_NO_SOURCE_FILE; 921 goto err_out; 922 } 923 } else { 924 NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ", 925 tlm_acls->acl_attr.st_ino, hardlink_pos); 926 927 fd = -1; 928 } 929 930 linkname[0] = 0; 931 932 real_size = tlm_acls->acl_attr.st_size; 933 (void) output_acl_header(&tlm_acls->acl_info, 934 local_commands); 935 936 /* 937 * section = 0: file is small enough for TAR 938 * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks 939 * and the file name gets munged 940 */ 941 file_size = real_size; 942 if (file_size > TLM_MAX_TAR_IMAGE) { 943 if (output_humongus_header(fullname, file_size, 944 local_commands) < 0) { 945 (void) close(fd); 946 real_size = -TLM_NO_SCRATCH_SPACE; 947 goto err_out; 948 } 949 section = 1; 950 } else { 951 section = 0; 952 } 953 954 /* 955 * For hardlink, if other link belonging to the same inode 956 * has been backed up, only backup an empty record. 957 */ 958 if (hardlink_done) 959 file_size = 0; 960 961 /* 962 * work 963 */ 964 if (file_size == 0) { 965 (void) output_file_header(fullname, 966 linkname, 967 tlm_acls, 968 section, 969 local_commands); 970 /* 971 * this can fall right through since zero size files 972 * will be skipped by the WHILE loop anyway 973 */ 974 } 975 976 while (file_size > 0) { 977 int section_size = llmin(file_size, 978 (longlong_t)TLM_MAX_TAR_IMAGE); 979 980 tlm_acls->acl_attr.st_size = (longlong_t)section_size; 981 (void) output_file_header(fullname, 982 linkname, 983 tlm_acls, 984 section, 985 local_commands); 986 while (section_size > 0) { 987 char *buf; 988 long actual_size; 989 int read_size; 990 991 /* 992 * check for Abort commands 993 */ 994 if (commands->tcs_reader != TLM_BACKUP_RUN) { 995 local_commands->tc_writer = TLM_ABORT; 996 goto tear_down; 997 } 998 999 local_commands->tc_buffers->tbs_buffer[ 1000 local_commands->tc_buffers->tbs_buffer_in]. 1001 tb_file_size = section_size; 1002 local_commands->tc_buffers->tbs_buffer[ 1003 local_commands->tc_buffers->tbs_buffer_in]. 1004 tb_seek_spot = seek_spot; 1005 1006 buf = get_write_buffer(section_size, 1007 &actual_size, FALSE, local_commands); 1008 if (!buf) 1009 goto tear_down; 1010 1011 /* 1012 * check for Abort commands 1013 */ 1014 if (commands->tcs_reader != TLM_BACKUP_RUN) { 1015 local_commands->tc_writer = TLM_ABORT; 1016 goto tear_down; 1017 } 1018 1019 read_size = min(section_size, actual_size); 1020 actual_size = read(fd, buf, read_size); 1021 NS_ADD(rdisk, actual_size); 1022 NS_INC(rfile); 1023 1024 if (actual_size == 0) 1025 break; 1026 1027 if (actual_size == -1) { 1028 NDMP_LOG(LOG_DEBUG, 1029 "problem(%d) reading file [%s][%s]", 1030 errno, fullname, snapname); 1031 goto tear_down; 1032 } 1033 seek_spot += actual_size; 1034 file_size -= actual_size; 1035 section_size -= actual_size; 1036 } 1037 section++; 1038 } 1039 1040 /* 1041 * If data belonging to this hardlink has been backed up, add the link 1042 * to hardlink queue. 1043 */ 1044 if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) { 1045 (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino, 1046 pos, NULL, 0); 1047 NDMP_LOG(LOG_DEBUG, 1048 "backed up hardlink file %s, inode = %llu, pos = %llu ", 1049 fullname, tlm_acls->acl_attr.st_ino, pos); 1050 } 1051 1052 /* 1053 * For hardlink, if other link belonging to the same inode has been 1054 * backed up, no add_node entry should be sent for this link. 1055 */ 1056 if (hardlink_done) { 1057 NDMP_LOG(LOG_DEBUG, 1058 "backed up hardlink link %s, inode = %llu, pos = %llu ", 1059 fullname, tlm_acls->acl_attr.st_ino, hardlink_pos); 1060 } else { 1061 (void) tlm_log_fhnode(job_stats, dir, name, 1062 &tlm_acls->acl_attr, pos); 1063 } 1064 1065 (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr, 1066 pos); 1067 1068 tear_down: 1069 local_commands->tc_buffers->tbs_buffer[ 1070 local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0; 1071 1072 (void) close(fd); 1073 1074 err_out: 1075 free(fullname); 1076 free(linkname); 1077 free(snapname); 1078 return (real_size); 1079 } 1080 1081 /* 1082 * tar_putfile 1083 * 1084 * Main file backup function for tar 1085 */ 1086 int 1087 tar_putfile(char *dir, char *name, char *chkdir, 1088 tlm_acls_t *tlm_acls, tlm_commands_t *commands, 1089 tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats, 1090 struct hardlink_q *hardlink_q) 1091 { 1092 int rv; 1093 1094 rv = tlm_output_file(dir, name, chkdir, tlm_acls, commands, 1095 local_commands, job_stats, hardlink_q); 1096 if (rv < 0) 1097 return (rv); 1098 1099 rv = tlm_output_xattr(dir, name, chkdir, tlm_acls, commands, 1100 local_commands, job_stats); 1101 1102 return (rv < 0 ? rv : 0); 1103 } 1104 1105 /* 1106 * get_write_buffer 1107 * 1108 * a wrapper to tlm_get_write_buffer so that 1109 * we can cleanly detect ABORT commands 1110 * without involving the TLM library with 1111 * our problems. 1112 */ 1113 static char * 1114 get_write_buffer(long size, long *actual_size, 1115 boolean_t zero, tlm_cmd_t *local_commands) 1116 { 1117 while (local_commands->tc_reader == TLM_BACKUP_RUN) { 1118 char *rec = tlm_get_write_buffer(size, actual_size, 1119 local_commands->tc_buffers, zero); 1120 if (rec != 0) { 1121 return (rec); 1122 } 1123 } 1124 return (NULL); 1125 } 1126 1127 #define NDMP_MORE_RECORDS 2 1128 1129 /* 1130 * write_tar_eof 1131 * 1132 * This function is initially written for NDMP support. It appends 1133 * two tar headers to the tar file, and also N more empty buffers 1134 * to make sure that the two tar headers will be read as a part of 1135 * a mover record and don't get locked because of EOM on the mover 1136 * side. 1137 */ 1138 void 1139 write_tar_eof(tlm_cmd_t *local_commands) 1140 { 1141 int i; 1142 long actual_size; 1143 tlm_buffers_t *bufs; 1144 1145 /* 1146 * output 2 zero filled records, 1147 * TAR wants this. 1148 */ 1149 (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 1150 &actual_size, TRUE, local_commands); 1151 (void) get_write_buffer(sizeof (tlm_tar_hdr_t), 1152 &actual_size, TRUE, local_commands); 1153 1154 /* 1155 * NDMP: Clear the rest of the buffer and write two more buffers 1156 * to the tape. 1157 */ 1158 bufs = local_commands->tc_buffers; 1159 (void) get_write_buffer(bufs->tbs_data_transfer_size, 1160 &actual_size, TRUE, local_commands); 1161 1162 for (i = 0; i < NDMP_MORE_RECORDS && 1163 local_commands->tc_reader == TLM_BACKUP_RUN; i++) { 1164 /* 1165 * We don't need the return value of get_write_buffer(), 1166 * since it's already zeroed out if the buffer is returned. 1167 */ 1168 (void) get_write_buffer(bufs->tbs_data_transfer_size, 1169 &actual_size, TRUE, local_commands); 1170 } 1171 1172 bufs->tbs_buffer[bufs->tbs_buffer_in].tb_full = TRUE; 1173 tlm_buffer_release_in_buf(bufs); 1174 } 1175 1176 /* 1177 * Callback to backup each ZFS property 1178 */ 1179 static int 1180 zfs_put_prop_cb(int prop, void *pp) 1181 { 1182 ndmp_metadata_header_t *mhp; 1183 ndmp_metadata_property_t *mpp; 1184 char buf[ZFS_MAXNAMELEN]; 1185 char sbuf[ZFS_MAXNAMELEN]; 1186 zprop_source_t stype; 1187 char *sourcestr; 1188 1189 if (pp == NULL) 1190 return (ZPROP_INVAL); 1191 1192 mhp = (ndmp_metadata_header_t *)pp; 1193 mpp = &mhp->nh_property[mhp->nh_count++]; 1194 1195 (void) strlcpy(mpp->mp_name, zfs_prop_to_name(prop), NAME_MAX); 1196 (void) zfs_prop_get(mhp->nh_handle, 1197 prop, buf, sizeof (buf), &stype, sbuf, sizeof (sbuf), B_TRUE); 1198 (void) strlcpy(mpp->mp_value, buf, NAME_MAX); 1199 1200 switch (stype) { 1201 case ZPROP_SRC_NONE: 1202 sourcestr = "none"; 1203 break; 1204 case ZPROP_SRC_LOCAL: 1205 sourcestr = mhp->nh_dataset; 1206 break; 1207 case ZPROP_SRC_TEMPORARY: 1208 sourcestr = "temporary"; 1209 break; 1210 case ZPROP_SRC_DEFAULT: 1211 sourcestr = "default"; 1212 break; 1213 default: 1214 sourcestr = sbuf; 1215 break; 1216 } 1217 (void) strlcpy(mpp->mp_source, sourcestr, NAME_MAX); 1218 1219 return (ZPROP_CONT); 1220 } 1221 1222 1223 /* 1224 * Notifies ndmpd that the metadata associated with the given ZFS dataset 1225 * should be backed up. 1226 */ 1227 int 1228 ndmp_include_zfs(ndmp_context_t *nctx, const char *dataset) 1229 { 1230 tlm_commands_t *cmds; 1231 ndmp_metadata_header_t *mhp; 1232 ndmp_metadata_property_t *mpp; 1233 tlm_cmd_t *lcmd; 1234 long actual_size; 1235 nvlist_t *uprops, *ulist; 1236 const char *pname; 1237 nvpair_t *elp; 1238 char *sval, *ssrc; 1239 char *wbuf, *pp, *tp; 1240 long size, lsize, sz; 1241 int align = RECORDSIZE - 1; 1242 1243 if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL) 1244 return (-1); 1245 1246 if ((lcmd = cmds->tcs_command) == NULL || 1247 lcmd->tc_buffers == NULL) 1248 return (-1); 1249 1250 size = sizeof (ndmp_metadata_header_t) + 1251 ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t); 1252 size += align; 1253 size &= ~align; 1254 1255 if ((mhp = malloc(size)) == NULL) 1256 return (-1); 1257 (void) memset(mhp, 0, size); 1258 1259 mhp->nh_plversion = nctx->nc_plversion; 1260 (void) strlcpy(mhp->nh_plname, nctx->nc_plname, 1261 sizeof (mhp->nh_plname)); 1262 (void) strlcpy(mhp->nh_magic, ZFS_META_MAGIC, sizeof (mhp->nh_magic)); 1263 (void) strlcpy(mhp->nh_dataset, dataset, sizeof (mhp->nh_dataset)); 1264 1265 if ((mhp->nh_handle = zfs_open(zlibh, dataset, 1266 ZFS_TYPE_DATASET)) == NULL) { 1267 free(mhp); 1268 return (ZPROP_INVAL); 1269 } 1270 1271 /* Get all the ZFS properties */ 1272 (void) zprop_iter(zfs_put_prop_cb, mhp, TRUE, TRUE, 1273 ZFS_TYPE_VOLUME | ZFS_TYPE_DATASET); 1274 1275 /* Get user properties */ 1276 uprops = zfs_get_user_props(mhp->nh_handle); 1277 1278 elp = nvlist_next_nvpair(uprops, NULL); 1279 1280 while (elp != NULL) { 1281 mpp = &mhp->nh_property[mhp->nh_count]; 1282 if (nvpair_value_nvlist(elp, &ulist) != 0 || 1283 nvlist_lookup_string(ulist, ZPROP_VALUE, &sval) != 0 || 1284 nvlist_lookup_string(ulist, ZPROP_SOURCE, &ssrc) != 0) { 1285 zfs_close(mhp->nh_handle); 1286 free(mhp); 1287 return (-1); 1288 } 1289 if ((pname = nvpair_name(elp)) != NULL) 1290 (void) strlcpy(mpp->mp_name, pname, NAME_MAX); 1291 1292 (void) strlcpy(mpp->mp_value, sval, NAME_MAX); 1293 (void) strlcpy(mpp->mp_source, ssrc, NAME_MAX); 1294 mhp->nh_count++; 1295 elp = nvlist_next_nvpair(uprops, elp); 1296 } 1297 1298 zfs_close(mhp->nh_handle); 1299 1300 if ((wbuf = get_write_buffer(size, &actual_size, TRUE, 1301 lcmd)) != NULL) { 1302 pp = (char *)mhp; 1303 1304 (void) memcpy(wbuf, pp, (actual_size < size) ? 1305 actual_size : size); 1306 pp += (actual_size < size) ? actual_size : size; 1307 1308 sz = actual_size; 1309 while (sz < size && 1310 ((tp = get_write_buffer(size - sz, &lsize, 1311 TRUE, lcmd))) != NULL) { 1312 (void) memcpy(tp, pp, size - sz); 1313 sz += lsize; 1314 pp += lsize; 1315 } 1316 if (sz > size) { 1317 tlm_unget_write_buffer(lcmd->tc_buffers, sz - size); 1318 } 1319 } 1320 1321 free(mhp); 1322 return (0); 1323 } 1324