Mon Apr 25 04:30:59 2011 UTC ()
- fix warnings
- try to handle ENOBUFS in a nicer way
- use errx() for usage message, not err(), as we do not waht strerror(errno)


(manu)
diff -r1.9 -r1.10 src/usr.sbin/perfused/msg.c
diff -r1.11 -r1.12 src/usr.sbin/perfused/perfused.c

cvs diff -r1.9 -r1.10 src/usr.sbin/perfused/msg.c (switch to unified diff)

--- src/usr.sbin/perfused/msg.c 2010/10/11 05:37:58 1.9
+++ src/usr.sbin/perfused/msg.c 2011/04/25 04:30:59 1.10
@@ -1,672 +1,678 @@ @@ -1,672 +1,678 @@
1/* $NetBSD: msg.c,v 1.9 2010/10/11 05:37:58 manu Exp $ */ 1/* $NetBSD: msg.c,v 1.10 2011/04/25 04:30:59 manu Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. 4 * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
5 *  5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 *  14 *
15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE. 25 * POSSIBILITY OF SUCH DAMAGE.
26 */  26 */
27 27
28#include <stdio.h> 28#include <stdio.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <unistd.h> 30#include <unistd.h>
31#include <err.h> 31#include <err.h>
32#include <errno.h> 32#include <errno.h>
33#include <string.h> 33#include <string.h>
34#include <sysexits.h> 34#include <sysexits.h>
35#include <syslog.h> 35#include <syslog.h>
36#include <paths.h> 36#include <paths.h>
37#include <puffs.h> 37#include <puffs.h>
38#include <limits.h> 38#include <limits.h>
39#include <sys/types.h> 39#include <sys/types.h>
40#include <sys/socket.h> 40#include <sys/socket.h>
41#include <sys/un.h> 41#include <sys/un.h>
42#include <machine/vmparam.h> 42#include <machine/vmparam.h>
43 43
44#include "../../lib/libperfuse/perfuse_if.h" 44#include "../../lib/libperfuse/perfuse_if.h"
45#include "perfused.h" 45#include "perfused.h"
46 46
47static int xchg_pb_inloop(struct puffs_usermount *a, struct puffs_framebuf *, 47static int xchg_pb_inloop(struct puffs_usermount *a, struct puffs_framebuf *,
48 int, enum perfuse_xchg_pb_reply); 48 int, enum perfuse_xchg_pb_reply);
49static int xchg_pb_early(struct puffs_usermount *a, struct puffs_framebuf *, 49static int xchg_pb_early(struct puffs_usermount *a, struct puffs_framebuf *,
50 int, enum perfuse_xchg_pb_reply); 50 int, enum perfuse_xchg_pb_reply);
51 51
52int 52int
53perfuse_open_sock(void) 53perfuse_open_sock(void)
54{ 54{
55 int s; 55 int s;
56 struct sockaddr_un sun; 56 struct sockaddr_un sun;
57 const struct sockaddr *sa; 57 const struct sockaddr *sa;
58 uint32_t opt; 58 uint32_t opt;
59 59
60 (void)unlink(_PATH_FUSE); 60 (void)unlink(_PATH_FUSE);
61 61
62 if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) == -1) 62 if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) == -1)
63 err(EX_OSERR, "socket failed"); 63 err(EX_OSERR, "socket failed");
64 64
65 sa = (const struct sockaddr *)(void *)&sun; 65 sa = (const struct sockaddr *)(void *)&sun;
66 sun.sun_len = sizeof(sun); 66 sun.sun_len = sizeof(sun);
67 sun.sun_family = AF_LOCAL; 67 sun.sun_family = AF_LOCAL;
68 (void)strcpy(sun.sun_path, _PATH_FUSE);  68 (void)strcpy(sun.sun_path, _PATH_FUSE);
69 69
70 /* 70 /*
71 * Set a buffer lentgh large enough so that a few FUSE packets 71 * Set a buffer lentgh large enough so that a few FUSE packets
72 * will fit.  72 * will fit.
73 * XXX We will have to find how many packets we need 73 * XXX We will have to find how many packets we need
74 */ 74 */
75 opt = 4 * FUSE_BUFSIZE; 75 opt = 4 * FUSE_BUFSIZE;
76 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) != 0) 76 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) != 0)
77 DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt); 77 DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
78 78
79 opt = 4 * FUSE_BUFSIZE; 79 opt = 4 * FUSE_BUFSIZE;
80 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) != 0) 80 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) != 0)
81 DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt); 81 DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
82 82
83 /* 83 /*
84 * Request peer credentials 84 * Request peer credentials
85 */ 85 */
86 opt = 1; 86 opt = 1;
87 if (setsockopt(s, 0, LOCAL_CREDS, &opt, sizeof(opt)) != 0) 87 if (setsockopt(s, 0, LOCAL_CREDS, &opt, sizeof(opt)) != 0)
88 DWARN("%s: setsockopt LOCAL_CREDS failed", __func__); 88 DWARN("%s: setsockopt LOCAL_CREDS failed", __func__);
89  89
90 if (bind(s, sa, (socklen_t )sun.sun_len) == -1) 90 if (bind(s, sa, (socklen_t )sun.sun_len) == -1)
91 err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE); 91 err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE);
92 92
93 if (connect(s, sa, (socklen_t )sun.sun_len) == -1) 93 if (connect(s, sa, (socklen_t )sun.sun_len) == -1)
94 err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE); 94 err(EX_OSERR, "cannot open \"%s\" socket", _PATH_FUSE);
95 95
96 return s; 96 return s;
97} 97}
98 98
99 99
100void * 100void *
101perfuse_recv_early(fd, sockcred, sockcred_len) 101perfuse_recv_early(fd, sockcred, sockcred_len)
102 int fd; 102 int fd;
103 struct sockcred *sockcred; 103 struct sockcred *sockcred;
104 size_t sockcred_len; 104 size_t sockcred_len;
105{ 105{
106 struct fuse_out_header foh; 106 struct fuse_out_header foh;
107 size_t len; 107 size_t len;
108 char *buf; 108 char *buf;
109 struct msghdr msg; 109 struct msghdr msg;
110 char cmsg_buf[sizeof(struct cmsghdr) + SOCKCREDSIZE(NGROUPS_MAX)]; 110 char cmsg_buf[sizeof(struct cmsghdr) + SOCKCREDSIZE(NGROUPS_MAX)];
111 struct cmsghdr *cmsg = (struct cmsghdr *)(void *)&cmsg_buf; 111 struct cmsghdr *cmsg = (struct cmsghdr *)(void *)&cmsg_buf;
112 struct sockcred *sc = (struct sockcred *)(void *)(cmsg + 1); 112 struct sockcred *sc = (struct sockcred *)(void *)(cmsg + 1);
113 struct iovec iov; 113 struct iovec iov;
114  114
115 len = sizeof(foh); 115 len = sizeof(foh);
116 116
117 /* 117 /*
118 * We use the complicated recvmsg because we want peer creds. 118 * We use the complicated recvmsg because we want peer creds.
119 */ 119 */
120 iov.iov_base = &foh; 120 iov.iov_base = &foh;
121 iov.iov_len = len; 121 iov.iov_len = len;
122 msg.msg_name = NULL; 122 msg.msg_name = NULL;
123 msg.msg_namelen = 0; 123 msg.msg_namelen = 0;
124 msg.msg_iov = &iov; 124 msg.msg_iov = &iov;
125 msg.msg_iovlen = 1; 125 msg.msg_iovlen = 1;
126 msg.msg_control = cmsg; 126 msg.msg_control = cmsg;
127 msg.msg_controllen = sizeof(cmsg_buf); 127 msg.msg_controllen = sizeof(cmsg_buf);
128 msg.msg_flags = 0; 128 msg.msg_flags = 0;
129 129
130 if (recvmsg(fd, &msg, MSG_NOSIGNAL|MSG_PEEK) != (ssize_t)len) { 130 if (recvmsg(fd, &msg, MSG_NOSIGNAL|MSG_PEEK) != (ssize_t)len) {
131 DWARN("short recv (header)"); 131 DWARN("short recv (header)");
132 return NULL; 132 return NULL;
133 } 133 }
134 134
135 if (cmsg->cmsg_type != SCM_CREDS) { 135 if (cmsg->cmsg_type != SCM_CREDS) {
136 DWARNX("No SCM_CREDS"); 136 DWARNX("No SCM_CREDS");
137 return NULL; 137 return NULL;
138 } 138 }
139 139
140 if (sockcred != NULL) 140 if (sockcred != NULL)
141 (void)memcpy(sockcred, sc, 141 (void)memcpy(sockcred, sc,
142 MIN(cmsg->cmsg_len - sizeof(*cmsg), sockcred_len)); 142 MIN(cmsg->cmsg_len - sizeof(*cmsg), sockcred_len));
143  143
144 144
145 len = foh.len; 145 len = foh.len;
146 if ((buf = malloc(len)) == NULL) 146 if ((buf = malloc(len)) == NULL)
147 err(EX_OSERR, "malloc(%zd) failed", len); 147 err(EX_OSERR, "malloc(%zd) failed", len);
148 148
149 if (recv(fd, buf, len, MSG_NOSIGNAL) != (ssize_t)len) { 149 if (recv(fd, buf, len, MSG_NOSIGNAL) != (ssize_t)len) {
150 DWARN("short recv (frame)"); 150 DWARN("short recv (frame)");
151 return NULL; 151 return NULL;
152 } 152 }
153 153
154 return buf; 154 return buf;
155} 155}
156 156
157 157
158perfuse_msg_t * 158perfuse_msg_t *
159perfuse_new_pb (pu, opc, opcode, payload_len, cred) 159perfuse_new_pb (pu, opc, opcode, payload_len, cred)
160 struct puffs_usermount *pu; 160 struct puffs_usermount *pu;
161 puffs_cookie_t opc; 161 puffs_cookie_t opc;
162 int opcode; 162 int opcode;
163 size_t payload_len; 163 size_t payload_len;
164 const struct puffs_cred *cred; 164 const struct puffs_cred *cred;
165{ 165{
166 struct puffs_framebuf *pb; 166 struct puffs_framebuf *pb;
167 struct fuse_in_header *fih; 167 struct fuse_in_header *fih;
168 struct puffs_cc *pcc; 168 struct puffs_cc *pcc;
169 uint64_t nodeid; 169 uint64_t nodeid;
170 void *data; 170 void *data;
171 size_t len; 171 size_t len;
172 172
173 if ((pb = puffs_framebuf_make()) == NULL) 173 if ((pb = puffs_framebuf_make()) == NULL)
174 DERR(EX_OSERR, "puffs_framebuf_make failed"); 174 DERR(EX_OSERR, "puffs_framebuf_make failed");
175 175
176 len = payload_len + sizeof(*fih); 176 len = payload_len + sizeof(*fih);
177 nodeid = (opc != 0) ? perfuse_get_ino(pu, opc) : PERFUSE_UNKNOWN_INO; 177 nodeid = (opc != 0) ? perfuse_get_ino(pu, opc) : PERFUSE_UNKNOWN_INO;
178 178
179 if (puffs_framebuf_reserve_space(pb, len) != 0) 179 if (puffs_framebuf_reserve_space(pb, len) != 0)
180 DERR(EX_OSERR, "puffs_framebuf_reserve_space failed"); 180 DERR(EX_OSERR, "puffs_framebuf_reserve_space failed");
181 181
182 if (puffs_framebuf_getwindow(pb, 0, &data, &len) != 0) 182 if (puffs_framebuf_getwindow(pb, 0, &data, &len) != 0)
183 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed"); 183 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");
184 if (len != payload_len + sizeof(*fih)) 184 if (len != payload_len + sizeof(*fih))
185 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short len"); 185 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short len");
186 186
187 (void)memset(data, 0, len); 187 (void)memset(data, 0, len);
188 fih = (struct fuse_in_header *)data; 188 fih = (struct fuse_in_header *)data;
189 fih->len = (uint32_t)len; 189 fih->len = (uint32_t)len;
190 fih->opcode = opcode; 190 fih->opcode = opcode;
191 fih->unique = perfuse_next_unique(pu); 191 fih->unique = perfuse_next_unique(pu);
192 fih->nodeid = nodeid; 192 fih->nodeid = nodeid;
193 fih->uid = (uid_t)-1; 193 fih->uid = (uid_t)-1;
194 fih->gid = (gid_t)-1; 194 fih->gid = (gid_t)-1;
195 fih->pid = 0; 195 fih->pid = 0;
196 if (cred != NULL) { 196 if (cred != NULL) {
197 (void)puffs_cred_getuid(cred, &fih->uid); 197 (void)puffs_cred_getuid(cred, &fih->uid);
198 (void)puffs_cred_getgid(cred, &fih->gid); 198 (void)puffs_cred_getgid(cred, &fih->gid);
199 } 199 }
200 if ((pcc = puffs_cc_getcc(pu)) != NULL) 200 if ((pcc = puffs_cc_getcc(pu)) != NULL)
201 (void)puffs_cc_getcaller(pcc, (pid_t *)&fih->pid, NULL); 201 (void)puffs_cc_getcaller(pcc, (pid_t *)&fih->pid, NULL);
202 202
203 return (perfuse_msg_t *)(void *)pb; 203 return (perfuse_msg_t *)(void *)pb;
204} 204}
205 205
206/* 206/*
207 * framebuf send/receive primitives based on pcc are 207 * framebuf send/receive primitives based on pcc are
208 * not available until puffs mainloop is entered. 208 * not available until puffs mainloop is entered.
209 * This xchg_pb_inloop() variant allow early communication. 209 * This xchg_pb_inloop() variant allow early communication.
210 */ 210 */
211static int 211static int
212xchg_pb_early(pu, pb, fd, reply) 212xchg_pb_early(pu, pb, fd, reply)
213 struct puffs_usermount *pu; 213 struct puffs_usermount *pu;
214 struct puffs_framebuf *pb; 214 struct puffs_framebuf *pb;
215 int fd; 215 int fd;
216 enum perfuse_xchg_pb_reply reply; 216 enum perfuse_xchg_pb_reply reply;
217{ 217{
218 int done; 218 int done;
219 int error; 219 int error;
220 220
221 done = 0; 221 done = 0;
222 while (done == 0) { 222 while (done == 0) {
223 if ((error = perfuse_writeframe(pu, pb, fd, &done)) != 0) 223 if ((error = perfuse_writeframe(pu, pb, fd, &done)) != 0)
224 return error; 224 return error;
225 } 225 }
226 226
227 if (reply == no_reply) { 227 if (reply == no_reply) {
228 puffs_framebuf_destroy(pb); 228 puffs_framebuf_destroy(pb);
229 return 0; 229 return 0;
230 } else { 230 } else {
231 puffs_framebuf_recycle(pb); 231 puffs_framebuf_recycle(pb);
232 } 232 }
233 233
234 done = 0; 234 done = 0;
235 while (done == 0) { 235 while (done == 0) {
236 if ((error = perfuse_readframe(pu, pb, fd, &done)) != 0) 236 if ((error = perfuse_readframe(pu, pb, fd, &done)) != 0)
237 return error; 237 return error;
238 } 238 }
239 239
240 return 0; 240 return 0;
241} 241}
242 242
243static int 243static int
244xchg_pb_inloop(pu, pb, fd, reply) 244xchg_pb_inloop(pu, pb, fd, reply)
245 struct puffs_usermount *pu; 245 struct puffs_usermount *pu;
246 struct puffs_framebuf *pb; 246 struct puffs_framebuf *pb;
247 int fd; 247 int fd;
248 enum perfuse_xchg_pb_reply reply; 248 enum perfuse_xchg_pb_reply reply;
249{ 249{
250 struct puffs_cc *pcc; 250 struct puffs_cc *pcc;
251 int error; 251 int error;
252 252
253 if (reply == no_reply) { 253 if (reply == no_reply) {
254 error = puffs_framev_enqueue_justsend(pu, fd, pb, 0, 0); 254 error = puffs_framev_enqueue_justsend(pu, fd, pb, 0, 0);
255 } else { 255 } else {
256 pcc = puffs_cc_getcc(pu); 256 pcc = puffs_cc_getcc(pu);
257 error = puffs_framev_enqueue_cc(pcc, fd, pb, 0); 257 error = puffs_framev_enqueue_cc(pcc, fd, pb, 0);
258 } 258 }
259 259
260 return error; 260 return error;
261} 261}
262 262
263int 263int
264perfuse_xchg_pb(pu, pm, expected_len, reply) 264perfuse_xchg_pb(pu, pm, expected_len, reply)
265 struct puffs_usermount *pu; 265 struct puffs_usermount *pu;
266 perfuse_msg_t *pm; 266 perfuse_msg_t *pm;
267 size_t expected_len; 267 size_t expected_len;
268 enum perfuse_xchg_pb_reply reply; 268 enum perfuse_xchg_pb_reply reply;
269{ 269{
270 struct puffs_framebuf *pb = (struct puffs_framebuf *)(void *)pm; 270 struct puffs_framebuf *pb = (struct puffs_framebuf *)(void *)pm;
271 int fd; 271 int fd;
272 int error; 272 int error;
273 struct fuse_out_header *foh; 273 struct fuse_out_header *foh;
274#ifdef PERFUSE_DEBUG 274#ifdef PERFUSE_DEBUG
275 struct fuse_in_header *fih; 275 struct fuse_in_header *fih;
276 uint64_t nodeid; 276 uint64_t nodeid;
277 int opcode; 277 int opcode;
278 uint64_t unique_in; 278 uint64_t unique_in;
279 uint64_t unique_out; 279 uint64_t unique_out;
280 280
281 fih = perfuse_get_inhdr(pm); 281 fih = perfuse_get_inhdr(pm);
282 unique_in = fih->unique; 282 unique_in = fih->unique;
283 nodeid = fih->nodeid; 283 nodeid = fih->nodeid;
284 opcode = fih->opcode; 284 opcode = fih->opcode;
285 285
286 if (perfuse_diagflags & PDF_FUSE) 286 if (perfuse_diagflags & PDF_FUSE)
287 DPRINTF("> unique = %"PRId64", nodeid = %"PRId64", " 287 DPRINTF("> unique = %"PRId64", nodeid = %"PRId64", "
288 "opcode = %s (%d)\n", 288 "opcode = %s (%d)\n",
289 unique_in, nodeid, perfuse_opname(opcode), opcode); 289 unique_in, nodeid, perfuse_opname(opcode), opcode);
290 290
291 if (perfuse_diagflags & PDF_DUMP) 291 if (perfuse_diagflags & PDF_DUMP)
292 perfuse_hexdump((char *)fih, fih->len); 292 perfuse_hexdump((char *)fih, fih->len);
293 293
294#endif /* PERFUSE_DEBUG */ 294#endif /* PERFUSE_DEBUG */
295 295
296 fd = (int)(long)perfuse_getspecific(pu); 296 fd = (int)(long)perfuse_getspecific(pu);
297 297
298 if (perfuse_inloop(pu)) 298 if (perfuse_inloop(pu))
299 error = xchg_pb_inloop(pu, pb, fd, reply); 299 error = xchg_pb_inloop(pu, pb, fd, reply);
300 else 300 else
301 error = xchg_pb_early(pu, pb, fd, reply); 301 error = xchg_pb_early(pu, pb, fd, reply);
302 302
303 if (error) 303 if (error)
304 DERR(EX_SOFTWARE, "xchg_pb failed"); 304 DERR(EX_SOFTWARE, "xchg_pb failed");
305 305
306 if (reply == no_reply) 306 if (reply == no_reply)
307 return 0; 307 return 0;
308 308
309 foh = perfuse_get_outhdr((perfuse_msg_t *)(void *)pb); 309 foh = perfuse_get_outhdr((perfuse_msg_t *)(void *)pb);
310#ifdef PERFUSE_DEBUG 310#ifdef PERFUSE_DEBUG
311 unique_out = foh->unique;  311 unique_out = foh->unique;
312 312
313 if (perfuse_diagflags & PDF_FUSE) 313 if (perfuse_diagflags & PDF_FUSE)
314 DPRINTF("< unique = %"PRId64", nodeid = %"PRId64", " 314 DPRINTF("< unique = %"PRId64", nodeid = %"PRId64", "
315 "opcode = %s (%d), " 315 "opcode = %s (%d), "
316 "error = %d\n", unique_out, nodeid,  316 "error = %d\n", unique_out, nodeid,
317 perfuse_opname(opcode), opcode, error); 317 perfuse_opname(opcode), opcode, error);
318 318
319 if (perfuse_diagflags & PDF_DUMP) 319 if (perfuse_diagflags & PDF_DUMP)
320 perfuse_hexdump((char *)foh, foh->len); 320 perfuse_hexdump((char *)foh, foh->len);
321 321
322 if (unique_in != unique_out) { 322 if (unique_in != unique_out) {
323 printf("%s: packet mismatch unique %"PRId64" vs %"PRId64"\n", 323 printf("%s: packet mismatch unique %"PRId64" vs %"PRId64"\n",
324 __func__, unique_in, unique_out); 324 __func__, unique_in, unique_out);
325 abort(); 325 abort();
326 errx(EX_SOFTWARE, "%s: packet mismatch unique " 326 errx(EX_SOFTWARE, "%s: packet mismatch unique "
327 "%"PRId64" vs %"PRId64"\n", 327 "%"PRId64" vs %"PRId64"\n",
328 __func__, unique_in, unique_out); 328 __func__, unique_in, unique_out);
329 } 329 }
330#endif /* PERFUSE_DEBUG */ 330#endif /* PERFUSE_DEBUG */
331  331
332 if ((expected_len != PERFUSE_UNSPEC_REPLY_LEN) && 332 if ((expected_len != PERFUSE_UNSPEC_REPLY_LEN) &&
333 (foh->len - sizeof(*foh) < expected_len) && 333 (foh->len - sizeof(*foh) < expected_len) &&
334 (foh->error == 0)) { 334 (foh->error == 0)) {
335 DERRX(EX_PROTOCOL,  335 DERRX(EX_PROTOCOL,
336 "Unexpected short reply: received %zd bytes, expected %zd", 336 "Unexpected short reply: received %zd bytes, expected %zd",
337 foh->len - sizeof(*foh), expected_len); 337 foh->len - sizeof(*foh), expected_len);
338 } 338 }
339 339
340 if ((expected_len != 0) && 340 if ((expected_len != 0) &&
341 (foh->len - sizeof(*foh) > expected_len)) 341 (foh->len - sizeof(*foh) > expected_len))
342 DWARNX("Unexpected long reply"); 342 DWARNX("Unexpected long reply");
343  343
344 /* 344 /*
345 * Negative Linux errno...  345 * Negative Linux errno...
346 */ 346 */
347 foh->error = -foh->error; 347 foh->error = -foh->error;
348 348
349 return foh->error; 349 return foh->error;
350} 350}
351 351
352 352
353struct fuse_in_header * 353struct fuse_in_header *
354perfuse_get_inhdr(pm) 354perfuse_get_inhdr(pm)
355 perfuse_msg_t *pm; 355 perfuse_msg_t *pm;
356{ 356{
357 struct puffs_framebuf *pb; 357 struct puffs_framebuf *pb;
358 struct fuse_in_header *fih; 358 struct fuse_in_header *fih;
359 void *hdr; 359 void *hdr;
360 size_t len; 360 size_t len;
361 361
362 pb = (struct puffs_framebuf *)(void *)pm; 362 pb = (struct puffs_framebuf *)(void *)pm;
363 len = sizeof(*fih); 363 len = sizeof(*fih);
364 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0) 364 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0)
365 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed"); 365 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");
366 if (len != sizeof(*fih)) 366 if (len != sizeof(*fih))
367 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header"); 367 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header");
368  368
369 fih = (struct fuse_in_header *)hdr; 369 fih = (struct fuse_in_header *)hdr;
370 370
371 return fih; 371 return fih;
372} 372}
373 373
374struct fuse_out_header * 374struct fuse_out_header *
375perfuse_get_outhdr(pm) 375perfuse_get_outhdr(pm)
376 perfuse_msg_t *pm; 376 perfuse_msg_t *pm;
377{ 377{
378 struct puffs_framebuf *pb; 378 struct puffs_framebuf *pb;
379 struct fuse_out_header *foh; 379 struct fuse_out_header *foh;
380 void *hdr; 380 void *hdr;
381 size_t len; 381 size_t len;
382 382
383 pb = (struct puffs_framebuf *)(void *)pm; 383 pb = (struct puffs_framebuf *)(void *)pm;
384 len = sizeof(*foh); 384 len = sizeof(*foh);
385 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0) 385 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0)
386 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed"); 386 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");
387 if (len != sizeof(*foh)) 387 if (len != sizeof(*foh))
388 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header"); 388 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header");
389  389
390 foh = (struct fuse_out_header *)hdr; 390 foh = (struct fuse_out_header *)hdr;
391 391
392 return foh; 392 return foh;
393} 393}
394 394
395char * 395char *
396perfuse_get_inpayload(pm) 396perfuse_get_inpayload(pm)
397 perfuse_msg_t *pm; 397 perfuse_msg_t *pm;
398{ 398{
399 struct puffs_framebuf *pb; 399 struct puffs_framebuf *pb;
400 struct fuse_in_header *fih; 400 struct fuse_in_header *fih;
401 void *hdr; 401 void *hdr;
402 void *payload; 402 void *payload;
403 size_t len; 403 size_t len;
404 404
405 pb = (struct puffs_framebuf *)(void *)pm; 405 pb = (struct puffs_framebuf *)(void *)pm;
406 len = sizeof(*fih); 406 len = sizeof(*fih);
407 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0) 407 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0)
408 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed"); 408 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");
409 if (len != sizeof(*fih)) 409 if (len != sizeof(*fih))
410 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header"); 410 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header");
411  411
412 fih = (struct fuse_in_header *)hdr; 412 fih = (struct fuse_in_header *)hdr;
413 413
414 len = fih->len - sizeof(*fih); 414 len = fih->len - sizeof(*fih);
415 if (puffs_framebuf_getwindow(pb, sizeof(*fih), &payload, &len) != 0) 415 if (puffs_framebuf_getwindow(pb, sizeof(*fih), &payload, &len) != 0)
416 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed"); 416 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");
417 if (len != fih->len - sizeof(*fih)) 417 if (len != fih->len - sizeof(*fih))
418 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header"); 418 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header");
419 419
420 return (char *)payload; 420 return (char *)payload;
421} 421}
422 422
423char * 423char *
424perfuse_get_outpayload(pm) 424perfuse_get_outpayload(pm)
425 perfuse_msg_t *pm; 425 perfuse_msg_t *pm;
426{ 426{
427 struct puffs_framebuf *pb; 427 struct puffs_framebuf *pb;
428 struct fuse_out_header *foh; 428 struct fuse_out_header *foh;
429 void *hdr; 429 void *hdr;
430 void *payload; 430 void *payload;
431 size_t len; 431 size_t len;
432 432
433 pb = (struct puffs_framebuf *)(void *)pm; 433 pb = (struct puffs_framebuf *)(void *)pm;
434 len = sizeof(*foh); 434 len = sizeof(*foh);
435 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0) 435 if (puffs_framebuf_getwindow(pb, 0, &hdr, &len) != 0)
436 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed"); 436 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");
437 if (len != sizeof(*foh)) 437 if (len != sizeof(*foh))
438 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header"); 438 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header");
439  439
440 foh = (struct fuse_out_header *)hdr; 440 foh = (struct fuse_out_header *)hdr;
441 441
442 len = foh->len - sizeof(*foh); 442 len = foh->len - sizeof(*foh);
443 if (puffs_framebuf_getwindow(pb, sizeof(*foh), &payload, &len) != 0) 443 if (puffs_framebuf_getwindow(pb, sizeof(*foh), &payload, &len) != 0)
444 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed"); 444 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");
445 if (len != foh->len - sizeof(*foh)) 445 if (len != foh->len - sizeof(*foh))
446 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header"); 446 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow short header");
447 447
448 return (char *)payload; 448 return (char *)payload;
449} 449}
450 450
451#define PUFFS_FRAMEBUF_GETWINDOW(pb, offset, data, len) \ 451#define PUFFS_FRAMEBUF_GETWINDOW(pb, offset, data, len) \
452 do { \ 452 do { \
453 int pfg_error; \ 453 int pfg_error; \
454 size_t pfg_len = *(len); \ 454 size_t pfg_len = *(len); \
455 \ 455 \
456 pfg_error = puffs_framebuf_getwindow(pb, offset, data, len); \ 456 pfg_error = puffs_framebuf_getwindow(pb, offset, data, len); \
457 if (pfg_error != 0) \ 457 if (pfg_error != 0) \
458 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");\ 458 DERR(EX_SOFTWARE, "puffs_framebuf_getwindow failed");\
459 \ 459 \
460 if (*(len) != pfg_len) \ 460 if (*(len) != pfg_len) \
461 DERRX(EX_SOFTWARE, "puffs_framebuf_getwindow size"); \ 461 DERRX(EX_SOFTWARE, "puffs_framebuf_getwindow size"); \
462 } while (0 /* CONSTCOND */); 462 } while (0 /* CONSTCOND */);
463 463
464/* ARGSUSED0 */ 464/* ARGSUSED0 */
465int 465int
466perfuse_readframe(pu, pufbuf, fd, done) 466perfuse_readframe(pu, pufbuf, fd, done)
467 struct puffs_usermount *pu; 467 struct puffs_usermount *pu;
468 struct puffs_framebuf *pufbuf; 468 struct puffs_framebuf *pufbuf;
469 int fd; 469 int fd;
470 int *done; 470 int *done;
471{ 471{
472 struct fuse_out_header foh; 472 struct fuse_out_header foh;
473 size_t len; 473 size_t len;
474 ssize_t readen; 474 ssize_t readen;
475 void *data; 475 void *data;
476 476
477 /* 477 /*
478 * Read the header  478 * Read the header
479 */ 479 */
480 len = sizeof(foh); 480 len = sizeof(foh);
481 PUFFS_FRAMEBUF_GETWINDOW(pufbuf, 0, &data, &len); 481 PUFFS_FRAMEBUF_GETWINDOW(pufbuf, 0, &data, &len);
482 482
483 switch (readen = recv(fd, data, len, MSG_NOSIGNAL|MSG_PEEK)) { 483 switch (readen = recv(fd, data, len, MSG_NOSIGNAL|MSG_PEEK)) {
484 case 0: 484 case 0:
485 DWARNX("%s: recv retunred 0", __func__); 485 DWARNX("%s: recv retunred 0", __func__);
486 return ECONNRESET; 486 return ECONNRESET;
487 /* NOTREACHED */ 487 /* NOTREACHED */
488 break; 488 break;
489 case -1: 489 case -1:
490 if (errno == EAGAIN) 490 if (errno == EAGAIN)
491 return 0; 491 return 0;
492 DWARN("%s: recv retunred -1", __func__); 492 DWARN("%s: recv retunred -1", __func__);
493 return errno; 493 return errno;
494 /* NOTREACHED */ 494 /* NOTREACHED */
495 break; 495 break;
496 default: 496 default:
497 break; 497 break;
498 } 498 }
499 499
500#ifdef PERFUSE_DEBUG 500#ifdef PERFUSE_DEBUG
501 if (readen != len) 501 if (readen != (ssize_t)len)
502 DERRX(EX_SOFTWARE, "%s: short recv %zd/%zd", 502 DERRX(EX_SOFTWARE, "%s: short recv %zd/%zd",
503 __func__, readen, len); 503 __func__, readen, len);
504#endif 504#endif
505 505
506 /* 506 /*
507 * We have a header, get remaing length to read 507 * We have a header, get remaing length to read
508 */ 508 */
509 if (puffs_framebuf_getdata_atoff(pufbuf, 0, &foh, sizeof(foh)) != 0) 509 if (puffs_framebuf_getdata_atoff(pufbuf, 0, &foh, sizeof(foh)) != 0)
510 DERR(EX_SOFTWARE, "puffs_framebuf_getdata_atoff failed"); 510 DERR(EX_SOFTWARE, "puffs_framebuf_getdata_atoff failed");
511 511
512 len = foh.len; 512 len = foh.len;
513 513
514#ifdef PERFUSE_DEBUG 514#ifdef PERFUSE_DEBUG
515 if (len > FUSE_BUFSIZE) 515 if (len > FUSE_BUFSIZE)
516 DERRX(EX_SOFTWARE, "%s: foh.len = %d", __func__, len); 516 DERRX(EX_SOFTWARE, "%s: foh.len = %zu", __func__, len);
517#endif 517#endif
518 518
519 /* 519 /*
520 * This is time to reserve space. 520 * This is time to reserve space.
521 */ 521 */
522 if (puffs_framebuf_reserve_space(pufbuf, len) == -1) 522 if (puffs_framebuf_reserve_space(pufbuf, len) == -1)
523 DERR(EX_OSERR, "puffs_framebuf_reserve_space failed"); 523 DERR(EX_OSERR, "puffs_framebuf_reserve_space failed");
524 524
525 /* 525 /*
526 * And read the remaining data 526 * And read the remaining data
527 */  527 */
528 PUFFS_FRAMEBUF_GETWINDOW(pufbuf, 0, &data, &len); 528 PUFFS_FRAMEBUF_GETWINDOW(pufbuf, 0, &data, &len);
529 529
530 switch (readen = recv(fd, data, len, MSG_NOSIGNAL)) { 530 switch (readen = recv(fd, data, len, MSG_NOSIGNAL)) {
531 case 0: 531 case 0:
532 DWARNX("%s: recv retunred 0", __func__); 532 DWARNX("%s: recv retunred 0", __func__);
533 return ECONNRESET; 533 return ECONNRESET;
534 /* NOTREACHED */ 534 /* NOTREACHED */
535 break; 535 break;
536 case -1: 536 case -1:
537 if (errno == EAGAIN) 537 if (errno == EAGAIN)
538 return 0; 538 return 0;
539 DWARN("%s: recv retunred -1", __func__); 539 DWARN("%s: recv retunred -1", __func__);
540 return errno; 540 return errno;
541 /* NOTREACHED */ 541 /* NOTREACHED */
542 break; 542 break;
543 default: 543 default:
544 break; 544 break;
545 } 545 }
546 546
547#ifdef PERFUSE_DEBUG 547#ifdef PERFUSE_DEBUG
548 if (readen != len) 548 if (readen != (ssize_t)len)
549 DERRX(EX_SOFTWARE, "%s: short recv %zd/%zd", 549 DERRX(EX_SOFTWARE, "%s: short recv %zd/%zd",
550 __func__, readen, len); 550 __func__, readen, len);
551#endif 551#endif
552 552
553 *done = 1; 553 *done = 1;
554 return 0; 554 return 0;
555} 555}
556 556
557/* ARGSUSED0 */ 557/* ARGSUSED0 */
558int 558int
559perfuse_writeframe(pu, pufbuf, fd, done) 559perfuse_writeframe(pu, pufbuf, fd, done)
560 struct puffs_usermount *pu; 560 struct puffs_usermount *pu;
561 struct puffs_framebuf *pufbuf; 561 struct puffs_framebuf *pufbuf;
562 int fd; 562 int fd;
563 int *done; 563 int *done;
564{ 564{
565 size_t len; 565 size_t len;
566 ssize_t written; 566 ssize_t written;
567 void *data; 567 void *data;
568 568
569 len = puffs_framebuf_tellsize(pufbuf); 569 len = puffs_framebuf_tellsize(pufbuf);
570 PUFFS_FRAMEBUF_GETWINDOW(pufbuf, 0, &data, &len); 570 PUFFS_FRAMEBUF_GETWINDOW(pufbuf, 0, &data, &len);
571 571
572 switch (written = send(fd, data, len, MSG_NOSIGNAL)) { 572 switch (written = send(fd, data, len, MSG_NOSIGNAL)) {
573 case 0: 573 case 0:
574 DWARNX("%s: send retunred 0", __func__); 574 DWARNX("%s: send retunred 0", __func__);
575 return ECONNRESET; 575 return ECONNRESET;
576 /* NOTREACHED */ 576 /* NOTREACHED */
577 break; 577 break;
578 case -1: 578 case -1:
579 if (errno == EAGAIN) 579 DWARN("%s: send retunred -1, errno = %d", __func__, errno);
 580 switch(errno) {
 581 case EAGAIN:
 582 case ENOBUFS:
580 return 0; 583 return 0;
581 DWARN("%s: send retunred -1", __func__); 584 break;
582 return errno; 585 default:
 586 return errno;
 587 break;
 588 }
583 /* NOTREACHED */ 589 /* NOTREACHED */
584 break; 590 break;
585 default: 591 default:
586 break; 592 break;
587 } 593 }
588 594
589#ifdef PERFUSE_DEBUG 595#ifdef PERFUSE_DEBUG
590 if (written != len) 596 if (written != (ssize_t)len)
591 DERRX(EX_SOFTWARE, "%s: short send %zd/%zd", 597 DERRX(EX_SOFTWARE, "%s: short send %zd/%zd",
592 __func__, written, len); 598 __func__, written, len);
593#endif 599#endif
594 600
595 *done = 1; 601 *done = 1;
596 return 0; 602 return 0;
597} 603}
598 604
599/* ARGSUSED0 */ 605/* ARGSUSED0 */
600int 606int
601perfuse_cmpframe(pu, pb1, pb2, match) 607perfuse_cmpframe(pu, pb1, pb2, match)
602 struct puffs_usermount *pu; 608 struct puffs_usermount *pu;
603 struct puffs_framebuf *pb1; 609 struct puffs_framebuf *pb1;
604 struct puffs_framebuf *pb2; 610 struct puffs_framebuf *pb2;
605 int *match; 611 int *match;
606{ 612{
607 struct fuse_in_header *fih; 613 struct fuse_in_header *fih;
608 struct fuse_out_header *foh; 614 struct fuse_out_header *foh;
609 uint64_t unique_in; 615 uint64_t unique_in;
610 uint64_t unique_out; 616 uint64_t unique_out;
611 size_t len; 617 size_t len;
612 618
613 len = sizeof(*fih); 619 len = sizeof(*fih);
614 PUFFS_FRAMEBUF_GETWINDOW(pb1, 0, (void **)&fih, &len); 620 PUFFS_FRAMEBUF_GETWINDOW(pb1, 0, (void **)&fih, &len);
615 unique_in = fih->unique; 621 unique_in = fih->unique;
616 622
617 len = sizeof(*foh); 623 len = sizeof(*foh);
618 PUFFS_FRAMEBUF_GETWINDOW(pb2, 0, (void **)&foh, &len); 624 PUFFS_FRAMEBUF_GETWINDOW(pb2, 0, (void **)&foh, &len);
619 unique_out = foh->unique; 625 unique_out = foh->unique;
620 626
621 return unique_in != unique_out; 627 return unique_in != unique_out;
622} 628}
623 629
624/* ARGSUSED0 */ 630/* ARGSUSED0 */
625void 631void
626perfuse_gotframe(pu, pb) 632perfuse_gotframe(pu, pb)
627 struct puffs_usermount *pu; 633 struct puffs_usermount *pu;
628 struct puffs_framebuf *pb; 634 struct puffs_framebuf *pb;
629{ 635{
630 struct fuse_out_header *foh; 636 struct fuse_out_header *foh;
631 size_t len; 637 size_t len;
632 638
633 len = sizeof(*foh); 639 len = sizeof(*foh);
634 PUFFS_FRAMEBUF_GETWINDOW(pb, 0, (void **)&foh, &len); 640 PUFFS_FRAMEBUF_GETWINDOW(pb, 0, (void **)&foh, &len);
635 641
636 DWARNX("Unexpected frame: unique = %"PRId64", error = %d",  642 DWARNX("Unexpected frame: unique = %"PRId64", error = %d",
637 foh->unique, foh->error); 643 foh->unique, foh->error);
638#ifdef PERFUSE_DEBUG 644#ifdef PERFUSE_DEBUG
639 perfuse_hexdump((char *)(void *)foh, foh->len); 645 perfuse_hexdump((char *)(void *)foh, foh->len);
640#endif 646#endif
641 647
642 return;  648 return;
643} 649}
644 650
645void 651void
646perfuse_fdnotify(pu, fd, what) 652perfuse_fdnotify(pu, fd, what)
647 struct puffs_usermount *pu; 653 struct puffs_usermount *pu;
648 int fd; 654 int fd;
649 int what; 655 int what;
650{ 656{
651 if (fd != (int)(long)perfuse_getspecific(pu)) 657 if (fd != (int)(long)perfuse_getspecific(pu))
652 DERRX(EX_SOFTWARE, "%s: unexpected notification for fd = %d", 658 DERRX(EX_SOFTWARE, "%s: unexpected notification for fd = %d",
653 __func__, fd);  659 __func__, fd);
654 660
655 if ((what != PUFFS_FBIO_READ) && (what != PUFFS_FBIO_WRITE)) 661 if ((what != PUFFS_FBIO_READ) && (what != PUFFS_FBIO_WRITE))
656 DERRX(EX_SOFTWARE, "%s: unexpected notification what = 0x%x", 662 DERRX(EX_SOFTWARE, "%s: unexpected notification what = 0x%x",
657 __func__, what);  663 __func__, what);
658 664
659 if (perfuse_unmount(pu) != 0) 665 if (perfuse_unmount(pu) != 0)
660 DWARN("unmount() failed"); 666 DWARN("unmount() failed");
661 667
662 if (shutdown(fd, SHUT_RDWR) != 0) 668 if (shutdown(fd, SHUT_RDWR) != 0)
663 DWARN("shutdown() failed"); 669 DWARN("shutdown() failed");
664 670
665 if (perfuse_diagflags & PDF_MISC) 671 if (perfuse_diagflags & PDF_MISC)
666 DPRINTF("Exit"); 672 DPRINTF("Exit");
667  673
668 exit(0); 674 exit(0);
669  675
670 /* NOTREACHED */ 676 /* NOTREACHED */
671 return; 677 return;
672} 678}

cvs diff -r1.11 -r1.12 src/usr.sbin/perfused/perfused.c (switch to unified diff)

--- src/usr.sbin/perfused/perfused.c 2010/10/11 05:37:58 1.11
+++ src/usr.sbin/perfused/perfused.c 2011/04/25 04:30:59 1.12
@@ -1,412 +1,412 @@ @@ -1,412 +1,412 @@
1/* $NetBSD: perfused.c,v 1.11 2010/10/11 05:37:58 manu Exp $ */ 1/* $NetBSD: perfused.c,v 1.12 2011/04/25 04:30:59 manu Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved. 4 * Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
5 *  5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 *  14 *
15 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 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 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 17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 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 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE. 25 * POSSIBILITY OF SUCH DAMAGE.
26 */  26 */
27 27
28#include <stdio.h> 28#include <stdio.h>
29#include <unistd.h> 29#include <unistd.h>
30#include <stdlib.h> 30#include <stdlib.h>
31#include <fcntl.h> 31#include <fcntl.h>
32#include <syslog.h> 32#include <syslog.h>
33#include <ctype.h> 33#include <ctype.h>
34#include <paths.h> 34#include <paths.h>
35#include <stdarg.h> 35#include <stdarg.h>
36#include <err.h> 36#include <err.h>
37#include <errno.h> 37#include <errno.h>
38#include <string.h> 38#include <string.h>
39#include <sysexits.h> 39#include <sysexits.h>
40#include <signal.h> 40#include <signal.h>
41#include <puffs.h> 41#include <puffs.h>
42#include <sys/wait.h> 42#include <sys/wait.h>
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/queue.h> 44#include <sys/queue.h>
45#include <sys/uio.h> 45#include <sys/uio.h>
46#include <sys/socket.h> 46#include <sys/socket.h>
47#include <sys/un.h> 47#include <sys/un.h>
48#include <machine/vmparam.h> 48#include <machine/vmparam.h>
49 49
50#include "../../lib/libperfuse/perfuse_if.h" 50#include "../../lib/libperfuse/perfuse_if.h"
51#include "perfused.h" 51#include "perfused.h"
52 52
53static int access_mount(const char *, uid_t, int); 53static int access_mount(const char *, uid_t, int);
54static void new_mount(int, int); 54static void new_mount(int, int);
55static int parse_debug(char *); 55static int parse_debug(char *);
56static void siginfo_handler(int); 56static void siginfo_handler(int);
57static int parse_options(int, char **); 57static int parse_options(int, char **);
58static void get_mount_info(int, struct perfuse_mount_info *); 58static void get_mount_info(int, struct perfuse_mount_info *);
59int main(int, char **); 59int main(int, char **);
60 60
61/* 61/*
62 * Flags for new_mount() 62 * Flags for new_mount()
63 */ 63 */
64#define PMNT_DEVFUSE 0x0 /* We use /dev/fuse */ 64#define PMNT_DEVFUSE 0x0 /* We use /dev/fuse */
65#define PMNT_SOCKPAIR 0x1 /* We use socketpair */ 65#define PMNT_SOCKPAIR 0x1 /* We use socketpair */
66 66
67 67
68static int 68static int
69access_mount(mnt, uid, ro) 69access_mount(mnt, uid, ro)
70 const char *mnt; 70 const char *mnt;
71 uid_t uid; 71 uid_t uid;
72 int ro; 72 int ro;
73{ 73{
74 struct stat st; 74 struct stat st;
75 mode_t mode; 75 mode_t mode;
76 76
77 if (uid == 0) 77 if (uid == 0)
78 return 0; 78 return 0;
79 79
80 if (stat(mnt, &st) == -1) 80 if (stat(mnt, &st) == -1)
81 return -1; 81 return -1;
82  82
83 if (st.st_uid != uid) 83 if (st.st_uid != uid)
84 return -1; 84 return -1;
85 85
86 mode = S_IRUSR; 86 mode = S_IRUSR;
87 if (!ro) 87 if (!ro)
88 mode |= S_IWUSR; 88 mode |= S_IWUSR;
89  89
90 if ((st.st_mode & mode) == mode) 90 if ((st.st_mode & mode) == mode)
91 return 0; 91 return 0;
92 92
93 return -1; 93 return -1;
94} 94}
95 95
96static void 96static void
97get_mount_info(fd, pmi) 97get_mount_info(fd, pmi)
98 int fd; 98 int fd;
99 struct perfuse_mount_info *pmi; 99 struct perfuse_mount_info *pmi;
100{ 100{
101 struct perfuse_mount_out *pmo; 101 struct perfuse_mount_out *pmo;
102 struct sockcred cred; 102 struct sockcred cred;
103 int opt; 103 int opt;
104 char *cp; 104 char *cp;
105 char *source = NULL; 105 char *source = NULL;
106 char *target = NULL; 106 char *target = NULL;
107 char *filesystemtype = NULL; 107 char *filesystemtype = NULL;
108 long mountflags = 0; 108 long mountflags = 0;
109 void *data = NULL; 109 void *data = NULL;
110 char *sock = NULL; 110 char *sock = NULL;
111 111
112 pmo = (struct perfuse_mount_out *) 112 pmo = (struct perfuse_mount_out *)
113 perfuse_recv_early(fd, &cred, sizeof(cred)); 113 perfuse_recv_early(fd, &cred, sizeof(cred));
114 114
115 if (pmo == NULL) { 115 if (pmo == NULL) {
116 if (shutdown(fd, SHUT_RDWR) != 0) 116 if (shutdown(fd, SHUT_RDWR) != 0)
117 DERR(EX_OSERR, "shutdown failed"); 117 DERR(EX_OSERR, "shutdown failed");
118 exit(EX_PROTOCOL); 118 exit(EX_PROTOCOL);
119 } 119 }
120 120
121 /* 121 /*
122 * We do not need peer creds beyond this point 122 * We do not need peer creds beyond this point
123 */ 123 */
124 opt = 0; 124 opt = 0;
125 if (setsockopt(fd, 0, LOCAL_CREDS, &opt, sizeof(opt)) != 0) 125 if (setsockopt(fd, 0, LOCAL_CREDS, &opt, sizeof(opt)) != 0)
126 DWARN("%s: setsockopt LOCAL_CREDS failed", __func__); 126 DWARN("%s: setsockopt LOCAL_CREDS failed", __func__);
127 127
128#ifdef PERFUSE_DEBUG 128#ifdef PERFUSE_DEBUG
129 if (perfuse_diagflags & PDF_MISC) 129 if (perfuse_diagflags & PDF_MISC)
130 DPRINTF("perfuse lengths: source = %"PRId32", " 130 DPRINTF("perfuse lengths: source = %"PRId32", "
131 "target = %"PRId32", filesystemtype = %"PRId32", " 131 "target = %"PRId32", filesystemtype = %"PRId32", "
132 "data = %"PRId32", sock = %"PRId32"\n",  132 "data = %"PRId32", sock = %"PRId32"\n",
133 pmo->pmo_source_len, pmo->pmo_target_len,  133 pmo->pmo_source_len, pmo->pmo_target_len,
134 pmo->pmo_filesystemtype_len, pmo->pmo_data_len, 134 pmo->pmo_filesystemtype_len, pmo->pmo_data_len,
135 pmo->pmo_sock_len); 135 pmo->pmo_sock_len);
136#endif 136#endif
137 cp = (char *)(void *)(pmo + 1); 137 cp = (char *)(void *)(pmo + 1);
138  138
139 if (pmo->pmo_source_len != 0) { 139 if (pmo->pmo_source_len != 0) {
140 source = cp; 140 source = cp;
141 cp += pmo->pmo_source_len; 141 cp += pmo->pmo_source_len;
142 } 142 }
143 143
144 if (pmo->pmo_target_len != 0) { 144 if (pmo->pmo_target_len != 0) {
145 target = cp; 145 target = cp;
146 cp += pmo->pmo_target_len; 146 cp += pmo->pmo_target_len;
147 } 147 }
148 148
149 if (pmo->pmo_filesystemtype_len != 0) { 149 if (pmo->pmo_filesystemtype_len != 0) {
150 filesystemtype = cp; 150 filesystemtype = cp;
151 cp += pmo->pmo_filesystemtype_len; 151 cp += pmo->pmo_filesystemtype_len;
152 } 152 }
153 153
154 mountflags = pmo->pmo_mountflags; 154 mountflags = pmo->pmo_mountflags;
155 155
156 if (pmo->pmo_data_len != 0) { 156 if (pmo->pmo_data_len != 0) {
157 data = cp; 157 data = cp;
158 cp += pmo->pmo_data_len; 158 cp += pmo->pmo_data_len;
159 } 159 }
160 160
161 if (pmo->pmo_sock_len != 0) { 161 if (pmo->pmo_sock_len != 0) {
162 sock = cp; 162 sock = cp;
163 cp += pmo->pmo_sock_len; 163 cp += pmo->pmo_sock_len;
164 } 164 }
165 165
166#ifdef PERFUSE_DEBUG 166#ifdef PERFUSE_DEBUG
167 if (perfuse_diagflags & PDF_MISC) 167 if (perfuse_diagflags & PDF_MISC)
168 DPRINTF("%s(\"%s\", \"%s\", \"%s\", 0x%lx, \"%s\", \"%s\")\n",  168 DPRINTF("%s(\"%s\", \"%s\", \"%s\", 0x%lx, \"%s\", \"%s\")\n",
169 __func__, source, target, filesystemtype,  169 __func__, source, target, filesystemtype,
170 mountflags, (const char *)data, sock); 170 mountflags, (const char *)data, sock);
171#endif 171#endif
172 pmi->pmi_source = source; 172 pmi->pmi_source = source;
173 pmi->pmi_target = target; 173 pmi->pmi_target = target;
174 pmi->pmi_filesystemtype = filesystemtype; 174 pmi->pmi_filesystemtype = filesystemtype;
175 pmi->pmi_mountflags = (int)mountflags; 175 pmi->pmi_mountflags = (int)mountflags;
176 pmi->pmi_data = data; 176 pmi->pmi_data = data;
177 177
178 pmi->pmi_uid = cred.sc_euid; 178 pmi->pmi_uid = cred.sc_euid;
179 179
180 /* 180 /*
181 * Connect to the remote socket, if provided 181 * Connect to the remote socket, if provided
182 */ 182 */
183 if (sock) { 183 if (sock) {
184 const struct sockaddr *sa; 184 const struct sockaddr *sa;
185 struct sockaddr_un sun; 185 struct sockaddr_un sun;
186 186
187 sa = (const struct sockaddr *)(void *)&sun; 187 sa = (const struct sockaddr *)(void *)&sun;
188 sun.sun_len = sizeof(sun); 188 sun.sun_len = sizeof(sun);
189 sun.sun_family = AF_LOCAL; 189 sun.sun_family = AF_LOCAL;
190 strcpy(sun.sun_path, sock); 190 strcpy(sun.sun_path, sock);
191 191
192 if (connect(fd, sa, sun.sun_len) != 0) 192 if (connect(fd, sa, sun.sun_len) != 0)
193 DERR(EX_OSERR, "connect \"%s\" failed", sun.sun_path); 193 DERR(EX_OSERR, "connect \"%s\" failed", sun.sun_path);
194 } 194 }
195 195
196 return; 196 return;
197} 197}
198 198
199static void 199static void
200new_mount(fd, pmnt_flags) 200new_mount(fd, pmnt_flags)
201 int fd; 201 int fd;
202 int pmnt_flags; 202 int pmnt_flags;
203{ 203{
204 struct puffs_usermount *pu; 204 struct puffs_usermount *pu;
205 struct perfuse_mount_info pmi; 205 struct perfuse_mount_info pmi;
206 struct perfuse_callbacks pc; 206 struct perfuse_callbacks pc;
207 int ro_flag; 207 int ro_flag;
208 pid_t pid; 208 pid_t pid;
209 int flags; 209 int flags;
210 210
211 pid = (perfuse_diagflags & PDF_FOREGROUND) ? 0 : fork(); 211 pid = (perfuse_diagflags & PDF_FOREGROUND) ? 0 : fork();
212 switch(pid) { 212 switch(pid) {
213 case -1: 213 case -1:
214 DERR(EX_OSERR, "cannot fork"); 214 DERR(EX_OSERR, "cannot fork");
215 break; 215 break;
216 case 0: 216 case 0:
217 break; 217 break;
218 default: 218 default:
219 return; 219 return;
220 /* NOTREACHED */ 220 /* NOTREACHED */
221 break; 221 break;
222 } 222 }
223 223
224 /* 224 /*
225 * Mount information (source, target, mount flags...) 225 * Mount information (source, target, mount flags...)
226 */ 226 */
227 get_mount_info(fd, &pmi); 227 get_mount_info(fd, &pmi);
228 228
229 /* 229 /*
230 * Check that peer owns mountpoint and read (and write) on it? 230 * Check that peer owns mountpoint and read (and write) on it?
231 */ 231 */
232 ro_flag = pmi.pmi_mountflags & MNT_RDONLY; 232 ro_flag = pmi.pmi_mountflags & MNT_RDONLY;
233 if (access_mount(pmi.pmi_target, pmi.pmi_uid, ro_flag) != 0) 233 if (access_mount(pmi.pmi_target, pmi.pmi_uid, ro_flag) != 0)
234 DERRX(EX_NOPERM, "insuficient privileges to mount on %s",  234 DERRX(EX_NOPERM, "insuficient privileges to mount on %s",
235 pmi.pmi_target); 235 pmi.pmi_target);
236 236
237 237
238 /* 238 /*
239 * Initialize libperfuse, which will initialize libpuffs 239 * Initialize libperfuse, which will initialize libpuffs
240 */ 240 */
241 pc.pc_new_msg = perfuse_new_pb; 241 pc.pc_new_msg = perfuse_new_pb;
242 pc.pc_xchg_msg = perfuse_xchg_pb; 242 pc.pc_xchg_msg = perfuse_xchg_pb;
243 pc.pc_destroy_msg = (perfuse_destroy_msg_fn)puffs_framebuf_destroy; 243 pc.pc_destroy_msg = (perfuse_destroy_msg_fn)puffs_framebuf_destroy;
244 pc.pc_get_inhdr = perfuse_get_inhdr; 244 pc.pc_get_inhdr = perfuse_get_inhdr;
245 pc.pc_get_inpayload = perfuse_get_inpayload; 245 pc.pc_get_inpayload = perfuse_get_inpayload;
246 pc.pc_get_outhdr = perfuse_get_outhdr; 246 pc.pc_get_outhdr = perfuse_get_outhdr;
247 pc.pc_get_outpayload = perfuse_get_outpayload; 247 pc.pc_get_outpayload = perfuse_get_outpayload;
248 248
249 pu = perfuse_init(&pc, &pmi); 249 pu = perfuse_init(&pc, &pmi);
250  250
251 puffs_framev_init(pu, perfuse_readframe, perfuse_writeframe,  251 puffs_framev_init(pu, perfuse_readframe, perfuse_writeframe,
252 perfuse_cmpframe, perfuse_gotframe, perfuse_fdnotify); 252 perfuse_cmpframe, perfuse_gotframe, perfuse_fdnotify);
253 253
254 if (puffs_framev_addfd(pu, fd, PUFFS_FBIO_READ|PUFFS_FBIO_WRITE) == -1) 254 if (puffs_framev_addfd(pu, fd, PUFFS_FBIO_READ|PUFFS_FBIO_WRITE) == -1)
255 DERR(EX_SOFTWARE, "puffs_framev_addfd failed"); 255 DERR(EX_SOFTWARE, "puffs_framev_addfd failed");
256 256
257 perfuse_setspecific(pu, (void *)(long)fd); 257 perfuse_setspecific(pu, (void *)(long)fd);
258 258
259 setproctitle("perfused %s", pmi.pmi_target); 259 setproctitle("perfused %s", pmi.pmi_target);
260 (void)kill(getpid(), SIGINFO); /* This is for -s option */ 260 (void)kill(getpid(), SIGINFO); /* This is for -s option */
261 261
262 perfuse_fs_init(pu); 262 perfuse_fs_init(pu);
263 263
264 /* 264 /*
265 * Non blocking I/O on /dev/fuse 265 * Non blocking I/O on /dev/fuse
266 * This must be done after perfuse_fs_init 266 * This must be done after perfuse_fs_init
267 */ 267 */
268 if ((flags = fcntl(fd, F_GETFL, 0)) == -1) 268 if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
269 DERR(EX_OSERR, "fcntl failed"); 269 DERR(EX_OSERR, "fcntl failed");
270 if (fcntl(fd, F_SETFL, flags|O_NONBLOCK) != 0) 270 if (fcntl(fd, F_SETFL, flags|O_NONBLOCK) != 0)
271 DERR(EX_OSERR, "fcntl failed"); 271 DERR(EX_OSERR, "fcntl failed");
272 272
273 /* 273 /*
274 * Hand over control to puffs main loop. 274 * Hand over control to puffs main loop.
275 */ 275 */
276 (void)perfuse_mainloop(pu); 276 (void)perfuse_mainloop(pu);
277 277
278 DERRX(EX_SOFTWARE, "perfuse_mainloop exit"); 278 DERRX(EX_SOFTWARE, "perfuse_mainloop exit");
279 279
280 /* NOTREACHED */ 280 /* NOTREACHED */
281 return; 281 return;
282} 282}
283 283
284static int  284static int
285parse_debug(optstr) 285parse_debug(optstr)
286 char *optstr; 286 char *optstr;
287{ 287{
288 int retval = PDF_SYSLOG; 288 int retval = PDF_SYSLOG;
289 char *opt; 289 char *opt;
290 char *lastp; 290 char *lastp;
291 291
292 for (opt = strtok_r(optstr, ",", &lastp); 292 for (opt = strtok_r(optstr, ",", &lastp);
293 opt; 293 opt;
294 opt = strtok_r(NULL, ",", &lastp)) { 294 opt = strtok_r(NULL, ",", &lastp)) {
295 if (strcmp(opt, "fuse") == 0) 295 if (strcmp(opt, "fuse") == 0)
296 retval |= PDF_FUSE; 296 retval |= PDF_FUSE;
297 else if (strcmp(opt, "puffs") == 0) 297 else if (strcmp(opt, "puffs") == 0)
298 retval |= PDF_PUFFS; 298 retval |= PDF_PUFFS;
299 else if (strcmp(opt, "dump") == 0) 299 else if (strcmp(opt, "dump") == 0)
300 retval |= PDF_DUMP; 300 retval |= PDF_DUMP;
301 else if (strcmp(opt, "fh") == 0) 301 else if (strcmp(opt, "fh") == 0)
302 retval |= PDF_FH; 302 retval |= PDF_FH;
303 else if (strcmp(opt, "readdir") == 0) 303 else if (strcmp(opt, "readdir") == 0)
304 retval |= PDF_READDIR; 304 retval |= PDF_READDIR;
305 else if (strcmp(opt, "reclaim") == 0) 305 else if (strcmp(opt, "reclaim") == 0)
306 retval |= PDF_RECLAIM; 306 retval |= PDF_RECLAIM;
307 else if (strcmp(opt, "requeue") == 0) 307 else if (strcmp(opt, "requeue") == 0)
308 retval |= PDF_REQUEUE; 308 retval |= PDF_REQUEUE;
309 else if (strcmp(opt, "sync") == 0) 309 else if (strcmp(opt, "sync") == 0)
310 retval |= PDF_SYNC; 310 retval |= PDF_SYNC;
311 else if (strcmp(opt, "misc") == 0) 311 else if (strcmp(opt, "misc") == 0)
312 retval |= PDF_MISC; 312 retval |= PDF_MISC;
313 else if (strcmp(opt, "filename") == 0) 313 else if (strcmp(opt, "filename") == 0)
314 retval |= PDF_FILENAME; 314 retval |= PDF_FILENAME;
315 else 315 else
316 DERRX(EX_USAGE, "unknown debug flag \"%s\"", opt); 316 DERRX(EX_USAGE, "unknown debug flag \"%s\"", opt);
317 } 317 }
318 318
319 return retval; 319 return retval;
320} 320}
321 321
322/* ARGSUSED0 */ 322/* ARGSUSED0 */
323static void 323static void
324siginfo_handler(sig) 324siginfo_handler(sig)
325 int sig; 325 int sig;
326{ 326{
327 static int old_flags = 0; 327 static int old_flags = 0;
328 int swap; 328 int swap;
329 329
330 swap = perfuse_diagflags; 330 swap = perfuse_diagflags;
331 perfuse_diagflags = old_flags; 331 perfuse_diagflags = old_flags;
332 old_flags = swap; 332 old_flags = swap;
333 333
334 DWARNX("debug %sabled", old_flags == 0 ? "en" : "dis"); 334 DWARNX("debug %sabled", old_flags == 0 ? "en" : "dis");
335 335
336 return; 336 return;
337} 337}
338 338
339static int 339static int
340parse_options(argc, argv) 340parse_options(argc, argv)
341 int argc; 341 int argc;
342 char **argv; 342 char **argv;
343{ 343{
344 int ch; 344 int ch;
345 int foreground = 0; 345 int foreground = 0;
346 int retval = -1; 346 int retval = -1;
347 347
348 perfuse_diagflags = PDF_FOREGROUND | PDF_SYSLOG; 348 perfuse_diagflags = PDF_FOREGROUND | PDF_SYSLOG;
349 349
350 while ((ch = getopt(argc, argv, "d:fsi:")) != -1) { 350 while ((ch = getopt(argc, argv, "d:fsi:")) != -1) {
351 switch (ch) { 351 switch (ch) {
352 case 'd': 352 case 'd':
353 perfuse_diagflags |= parse_debug(optarg); 353 perfuse_diagflags |= parse_debug(optarg);
354 break; 354 break;
355 case 's': 355 case 's':
356 if (signal(SIGINFO, siginfo_handler) != 0) 356 if (signal(SIGINFO, siginfo_handler) != 0)
357 DERR(EX_OSERR, "signal failed"); 357 DERR(EX_OSERR, "signal failed");
358 break; 358 break;
359 case 'f': 359 case 'f':
360 foreground = 1; 360 foreground = 1;
361 perfuse_diagflags |= PDF_MISC; 361 perfuse_diagflags |= PDF_MISC;
362 break; 362 break;
363 case 'i': 363 case 'i':
364 retval = atoi(optarg); 364 retval = atoi(optarg);
365 foreground = 1; 365 foreground = 1;
366 break; 366 break;
367 default: 367 default:
368 DERR(EX_USAGE, "%s [-fs] [-d level] [-i fd]", argv[0]); 368 DERRX(EX_USAGE, "%s [-fs] [-d classes] [-i fd]", argv[0]);
369 break; 369 break;
370 } 370 }
371 } 371 }
372  372
373 if (!foreground) 373 if (!foreground)
374 perfuse_diagflags &= ~PDF_FOREGROUND; 374 perfuse_diagflags &= ~PDF_FOREGROUND;
375 375
376 return retval;  376 return retval;
377} 377}
378 378
379int 379int
380main(argc, argv) 380main(argc, argv)
381 int argc; 381 int argc;
382 char **argv; 382 char **argv;
383{ 383{
384 int s; 384 int s;
385 385
386 s = parse_options(argc, argv); 386 s = parse_options(argc, argv);
387 387
388 if (perfuse_diagflags & PDF_SYSLOG) 388 if (perfuse_diagflags & PDF_SYSLOG)
389 openlog("perfused", 0, LOG_DAEMON); 389 openlog("perfused", 0, LOG_DAEMON);
390 390
391 if (!(perfuse_diagflags & PDF_FOREGROUND)) 391 if (!(perfuse_diagflags & PDF_FOREGROUND))
392 if (daemon(0, 0) != 0) 392 if (daemon(0, 0) != 0)
393 DERR(EX_OSERR, "daemon failed"); 393 DERR(EX_OSERR, "daemon failed");
394 394
395 if (s != -1) { 395 if (s != -1) {
396 new_mount(s, PMNT_SOCKPAIR); 396 new_mount(s, PMNT_SOCKPAIR);
397 DERRX(EX_SOFTWARE, "new_mount exit while -i is used"); 397 DERRX(EX_SOFTWARE, "new_mount exit while -i is used");
398 } 398 }
399 399
400 s = perfuse_open_sock(); 400 s = perfuse_open_sock();
401  401
402 do { 402 do {
403#ifdef PERFUSE_DEBUG 403#ifdef PERFUSE_DEBUG
404 if (perfuse_diagflags & PDF_MISC) 404 if (perfuse_diagflags & PDF_MISC)
405 DPRINTF("perfused ready\n"); 405 DPRINTF("perfused ready\n");
406#endif 406#endif
407 new_mount(s, PMNT_DEVFUSE); 407 new_mount(s, PMNT_DEVFUSE);
408 } while (1 /* CONSTCOND */); 408 } while (1 /* CONSTCOND */);
409  409
410 /* NOTREACHED */ 410 /* NOTREACHED */
411 return 0; 411 return 0;
412} 412}