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 *
hardlink_q_init()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
hardlink_q_cleanup(struct hardlink_q * hl_q)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
hardlink_q_get(struct hardlink_q * hl_q,unsigned long inode,unsigned long long * offset,char ** path)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
hardlink_q_add(struct hardlink_q * hl_q,unsigned long inode,unsigned long long offset,char * path,int is_tmp_file)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
hardlink_q_dump(struct hardlink_q * hl_q)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 }
217