Print this page
    
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Revert "NEX-5801 Snapshots left over after failed backups"
This reverts commit f182fb95f09036db71fbfc6f0a6b90469b761f21.
NEX-5801 Snapshots left over after failed backups
Reviewed by: Rick Mesta <rick.mesta@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@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_util.c
          +++ new/usr/src/cmd/ndmpd/tlm/tlm_util.c
   1    1  /*
   2    2   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3    3   * Use is subject to license terms.
   4    4   * Copyright 2012 Milan Jurik. All rights reserved.
   5    5   */
   6    6  
   7    7  /*
   8    8   * BSD 3 Clause License
   9    9   *
  10   10   * Copyright (c) 2007, The Storage Networking Industry Association.
  11   11   *
  12   12   * Redistribution and use in source and binary forms, with or without
  13   13   * modification, are permitted provided that the following conditions
  14   14   * are met:
  15   15   *      - Redistributions of source code must retain the above copyright
  16   16   *        notice, this list of conditions and the following disclaimer.
  17   17   *
  18   18   *      - Redistributions in binary form must reproduce the above copyright
  19   19   *        notice, this list of conditions and the following disclaimer in
  20   20   *        the documentation and/or other materials provided with the
  21   21   *        distribution.
  22   22   *
  23   23   *      - Neither the name of The Storage Networking Industry Association (SNIA)
  24   24   *        nor the names of its contributors may be used to endorse or promote
  25   25   *        products derived from this software without specific prior written
  26   26   *        permission.
  27   27   *
  28   28   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  29   29   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  
    | 
      ↓ open down ↓ | 
    29 lines elided | 
    
      ↑ open up ↑ | 
  
  30   30   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31   31   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  32   32   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33   33   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  34   34   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  35   35   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36   36   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  37   37   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38   38   * POSSIBILITY OF SUCH DAMAGE.
  39   39   */
       40 +/* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
       41 +
       42 +#include <syslog.h>
  40   43  #include <stdio.h>
  41   44  #include <stdlib.h>
  42   45  #include <string.h>
  43   46  #include <strings.h>
  44   47  #include <cstack.h>
  45   48  #include <ctype.h>
  46   49  #include <tlm.h>
  47   50  #include "tlm_proto.h"
  48   51  
  49   52  /*
  50   53   * Implementation of a list based stack class. The stack only holds
  51   54   * pointers/references to application objects. The objects are not
  52   55   * copied and the stack never attempts to dereference or access the
  53   56   * data objects. Applications should treat cstack_t references as
  54   57   * opaque handles.
  55   58   */
  56   59  
  57   60  /*
  58   61   * cstack_new
  59   62   *
  60   63   * Allocate and initialize a new stack, which is just an empty cstack_t.
  61   64   * A pointer to the new stack is returned. This should be treated as an
  62   65   * opaque handle by the caller.
  63   66   */
  64   67  cstack_t *
  65   68  cstack_new(void)
  66   69  {
  67   70          cstack_t *stk;
  68   71  
  69   72          if ((stk = ndmp_malloc(sizeof (cstack_t))) == NULL)
  70   73                  return (NULL);
  71   74  
  72   75          return (stk);
  73   76  }
  74   77  
  75   78  
  76   79  /*
  77   80   * cstack_delete
  78   81   *
  
    | 
      ↓ open down ↓ | 
    29 lines elided | 
    
      ↑ open up ↑ | 
  
  79   82   * Deallocate the stack. This goes through the list freeing all of the
  80   83   * cstack nodes but not the data because we don't know how the data was
  81   84   * allocated. A stack really should be empty before it is deleted.
  82   85   */
  83   86  void
  84   87  cstack_delete(cstack_t *stk)
  85   88  {
  86   89          cstack_t *tmp;
  87   90  
  88   91          if (stk == NULL) {
  89      -                NDMP_LOG(LOG_DEBUG, "cstack_delete: invalid stack");
  90   92                  return;
  91   93          }
  92   94  
  93   95          while ((tmp = stk->next) != NULL) {
  94   96                  stk->next = tmp->next;
  95      -                NDMP_LOG(LOG_DEBUG, "cstack_delete(element): 0x%p", tmp);
  96   97                  free(tmp);
  97   98          }
  98   99  
  99      -        NDMP_LOG(LOG_DEBUG, "cstack_delete: 0x%p", stk);
 100  100          free(stk);
 101  101  }
 102  102  
 103  103  
 104  104  /*
 105  105   * cstack_push
 106  106   *
 107  107   * Push an element onto the stack. Allocate a new node and assign the
 108  108   * data and len values. We don't care what about the real values of
 109  109   * data or len and we never try to access them. The stack head will
 110  110   * point to the new node.
 111  111   *
 112  112   * Returns 0 on success. Otherwise returns -1 to indicate overflow.
 113  113   */
 114  114  int
 115  115  cstack_push(cstack_t *stk, void *data, int len)
 116  116  {
 117  117          cstack_t *stk_node;
 118  118  
 119  119          if (stk == NULL) {
 120      -                NDMP_LOG(LOG_DEBUG, "cstack_push: invalid stack");
 121  120                  return (-1);
 122  121          }
 123  122  
 124  123          if ((stk_node = ndmp_malloc(sizeof (cstack_t))) == NULL)
 125  124                  return (-1);
 126  125  
 127  126          stk_node->data = data;
 128  127          stk_node->len = len;
 129  128          stk_node->next = stk->next;
 130  129          stk->next = stk_node;
 131  130  
 132      -        NDMP_LOG(LOG_DEBUG, "cstack_push(0x%p): 0x%p", stk, stk_node);
 133  131          return (0);
 134  132  }
 135  133  
 136  134  
 137  135  /*
 138  136   * cstack_pop
 139  137   *
 140  138   * Pop an element off the stack. Set up the data and len references for
 141  139   * the caller, advance the stack head and free the popped stack node.
 142  140   *
 143  141   * Returns 0 on success. Otherwise returns -1 to indicate underflow.
 144  142   */
 145  143  int
 146  144  cstack_pop(cstack_t *stk, void **data, int *len)
 147  145  {
 148  146          cstack_t *stk_node;
 149  147  
 150  148          if (stk == NULL) {
 151      -                NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
 152  149                  return (-1);
 153  150          }
 154  151  
 155  152          if ((stk_node = stk->next) == NULL) {
 156      -                NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
 157  153                  return (-1);
 158  154          }
 159  155  
 160  156          if (data)
 161  157                  *data = stk_node->data;
 162  158  
 163  159          if (len)
 164  160                  *len = stk_node->len;
 165  161  
 166  162          stk->next = stk_node->next;
 167      -        NDMP_LOG(LOG_DEBUG, "cstack_pop(0x%p): 0x%p", stk, stk_node);
 168  163  
 169  164          free(stk_node);
 170  165          return (0);
 171  166  }
 172  167  
 173  168  /*
 174  169   * cstack_top
 175  170   *
 176  171   * Returns the top data element on the stack without removing it.
 177  172   *
 178  173   * Returns 0 on success. Otherwise returns -1 to indicate underflow.
 179  174   */
 180  175  int
 181  176  cstack_top(cstack_t *stk, void **data, int *len)
 182  177  {
 183  178          if (stk == NULL) {
 184      -                NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
 185  179                  return (-1);
 186  180          }
 187  181  
 188  182          if (stk->next == NULL) {
 189      -                NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
 190  183                  return (-1);
 191  184          }
 192  185  
 193  186          if (data)
 194  187                  *data = stk->next->data;
 195  188  
 196  189          if (len)
 197  190                  *len = stk->next->len;
 198  191  
 199  192          return (0);
 200  193  }
 201  194  
 202  195  /*
 203  196   * match
 204  197   *
 205  198   * Matching rules:
 206  199   *      c       Any non-special character matches itslef
 207  200   *      ?       Match any character
 208  201   *      ab      character 'a' followed by character 'b'
 209  202   *      S       Any string of non-special characters
 210  203   *      AB      String 'A' followed by string 'B'
 211  204   *      *       Any String, including the empty string
 212  205   */
 213  206  boolean_t
 214  207  match(char *patn, char *str)
 215  208  {
 216  209          for (; ; ) {
 217  210                  switch (*patn) {
 218  211                  case 0:
 219  212                          return (*str == 0);
 220  213  
 221  214                  case '?':
 222  215                          if (*str != 0) {
 223  216                                  str++;
 224  217                                  patn++;
 225  218                                  continue;
 226  219                          }
 227  220                          return (FALSE);
 228  221  
 229  222                  case '*':
 230  223                          patn++;
 231  224                          if (*patn == 0)
 232  225                                  return (TRUE);
 233  226  
 234  227                          while (*str) {
 235  228                                  if (match(patn, str))
 236  229                                          return (TRUE);
 237  230                                  str++;
 238  231                          }
 239  232                          return (FALSE);
 240  233  
 241  234                  default:
 242  235                          if (*str != *patn)
 243  236                                  return (FALSE);
 244  237                          str++;
 245  238                          patn++;
 246  239                          continue;
 247  240                  }
 248  241          }
 249  242  }
 250  243  
 251  244  /*
 252  245   * Match recursive call
 253  246   */
 254  247  int
 255  248  match_ci(char *patn, char *str)
 256  249  {
 257  250          /*
 258  251           * "<" is a special pattern that matches only those names
 259  252           * that do NOT have an extension. "." and ".." are ok.
 260  253           */
 261  254          if (strcmp(patn, "<") == 0) {
 262  255                  if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
 263  256                          return (TRUE);
 264  257                  if (strchr(str, '.') == 0)
 265  258                          return (TRUE);
 266  259                  return (FALSE);
 267  260          }
 268  261          for (; ; ) {
 269  262                  switch (*patn) {
 270  263                  case 0:
 271  264                          return (*str == 0);
 272  265  
 273  266                  case '?':
 274  267                          if (*str != 0) {
 275  268                                  str++;
 276  269                                  patn++;
 277  270                                  continue;
 278  271                          }
 279  272                          return (FALSE);
 280  273  
 281  274                  case '*':
 282  275                          patn++;
 283  276                          if (*patn == 0)
 284  277                                  return (TRUE);
 285  278  
 286  279                          while (*str) {
 287  280                                  if (match_ci(patn, str))
 288  281                                          return (TRUE);
 289  282                                  str++;
 290  283                          }
 291  284                          return (FALSE);
 292  285  
 293  286                  default:
 294  287                          if (*str != *patn) {
 295  288                                  int     c1 = *str;
 296  289                                  int     c2 = *patn;
 297  290  
 298  291                                  c1 = tolower(c1);
 299  292                                  c2 = tolower(c2);
 300  293                                  if (c1 != c2)
 301  294                                          return (FALSE);
 302  295                          }
 303  296                          str++;
 304  297                          patn++;
 305  298                          continue;
 306  299                  }
 307  300          }
 308  301          /* NOT REACHED */
 309  302  }
 310  303  
 311  304  /*
 312  305   * Linear matching against a list utility function
 313  306   */
 314  307  static boolean_t
 315  308  parse_match(char line, char *seps)
 316  309  {
 317  310          char *sep = seps;
 318  311  
 319  312          while (*sep != 0) {
 320  313                  /* compare this char with the seperator list */
 321  314                  if (*sep == line)
 322  315                          return (TRUE);
 323  316                  sep++;
 324  317          }
 325  318          return (FALSE);
 326  319  }
 327  320  
 328  321  /*
 329  322   * Returns the next entry of the list after
 330  323   * each separator
 331  324   */
 332  325  char *
 333  326  parse(char **line, char *seps)
 334  327  {
 335  328          char *start = *line;
 336  329  
 337  330          while (**line != 0) {
 338  331                  *line = *line + 1;
 339  332                  if (parse_match(**line, seps)) {
 340  333                          /* hit a terminator, skip trailing terminators */
 341  334                          while (parse_match(**line, seps)) {
 342  335                                  **line = 0;
 343  336                                  *line = *line + 1;
 344  337                          }
 345  338                          break;
 346  339                  }
 347  340          }
 348  341          return (start);
 349  342  }
 350  343  
 351  344  /*
 352  345   * oct_atoi
 353  346   *
 354  347   * Convert an octal string to integer
 355  348   */
 356  349  int
 357  350  oct_atoi(char *p)
 358  351  {
 359  352          int v = 0;
 360  353          int c;
 361  354  
 362  355          while (*p == ' ')
 363  356                  p++;
 364  357  
 365  358          while ('0' <= (c = *p++) && c <= '7') {
 366  359                  v <<= 3;
 367  360                  v += c - '0';
 368  361          }
 369  362  
 370  363          return (v);
 371  364  }
 372  365  
 373  366  /*
 374  367   * strupr
 375  368   *
 376  369   * Convert a string to uppercase using the appropriate codepage. The
 377  370   * string is converted in place. A pointer to the string is returned.
 378  371   * There is an assumption here that uppercase and lowercase values
 379  372   * always result encode to the same length.
 380  373   */
 381  374  char *
 382  375  strupr(char *s)
 383  376  {
 384  377          char c;
 385  378          unsigned char *p = (unsigned char *)s;
 386  379  
 387  380          while (*p) {
 388  381                  c = toupper(*p);
 389  382                  *p++ = c;
 390  383          }
 391  384          return (s);
 392  385  }
 393  386  
 394  387  /*
 395  388   * trim_whitespace
 396  389   *
 397  390   * Trim leading and trailing whitespace chars(as defined by isspace)
 398  391   * from a buffer. Example; if the input buffer contained "  text  ",
 399  392   * it will contain "text", when we return. We assume that the buffer
 400  393   * contains a null terminated string. A pointer to the buffer is
 401  394   * returned.
 402  395   */
 403  396  char *
 404  397  trim_whitespace(char *buf)
 405  398  {
 406  399          char *p = buf;
 407  400          char *q = buf;
 408  401  
 409  402          if (buf == 0)
 410  403                  return (0);
 411  404  
 412  405          while (*p && isspace(*p))
 413  406                  ++p;
 414  407  
 415  408          while ((*q = *p++) != 0)
 416  409                  ++q;
 417  410  
 418  411          if (q != buf) {
 419  412                  while ((--q, isspace(*q)) != 0)
 420  413                          *q = '\0';
 421  414          }
 422  415  
 423  416          return (buf);
 424  417  }
 425  418  
 426  419  /*
 427  420   * trim_name
 428  421   *
 429  422   * Trims the slash and dot slash from the beginning of the
 430  423   * path name.
 431  424   */
 432  425  char *
 433  426  trim_name(char *nm)
 434  427  {
 435  428          while (*nm) {
 436  429                  if (*nm == '/') {
 437  430                          nm++;
 438  431                          continue;
 439  432                  }
 440  433                  if (*nm == '.' && nm[1] == '/' && nm[2]) {
 441  434                          nm += 2;
 442  435                          continue;
 443  436                  }
 444  437                  break;
 445  438          }
 446  439          return (nm);
 447  440  }
 448  441  
 449  442  /*
 450  443   * get_volname
 451  444   *
 452  445   * Extract the volume name from the path
 453  446   */
 454  447  char *
 455  448  get_volname(char *path)
 456  449  {
 457  450          char *cp, *save;
 458  451          int sp;
 459  452  
 460  453          if (!path)
 461  454                  return (NULL);
 462  455  
 463  456          if (!(save = strdup(path)))
 464  457                  return (NULL);
 465  458  
 466  459          sp = strspn(path, "/");
 467  460          if (*(path + sp) == '\0') {
 468  461                  free(save);
 469  462                  return (NULL);
 470  463          }
 471  464  
 472  465          if ((cp = strchr(save + sp, '/')))
 473  466                  *cp = '\0';
 474  467  
 475  468          return (save);
 476  469  }
 477  470  
 478  471  /*
 479  472   * fs_volexist
 480  473   *
 481  474   * Check if the volume exists
 482  475   */
 483  476  boolean_t
 484  477  fs_volexist(char *path)
 485  478  {
 486  479          struct stat64 st;
 487  480          char *p;
 488  481  
 489  482          if ((p = get_volname(path)) == NULL)
 490  483                  return (FALSE);
 491  484  
 492  485          if (stat64(p, &st) != 0) {
 493  486                  free(p);
 494  487                  return (FALSE);
 495  488          }
 496  489  
 497  490          free(p);
 498  491          return (TRUE);
 499  492  }
 500  493  
 501  494  /*
 502  495   * tlm_tarhdr_size
 503  496   *
 504  497   * Returns the size of the TLM_TAR_HDR structure.
 505  498   */
 506  499  int
 507  500  tlm_tarhdr_size(void)
 508  501  {
 509  502          return (sizeof (tlm_tar_hdr_t));
 510  503  }
 511  504  
 512  505  /*
 513  506   * dup_dir_info
 514  507   *
 515  508   * Make and return a copy of the directory info.
 516  509   */
 517  510  struct full_dir_info *
 518  511  dup_dir_info(struct full_dir_info *old_dir_info)
 519  512  {
 520  513          struct  full_dir_info *new_dir_info;
 521  514          new_dir_info = ndmp_malloc(sizeof (struct full_dir_info));
 522  515  
 523  516          if (new_dir_info) {
 524  517                  bcopy(old_dir_info, new_dir_info,
 525  518                      sizeof (struct full_dir_info));
 526  519          }
 527  520          return (new_dir_info);
 528  521  }
 529  522  
 530  523  /*
 531  524   * tlm_new_dir_info
 532  525   *
 533  526   * Create a new structure, set fh field to what is specified and the path
 534  527   * to the concatenation of directory and the component
 535  528   */
 536  529  struct full_dir_info *
  
    | 
      ↓ open down ↓ | 
    337 lines elided | 
    
      ↑ open up ↑ | 
  
 537  530  tlm_new_dir_info(struct  fs_fhandle *fhp, char *dir, char *nm)
 538  531  {
 539  532          struct full_dir_info *fdip;
 540  533  
 541  534          if (!(fdip = ndmp_malloc(sizeof (struct full_dir_info))))
 542  535                  return (NULL);
 543  536  
 544  537          (void) memcpy(&fdip->fd_dir_fh, fhp, sizeof (fs_fhandle_t));
 545  538          if (!tlm_cat_path(fdip->fd_dir_name, dir, nm)) {
 546  539                  free(fdip);
 547      -                NDMP_LOG(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
      540 +                syslog(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
 548  541                      dir, nm);
 549  542                  return (NULL);
 550  543          }
 551  544          return (fdip);
 552  545  }
 553  546  
 554  547  /*
 555  548   * sysattr_rdonly
 556  549   *
 557  550   * Check if the attribute file is one of the readonly system
 558  551   * attributes.
 559  552   */
 560  553  int
 561  554  sysattr_rdonly(char *name)
 562  555  {
 563  556          return (name && strcmp(name, SYSATTR_RDONLY) == 0);
 564  557  }
 565  558  
 566  559  /*
 567  560   * sysattr_rw
 568  561   *
 569  562   * Check if the attribute file is one of the read/write system
 570  563   * attributes.
 571  564   */
 572  565  int
 573  566  sysattr_rw(char *name)
 574  567  {
 575  568          return (name && strcmp(name, SYSATTR_RW) == 0);
 576  569  }
  
    | 
      ↓ open down ↓ | 
    19 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX