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 /* LINTED: E_CONSTANT_CONDITION */ 63 SLIST_INIT(qhead); 64 } 65 66 if (hardlink_q_dbg & HL_DBG_INIT) 67 NDMP_LOG(LOG_DEBUG, "qhead = %p", qhead); 68 69 return (qhead); 70 } 71 72 void 73 hardlink_q_cleanup(struct hardlink_q *hl_q) 74 { 75 struct hardlink_node *hl; 76 77 if (hardlink_q_dbg & HL_DBG_CLEANUP) 78 NDMP_LOG(LOG_DEBUG, "(1): qhead = %p", hl_q); 79 80 if (!hl_q) 81 return; 82 83 while (!SLIST_EMPTY(hl_q)) { 84 hl = SLIST_FIRST(hl_q); 85 86 if (hardlink_q_dbg & HL_DBG_CLEANUP) 87 NDMP_LOG(LOG_DEBUG, "(2): remove node, inode = %lu", 88 hl->inode); 89 90 /* LINTED: E_CONSTANT_CONDITION */ 91 SLIST_REMOVE_HEAD(hl_q, next_hardlink); 92 93 /* remove the temporary file */ 94 if (hl->is_tmp) { 95 if (hl->path) { 96 NDMP_LOG(LOG_DEBUG, "(3): remove temp file %s", 97 hl->path); 98 if (remove(hl->path)) { 99 NDMP_LOG(LOG_DEBUG, 100 "error removing temp file"); 101 } 102 } else { 103 NDMP_LOG(LOG_DEBUG, "no link name, inode = %lu", 104 hl->inode); 105 } 106 } 107 108 if (hl->path) 109 free(hl->path); 110 free(hl); 111 } 112 113 free(hl_q); 114 } 115 116 /* 117 * Return 0 if a list node has the same inode, and initialize offset and path 118 * with the information in the list node. 119 * Return -1 if no matching node is found. 120 */ 121 int 122 hardlink_q_get(struct hardlink_q *hl_q, unsigned long inode, 123 unsigned long long *offset, char **path) 124 { 125 struct hardlink_node *hl; 126 127 if (hardlink_q_dbg & HL_DBG_GET) 128 NDMP_LOG(LOG_DEBUG, "(1): qhead = %p, inode = %lu", 129 hl_q, inode); 130 131 if (!hl_q) 132 return (-1); 133 134 SLIST_FOREACH(hl, hl_q, next_hardlink) { 135 if (hardlink_q_dbg & HL_DBG_GET) 136 NDMP_LOG(LOG_DEBUG, "(2): checking, inode = %lu", 137 hl->inode); 138 139 if (hl->inode != inode) 140 continue; 141 142 if (offset) 143 *offset = hl->offset; 144 145 if (path) 146 *path = hl->path; 147 148 return (0); 149 } 150 151 return (-1); 152 } 153 154 /* 155 * Add a node to hardlink_q. Reject a duplicated entry. 156 * 157 * Return 0 if successful, and -1 if failed. 158 */ 159 int 160 hardlink_q_add(struct hardlink_q *hl_q, unsigned long inode, 161 unsigned long long offset, char *path, int is_tmp_file) 162 { 163 struct hardlink_node *hl; 164 165 if (hardlink_q_dbg & HL_DBG_ADD) 166 NDMP_LOG(LOG_DEBUG, 167 "(1): qhead = %p, inode = %lu, path = %p (%s)", 168 hl_q, inode, path, path? path : "(--)"); 169 170 if (!hl_q) 171 return (-1); 172 173 if (!hardlink_q_get(hl_q, inode, 0, 0)) { 174 NDMP_LOG(LOG_DEBUG, "hardlink (inode = %lu) exists in queue %p", 175 inode, hl_q); 176 return (-1); 177 } 178 179 hl = (struct hardlink_node *)malloc(sizeof (struct hardlink_node)); 180 if (!hl) 181 return (-1); 182 183 hl->inode = inode; 184 hl->offset = offset; 185 hl->is_tmp = is_tmp_file; 186 if (path) 187 hl->path = strdup(path); 188 else 189 hl->path = NULL; 190 191 if (hardlink_q_dbg & HL_DBG_ADD) 192 NDMP_LOG(LOG_DEBUG, 193 "(2): added node, inode = %lu, path = %p (%s)", 194 hl->inode, hl->path, hl->path? hl->path : "(--)"); 195 196 /* LINTED: E_CONSTANT_CONDITION */ 197 SLIST_INSERT_HEAD(hl_q, hl, next_hardlink); 198 199 return (0); 200 } 201 202 int 203 hardlink_q_dump(struct hardlink_q *hl_q) 204 { 205 struct hardlink_node *hl; 206 207 if (!hl_q) 208 return (0); 209 210 (void) printf("Dumping hardlink_q, head = %p:\n", (void *) hl_q); 211 212 SLIST_FOREACH(hl, hl_q, next_hardlink) 213 (void) printf( 214 "\t node = %lu, offset = %llu, path = %s, is_tmp = %d\n", 215 hl->inode, hl->offset, hl->path? hl->path : "--", 216 hl->is_tmp); 217 218 return (0); 219 } 220