subr.c revision 1.9 1 /* $NetBSD: subr.c,v 1.9 2010/10/11 01:08:26 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 perfuse_state *ps;
48 struct puffs_node *pn;
49 struct perfuse_node_data *pnd;
50
51 ps = puffs_getspecific(pu);
52
53 if ((pnd = malloc(sizeof(*pnd))) == NULL)
54 DERR(EX_OSERR, "malloc failed");
55
56 if ((pn = puffs_pn_new(pu, pnd)) == NULL)
57 DERR(EX_SOFTWARE, "puffs_pn_new failed");
58
59 (void)memset(pnd, 0, sizeof(*pnd));
60 pnd->pnd_rfh = FUSE_UNKNOWN_FH;
61 pnd->pnd_wfh = FUSE_UNKNOWN_FH;
62 pnd->pnd_ino = PERFUSE_UNKNOWN_INO;
63 pnd->pnd_nlookup = 1;
64 pnd->pnd_parent = parent;
65 pnd->pnd_pn = (puffs_cookie_t)pn;
66 (void)strlcpy(pnd->pnd_name, name, MAXPATHLEN);
67 TAILQ_INIT(&pnd->pnd_pcq);
68 TAILQ_INIT(&pnd->pnd_children);
69
70 if (parent != NULL) {
71 struct perfuse_node_data *parent_pnd;
72
73 parent_pnd = PERFUSE_NODE_DATA(parent);
74 TAILQ_INSERT_TAIL(&parent_pnd->pnd_children, pnd, pnd_next);
75
76 parent_pnd->pnd_childcount++;
77 }
78
79 return pn;
80 }
81
82 void
83 perfuse_destroy_pn(pu, pn)
84 struct puffs_usermount *pu;
85 struct puffs_node *pn;
86 {
87 struct perfuse_state *ps;
88 struct perfuse_node_data *pnd;
89
90 ps = puffs_getspecific(pu);
91 pnd = PERFUSE_NODE_DATA(pn);
92
93 if (pnd->pnd_parent != NULL) {
94 struct perfuse_node_data *parent_pnd;
95
96 parent_pnd = PERFUSE_NODE_DATA(pnd->pnd_parent);
97 TAILQ_REMOVE(&parent_pnd->pnd_children, pnd, pnd_next);
98 }
99
100 if ((pnd = puffs_pn_getpriv(pn)) != NULL) {
101 if (pnd->pnd_parent != NULL)
102 PERFUSE_NODE_DATA(pnd->pnd_parent)->pnd_childcount--;
103
104 if (pnd->pnd_dirent != NULL)
105 free(pnd->pnd_dirent);
106
107 if (pnd->pnd_all_fd != NULL)
108 free(pnd->pnd_all_fd);
109 #ifdef PERFUSE_DEBUG
110 if (pnd->pnd_flags & PND_OPEN)
111 DERRX(EX_SOFTWARE, "%s: file open", __func__);
112
113 if (!TAILQ_EMPTY(&pnd->pnd_pcq))
114 DERRX(EX_SOFTWARE, "%s: non empty pnd_pcq", __func__);
115 #endif /* PERFUSE_DEBUG */
116
117 free(pnd);
118 }
119
120 puffs_pn_put(pn);
121
122 return;
123 }
124
125
126 void
127 perfuse_new_fh(opc, fh, mode)
128 puffs_cookie_t opc;
129 uint64_t fh;
130 int mode;
131 {
132 struct perfuse_node_data *pnd;
133
134 pnd = PERFUSE_NODE_DATA(opc);
135
136 if (mode & FWRITE) {
137 if (pnd->pnd_flags & PND_WFH)
138 DERRX(EX_SOFTWARE, "%s: opc = %p, write fh already set",
139 __func__, (void *)opc);
140 pnd->pnd_wfh = fh;
141 pnd->pnd_flags |= PND_WFH;
142 }
143
144 if (mode & FREAD) {
145 if (pnd->pnd_flags & PND_RFH)
146 DERRX(EX_SOFTWARE, "%s: opc = %p, read fh already set",
147 __func__, (void *)opc);
148 pnd->pnd_rfh = fh;
149 pnd->pnd_flags |= PND_RFH;
150 }
151
152 return;
153 }
154
155 void
156 perfuse_destroy_fh(opc, fh)
157 puffs_cookie_t opc;
158 uint64_t fh;
159 {
160 struct perfuse_node_data *pnd;
161
162 pnd = PERFUSE_NODE_DATA(opc);
163
164 if (fh == pnd->pnd_rfh) {
165 if (!(pnd->pnd_flags & PND_RFH) && (fh != FUSE_UNKNOWN_FH))
166 DERRX(EX_SOFTWARE,
167 "%s: opc = %p, unset rfh = %"PRIx64"",
168 __func__, (void *)opc, fh);
169 pnd->pnd_rfh = FUSE_UNKNOWN_FH;
170 pnd->pnd_flags &= ~PND_RFH;
171 }
172
173 if (fh == pnd->pnd_wfh) {
174 if (!(pnd->pnd_flags & PND_WFH) && (fh != FUSE_UNKNOWN_FH))
175 DERRX(EX_SOFTWARE,
176 "%s: opc = %p, unset wfh = %"PRIx64"",
177 __func__, (void *)opc, fh);
178 pnd->pnd_wfh = FUSE_UNKNOWN_FH;
179 pnd->pnd_flags &= ~PND_WFH;
180 }
181
182 return;
183 }
184
185 uint64_t
186 perfuse_get_fh(opc, mode)
187 puffs_cookie_t opc;
188 int mode;
189 {
190 struct perfuse_node_data *pnd;
191
192 pnd = PERFUSE_NODE_DATA(opc);
193
194 if (mode & FWRITE) {
195 if (pnd->pnd_flags & PND_WFH)
196 return pnd->pnd_wfh;
197 }
198
199 if (mode & FREAD) {
200 if (pnd->pnd_flags & PND_RFH)
201 return pnd->pnd_rfh;
202
203 if (pnd->pnd_flags & PND_WFH)
204 return pnd->pnd_wfh;
205
206 }
207
208 return FUSE_UNKNOWN_FH;
209 }
210
211 static size_t
212 node_path(opc, buf, buflen)
213 puffs_cookie_t opc;
214 char *buf;
215 size_t buflen;
216 {
217 struct perfuse_node_data *pnd;
218 size_t written;
219
220 pnd = PERFUSE_NODE_DATA(opc);
221 if (pnd->pnd_parent == opc)
222 return 0;
223
224 written = node_path(pnd->pnd_parent, buf, buflen);
225 buf += written;
226 buflen -= written;
227
228 return written + snprintf(buf, buflen, "/%s", pnd->pnd_name);
229 }
230
231 char *
232 perfuse_node_path(opc)
233 puffs_cookie_t opc;
234 {
235 static char buf[MAXPATHLEN + 1];
236
237 if (node_path(opc, buf, sizeof(buf)) == 0)
238 sprintf(buf, "/");
239
240 return buf;
241 }
242