xref: /netbsd-src/lib/libperfuse/subr.c (revision cb861154c176d3dcc8ff846f449e3c16a5f5edb5)
1 /*  $NetBSD: subr.c,v 1.11 2011/04/25 04:54:53 manu Exp $ */
2 
3 /*-
4  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions
8  *  are met:
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19  *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  *  POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <sysexits.h>
33 #include <syslog.h>
34 #include <puffs.h>
35 #include <paths.h>
36 
37 #include "perfuse_priv.h"
38 
39 static size_t node_path(puffs_cookie_t, char *, size_t);
40 
41 struct puffs_node *
42 perfuse_new_pn(pu, name, parent)
43 	struct puffs_usermount *pu;
44 	const char *name;
45 	struct puffs_node *parent;
46 {
47 	struct puffs_node *pn;
48 	struct perfuse_node_data *pnd;
49 
50 	if ((pnd = malloc(sizeof(*pnd))) == NULL)
51 		DERR(EX_OSERR, "malloc failed");
52 
53 	if ((pn = puffs_pn_new(pu, pnd)) == NULL)
54 		DERR(EX_SOFTWARE, "puffs_pn_new failed");
55 
56 	(void)memset(pnd, 0, sizeof(*pnd));
57 	pnd->pnd_rfh = FUSE_UNKNOWN_FH;
58 	pnd->pnd_wfh = FUSE_UNKNOWN_FH;
59 	pnd->pnd_ino = PERFUSE_UNKNOWN_INO;
60 	pnd->pnd_nlookup = 1;
61 	pnd->pnd_parent = parent;
62 	pnd->pnd_pn = (puffs_cookie_t)pn;
63 	(void)strlcpy(pnd->pnd_name, name, MAXPATHLEN);
64 	TAILQ_INIT(&pnd->pnd_pcq);
65 	TAILQ_INIT(&pnd->pnd_children);
66 
67 	if (parent != NULL) {
68 		struct perfuse_node_data *parent_pnd;
69 
70 		parent_pnd = PERFUSE_NODE_DATA(parent);
71 		TAILQ_INSERT_TAIL(&parent_pnd->pnd_children, pnd, pnd_next);
72 
73 		parent_pnd->pnd_childcount++;
74 	}
75 
76 	return pn;
77 }
78 
79 void
80 perfuse_destroy_pn(pn)
81 	struct puffs_node *pn;
82 {
83 	struct perfuse_node_data *pnd;
84 
85 	pnd = PERFUSE_NODE_DATA(pn);
86 
87 	if (pnd->pnd_parent != NULL) {
88 		struct perfuse_node_data *parent_pnd;
89 
90 		parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent);
91 		TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next);
92 	}
93 
94 	if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
95 		if (pnd->pnd_parent != NULL)
96 			PERFUSE_NODE_DATA(pnd->pnd_parent)->pnd_childcount--;
97 
98 		if (pnd->pnd_dirent != NULL)
99 			free(pnd->pnd_dirent);
100 
101 		if (pnd->pnd_all_fd != NULL)
102 			free(pnd->pnd_all_fd);
103 #ifdef PERFUSE_DEBUG
104 		if (pnd->pnd_flags & PND_OPEN)
105 			DERRX(EX_SOFTWARE, "%s: file open", __func__);
106 
107 		if (!TAILQ_EMPTY(&pnd->pnd_pcq))
108 			DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__);
109 #endif /* PERFUSE_DEBUG */
110 
111 		free(pnd);
112 	}
113 
114 	puffs_pn_put(pn);
115 
116 	return;
117 }
118 
119 
120 void
121 perfuse_new_fh(opc, fh, mode)
122 	puffs_cookie_t opc;
123 	uint64_t fh;
124 	int mode;
125 {
126 	struct perfuse_node_data *pnd;
127 
128 	pnd = PERFUSE_NODE_DATA(opc);
129 
130 	if (mode & FWRITE) {
131 		if (pnd->pnd_flags & PND_WFH)
132 			DERRX(EX_SOFTWARE, "%s: opc = %p, write fh already set",
133 			      __func__, (void *)opc);
134 		pnd->pnd_wfh = fh;
135 		pnd->pnd_flags |= PND_WFH;
136 	}
137 
138 	if (mode & FREAD) {
139 		if (pnd->pnd_flags & PND_RFH)
140 			DERRX(EX_SOFTWARE, "%s: opc = %p, read fh already set",
141 			      __func__, (void *)opc);
142 		pnd->pnd_rfh = fh;
143 		pnd->pnd_flags |= PND_RFH;
144 	}
145 
146 	return;
147 }
148 
149 void
150 perfuse_destroy_fh(opc, fh)
151 	puffs_cookie_t opc;
152 	uint64_t fh;
153 {
154 	struct perfuse_node_data *pnd;
155 
156 	pnd = PERFUSE_NODE_DATA(opc);
157 
158 	if (fh == pnd->pnd_rfh) {
159 		if (!(pnd->pnd_flags & PND_RFH) && (fh != FUSE_UNKNOWN_FH))
160 			DERRX(EX_SOFTWARE,
161 			      "%s: opc = %p, unset rfh = %"PRIx64"",
162 			      __func__, (void *)opc, fh);
163 		pnd->pnd_rfh = FUSE_UNKNOWN_FH;
164 		pnd->pnd_flags &= ~PND_RFH;
165 	}
166 
167 	if (fh == pnd->pnd_wfh) {
168 		if (!(pnd->pnd_flags & PND_WFH) && (fh != FUSE_UNKNOWN_FH))
169 			DERRX(EX_SOFTWARE,
170 			      "%s: opc = %p, unset wfh = %"PRIx64"",
171 			      __func__, (void *)opc, fh);
172 		pnd->pnd_wfh = FUSE_UNKNOWN_FH;
173 		pnd->pnd_flags &= ~PND_WFH;
174 	}
175 
176 	return;
177 }
178 
179 uint64_t
180 perfuse_get_fh(opc, mode)
181 	puffs_cookie_t opc;
182 	int mode;
183 {
184 	struct perfuse_node_data *pnd;
185 
186 	pnd = PERFUSE_NODE_DATA(opc);
187 
188 	if (mode & FWRITE) {
189 		if (pnd->pnd_flags & PND_WFH)
190 			return pnd->pnd_wfh;
191 	}
192 
193 	if (mode & FREAD) {
194 		if (pnd->pnd_flags & PND_RFH)
195 			return pnd->pnd_rfh;
196 
197 		if (pnd->pnd_flags & PND_WFH)
198 			return pnd->pnd_wfh;
199 
200 	}
201 
202 	return FUSE_UNKNOWN_FH;
203 }
204 
205 static size_t
206 node_path(opc, buf, buflen)
207 	puffs_cookie_t opc;
208 	char *buf;
209 	size_t buflen;
210 {
211 	struct perfuse_node_data *pnd;
212 	size_t written;
213 
214 	pnd = PERFUSE_NODE_DATA(opc);
215 	if (pnd->pnd_parent == opc)
216 		return 0;
217 
218 	written = node_path(pnd->pnd_parent, buf, buflen);
219 	buf += written;
220 	buflen -= written;
221 
222 	return written + snprintf(buf, buflen, "/%s", pnd->pnd_name);
223 }
224 
225 char *
226 perfuse_node_path(opc)
227 	puffs_cookie_t opc;
228 {
229 	static char buf[MAXPATHLEN + 1];
230 
231 	if (node_path(opc, buf, sizeof(buf)) == 0)
232 		sprintf(buf, "/");
233 
234 	return buf;
235 }
236