1 /*
   2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * BSD 3 Clause License
   8  *
   9  * Copyright (c) 2007, The Storage Networking Industry Association.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  *      - Redistributions of source code must retain the above copyright
  15  *        notice, this list of conditions and the following disclaimer.
  16  *
  17  *      - Redistributions in binary form must reproduce the above copyright
  18  *        notice, this list of conditions and the following disclaimer in
  19  *        the documentation and/or other materials provided with the
  20  *        distribution.
  21  *
  22  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  23  *        nor the names of its contributors may be used to endorse or promote
  24  *        products derived from this software without specific prior written
  25  *        permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37  * POSSIBILITY OF SUCH DAMAGE.
  38  */
  39 #include <stdlib.h>
  40 #include <stdio.h>
  41 #include <string.h>
  42 #include <sys/queue.h>
  43 #include <sys/syslog.h>
  44 #include "tlm.h"
  45 #include "tlm_proto.h"
  46 
  47 #define HL_DBG_INIT             0x0001
  48 #define HL_DBG_CLEANUP  0x0002
  49 #define HL_DBG_GET      0x0004
  50 #define HL_DBG_ADD      0x0008
  51 
  52 static int hardlink_q_dbg = -1;
  53 
  54 
  55 struct hardlink_q *
  56 hardlink_q_init()
  57 {
  58         struct hardlink_q *qhead;
  59 
  60         qhead = (struct hardlink_q *)malloc(sizeof (struct hardlink_q));
  61         if (qhead) {
  62                 SLIST_INIT(qhead);
  63         }
  64 
  65         if (hardlink_q_dbg & HL_DBG_INIT)
  66                 NDMP_LOG(LOG_DEBUG, "qhead = %p", qhead);
  67 
  68         return (qhead);
  69 }
  70 
  71 void
  72 hardlink_q_cleanup(struct hardlink_q *hl_q)
  73 {
  74         struct hardlink_node *hl;
  75 
  76         if (hardlink_q_dbg & HL_DBG_CLEANUP)
  77                 NDMP_LOG(LOG_DEBUG, "(1): qhead = %p", hl_q);
  78 
  79         if (!hl_q)
  80                 return;
  81 
  82         while (!SLIST_EMPTY(hl_q)) {
  83                 hl = SLIST_FIRST(hl_q);
  84 
  85                 if (hardlink_q_dbg & HL_DBG_CLEANUP)
  86                         NDMP_LOG(LOG_DEBUG, "(2): remove node, inode = %lu",
  87                             hl->inode);
  88 
  89                 SLIST_REMOVE_HEAD(hl_q, next_hardlink);
  90 
  91                 /* remove the temporary file */
  92                 if (hl->is_tmp) {
  93                         if (hl->path) {
  94                                 NDMP_LOG(LOG_DEBUG, "(3): remove temp file %s",
  95                                     hl->path);
  96                                 if (remove(hl->path)) {
  97                                         NDMP_LOG(LOG_DEBUG,
  98                                             "error removing temp file");
  99                                 }
 100                         } else {
 101                                 NDMP_LOG(LOG_DEBUG, "no link name, inode = %lu",
 102                                     hl->inode);
 103                         }
 104                 }
 105 
 106                 if (hl->path)
 107                         free(hl->path);
 108                 free(hl);
 109         }
 110 
 111         free(hl_q);
 112 }
 113 
 114 /*
 115  * Return 0 if a list node has the same inode, and initialize offset and path
 116  * with the information in the list node.
 117  * Return -1 if no matching node is found.
 118  */
 119 int
 120 hardlink_q_get(struct hardlink_q *hl_q, unsigned long inode,
 121     unsigned long long *offset, char **path)
 122 {
 123         struct hardlink_node *hl;
 124 
 125         if (hardlink_q_dbg & HL_DBG_GET)
 126                 NDMP_LOG(LOG_DEBUG, "(1): qhead = %p, inode = %lu",
 127                     hl_q, inode);
 128 
 129         if (!hl_q)
 130                 return (-1);
 131 
 132         SLIST_FOREACH(hl, hl_q, next_hardlink) {
 133                 if (hardlink_q_dbg & HL_DBG_GET)
 134                         NDMP_LOG(LOG_DEBUG, "(2): checking, inode = %lu",
 135                             hl->inode);
 136 
 137                 if (hl->inode != inode)
 138                         continue;
 139 
 140                 if (offset)
 141                         *offset = hl->offset;
 142 
 143                 if (path)
 144                         *path = hl->path;
 145 
 146                 return (0);
 147         }
 148 
 149         return (-1);
 150 }
 151 
 152 /*
 153  * Add a node to hardlink_q.  Reject a duplicated entry.
 154  *
 155  * Return 0 if successful, and -1 if failed.
 156  */
 157 int
 158 hardlink_q_add(struct hardlink_q *hl_q, unsigned long inode,
 159     unsigned long long offset, char *path, int is_tmp_file)
 160 {
 161         struct hardlink_node *hl;
 162 
 163         if (hardlink_q_dbg & HL_DBG_ADD)
 164                 NDMP_LOG(LOG_DEBUG,
 165                     "(1): qhead = %p, inode = %lu, path = %p (%s)",
 166                     hl_q, inode, path, path? path : "(--)");
 167 
 168         if (!hl_q)
 169                 return (-1);
 170 
 171         if (!hardlink_q_get(hl_q, inode, 0, 0)) {
 172                 NDMP_LOG(LOG_DEBUG, "hardlink (inode = %lu) exists in queue %p",
 173                     inode, hl_q);
 174                 return (-1);
 175         }
 176 
 177         hl = (struct hardlink_node *)malloc(sizeof (struct hardlink_node));
 178         if (!hl)
 179                 return (-1);
 180 
 181         hl->inode = inode;
 182         hl->offset = offset;
 183         hl->is_tmp = is_tmp_file;
 184         if (path)
 185                 hl->path = strdup(path);
 186         else
 187                 hl->path = NULL;
 188 
 189         if (hardlink_q_dbg & HL_DBG_ADD)
 190                 NDMP_LOG(LOG_DEBUG,
 191                     "(2): added node, inode = %lu, path = %p (%s)",
 192                     hl->inode, hl->path, hl->path? hl->path : "(--)");
 193 
 194         SLIST_INSERT_HEAD(hl_q, hl, next_hardlink);
 195 
 196         return (0);
 197 }
 198 
 199 int
 200 hardlink_q_dump(struct hardlink_q *hl_q)
 201 {
 202         struct hardlink_node *hl;
 203 
 204         if (!hl_q)
 205                 return (0);
 206 
 207         (void) printf("Dumping hardlink_q, head = %p:\n", (void *) hl_q);
 208 
 209         SLIST_FOREACH(hl, hl_q, next_hardlink)
 210                 (void) printf(
 211                     "\t node = %lu, offset = %llu, path = %s, is_tmp = %d\n",
 212                     hl->inode, hl->offset, hl->path? hl->path : "--",
 213                     hl->is_tmp);
 214 
 215         return (0);
 216 }