xref: /netbsd/lib/libperfuse/subr.c (revision 6550d01e)
1 /*  $NetBSD: subr.c,v 1.10 2010/10/11 05:37:58 manu Exp $ */
2 
3 /*-
4  *  Copyright (c) 2010 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(pu, pn)
81 	struct puffs_usermount *pu;
82 	struct puffs_node *pn;
83 {
84 	struct perfuse_node_data *pnd;
85 
86 	pnd = PERFUSE_NODE_DATA(pn);
87 
88 	if (pnd->pnd_parent != NULL) {
89 		struct perfuse_node_data *parent_pnd;
90 
91 		parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent);
92 		TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next);
93 	}
94 
95 	if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
96 		if (pnd->pnd_parent != NULL)
97 			PERFUSE_NODE_DATA(pnd->pnd_parent)->pnd_childcount--;
98 
99 		if (pnd->pnd_dirent != NULL)
100 			free(pnd->pnd_dirent);
101 
102 		if (pnd->pnd_all_fd != NULL)
103 			free(pnd->pnd_all_fd);
104 #ifdef PERFUSE_DEBUG
105 		if (pnd->pnd_flags & PND_OPEN)
106 			DERRX(EX_SOFTWARE, "%s: file open", __func__);
107 
108 		if (!TAILQ_EMPTY(&pnd->pnd_pcq))
109 			DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__);
110 #endif /* PERFUSE_DEBUG */
111 
112 		free(pnd);
113 	}
114 
115 	puffs_pn_put(pn);
116 
117 	return;
118 }
119 
120 
121 void
122 perfuse_new_fh(opc, fh, mode)
123 	puffs_cookie_t opc;
124 	uint64_t fh;
125 	int mode;
126 {
127 	struct perfuse_node_data *pnd;
128 
129 	pnd = PERFUSE_NODE_DATA(opc);
130 
131 	if (mode & FWRITE) {
132 		if (pnd->pnd_flags & PND_WFH)
133 			DERRX(EX_SOFTWARE, "%s: opc = %p, write fh already set",
134 			      __func__, (void *)opc);
135 		pnd->pnd_wfh = fh;
136 		pnd->pnd_flags |= PND_WFH;
137 	}
138 
139 	if (mode & FREAD) {
140 		if (pnd->pnd_flags & PND_RFH)
141 			DERRX(EX_SOFTWARE, "%s: opc = %p, read fh already set",
142 			      __func__, (void *)opc);
143 		pnd->pnd_rfh = fh;
144 		pnd->pnd_flags |= PND_RFH;
145 	}
146 
147 	return;
148 }
149 
150 void
151 perfuse_destroy_fh(opc, fh)
152 	puffs_cookie_t opc;
153 	uint64_t fh;
154 {
155 	struct perfuse_node_data *pnd;
156 
157 	pnd = PERFUSE_NODE_DATA(opc);
158 
159 	if (fh == pnd->pnd_rfh) {
160 		if (!(pnd->pnd_flags & PND_RFH) && (fh != FUSE_UNKNOWN_FH))
161 			DERRX(EX_SOFTWARE,
162 			      "%s: opc = %p, unset rfh = %"PRIx64"",
163 			      __func__, (void *)opc, fh);
164 		pnd->pnd_rfh = FUSE_UNKNOWN_FH;
165 		pnd->pnd_flags &= ~PND_RFH;
166 	}
167 
168 	if (fh == pnd->pnd_wfh) {
169 		if (!(pnd->pnd_flags & PND_WFH) && (fh != FUSE_UNKNOWN_FH))
170 			DERRX(EX_SOFTWARE,
171 			      "%s: opc = %p, unset wfh = %"PRIx64"",
172 			      __func__, (void *)opc, fh);
173 		pnd->pnd_wfh = FUSE_UNKNOWN_FH;
174 		pnd->pnd_flags &= ~PND_WFH;
175 	}
176 
177 	return;
178 }
179 
180 uint64_t
181 perfuse_get_fh(opc, mode)
182 	puffs_cookie_t opc;
183 	int mode;
184 {
185 	struct perfuse_node_data *pnd;
186 
187 	pnd = PERFUSE_NODE_DATA(opc);
188 
189 	if (mode & FWRITE) {
190 		if (pnd->pnd_flags & PND_WFH)
191 			return pnd->pnd_wfh;
192 	}
193 
194 	if (mode & FREAD) {
195 		if (pnd->pnd_flags & PND_RFH)
196 			return pnd->pnd_rfh;
197 
198 		if (pnd->pnd_flags & PND_WFH)
199 			return pnd->pnd_wfh;
200 
201 	}
202 
203 	return FUSE_UNKNOWN_FH;
204 }
205 
206 static size_t
207 node_path(opc, buf, buflen)
208 	puffs_cookie_t opc;
209 	char *buf;
210 	size_t buflen;
211 {
212 	struct perfuse_node_data *pnd;
213 	size_t written;
214 
215 	pnd = PERFUSE_NODE_DATA(opc);
216 	if (pnd->pnd_parent == opc)
217 		return 0;
218 
219 	written = node_path(pnd->pnd_parent, buf, buflen);
220 	buf += written;
221 	buflen -= written;
222 
223 	return written + snprintf(buf, buflen, "/%s", pnd->pnd_name);
224 }
225 
226 char *
227 perfuse_node_path(opc)
228 	puffs_cookie_t opc;
229 {
230 	static char buf[MAXPATHLEN + 1];
231 
232 	if (node_path(opc, buf, sizeof(buf)) == 0)
233 		sprintf(buf, "/");
234 
235 	return buf;
236 }
237