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
↓ 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>
↓ 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);
↓ 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,
↓ 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",
↓ 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) {
↓ 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);
↓ 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);
↓ 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,
↓ 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[
↓ 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          }
↓ 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                  }
↓ 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);
↓ 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  
↓ open down ↓ 391 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX