| @@ -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 | |
47 | static int xchg_pb_inloop(struct puffs_usermount *a, struct puffs_framebuf *, | | 47 | static 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); |
49 | static int xchg_pb_early(struct puffs_usermount *a, struct puffs_framebuf *, | | 49 | static 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 | |
52 | int | | 52 | int |
53 | perfuse_open_sock(void) | | 53 | perfuse_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 | |
100 | void * | | 100 | void * |
101 | perfuse_recv_early(fd, sockcred, sockcred_len) | | 101 | perfuse_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 | |
158 | perfuse_msg_t * | | 158 | perfuse_msg_t * |
159 | perfuse_new_pb (pu, opc, opcode, payload_len, cred) | | 159 | perfuse_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 | */ |
211 | static int | | 211 | static int |
212 | xchg_pb_early(pu, pb, fd, reply) | | 212 | xchg_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 | |
243 | static int | | 243 | static int |
244 | xchg_pb_inloop(pu, pb, fd, reply) | | 244 | xchg_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 | |
263 | int | | 263 | int |
264 | perfuse_xchg_pb(pu, pm, expected_len, reply) | | 264 | perfuse_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 | |
353 | struct fuse_in_header * | | 353 | struct fuse_in_header * |
354 | perfuse_get_inhdr(pm) | | 354 | perfuse_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 | |
374 | struct fuse_out_header * | | 374 | struct fuse_out_header * |
375 | perfuse_get_outhdr(pm) | | 375 | perfuse_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 | |
395 | char * | | 395 | char * |
396 | perfuse_get_inpayload(pm) | | 396 | perfuse_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 | |
423 | char * | | 423 | char * |
424 | perfuse_get_outpayload(pm) | | 424 | perfuse_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 */ |
465 | int | | 465 | int |
466 | perfuse_readframe(pu, pufbuf, fd, done) | | 466 | perfuse_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 */ |
558 | int | | 558 | int |
559 | perfuse_writeframe(pu, pufbuf, fd, done) | | 559 | perfuse_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 */ |
600 | int | | 606 | int |
601 | perfuse_cmpframe(pu, pb1, pb2, match) | | 607 | perfuse_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 */ |
625 | void | | 631 | void |
626 | perfuse_gotframe(pu, pb) | | 632 | perfuse_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 | |
645 | void | | 651 | void |
646 | perfuse_fdnotify(pu, fd, what) | | 652 | perfuse_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 | } |