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