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 <sys/mkdev.h>
  50 #include <libzfs.h>
  51 #include <libcmdutils.h>
  52 #include <pwd.h>
  53 #include <grp.h>
  54 #include "tlm_proto.h"
  55 
  56 
  57 static char *get_write_buffer(long size,
  58     long *actual_size,
 
 
  98                 mem += rec_size;
  99                 len -= rec_size;
 100         }
 101 }
 102 
 103 /*
 104  * tlm_output_dir
 105  *
 106  * Put the directory information into the output buffers.
 107  */
 108 int
 109 tlm_output_dir(char *name, tlm_acls_t *tlm_acls,
 110     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
 111 {
 112         u_longlong_t pos;
 113 
 114         /*
 115          * Send the node or path history of the directory itself.
 116          */
 117         pos = tlm_get_data_offset(local_commands);
 118         NDMP_LOG(LOG_DEBUG, "pos: %10lld  [%s]", pos, name);
 119         (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos);
 120         (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos);
 121         /* fhdir_cb is handled in ndmpd_tar3.c */
 122 
 123         (void) output_acl_header(&tlm_acls->acl_info,
 124             local_commands);
 125         (void) output_file_header(name, "", tlm_acls, 0,
 126             local_commands);
 127 
 128         return (0);
 129 }
 130 
 131 /*
 132  * tar_putdir
 133  *
 134  * Main dir backup function for tar
 135  */
 136 int
 137 tar_putdir(char *name, tlm_acls_t *tlm_acls,
 138     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
 
 240  * output the TAR header record for extended attributes
 241  */
 242 static int
 243 output_xattr_header(char *fname, char *aname, int fd,
 244     tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands)
 245 {
 246         struct stat64 *attr = &tlm_acls->acl_attr;
 247         struct xattr_hdr *xhdr;
 248         struct xattr_buf *xbuf;
 249         tlm_tar_hdr_t *tar_hdr;
 250         long    actual_size;
 251         char    *section_name = ndmp_malloc(TLM_MAX_PATH_NAME);
 252         int     hsize;
 253         int     comlen;
 254         int     namesz;
 255 
 256         if (section_name == NULL)
 257                 return (-TLM_NO_SCRATCH_SPACE);
 258 
 259         if (fstat64(fd, attr) == -1) {
 260                 NDMP_LOG(LOG_DEBUG, "output_file_header stat failed.");
 261                 free(section_name);
 262                 return (-TLM_OPEN_ERR);
 263         }
 264 
 265         /*
 266          * if the file has to go out in sections,
 267          * we must mung the name.
 268          */
 269         if (section == 0) {
 270                 (void) snprintf(section_name, TLM_MAX_PATH_NAME,
 271                     "/dev/null/%s.hdr", aname);
 272         } else {
 273                 (void) snprintf(section_name,
 274                     TLM_MAX_PATH_NAME, "%s.%03d", aname, section);
 275         }
 276         namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */
 277         hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf);
 278         comlen = namesz + sizeof (struct xattr_buf);
 279 
 280         tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
 
 283                 free(section_name);
 284                 return (0);
 285         }
 286 
 287         (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
 288 
 289         tar_hdr->th_linkflag = LF_XATTR;
 290         (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
 291             hsize);
 292         (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
 293             attr->st_mode & 07777);
 294         (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
 295             attr->st_uid);
 296         (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
 297             attr->st_gid);
 298         (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
 299             attr->st_mtime);
 300         (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
 301             sizeof (tar_hdr->th_magic));
 302 
 303         NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d",
 304             aname, hsize, attr->st_mode & 07777, attr->st_uid, attr->st_gid);
 305 
 306         tlm_build_header_checksum(tar_hdr);
 307 
 308         xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE,
 309             &actual_size, TRUE, local_commands);
 310         if (!xhdr) {
 311                 free(section_name);
 312                 return (0);
 313         }
 314 
 315         (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s",
 316             XATTR_ARCH_VERS);
 317         (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d",
 318             sizeof (xhdr->h_size) - 1, hsize);
 319         (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len),
 320             "%0*d", sizeof (xhdr->h_component_len) - 1, comlen);
 321         (void) snprintf(xhdr->h_link_component_len,
 322             sizeof (xhdr->h_link_component_len), "%0*d",
 323             sizeof (xhdr->h_link_component_len) - 1, 0);
 324 
 325         xbuf = (struct xattr_buf *)(((caddr_t)xhdr) +
 
 471                 (void) output_mem(local_commands, (void *)link,
 472                     lnklen);
 473                 long_link = TRUE;
 474         }
 475         tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
 476             &actual_size, TRUE, local_commands);
 477         if (!tar_hdr) {
 478                 free(section_name);
 479                 return (0);
 480         }
 481         if (long_name) {
 482                 (void) snprintf(tar_hdr->th_name,
 483                     sizeof (tar_hdr->th_name),
 484                     "%s%08qd.fil",
 485                     LONGNAME_PREFIX,
 486                     file_count++);
 487         } else {
 488                 (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
 489         }
 490 
 491         NDMP_LOG(LOG_DEBUG, "long_link: %s [%s]", long_link ? "TRUE" : "FALSE",
 492             link);
 493 
 494         if (long_link) {
 495                 (void) snprintf(tar_hdr->th_linkname,
 496                     sizeof (tar_hdr->th_name),
 497                     "%s%08qd.slk",
 498                     LONGNAME_PREFIX,
 499                     file_count++);
 500         } else {
 501                 (void) strlcpy(tar_hdr->th_linkname, link, TLM_NAME_SIZE);
 502         }
 503         switch (attr->st_mode & S_IFMT) {
 504         case S_IFDIR:
 505                 tar_hdr->th_linkflag = LF_DIR;
 506                 break;
 507         case S_IFIFO:
 508                 tar_hdr->th_linkflag = LF_FIFO;
 509                 break;
 510         case S_IFBLK:
 511         case S_IFCHR:
 512                 if (S_ISBLK(attr->st_mode))
 513                         tar_hdr->th_linkflag = LF_BLK;
 514                 else
 515                         tar_hdr->th_linkflag = LF_CHR;
 516                 (void) snprintf(tar_hdr->th_shared.th_dev.th_devmajor,
 517                     sizeof (tar_hdr->th_shared.th_dev.th_devmajor), "%06o ",
 518                     major(attr->st_rdev));
 519                 (void) snprintf(tar_hdr->th_shared.th_dev.th_devminor,
 520                     sizeof (tar_hdr->th_shared.th_dev.th_devminor), "%06o ",
 521                     minor(attr->st_rdev));
 522                 break;
 523         default:
 524                 if (attr->st_nlink > 1) {
 525                         /* mark file with hardlink LF_LINK */
 526                         tar_hdr->th_linkflag = LF_LINK;
 527                         (void) snprintf(tar_hdr->th_shared.th_hlink_ino,
 528                             sizeof (tar_hdr->th_shared.th_hlink_ino),
 529                             "%011llo ", attr->st_ino);
 530                 } else {
 531                         tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL :
 532                             LF_SYMLINK;
 533                         NDMP_LOG(LOG_DEBUG, "linkflag: '%c'",
 534                             tar_hdr->th_linkflag);
 535                 }
 536         }
 537         (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
 538             (long)attr->st_size);
 539         (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
 540             attr->st_mode & 07777);
 541         (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
 542             uid);
 543         (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
 544             gid);
 545         (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), "%.31s",
 546             uname);
 547         (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), "%.31s",
 548             gname);
 549         (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
 550             attr->st_mtime);
 551         (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
 552             sizeof (tar_hdr->th_magic));
 553 
 554         tlm_build_header_checksum(tar_hdr);
 
 563 
 564 
 565 /*
 566  * tlm_readlink
 567  *
 568  * Read where the softlink points to.  Read the link in the checkpointed
 569  * path if the backup is being done on a checkpointed file system.
 570  */
 571 static int
 572 tlm_readlink(char *nm, char *snap, char *buf, int bufsize)
 573 {
 574         int len;
 575 
 576         if ((len = readlink(snap, buf, bufsize)) >= 0) {
 577                 /*
 578                  * realink(2) doesn't null terminate the link name.  We must
 579                  * do it here.
 580                  */
 581                 buf[len] = '\0';
 582         } else {
 583                 NDMP_LOG(LOG_DEBUG, "Error %d reading softlink of [%s]",
 584                     errno, nm);
 585                 buf[0] = '\0';
 586 
 587                 /* Backup the link if the destination missing */
 588                 if (errno == ENOENT)
 589                         return (0);
 590 
 591         }
 592 
 593         return (len);
 594 }
 595 
 596 /*
 597  * Read the system attribute file in a single buffer to write
 598  * it as a single write. A partial write to system attribute would
 599  * cause an EINVAL on write.
 600  */
 601 static char *
 602 get_write_one_buf(char *buf, char *rec, int buf_size, int rec_size,
 603     tlm_cmd_t *lc)
 
 627 
 628 
 629 /*
 630  * tlm_output_xattr
 631  *
 632  * Put this file into the output buffers.
 633  */
 634 /*ARGSUSED*/
 635 longlong_t
 636 tlm_output_xattr(char  *dir, char *name, char *chkdir,
 637     tlm_acls_t *tlm_acls, tlm_commands_t *commands,
 638     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
 639 {
 640         char    *fullname;              /* directory + name */
 641         char    *snapname;              /* snapshot name */
 642         int     section;                /* section of a huge file */
 643         int     fd;
 644         int     afd = 0;
 645         longlong_t seek_spot = 0;       /* location in the file */
 646                                         /* for Multi Volume record */
 647         u_longlong_t pos;
 648         DIR *dp;
 649         struct dirent *dtp;
 650         char *attrname;
 651         char *fnamep;
 652         int rv = 0;
 653 
 654         if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
 655                 return (TLM_NO_SOURCE_FILE);
 656         }
 657 
 658         fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
 659         if (fullname == NULL) {
 660                 free(fullname);
 661                 return (-TLM_NO_SCRATCH_SPACE);
 662         }
 663 
 664         if (!tlm_cat_path(fullname, dir, name)) {
 665                 NDMP_LOG(LOG_DEBUG, "Path too long.");
 666                 free(fullname);
 667                 return (-TLM_NO_SCRATCH_SPACE);
 668         }
 669 
 670         if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 &&
 671             sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) {
 672                 free(fullname);
 673                 return (0);
 674         }
 675 
 676         attrname = ndmp_malloc(TLM_MAX_PATH_NAME);
 677         snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
 678         if (attrname == NULL || snapname == NULL) {
 679                 rv = -TLM_NO_SCRATCH_SPACE;
 680                 goto err_out;
 681         }
 682 
 683         if (!tlm_cat_path(snapname, chkdir, name)) {
 684                 NDMP_LOG(LOG_DEBUG, "Path too long.");
 685                 rv = -TLM_NO_SCRATCH_SPACE;
 686                 goto err_out;
 687         }
 688 
 689         fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
 690 
 691         /*
 692          * Open the file for reading.
 693          */
 694         fd = attropen(fnamep, ".", O_RDONLY);
 695         if (fd == -1) {
 696                 NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s][%s]",
 697                     fullname, fnamep);
 698                 rv = TLM_NO_SOURCE_FILE;
 699                 goto err_out;
 700         }
 701 
 702         pos = tlm_get_data_offset(local_commands);
 703         NDMP_LOG(LOG_DEBUG, "pos: %10lld  [%s]", pos, name);
 704 
 705         section = 0;
 706 
 707         dp = (DIR *)fdopendir(fd);
 708         if (dp == NULL) {
 709                 NDMP_LOG(LOG_DEBUG, "BACKUP> Can't open file [%s]", fullname);
 710                 (void) close(fd);
 711                 rv = TLM_NO_SOURCE_FILE;
 712                 goto err_out;
 713         }
 714 
 715         while ((dtp = readdir(dp)) != NULL) {
 716                 int section_size;
 717 
 718                 if (*dtp->d_name == '.')
 719                         continue;
 720 
 721                 if (sysattr_rdonly(dtp->d_name))
 722                         continue;
 723 
 724                 afd = attropen(fnamep, dtp->d_name, O_RDONLY);
 725                 if (afd == -1) {
 726                         NDMP_LOG(LOG_DEBUG,
 727                             "problem(%d) opening xattr file [%s][%s]", errno,
 728                             fullname, fnamep);
 729                         goto tear_down;
 730                 }
 731 
 732                 (void) output_xattr_header(fullname, dtp->d_name, afd,
 733                     tlm_acls, section, local_commands);
 734                 (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s",
 735                     dtp->d_name);
 736                 (void) output_file_header(attrname, "", tlm_acls, 0,
 737                     local_commands);
 738 
 739                 section_size = (long)llmin(tlm_acls->acl_attr.st_size,
 740                     (longlong_t)TLM_MAX_TAR_IMAGE);
 741 
 742                 /* We only can read upto one section extended attribute */
 743                 while (section_size > 0) {
 744                         char    *buf;
 745                         long    actual_size;
 746                         int     read_size;
 747                         int sysattr_read = 0;
 748                         char *rec;
 749                         int size;
 750 
 751                         /*
 752                          * check for Abort commands
 753                          */
 754                         if (commands->tcs_reader != TLM_BACKUP_RUN) {
 755                                 local_commands->tc_writer = TLM_ABORT;
 756                                 goto tear_down;
 757                         }
 758 
 759                         local_commands->tc_buffers->tbs_buffer[
 760                             local_commands->tc_buffers->tbs_buffer_in].
 761                             tb_file_size = section_size;
 762                         local_commands->tc_buffers->tbs_buffer[
 763                             local_commands->tc_buffers->tbs_buffer_in].
 764                             tb_seek_spot = seek_spot;
 765 
 766                         buf = get_write_buffer(section_size,
 767                             &actual_size, FALSE, local_commands);
 768                         if (!buf)
 769                                 goto tear_down;
 
 788                         }
 789 
 790                         read_size = min(section_size, actual_size);
 791                         if ((actual_size = read(afd, buf, read_size)) < 0)
 792                                 break;
 793 
 794                         if (sysattr_read) {
 795                                 if (get_write_one_buf(buf, rec, read_size,
 796                                     size, local_commands) == 0) {
 797                                         free(buf);
 798                                         goto tear_down;
 799                                 }
 800                                 free(buf);
 801                         }
 802 
 803 
 804                         NS_ADD(rdisk, actual_size);
 805                         NS_INC(rfile);
 806 
 807                         if (actual_size == -1) {
 808                                 NDMP_LOG(LOG_DEBUG,
 809                                     "problem(%d) reading file [%s][%s]",
 810                                     errno, fullname, snapname);
 811                                 goto tear_down;
 812                         }
 813                         seek_spot += actual_size;
 814                         section_size -= actual_size;
 815                 }
 816                 (void) close(afd);
 817                 afd = -1;
 818         }
 819 
 820 tear_down:
 821         local_commands->tc_buffers->tbs_buffer[
 822             local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
 823 
 824         if (afd > 0)
 825                 (void) close(afd);
 826 
 827         /* closedir closes fd too */
 828         (void) closedir(dp);
 
 850         char    *linkname;              /* where this file points */
 851         int     section = 0;            /* section of a huge file */
 852         int     fd;
 853         longlong_t real_size;           /* the origional file size */
 854         longlong_t file_size;           /* real size of this file */
 855         longlong_t seek_spot = 0;       /* location in the file */
 856                                         /* for Multi Volume record */
 857         u_longlong_t pos;
 858         char *fnamep;
 859 
 860         /* Indicate whether a file with the same inode has been backed up. */
 861         int hardlink_done = 0;
 862 
 863         /*
 864          * If a file with the same inode has been backed up, hardlink_pos holds
 865          * the tape offset of the data record.
 866          */
 867         u_longlong_t hardlink_pos = 0;
 868 
 869         if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) {
 870                 NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]", dir, name);
 871                 return (-TLM_NO_SCRATCH_SPACE);
 872         }
 873 
 874         fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
 875         linkname = ndmp_malloc(TLM_MAX_PATH_NAME);
 876         snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
 877         if (fullname == NULL || linkname == NULL || snapname == NULL) {
 878                 real_size = -TLM_NO_SCRATCH_SPACE;
 879                 goto err_out;
 880         }
 881         if (!tlm_cat_path(fullname, dir, name) ||
 882             !tlm_cat_path(snapname, chkdir, name)) {
 883                 NDMP_LOG(LOG_DEBUG, "Path too long.");
 884                 real_size = -TLM_NO_SCRATCH_SPACE;
 885                 goto err_out;
 886         }
 887 
 888         pos = tlm_get_data_offset(local_commands);
 889         NDMP_LOG(LOG_DEBUG, "pos: %10lld  [%s]", pos, name);
 890 
 891         if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
 892                 if (S_ISLNK(tlm_acls->acl_attr.st_mode)) {
 893                         file_size = tlm_readlink(fullname, snapname, linkname,
 894                             TLM_MAX_PATH_NAME-1);
 895                         if (file_size < 0) {
 896                                 real_size = -ENOENT;
 897                                 goto err_out;
 898                         }
 899                 }
 900 
 901                 /*
 902                  * Since soft links can not be read(2), we should only
 903                  * backup the file header.
 904                  */
 905                 (void) output_file_header(fullname,
 906                     linkname,
 907                     tlm_acls,
 908                     section,
 909                     local_commands);
 
 919                 return (0);
 920         }
 921 
 922         fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
 923 
 924         /*
 925          * For hardlink, only read the data if no other link
 926          * belonging to the same inode has been backed up.
 927          */
 928         if (tlm_acls->acl_attr.st_nlink > 1) {
 929                 hardlink_done = !hardlink_q_get(hardlink_q,
 930                     tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL);
 931         }
 932 
 933         if (!hardlink_done) {
 934                 /*
 935                  * Open the file for reading.
 936                  */
 937                 fd = open(fnamep, O_RDONLY);
 938                 if (fd == -1) {
 939                         NDMP_LOG(LOG_DEBUG,
 940                             "BACKUP> Can't open file [%s][%s] err(%d)",
 941                             fullname, fnamep, errno);
 942                         real_size = -TLM_NO_SOURCE_FILE;
 943                         goto err_out;
 944                 }
 945         } else {
 946                 NDMP_LOG(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ",
 947                     tlm_acls->acl_attr.st_ino, hardlink_pos);
 948 
 949                 fd = -1;
 950         }
 951 
 952         linkname[0] = 0;
 953 
 954         real_size = tlm_acls->acl_attr.st_size;
 955         (void) output_acl_header(&tlm_acls->acl_info,
 956             local_commands);
 957 
 958         /*
 959          * section = 0: file is small enough for TAR
 960          * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks
 961          *              and the file name gets munged
 962          */
 963         file_size = real_size;
 964         if (file_size > TLM_MAX_TAR_IMAGE) {
 965                 if (output_humongus_header(fullname, file_size,
 966                     local_commands) < 0) {
 
1030                         if (!buf)
1031                                 goto tear_down;
1032 
1033                         /*
1034                          * check for Abort commands
1035                          */
1036                         if (commands->tcs_reader != TLM_BACKUP_RUN) {
1037                                 local_commands->tc_writer = TLM_ABORT;
1038                                 goto tear_down;
1039                         }
1040 
1041                         read_size = min(section_size, actual_size);
1042                         actual_size = read(fd, buf, read_size);
1043                         NS_ADD(rdisk, actual_size);
1044                         NS_INC(rfile);
1045 
1046                         if (actual_size == 0)
1047                                 break;
1048 
1049                         if (actual_size == -1) {
1050                                 NDMP_LOG(LOG_DEBUG,
1051                                     "problem(%d) reading file [%s][%s]",
1052                                     errno, fullname, snapname);
1053                                 goto tear_down;
1054                         }
1055                         seek_spot += actual_size;
1056                         file_size -= actual_size;
1057                         section_size -= actual_size;
1058                 }
1059                 section++;
1060         }
1061 
1062         /*
1063          * If data belonging to this hardlink has been backed up, add the link
1064          * to hardlink queue.
1065          */
1066         if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) {
1067                 (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino,
1068                     pos, NULL, 0);
1069                 NDMP_LOG(LOG_DEBUG,
1070                     "backed up hardlink file %s, inode = %llu, pos = %llu ",
1071                     fullname, tlm_acls->acl_attr.st_ino, pos);
1072         }
1073 
1074         /*
1075          * For hardlink, if other link belonging to the same inode has been
1076          * backed up, no add_node entry should be sent for this link.
1077          */
1078         if (hardlink_done) {
1079                 NDMP_LOG(LOG_DEBUG,
1080                     "backed up hardlink link %s, inode = %llu, pos = %llu ",
1081                     fullname, tlm_acls->acl_attr.st_ino, hardlink_pos);
1082         } else {
1083                 (void) tlm_log_fhnode(job_stats, dir, name,
1084                     &tlm_acls->acl_attr, pos);
1085         }
1086 
1087         (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr,
1088             pos);
1089 
1090 tear_down:
1091         local_commands->tc_buffers->tbs_buffer[
1092             local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
1093 
1094         (void) close(fd);
1095 
1096 err_out:
1097         free(fullname);
1098         free(linkname);
1099         free(snapname);
 
 | 
 
 
  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 /* Copyright 2017 Nexenta Systems, Inc. All rights reserved. */
  40 
  41 #include <syslog.h>
  42 #include <stdio.h>
  43 #include <limits.h>
  44 #include <time.h>
  45 #include <sys/stat.h>
  46 #include <unistd.h>
  47 #include <dirent.h>
  48 #include <pthread.h>
  49 #include <archives.h>
  50 #include <tlm.h>
  51 #include <sys/fs/zfs.h>
  52 #include <sys/mkdev.h>
  53 #include <libzfs.h>
  54 #include <libcmdutils.h>
  55 #include <pwd.h>
  56 #include <grp.h>
  57 #include "tlm_proto.h"
  58 
  59 
  60 static char *get_write_buffer(long size,
  61     long *actual_size,
 
 
 101                 mem += rec_size;
 102                 len -= rec_size;
 103         }
 104 }
 105 
 106 /*
 107  * tlm_output_dir
 108  *
 109  * Put the directory information into the output buffers.
 110  */
 111 int
 112 tlm_output_dir(char *name, tlm_acls_t *tlm_acls,
 113     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
 114 {
 115         u_longlong_t pos;
 116 
 117         /*
 118          * Send the node or path history of the directory itself.
 119          */
 120         pos = tlm_get_data_offset(local_commands);
 121         (void) tlm_log_fhnode(job_stats, name, "", &tlm_acls->acl_attr, pos);
 122         (void) tlm_log_fhpath_name(job_stats, name, &tlm_acls->acl_attr, pos);
 123         /* fhdir_cb is handled in ndmpd_tar3.c */
 124 
 125         (void) output_acl_header(&tlm_acls->acl_info,
 126             local_commands);
 127         (void) output_file_header(name, "", tlm_acls, 0,
 128             local_commands);
 129 
 130         return (0);
 131 }
 132 
 133 /*
 134  * tar_putdir
 135  *
 136  * Main dir backup function for tar
 137  */
 138 int
 139 tar_putdir(char *name, tlm_acls_t *tlm_acls,
 140     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
 
 242  * output the TAR header record for extended attributes
 243  */
 244 static int
 245 output_xattr_header(char *fname, char *aname, int fd,
 246     tlm_acls_t *tlm_acls, int section, tlm_cmd_t *local_commands)
 247 {
 248         struct stat64 *attr = &tlm_acls->acl_attr;
 249         struct xattr_hdr *xhdr;
 250         struct xattr_buf *xbuf;
 251         tlm_tar_hdr_t *tar_hdr;
 252         long    actual_size;
 253         char    *section_name = ndmp_malloc(TLM_MAX_PATH_NAME);
 254         int     hsize;
 255         int     comlen;
 256         int     namesz;
 257 
 258         if (section_name == NULL)
 259                 return (-TLM_NO_SCRATCH_SPACE);
 260 
 261         if (fstat64(fd, attr) == -1) {
 262                 syslog(LOG_ERR, "output_file_header stat failed.");
 263                 free(section_name);
 264                 return (-TLM_OPEN_ERR);
 265         }
 266 
 267         /*
 268          * if the file has to go out in sections,
 269          * we must mung the name.
 270          */
 271         if (section == 0) {
 272                 (void) snprintf(section_name, TLM_MAX_PATH_NAME,
 273                     "/dev/null/%s.hdr", aname);
 274         } else {
 275                 (void) snprintf(section_name,
 276                     TLM_MAX_PATH_NAME, "%s.%03d", aname, section);
 277         }
 278         namesz = strlen(section_name) + strlen(fname) + 2; /* 2 nulls */
 279         hsize = namesz + sizeof (struct xattr_hdr) + sizeof (struct xattr_buf);
 280         comlen = namesz + sizeof (struct xattr_buf);
 281 
 282         tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
 
 285                 free(section_name);
 286                 return (0);
 287         }
 288 
 289         (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
 290 
 291         tar_hdr->th_linkflag = LF_XATTR;
 292         (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
 293             hsize);
 294         (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
 295             attr->st_mode & 07777);
 296         (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
 297             attr->st_uid);
 298         (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
 299             attr->st_gid);
 300         (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
 301             attr->st_mtime);
 302         (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
 303             sizeof (tar_hdr->th_magic));
 304 
 305         tlm_build_header_checksum(tar_hdr);
 306 
 307         xhdr = (struct xattr_hdr *)get_write_buffer(RECORDSIZE,
 308             &actual_size, TRUE, local_commands);
 309         if (!xhdr) {
 310                 free(section_name);
 311                 return (0);
 312         }
 313 
 314         (void) snprintf(xhdr->h_version, sizeof (xhdr->h_version), "%s",
 315             XATTR_ARCH_VERS);
 316         (void) snprintf(xhdr->h_size, sizeof (xhdr->h_size), "%0*d",
 317             sizeof (xhdr->h_size) - 1, hsize);
 318         (void) snprintf(xhdr->h_component_len, sizeof (xhdr->h_component_len),
 319             "%0*d", sizeof (xhdr->h_component_len) - 1, comlen);
 320         (void) snprintf(xhdr->h_link_component_len,
 321             sizeof (xhdr->h_link_component_len), "%0*d",
 322             sizeof (xhdr->h_link_component_len) - 1, 0);
 323 
 324         xbuf = (struct xattr_buf *)(((caddr_t)xhdr) +
 
 470                 (void) output_mem(local_commands, (void *)link,
 471                     lnklen);
 472                 long_link = TRUE;
 473         }
 474         tar_hdr = (tlm_tar_hdr_t *)get_write_buffer(RECORDSIZE,
 475             &actual_size, TRUE, local_commands);
 476         if (!tar_hdr) {
 477                 free(section_name);
 478                 return (0);
 479         }
 480         if (long_name) {
 481                 (void) snprintf(tar_hdr->th_name,
 482                     sizeof (tar_hdr->th_name),
 483                     "%s%08qd.fil",
 484                     LONGNAME_PREFIX,
 485                     file_count++);
 486         } else {
 487                 (void) strlcpy(tar_hdr->th_name, section_name, TLM_NAME_SIZE);
 488         }
 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         switch (attr->st_mode & S_IFMT) {
 500         case S_IFDIR:
 501                 tar_hdr->th_linkflag = LF_DIR;
 502                 break;
 503         case S_IFIFO:
 504                 tar_hdr->th_linkflag = LF_FIFO;
 505                 break;
 506         case S_IFBLK:
 507         case S_IFCHR:
 508                 if (S_ISBLK(attr->st_mode))
 509                         tar_hdr->th_linkflag = LF_BLK;
 510                 else
 511                         tar_hdr->th_linkflag = LF_CHR;
 512                 (void) snprintf(tar_hdr->th_shared.th_dev.th_devmajor,
 513                     sizeof (tar_hdr->th_shared.th_dev.th_devmajor), "%06o ",
 514                     major(attr->st_rdev));
 515                 (void) snprintf(tar_hdr->th_shared.th_dev.th_devminor,
 516                     sizeof (tar_hdr->th_shared.th_dev.th_devminor), "%06o ",
 517                     minor(attr->st_rdev));
 518                 break;
 519         default:
 520                 if (attr->st_nlink > 1) {
 521                         /* mark file with hardlink LF_LINK */
 522                         tar_hdr->th_linkflag = LF_LINK;
 523                         (void) snprintf(tar_hdr->th_shared.th_hlink_ino,
 524                             sizeof (tar_hdr->th_shared.th_hlink_ino),
 525                             "%011llo ", attr->st_ino);
 526                 } else {
 527                         tar_hdr->th_linkflag = *link == 0 ? LF_NORMAL :
 528                             LF_SYMLINK;
 529                 }
 530         }
 531         (void) snprintf(tar_hdr->th_size, sizeof (tar_hdr->th_size), "%011o ",
 532             (long)attr->st_size);
 533         (void) snprintf(tar_hdr->th_mode, sizeof (tar_hdr->th_mode), "%06o ",
 534             attr->st_mode & 07777);
 535         (void) snprintf(tar_hdr->th_uid, sizeof (tar_hdr->th_uid), "%06o ",
 536             uid);
 537         (void) snprintf(tar_hdr->th_gid, sizeof (tar_hdr->th_gid), "%06o ",
 538             gid);
 539         (void) snprintf(tar_hdr->th_uname, sizeof (tar_hdr->th_uname), "%.31s",
 540             uname);
 541         (void) snprintf(tar_hdr->th_gname, sizeof (tar_hdr->th_gname), "%.31s",
 542             gname);
 543         (void) snprintf(tar_hdr->th_mtime, sizeof (tar_hdr->th_mtime), "%011o ",
 544             attr->st_mtime);
 545         (void) strlcpy(tar_hdr->th_magic, TLM_MAGIC,
 546             sizeof (tar_hdr->th_magic));
 547 
 548         tlm_build_header_checksum(tar_hdr);
 
 557 
 558 
 559 /*
 560  * tlm_readlink
 561  *
 562  * Read where the softlink points to.  Read the link in the checkpointed
 563  * path if the backup is being done on a checkpointed file system.
 564  */
 565 static int
 566 tlm_readlink(char *nm, char *snap, char *buf, int bufsize)
 567 {
 568         int len;
 569 
 570         if ((len = readlink(snap, buf, bufsize)) >= 0) {
 571                 /*
 572                  * realink(2) doesn't null terminate the link name.  We must
 573                  * do it here.
 574                  */
 575                 buf[len] = '\0';
 576         } else {
 577                 syslog(LOG_ERR, "Error %d reading softlink of [%s]",
 578                     errno, nm);
 579                 buf[0] = '\0';
 580 
 581                 /* Backup the link if the destination missing */
 582                 if (errno == ENOENT)
 583                         return (0);
 584 
 585         }
 586 
 587         return (len);
 588 }
 589 
 590 /*
 591  * Read the system attribute file in a single buffer to write
 592  * it as a single write. A partial write to system attribute would
 593  * cause an EINVAL on write.
 594  */
 595 static char *
 596 get_write_one_buf(char *buf, char *rec, int buf_size, int rec_size,
 597     tlm_cmd_t *lc)
 
 621 
 622 
 623 /*
 624  * tlm_output_xattr
 625  *
 626  * Put this file into the output buffers.
 627  */
 628 /*ARGSUSED*/
 629 longlong_t
 630 tlm_output_xattr(char  *dir, char *name, char *chkdir,
 631     tlm_acls_t *tlm_acls, tlm_commands_t *commands,
 632     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
 633 {
 634         char    *fullname;              /* directory + name */
 635         char    *snapname;              /* snapshot name */
 636         int     section;                /* section of a huge file */
 637         int     fd;
 638         int     afd = 0;
 639         longlong_t seek_spot = 0;       /* location in the file */
 640                                         /* for Multi Volume record */
 641         DIR *dp;
 642         struct dirent *dtp;
 643         char *attrname;
 644         char *fnamep;
 645         int rv = 0;
 646 
 647         if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
 648                 return (TLM_NO_SOURCE_FILE);
 649         }
 650 
 651         fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
 652         if (fullname == NULL) {
 653                 free(fullname);
 654                 return (-TLM_NO_SCRATCH_SPACE);
 655         }
 656 
 657         if (!tlm_cat_path(fullname, dir, name)) {
 658                 syslog(LOG_ERR, "Path too long.");
 659                 free(fullname);
 660                 return (-TLM_NO_SCRATCH_SPACE);
 661         }
 662 
 663         if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 &&
 664             sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) {
 665                 free(fullname);
 666                 return (0);
 667         }
 668 
 669         attrname = ndmp_malloc(TLM_MAX_PATH_NAME);
 670         snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
 671         if (attrname == NULL || snapname == NULL) {
 672                 rv = -TLM_NO_SCRATCH_SPACE;
 673                 goto err_out;
 674         }
 675 
 676         if (!tlm_cat_path(snapname, chkdir, name)) {
 677                 syslog(LOG_ERR, "Path too long.");
 678                 rv = -TLM_NO_SCRATCH_SPACE;
 679                 goto err_out;
 680         }
 681 
 682         fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
 683 
 684         /*
 685          * Open the file for reading.
 686          */
 687         fd = attropen(fnamep, ".", O_RDONLY);
 688         if (fd == -1) {
 689                 syslog(LOG_ERR, "BACKUP> Can't open file [%s][%s]",
 690                     fullname, fnamep);
 691                 rv = TLM_NO_SOURCE_FILE;
 692                 goto err_out;
 693         }
 694 
 695         section = 0;
 696 
 697         dp = (DIR *)fdopendir(fd);
 698         if (dp == NULL) {
 699                 syslog(LOG_ERR, "BACKUP> Can't open file [%s]", fullname);
 700                 (void) close(fd);
 701                 rv = TLM_NO_SOURCE_FILE;
 702                 goto err_out;
 703         }
 704 
 705         while ((dtp = readdir(dp)) != NULL) {
 706                 int section_size;
 707 
 708                 if (*dtp->d_name == '.')
 709                         continue;
 710 
 711                 if (sysattr_rdonly(dtp->d_name))
 712                         continue;
 713 
 714                 afd = attropen(fnamep, dtp->d_name, O_RDONLY);
 715                 if (afd == -1) {
 716                         syslog(LOG_ERR,
 717                             "problem(%d) opening xattr file [%s][%s]", errno,
 718                             fullname, fnamep);
 719                         goto tear_down;
 720                 }
 721 
 722                 (void) output_xattr_header(fullname, dtp->d_name, afd,
 723                     tlm_acls, section, local_commands);
 724                 (void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s",
 725                     dtp->d_name);
 726                 (void) output_file_header(attrname, "", tlm_acls, 0,
 727                     local_commands);
 728 
 729                 section_size = (long)llmin(tlm_acls->acl_attr.st_size,
 730                     (longlong_t)TLM_MAX_TAR_IMAGE);
 731 
 732                 /* We only can read upto one section extended attribute */
 733                 while (section_size > 0) {
 734                         char    *buf;
 735                         long    actual_size;
 736                         int     read_size;
 737                         int sysattr_read = 0;
 738                         char *rec = NULL;
 739                         int size = 0;
 740 
 741                         /*
 742                          * check for Abort commands
 743                          */
 744                         if (commands->tcs_reader != TLM_BACKUP_RUN) {
 745                                 local_commands->tc_writer = TLM_ABORT;
 746                                 goto tear_down;
 747                         }
 748 
 749                         local_commands->tc_buffers->tbs_buffer[
 750                             local_commands->tc_buffers->tbs_buffer_in].
 751                             tb_file_size = section_size;
 752                         local_commands->tc_buffers->tbs_buffer[
 753                             local_commands->tc_buffers->tbs_buffer_in].
 754                             tb_seek_spot = seek_spot;
 755 
 756                         buf = get_write_buffer(section_size,
 757                             &actual_size, FALSE, local_commands);
 758                         if (!buf)
 759                                 goto tear_down;
 
 778                         }
 779 
 780                         read_size = min(section_size, actual_size);
 781                         if ((actual_size = read(afd, buf, read_size)) < 0)
 782                                 break;
 783 
 784                         if (sysattr_read) {
 785                                 if (get_write_one_buf(buf, rec, read_size,
 786                                     size, local_commands) == 0) {
 787                                         free(buf);
 788                                         goto tear_down;
 789                                 }
 790                                 free(buf);
 791                         }
 792 
 793 
 794                         NS_ADD(rdisk, actual_size);
 795                         NS_INC(rfile);
 796 
 797                         if (actual_size == -1) {
 798                                 syslog(LOG_ERR,
 799                                     "problem(%d) reading file [%s][%s]",
 800                                     errno, fullname, snapname);
 801                                 goto tear_down;
 802                         }
 803                         seek_spot += actual_size;
 804                         section_size -= actual_size;
 805                 }
 806                 (void) close(afd);
 807                 afd = -1;
 808         }
 809 
 810 tear_down:
 811         local_commands->tc_buffers->tbs_buffer[
 812             local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
 813 
 814         if (afd > 0)
 815                 (void) close(afd);
 816 
 817         /* closedir closes fd too */
 818         (void) closedir(dp);
 
 840         char    *linkname;              /* where this file points */
 841         int     section = 0;            /* section of a huge file */
 842         int     fd;
 843         longlong_t real_size;           /* the origional file size */
 844         longlong_t file_size;           /* real size of this file */
 845         longlong_t seek_spot = 0;       /* location in the file */
 846                                         /* for Multi Volume record */
 847         u_longlong_t pos;
 848         char *fnamep;
 849 
 850         /* Indicate whether a file with the same inode has been backed up. */
 851         int hardlink_done = 0;
 852 
 853         /*
 854          * If a file with the same inode has been backed up, hardlink_pos holds
 855          * the tape offset of the data record.
 856          */
 857         u_longlong_t hardlink_pos = 0;
 858 
 859         if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) {
 860                 syslog(LOG_ERR, "Path too long [%s][%s]", dir, name);
 861                 return (-TLM_NO_SCRATCH_SPACE);
 862         }
 863 
 864         fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
 865         linkname = ndmp_malloc(TLM_MAX_PATH_NAME);
 866         snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
 867         if (fullname == NULL || linkname == NULL || snapname == NULL) {
 868                 real_size = -TLM_NO_SCRATCH_SPACE;
 869                 goto err_out;
 870         }
 871         if (!tlm_cat_path(fullname, dir, name) ||
 872             !tlm_cat_path(snapname, chkdir, name)) {
 873                 syslog(LOG_ERR, "Path too long.");
 874                 real_size = -TLM_NO_SCRATCH_SPACE;
 875                 goto err_out;
 876         }
 877 
 878         pos = tlm_get_data_offset(local_commands);
 879 
 880         if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
 881                 if (S_ISLNK(tlm_acls->acl_attr.st_mode)) {
 882                         file_size = tlm_readlink(fullname, snapname, linkname,
 883                             TLM_MAX_PATH_NAME-1);
 884                         if (file_size < 0) {
 885                                 real_size = -ENOENT;
 886                                 goto err_out;
 887                         }
 888                 }
 889 
 890                 /*
 891                  * Since soft links can not be read(2), we should only
 892                  * backup the file header.
 893                  */
 894                 (void) output_file_header(fullname,
 895                     linkname,
 896                     tlm_acls,
 897                     section,
 898                     local_commands);
 
 908                 return (0);
 909         }
 910 
 911         fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;
 912 
 913         /*
 914          * For hardlink, only read the data if no other link
 915          * belonging to the same inode has been backed up.
 916          */
 917         if (tlm_acls->acl_attr.st_nlink > 1) {
 918                 hardlink_done = !hardlink_q_get(hardlink_q,
 919                     tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL);
 920         }
 921 
 922         if (!hardlink_done) {
 923                 /*
 924                  * Open the file for reading.
 925                  */
 926                 fd = open(fnamep, O_RDONLY);
 927                 if (fd == -1) {
 928                         syslog(LOG_ERR,
 929                             "BACKUP> Can't open file [%s][%s] err(%d)",
 930                             fullname, fnamep, errno);
 931                         real_size = -TLM_NO_SOURCE_FILE;
 932                         goto err_out;
 933                 }
 934         } else {
 935                 syslog(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ",
 936                     tlm_acls->acl_attr.st_ino, hardlink_pos);
 937 
 938                 fd = -1;
 939         }
 940 
 941         linkname[0] = 0;
 942 
 943         real_size = tlm_acls->acl_attr.st_size;
 944         (void) output_acl_header(&tlm_acls->acl_info,
 945             local_commands);
 946 
 947         /*
 948          * section = 0: file is small enough for TAR
 949          * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks
 950          *              and the file name gets munged
 951          */
 952         file_size = real_size;
 953         if (file_size > TLM_MAX_TAR_IMAGE) {
 954                 if (output_humongus_header(fullname, file_size,
 955                     local_commands) < 0) {
 
1019                         if (!buf)
1020                                 goto tear_down;
1021 
1022                         /*
1023                          * check for Abort commands
1024                          */
1025                         if (commands->tcs_reader != TLM_BACKUP_RUN) {
1026                                 local_commands->tc_writer = TLM_ABORT;
1027                                 goto tear_down;
1028                         }
1029 
1030                         read_size = min(section_size, actual_size);
1031                         actual_size = read(fd, buf, read_size);
1032                         NS_ADD(rdisk, actual_size);
1033                         NS_INC(rfile);
1034 
1035                         if (actual_size == 0)
1036                                 break;
1037 
1038                         if (actual_size == -1) {
1039                                 syslog(LOG_ERR,
1040                                     "problem(%d) reading file [%s][%s]",
1041                                     errno, fullname, snapname);
1042                                 goto tear_down;
1043                         }
1044                         seek_spot += actual_size;
1045                         file_size -= actual_size;
1046                         section_size -= actual_size;
1047                 }
1048                 section++;
1049         }
1050 
1051         /*
1052          * If data belonging to this hardlink has been backed up, add the link
1053          * to hardlink queue.
1054          */
1055         if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) {
1056                 (void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino,
1057                     pos, NULL, 0);
1058                 syslog(LOG_DEBUG,
1059                     "backed up hardlink file %s, inode = %llu, pos = %llu ",
1060                     fullname, tlm_acls->acl_attr.st_ino, pos);
1061         }
1062 
1063         /*
1064          * For hardlink, if other link belonging to the same inode has been
1065          * backed up, no add_node entry should be sent for this link.
1066          */
1067         if (hardlink_done) {
1068                 syslog(LOG_DEBUG,
1069                     "backed up hardlink link %s, inode = %llu, pos = %llu ",
1070                     fullname, tlm_acls->acl_attr.st_ino, hardlink_pos);
1071         } else {
1072                 (void) tlm_log_fhnode(job_stats, dir, name,
1073                     &tlm_acls->acl_attr, pos);
1074         }
1075 
1076         (void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr,
1077             pos);
1078 
1079 tear_down:
1080         local_commands->tc_buffers->tbs_buffer[
1081             local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;
1082 
1083         (void) close(fd);
1084 
1085 err_out:
1086         free(fullname);
1087         free(linkname);
1088         free(snapname);
 
 |