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