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 struct hardlink_q *
  53 hardlink_q_init()
  54 {
  55         struct hardlink_q *qhead;
  56 
  57         qhead = (struct hardlink_q *)malloc(sizeof (struct hardlink_q));
  58         if (qhead) {
  59                 SLIST_INIT(qhead);
  60         }
  61 
  62         return (qhead);
  63 }
  64 
  65 void
  66 hardlink_q_cleanup(struct hardlink_q *hl_q)
  67 {
  68         struct hardlink_node *hl;
  69 
  70         if (!hl_q)
  71                 return;
  72 
  73         while (!SLIST_EMPTY(hl_q)) {
  74                 hl = SLIST_FIRST(hl_q);
  75 
  76                 SLIST_REMOVE_HEAD(hl_q, next_hardlink);
  77 
  78                 /* remove the temporary file */
  79                 if (hl->is_tmp) {
  80                         if (hl->path) {
  81                                 (void) remove(hl->path);
  82                         }
  83                 }
  84 
  85                 if (hl->path)
  86                         free(hl->path);
  87                 free(hl);
  88         }
  89 
  90         free(hl_q);
  91 }
  92 
  93 /*
  94  * Return 0 if a list node has the same inode, and initialize offset and path
  95  * with the information in the list node.
  96  * Return -1 if no matching node is found.
  97  */
  98 int
  99 hardlink_q_get(struct hardlink_q *hl_q, unsigned long inode,
 100     unsigned long long *offset, char **path)
 101 {
 102         struct hardlink_node *hl;
 103 
 104         if (!hl_q)
 105                 return (-1);
 106 
 107         SLIST_FOREACH(hl, hl_q, next_hardlink) {
 108 
 109                 if (hl->inode != inode)
 110                         continue;
 111 
 112                 if (offset)
 113                         *offset = hl->offset;
 114 
 115                 if (path)
 116                         *path = hl->path;
 117 
 118                 return (0);
 119         }
 120 
 121         return (-1);
 122 }
 123 
 124 /*
 125  * Add a node to hardlink_q.  Reject a duplicated entry.
 126  *
 127  * Return 0 if successful, and -1 if failed.
 128  */
 129 int
 130 hardlink_q_add(struct hardlink_q *hl_q, unsigned long inode,
 131     unsigned long long offset, char *path, int is_tmp_file)
 132 {
 133         struct hardlink_node *hl;
 134 
 135         if (!hl_q)
 136                 return (-1);
 137 
 138         if (!hardlink_q_get(hl_q, inode, 0, 0)) {
 139                 return (-1);
 140         }
 141 
 142         hl = (struct hardlink_node *)malloc(sizeof (struct hardlink_node));
 143         if (!hl)
 144                 return (-1);
 145 
 146         hl->inode = inode;
 147         hl->offset = offset;
 148         hl->is_tmp = is_tmp_file;
 149         if (path)
 150                 hl->path = strdup(path);
 151         else
 152                 hl->path = NULL;
 153 
 154         SLIST_INSERT_HEAD(hl_q, hl, next_hardlink);
 155 
 156         return (0);
 157 }
 158 
 159 int
 160 hardlink_q_dump(struct hardlink_q *hl_q)
 161 {
 162         struct hardlink_node *hl;
 163 
 164         if (!hl_q)
 165                 return (0);
 166 
 167         (void) printf("Dumping hardlink_q, head = %p:\n", (void *) hl_q);
 168 
 169         SLIST_FOREACH(hl, hl_q, next_hardlink)
 170                 (void) printf(
 171                     "\t node = %lu, offset = %llu, path = %s, is_tmp = %d\n",
 172                     hl->inode, hl->offset, hl->path? hl->path : "--",
 173                     hl->is_tmp);
 174 
 175         return (0);
 176 }