1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <lib/fdio/util.h>
6 #include <lib/zxio/inception.h>
7 #include <lib/zxio/null.h>
8 #include <lib/zxio/zxio.h>
9 #include <poll.h>
10 #include <stdatomic.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <sys/ioctl.h>
14 #include <zircon/device/ioctl.h>
15 #include <zircon/processargs.h>
16 #include <zircon/syscalls.h>
17
18 #include "private-remoteio.h"
19 #include "private.h"
20
21 // Initial memory layout for types that bridge between |fdio_t| and |zxio_t|.
22 //
23 // Every |fdio_t| implementation starts with an embedded |fdio_t|, which the
24 // callers use to find the fdio |ops| table. There are several |fdio_t|
25 // implementations that use zxio as a backed. All of them have a memory layout
26 // that matches this structure. Defining this structure lets us define
27 // most of the fdio ops that use the zxio backend in a generic way.
28 //
29 // Will be removed once the transition to the zxio backend is complete.
30 typedef struct fdio_zxio {
31 fdio_t io;
32 zxio_storage_t storage;
33 } fdio_zxio_t;
34
fdio_get_zxio(fdio_t * io)35 static inline zxio_t* fdio_get_zxio(fdio_t* io) {
36 fdio_zxio_t* wrapper = (fdio_zxio_t*)io;
37 return &wrapper->storage.io;
38 }
39
fdio_zxio_close(fdio_t * io)40 static zx_status_t fdio_zxio_close(fdio_t* io) {
41 zxio_t* z = fdio_get_zxio(io);
42 return zxio_close(z);
43 }
44
fdio_zxio_wait_begin(fdio_t * io,uint32_t events,zx_handle_t * out_handle,zx_signals_t * out_signals)45 static void fdio_zxio_wait_begin(fdio_t* io, uint32_t events,
46 zx_handle_t* out_handle,
47 zx_signals_t* out_signals) {
48 zxio_t* z = fdio_get_zxio(io);
49 zxio_signals_t signals = ZXIO_SIGNAL_NONE;
50 if (events & POLLIN) {
51 signals |= ZXIO_READABLE | ZXIO_READ_DISABLED;
52 }
53 if (events & POLLOUT) {
54 signals |= ZXIO_WRITABLE | ZXIO_WRITE_DISABLED;
55 }
56 if (events & POLLRDHUP) {
57 signals |= ZXIO_READ_DISABLED;
58 }
59 zxio_wait_begin(z, signals, out_handle, out_signals);
60 }
61
fdio_zxio_wait_end(fdio_t * io,zx_signals_t signals,uint32_t * out_events)62 static void fdio_zxio_wait_end(fdio_t* io, zx_signals_t signals,
63 uint32_t* out_events) {
64 zxio_t* z = fdio_get_zxio(io);
65 zxio_signals_t zxio_signals = ZXIO_SIGNAL_NONE;
66 zxio_wait_end(z, signals, &zxio_signals);
67
68 uint32_t events = 0;
69 if (zxio_signals & (ZXIO_READABLE | ZXIO_READ_DISABLED)) {
70 events |= POLLIN;
71 }
72 if (zxio_signals & (ZXIO_WRITABLE | ZXIO_WRITE_DISABLED)) {
73 events |= POLLOUT;
74 }
75 if (zxio_signals & ZXIO_READ_DISABLED) {
76 events |= POLLRDHUP;
77 }
78 *out_events = events;
79 }
80
fdio_zxio_clone(fdio_t * io,zx_handle_t * handles,uint32_t * types)81 static zx_status_t fdio_zxio_clone(fdio_t* io, zx_handle_t* handles,
82 uint32_t* types) {
83 zxio_t* z = fdio_get_zxio(io);
84 zx_handle_t local, remote;
85 zx_status_t status = zx_channel_create(0, &local, &remote);
86 if (status != ZX_OK) {
87 return status;
88 }
89 uint32_t flags = fuchsia_io_OPEN_RIGHT_READABLE | fuchsia_io_OPEN_RIGHT_WRITABLE;
90 status = zxio_clone_async(z, flags, remote);
91 if (status != ZX_OK) {
92 zx_handle_close(local);
93 return status;
94 }
95 handles[0] = local;
96 types[0] = PA_FDIO_REMOTE;
97 return 1;
98 }
99
fdio_zxio_unwrap(fdio_t * io,zx_handle_t * handles,uint32_t * types)100 static zx_status_t fdio_zxio_unwrap(fdio_t* io, zx_handle_t* handles,
101 uint32_t* types) {
102 zxio_t* z = fdio_get_zxio(io);
103 zx_handle_t handle = ZX_HANDLE_INVALID;
104 zx_status_t status = zxio_release(z, &handle);
105 if (status != ZX_OK) {
106 return status;
107 }
108 handles[0] = handle;
109 types[0] = PA_FDIO_REMOTE;
110 return 1;
111 }
112
fdio_zxio_sync(fdio_t * io)113 static zx_status_t fdio_zxio_sync(fdio_t* io) {
114 zxio_t* z = fdio_get_zxio(io);
115 return zxio_sync(z);
116 }
117
fdio_zxio_get_attr(fdio_t * io,fuchsia_io_NodeAttributes * out)118 static zx_status_t fdio_zxio_get_attr(fdio_t* io, fuchsia_io_NodeAttributes* out) {
119 zxio_t* z = fdio_get_zxio(io);
120 return zxio_attr_get(z, out);
121 }
122
fdio_zxio_set_attr(fdio_t * io,uint32_t flags,const fuchsia_io_NodeAttributes * attr)123 static zx_status_t fdio_zxio_set_attr(fdio_t* io, uint32_t flags, const fuchsia_io_NodeAttributes* attr) {
124 zxio_t* z = fdio_get_zxio(io);
125 return zxio_attr_set(z, flags, attr);
126 }
127
fdio_zxio_read(fdio_t * io,void * data,size_t len)128 static ssize_t fdio_zxio_read(fdio_t* io, void* data, size_t len) {
129 zxio_t* z = fdio_get_zxio(io);
130 size_t actual = 0;
131 zx_status_t status = zxio_read(z, data, len, &actual);
132 return status != ZX_OK ? status : (ssize_t)actual;
133 }
134
fdio_zxio_read_at(fdio_t * io,void * data,size_t len,off_t at)135 static ssize_t fdio_zxio_read_at(fdio_t* io, void* data, size_t len, off_t at) {
136 zxio_t* z = fdio_get_zxio(io);
137 size_t actual = 0;
138 zx_status_t status = zxio_read_at(z, at, data, len, &actual);
139 return status != ZX_OK ? status : (ssize_t)actual;
140 }
141
fdio_zxio_write(fdio_t * io,const void * data,size_t len)142 static ssize_t fdio_zxio_write(fdio_t* io, const void* data, size_t len) {
143 zxio_t* z = fdio_get_zxio(io);
144 size_t actual = 0;
145 zx_status_t status = zxio_write(z, data, len, &actual);
146 return status != ZX_OK ? status : (ssize_t)actual;
147 }
148
fdio_zxio_write_at(fdio_t * io,const void * data,size_t len,off_t at)149 static ssize_t fdio_zxio_write_at(fdio_t* io, const void* data, size_t len, off_t at) {
150 zxio_t* z = fdio_get_zxio(io);
151 size_t actual = 0;
152 zx_status_t status = zxio_write_at(z, at, data, len, &actual);
153 return status != ZX_OK ? status : (ssize_t)actual;
154 }
155
156 static_assert(SEEK_SET == fuchsia_io_SeekOrigin_START, "");
157 static_assert(SEEK_CUR == fuchsia_io_SeekOrigin_CURRENT, "");
158 static_assert(SEEK_END == fuchsia_io_SeekOrigin_END, "");
159
fdio_zxio_seek(fdio_t * io,off_t offset,int whence)160 static off_t fdio_zxio_seek(fdio_t* io, off_t offset, int whence) {
161 zxio_t* z = fdio_get_zxio(io);
162 size_t result = 0u;
163 zx_status_t status = zxio_seek(z, offset, whence, &result);
164 return status != ZX_OK ? status : (ssize_t)result;
165 }
166
fdio_zxio_truncate(fdio_t * io,off_t off)167 static zx_status_t fdio_zxio_truncate(fdio_t* io, off_t off) {
168 zxio_t* z = fdio_get_zxio(io);
169 return zxio_truncate(z, off);
170 }
171
fdio_zxio_get_flags(fdio_t * io,uint32_t * out_flags)172 static zx_status_t fdio_zxio_get_flags(fdio_t* io, uint32_t* out_flags) {
173 zxio_t* z = fdio_get_zxio(io);
174 return zxio_flags_get(z, out_flags);
175 }
176
fdio_zxio_set_flags(fdio_t * io,uint32_t flags)177 static zx_status_t fdio_zxio_set_flags(fdio_t* io, uint32_t flags) {
178 zxio_t* z = fdio_get_zxio(io);
179 return zxio_flags_set(z, flags);
180 }
181
182 // Generic ---------------------------------------------------------------------
183
184 fdio_ops_t fdio_zxio_ops = {
185 .read = fdio_zxio_read,
186 .read_at = fdio_zxio_read_at,
187 .write = fdio_zxio_write,
188 .write_at = fdio_zxio_write_at,
189 .seek = fdio_zxio_seek,
190 .misc = fdio_default_misc,
191 .close = fdio_zxio_close,
192 .open = fdio_default_open,
193 .clone = fdio_zxio_clone,
194 .ioctl = fdio_default_ioctl,
195 .wait_begin = fdio_zxio_wait_begin,
196 .wait_end = fdio_zxio_wait_end,
197 .unwrap = fdio_zxio_unwrap,
198 .posix_ioctl = fdio_default_posix_ioctl,
199 .get_vmo = fdio_default_get_vmo,
200 .get_token = fdio_default_get_token,
201 .get_attr = fdio_zxio_get_attr,
202 .set_attr = fdio_zxio_set_attr,
203 .sync = fdio_zxio_sync,
204 .readdir = fdio_default_readdir,
205 .rewind = fdio_default_rewind,
206 .unlink = fdio_default_unlink,
207 .truncate = fdio_zxio_truncate,
208 .rename = fdio_default_rename,
209 .link = fdio_default_link,
210 .get_flags = fdio_zxio_get_flags,
211 .set_flags = fdio_zxio_set_flags,
212 .recvfrom = fdio_default_recvfrom,
213 .sendto = fdio_default_sendto,
214 .recvmsg = fdio_default_recvmsg,
215 .sendmsg = fdio_default_sendmsg,
216 .shutdown = fdio_default_shutdown,
217 };
218
219 __EXPORT
fdio_zxio_create(zxio_storage_t ** out_storage)220 fdio_t* fdio_zxio_create(zxio_storage_t** out_storage) {
221 fdio_zxio_t* fv = fdio_alloc(sizeof(fdio_zxio_t));
222 if (fv == NULL) {
223 return NULL;
224 }
225 fv->io.ops = &fdio_zxio_ops;
226 fv->io.magic = FDIO_MAGIC;
227 atomic_init(&fv->io.refcount, 1);
228 memset(&fv->storage, 0, sizeof(fv->storage));
229 zxio_null_init(&fv->storage.io);
230 *out_storage = &fv->storage;
231 return &fv->io;
232 }
233
234 // Null ------------------------------------------------------------------------
235
236 __EXPORT
fdio_null_create(void)237 fdio_t* fdio_null_create(void) {
238 zxio_storage_t* storage = NULL;
239 return fdio_zxio_create(&storage);
240 }
241
242 // Remote ----------------------------------------------------------------------
243
244 // POLL_MASK and POLL_SHIFT intend to convert the lower five POLL events into
245 // ZX_USER_SIGNALs and vice-versa. Other events need to be manually converted to
246 // a zx_signals_t, if they are desired.
247 #define POLL_SHIFT 24
248 #define POLL_MASK 0x1F
249
fdio_get_zxio_remote(fdio_t * io)250 static zxio_remote_t* fdio_get_zxio_remote(fdio_t* io) {
251 return (zxio_remote_t*)fdio_get_zxio(io);
252 }
253
fdio_zxio_remote_open(fdio_t * io,const char * path,uint32_t flags,uint32_t mode,fdio_t ** out)254 static zx_status_t fdio_zxio_remote_open(fdio_t* io, const char* path,
255 uint32_t flags, uint32_t mode,
256 fdio_t** out) {
257 zxio_remote_t* rio = fdio_get_zxio_remote(io);
258 return zxrio_open_handle(rio->control, path, flags, mode, out);
259 }
260
fidl_ioctl(zx_handle_t h,uint32_t op,const void * in_buf,size_t in_len,void * out_buf,size_t out_len,size_t * out_actual)261 static zx_status_t fidl_ioctl(zx_handle_t h, uint32_t op, const void* in_buf,
262 size_t in_len, void* out_buf, size_t out_len,
263 size_t* out_actual) {
264 size_t in_handle_count = 0;
265 size_t out_handle_count = 0;
266 switch (IOCTL_KIND(op)) {
267 case IOCTL_KIND_GET_HANDLE:
268 out_handle_count = 1;
269 break;
270 case IOCTL_KIND_GET_TWO_HANDLES:
271 out_handle_count = 2;
272 break;
273 case IOCTL_KIND_GET_THREE_HANDLES:
274 out_handle_count = 3;
275 break;
276 case IOCTL_KIND_SET_HANDLE:
277 in_handle_count = 1;
278 break;
279 case IOCTL_KIND_SET_TWO_HANDLES:
280 in_handle_count = 2;
281 break;
282 }
283
284 if (in_len < in_handle_count * sizeof(zx_handle_t)) {
285 return ZX_ERR_INVALID_ARGS;
286 }
287 if (out_len < out_handle_count * sizeof(zx_handle_t)) {
288 return ZX_ERR_INVALID_ARGS;
289 }
290
291 zx_handle_t hbuf[out_handle_count];
292 size_t out_handle_actual;
293 zx_status_t io_status, status;
294 if ((io_status = fuchsia_io_NodeIoctl(h, op,
295 out_len, (zx_handle_t*) in_buf,
296 in_handle_count, in_buf,
297 in_len, &status, hbuf,
298 out_handle_count, &out_handle_actual,
299 out_buf, out_len, out_actual)) != ZX_OK) {
300 return io_status;
301 }
302
303 if (status != ZX_OK) {
304 zx_handle_close_many(hbuf, out_handle_actual);
305 return status;
306 }
307 if (out_handle_actual != out_handle_count) {
308 zx_handle_close_many(hbuf, out_handle_actual);
309 return ZX_ERR_IO;
310 }
311
312 memcpy(out_buf, hbuf, out_handle_count * sizeof(zx_handle_t));
313 return ZX_OK;
314 }
315
fdio_zxio_remote_ioctl(fdio_t * io,uint32_t op,const void * in_buf,size_t in_len,void * out_buf,size_t out_len)316 static ssize_t fdio_zxio_remote_ioctl(fdio_t* io, uint32_t op, const void* in_buf,
317 size_t in_len, void* out_buf, size_t out_len) {
318 zxio_remote_t* rio = fdio_get_zxio_remote(io);
319 if (in_len > FDIO_IOCTL_MAX_INPUT || out_len > FDIO_CHUNK_SIZE) {
320 return ZX_ERR_INVALID_ARGS;
321 }
322 size_t actual = 0u;
323 zx_status_t status = fidl_ioctl(rio->control, op, in_buf, in_len, out_buf, out_len, &actual);
324 if (status != ZX_OK) {
325 return status;
326 }
327 return actual;
328 }
329
fdio_zxio_remote_wait_begin(fdio_t * io,uint32_t events,zx_handle_t * handle,zx_signals_t * _signals)330 static void fdio_zxio_remote_wait_begin(fdio_t* io, uint32_t events,
331 zx_handle_t* handle, zx_signals_t* _signals) {
332 zxio_remote_t* rio = fdio_get_zxio_remote(io);
333 *handle = rio->event;
334
335 zx_signals_t signals = 0;
336 // Manually add signals that don't fit within POLL_MASK
337 if (events & POLLRDHUP) {
338 signals |= ZX_CHANNEL_PEER_CLOSED;
339 }
340
341 // POLLERR is always detected
342 *_signals = (((POLLERR | events) & POLL_MASK) << POLL_SHIFT) | signals;
343 }
344
fdio_zxio_remote_wait_end(fdio_t * io,zx_signals_t signals,uint32_t * _events)345 static void fdio_zxio_remote_wait_end(fdio_t* io, zx_signals_t signals, uint32_t* _events) {
346 // Manually add events that don't fit within POLL_MASK
347 uint32_t events = 0;
348 if (signals & ZX_CHANNEL_PEER_CLOSED) {
349 events |= POLLRDHUP;
350 }
351 *_events = ((signals >> POLL_SHIFT) & POLL_MASK) | events;
352 }
353
fdio_zxio_remote_get_vmo(fdio_t * io,int flags,zx_handle_t * out_vmo)354 static zx_status_t fdio_zxio_remote_get_vmo(fdio_t* io, int flags, zx_handle_t* out_vmo) {
355 zxio_remote_t* rio = fdio_get_zxio_remote(io);
356 zx_handle_t vmo = ZX_HANDLE_INVALID;
357 zx_status_t io_status, status;
358 io_status = fuchsia_io_FileGetVmo(rio->control, flags, &status, &vmo);
359 if (io_status != ZX_OK) {
360 return io_status;
361 }
362 if (status != ZX_OK) {
363 return status;
364 }
365 if (vmo == ZX_HANDLE_INVALID) {
366 return ZX_ERR_IO;
367 }
368 *out_vmo = vmo;
369 return ZX_OK;
370 }
371
fdio_zxio_remote_get_token(fdio_t * io,zx_handle_t * out_token)372 static zx_status_t fdio_zxio_remote_get_token(fdio_t* io, zx_handle_t* out_token) {
373 zxio_remote_t* rio = fdio_get_zxio_remote(io);
374 zx_status_t io_status, status;
375 io_status = fuchsia_io_DirectoryGetToken(rio->control, &status, out_token);
376 return io_status != ZX_OK ? io_status : status;
377 }
378
fdio_zxio_remote_readdir(fdio_t * io,void * ptr,size_t max,size_t * out_actual)379 static zx_status_t fdio_zxio_remote_readdir(fdio_t* io, void* ptr, size_t max, size_t* out_actual) {
380 zxio_remote_t* rio = fdio_get_zxio_remote(io);
381 size_t actual = 0u;
382 zx_status_t io_status, status;
383 io_status = fuchsia_io_DirectoryReadDirents(rio->control, max, &status, ptr,
384 max, &actual);
385 if (io_status != ZX_OK) {
386 return io_status;
387 }
388 if (status != ZX_OK) {
389 return status;
390 }
391 if (actual > max) {
392 return ZX_ERR_IO;
393 }
394 *out_actual = actual;
395 return status;
396 }
397
fdio_zxio_remote_rewind(fdio_t * io)398 static zx_status_t fdio_zxio_remote_rewind(fdio_t* io) {
399 zxio_remote_t* rio = fdio_get_zxio_remote(io);
400 zx_status_t io_status, status;
401 io_status = fuchsia_io_DirectoryRewind(rio->control, &status);
402 return io_status != ZX_OK ? io_status : status;
403 }
404
fdio_zxio_remote_unlink(fdio_t * io,const char * path,size_t len)405 static zx_status_t fdio_zxio_remote_unlink(fdio_t* io, const char* path, size_t len) {
406 zxio_remote_t* rio = fdio_get_zxio_remote(io);
407 zx_status_t io_status, status;
408 io_status = fuchsia_io_DirectoryUnlink(rio->control, path, len, &status);
409 return io_status != ZX_OK ? io_status : status;
410 }
411
fdio_zxio_remote_rename(fdio_t * io,const char * src,size_t srclen,zx_handle_t dst_token,const char * dst,size_t dstlen)412 static zx_status_t fdio_zxio_remote_rename(fdio_t* io, const char* src, size_t srclen,
413 zx_handle_t dst_token, const char* dst, size_t dstlen) {
414 zxio_remote_t* rio = fdio_get_zxio_remote(io);
415 zx_status_t io_status, status;
416 io_status = fuchsia_io_DirectoryRename(rio->control, src, srclen, dst_token,
417 dst, dstlen, &status);
418 return io_status != ZX_OK ? io_status : status;
419 }
420
fdio_zxio_remote_link(fdio_t * io,const char * src,size_t srclen,zx_handle_t dst_token,const char * dst,size_t dstlen)421 static zx_status_t fdio_zxio_remote_link(fdio_t* io, const char* src, size_t srclen,
422 zx_handle_t dst_token, const char* dst, size_t dstlen) {
423 zxio_remote_t* rio = fdio_get_zxio_remote(io);
424 zx_status_t io_status, status;
425 io_status = fuchsia_io_DirectoryLink(rio->control, src, srclen, dst_token,
426 dst, dstlen, &status);
427 return io_status != ZX_OK ? io_status : status;
428 }
429
430 static fdio_ops_t fdio_zxio_remote_ops = {
431 .read = fdio_zxio_read,
432 .read_at = fdio_zxio_read_at,
433 .write = fdio_zxio_write,
434 .write_at = fdio_zxio_write_at,
435 .seek = fdio_zxio_seek,
436 .misc = fdio_default_misc,
437 .close = fdio_zxio_close,
438 .open = fdio_zxio_remote_open,
439 .clone = fdio_zxio_clone,
440 .ioctl = fdio_zxio_remote_ioctl,
441 .wait_begin = fdio_zxio_remote_wait_begin,
442 .wait_end = fdio_zxio_remote_wait_end,
443 .unwrap = fdio_zxio_unwrap,
444 .posix_ioctl = fdio_default_posix_ioctl,
445 .get_vmo = fdio_zxio_remote_get_vmo,
446 .get_token = fdio_zxio_remote_get_token,
447 .get_attr = fdio_zxio_get_attr,
448 .set_attr = fdio_zxio_set_attr,
449 .sync = fdio_zxio_sync,
450 .readdir = fdio_zxio_remote_readdir,
451 .rewind = fdio_zxio_remote_rewind,
452 .unlink = fdio_zxio_remote_unlink,
453 .truncate = fdio_zxio_truncate,
454 .rename = fdio_zxio_remote_rename,
455 .link = fdio_zxio_remote_link,
456 .get_flags = fdio_zxio_get_flags,
457 .set_flags = fdio_zxio_set_flags,
458 .recvfrom = fdio_default_recvfrom,
459 .sendto = fdio_default_sendto,
460 .recvmsg = fdio_default_recvmsg,
461 .sendmsg = fdio_default_sendmsg,
462 .shutdown = fdio_default_shutdown,
463 };
464
465 __EXPORT
fdio_remote_create(zx_handle_t control,zx_handle_t event)466 fdio_t* fdio_remote_create(zx_handle_t control, zx_handle_t event) {
467 fdio_zxio_t* fv = fdio_alloc(sizeof(fdio_zxio_t));
468 if (fv == NULL) {
469 zx_handle_close(control);
470 zx_handle_close(event);
471 return NULL;
472 }
473 fv->io.ops = &fdio_zxio_remote_ops;
474 fv->io.magic = FDIO_MAGIC;
475 atomic_init(&fv->io.refcount, 1);
476 zx_status_t status = zxio_remote_init(&fv->storage, control, event);
477 if (status != ZX_OK) {
478 return NULL;
479 }
480 return &fv->io;
481 }
482
483 __EXPORT
fdio_get_service_handle(int fd,zx_handle_t * out)484 zx_status_t fdio_get_service_handle(int fd, zx_handle_t* out) {
485 mtx_lock(&fdio_lock);
486 if ((fd < 0) || (fd >= FDIO_MAX_FD) || (fdio_fdtab[fd] == NULL)) {
487 mtx_unlock(&fdio_lock);
488 return ZX_ERR_NOT_FOUND;
489 }
490 fdio_t* io = fdio_fdtab[fd];
491 io->dupcount--;
492 fdio_fdtab[fd] = NULL;
493 if (io->dupcount > 0) {
494 // still alive in other fdtab slots
495 // this fd goes away but we can't give away the handle
496 mtx_unlock(&fdio_lock);
497 fdio_release(io);
498 return ZX_ERR_UNAVAILABLE;
499 } else {
500 mtx_unlock(&fdio_lock);
501 zx_status_t r;
502 if (io->ops == &fdio_zxio_remote_ops) {
503 zxio_remote_t* file = fdio_get_zxio_remote(io);
504 r = zxio_release(&file->io, out);
505 } else {
506 r = ZX_ERR_NOT_SUPPORTED;
507 io->ops->close(io);
508 }
509 fdio_release(io);
510 return r;
511 }
512 }
513
514 __EXPORT
fdio_unsafe_borrow_channel(fdio_t * io)515 zx_handle_t fdio_unsafe_borrow_channel(fdio_t* io) {
516 if (io == NULL) {
517 return ZX_HANDLE_INVALID;
518 }
519
520 if (io->ops == &fdio_zxio_remote_ops) {
521 zxio_remote_t* file = fdio_get_zxio_remote(io);
522 return file->control;
523 }
524 return ZX_HANDLE_INVALID;
525 }
526
527 // Vmofile ---------------------------------------------------------------------
528
fdio_get_zxio_vmofile(fdio_t * io)529 static inline zxio_vmofile_t* fdio_get_zxio_vmofile(fdio_t* io) {
530 return (zxio_vmofile_t*)fdio_get_zxio(io);
531 }
532
fdio_zxio_vmofile_get_vmo(fdio_t * io,int flags,zx_handle_t * out_vmo)533 static zx_status_t fdio_zxio_vmofile_get_vmo(fdio_t* io, int flags,
534 zx_handle_t* out_vmo) {
535 zxio_vmofile_t* file = fdio_get_zxio_vmofile(io);
536
537 if (out_vmo == NULL) {
538 return ZX_ERR_INVALID_ARGS;
539 }
540
541 size_t length = file->end - file->off;
542 if (flags & fuchsia_io_VMO_FLAG_PRIVATE) {
543 // Why don't we consider file->off in this branch? It seems like we
544 // want to clone the part of the VMO from file->off to file->end rather
545 // than length bytes at the start of the VMO.
546 return zx_vmo_clone(file->vmo, ZX_VMO_CLONE_COPY_ON_WRITE, 0, length,
547 out_vmo);
548 } else {
549 size_t vmo_length = 0;
550 if (file->off != 0 || zx_vmo_get_size(file->vmo, &vmo_length) != ZX_OK ||
551 length != vmo_length) {
552 return ZX_ERR_NOT_FOUND;
553 }
554 zx_rights_t rights = ZX_RIGHTS_BASIC | ZX_RIGHT_GET_PROPERTY |
555 ZX_RIGHT_MAP;
556 rights |= (flags & fuchsia_io_VMO_FLAG_READ) ? ZX_RIGHT_READ : 0;
557 rights |= (flags & fuchsia_io_VMO_FLAG_WRITE) ? ZX_RIGHT_WRITE : 0;
558 rights |= (flags & fuchsia_io_VMO_FLAG_EXEC) ? ZX_RIGHT_EXECUTE : 0;
559 return zx_handle_duplicate(file->vmo, rights, out_vmo);
560 }
561 }
562
563 fdio_ops_t fdio_zxio_vmofile_ops = {
564 .read = fdio_zxio_read,
565 .read_at = fdio_zxio_read_at,
566 .write = fdio_zxio_write,
567 .write_at = fdio_zxio_write_at,
568 .seek = fdio_zxio_seek,
569 .misc = fdio_default_misc,
570 .close = fdio_zxio_close,
571 .open = fdio_default_open,
572 .clone = fdio_zxio_clone,
573 .ioctl = fdio_default_ioctl,
574 .wait_begin = fdio_default_wait_begin,
575 .wait_end = fdio_default_wait_end,
576 .unwrap = fdio_zxio_unwrap,
577 .posix_ioctl = fdio_default_posix_ioctl,
578 .get_vmo = fdio_zxio_vmofile_get_vmo,
579 .get_token = fdio_default_get_token,
580 .get_attr = fdio_zxio_get_attr,
581 .set_attr = fdio_zxio_set_attr,
582 .sync = fdio_zxio_sync,
583 .readdir = fdio_default_readdir,
584 .rewind = fdio_default_rewind,
585 .unlink = fdio_default_unlink,
586 .truncate = fdio_zxio_truncate,
587 .rename = fdio_default_rename,
588 .link = fdio_default_link,
589 .get_flags = fdio_zxio_get_flags,
590 .set_flags = fdio_zxio_set_flags,
591 .recvfrom = fdio_default_recvfrom,
592 .sendto = fdio_default_sendto,
593 .recvmsg = fdio_default_recvmsg,
594 .sendmsg = fdio_default_sendmsg,
595 .shutdown = fdio_default_shutdown,
596 };
597
fdio_vmofile_create(zx_handle_t control,zx_handle_t vmo,zx_off_t offset,zx_off_t length,zx_off_t seek)598 fdio_t* fdio_vmofile_create(zx_handle_t control, zx_handle_t vmo,
599 zx_off_t offset, zx_off_t length,
600 zx_off_t seek) {
601 fdio_zxio_t* fv = fdio_alloc(sizeof(fdio_zxio_t));
602 if (fv == NULL) {
603 zx_handle_close(control);
604 zx_handle_close(vmo);
605 return NULL;
606 }
607 fv->io.ops = &fdio_zxio_vmofile_ops;
608 fv->io.magic = FDIO_MAGIC;
609 atomic_init(&fv->io.refcount, 1);
610 zx_status_t status = zxio_vmofile_init(&fv->storage, control, vmo, offset,
611 length, seek);
612 if (status != ZX_OK) {
613 return NULL;
614 }
615 return &fv->io;
616 }
617
618 __EXPORT
fdio_vmo_fd(zx_handle_t vmo,uint64_t offset,uint64_t length)619 int fdio_vmo_fd(zx_handle_t vmo, uint64_t offset, uint64_t length) {
620 fdio_t* io;
621 int fd;
622 if ((io = fdio_vmofile_create(ZX_HANDLE_INVALID, vmo, offset, length, 0u)) == NULL) {
623 return -1;
624 }
625 if ((fd = fdio_bind_to_fd(io, -1, 0)) < 0) {
626 fdio_close(io);
627 fdio_release(io);
628 return -1;
629 }
630 return fd;
631 }
632
633 // Pipe ------------------------------------------------------------------------
634
read_blocking(zxio_t * io,void * buffer,size_t capacity,size_t * out_actual)635 static zx_status_t read_blocking(zxio_t* io, void* buffer, size_t capacity,
636 size_t* out_actual) {
637 for (;;) {
638 zx_status_t status = zxio_read(io, buffer, capacity, out_actual);
639 if (status != ZX_ERR_SHOULD_WAIT) {
640 return status;
641 }
642 zxio_signals_t observed = ZXIO_SIGNAL_NONE;
643 status = zxio_wait_one(io, ZXIO_READABLE | ZXIO_READ_DISABLED,
644 ZX_TIME_INFINITE, &observed);
645 if (status != ZX_OK) {
646 return status;
647 }
648 }
649 }
650
write_blocking(zxio_t * io,const void * buffer,size_t capacity,size_t * out_actual)651 static zx_status_t write_blocking(zxio_t* io, const void* buffer,
652 size_t capacity, size_t* out_actual) {
653 for (;;) {
654 zx_status_t status = zxio_write(io, buffer, capacity, out_actual);
655 if (status != ZX_ERR_SHOULD_WAIT) {
656 return status;
657 }
658 zxio_signals_t observed = ZXIO_SIGNAL_NONE;
659 status = zxio_wait_one(io, ZXIO_WRITABLE | ZXIO_WRITE_DISABLED,
660 ZX_TIME_INFINITE, &observed);
661 if (status != ZX_OK) {
662 return status;
663 }
664 }
665 }
666
read_internal(zxio_t * io,bool blocking,void * data,size_t len)667 static ssize_t read_internal(zxio_t* io, bool blocking, void* data, size_t len) {
668 size_t actual = 0u;
669 zx_status_t status = ZX_OK;
670 if (blocking) {
671 status = read_blocking(io, data, len, &actual);
672 } else {
673 status = zxio_read(io, data, len, &actual);
674 }
675 return status != ZX_OK ? status : (ssize_t)actual;
676 }
677
write_internal(zxio_t * io,bool blocking,const void * data,size_t len)678 static ssize_t write_internal(zxio_t* io, bool blocking, const void* data, size_t len) {
679 size_t actual = 0u;
680 zx_status_t status = ZX_OK;
681 if (blocking) {
682 status = write_blocking(io, data, len, &actual);
683 } else {
684 status = zxio_write(io, data, len, &actual);
685 }
686 return status != ZX_OK ? status : (ssize_t)actual;
687 }
688
fdio_get_zxio_pipe(fdio_t * io)689 static inline zxio_pipe_t* fdio_get_zxio_pipe(fdio_t* io) {
690 return (zxio_pipe_t*)fdio_get_zxio(io);
691 }
692
fdio_zxio_pipe_clone(fdio_t * io,zx_handle_t * handles,uint32_t * types)693 static zx_status_t fdio_zxio_pipe_clone(fdio_t* io, zx_handle_t* handles, uint32_t* types) {
694 zxio_pipe_t* pipe = fdio_get_zxio_pipe(io);
695 zx_status_t status = zx_handle_duplicate(pipe->socket, ZX_RIGHT_SAME_RIGHTS,
696 &handles[0]);
697 if (status != ZX_OK) {
698 return status;
699 }
700 types[0] = PA_FDIO_SOCKET;
701 return 1;
702 }
703
fdio_zxio_pipe_unwrap(fdio_t * io,zx_handle_t * handles,uint32_t * types)704 static zx_status_t fdio_zxio_pipe_unwrap(fdio_t* io, zx_handle_t* handles,
705 uint32_t* types) {
706 zxio_t* z = fdio_get_zxio(io);
707 zx_handle_t handle = ZX_HANDLE_INVALID;
708 zx_status_t status = zxio_release(z, &handle);
709 if (status != ZX_OK) {
710 return status;
711 }
712 handles[0] = handle;
713 types[0] = PA_FDIO_SOCKET;
714 return 1;
715 }
716
fdio_zxio_pipe_read(fdio_t * io,void * data,size_t len)717 static ssize_t fdio_zxio_pipe_read(fdio_t* io, void* data, size_t len) {
718 zxio_t* z = fdio_get_zxio(io);
719 bool blocking = !(io->ioflag & IOFLAG_NONBLOCK);
720 return read_internal(z, blocking, data, len);
721 }
722
fdio_zxio_pipe_write(fdio_t * io,const void * data,size_t len)723 static ssize_t fdio_zxio_pipe_write(fdio_t* io, const void* data, size_t len) {
724 zxio_t* z = fdio_get_zxio(io);
725 bool blocking = !(io->ioflag & IOFLAG_NONBLOCK);
726 return write_internal(z, blocking, data, len);
727 }
728
fdio_zxio_pipe_posix_ioctl(fdio_t * io,int request,va_list va)729 static ssize_t fdio_zxio_pipe_posix_ioctl(fdio_t* io, int request, va_list va) {
730 zxio_pipe_t* pipe = fdio_get_zxio_pipe(io);
731 switch (request) {
732 case FIONREAD: {
733 zx_info_socket_t info;
734 memset(&info, 0, sizeof(info));
735 zx_status_t status = zx_object_get_info(pipe->socket, ZX_INFO_SOCKET,
736 &info, sizeof(info), NULL, NULL);
737 if (status != ZX_OK) {
738 return status;
739 }
740 size_t available = info.rx_buf_available;
741 if (available > INT_MAX) {
742 available = INT_MAX;
743 }
744 int* actual = va_arg(va, int*);
745 *actual = available;
746 return ZX_OK;
747 }
748 default:
749 return ZX_ERR_NOT_SUPPORTED;
750 }
751 }
752
fdio_zxio_pipe_recvfrom(fdio_t * io,void * data,size_t len,int flags,struct sockaddr * restrict addr,socklen_t * restrict addrlen)753 static ssize_t fdio_zxio_pipe_recvfrom(fdio_t* io, void* data, size_t len, int flags,
754 struct sockaddr* restrict addr,
755 socklen_t* restrict addrlen) {
756 if (flags & ~MSG_DONTWAIT) {
757 return ZX_ERR_INVALID_ARGS;
758 }
759 zxio_t* z = fdio_get_zxio(io);
760 bool blocking = !((io->ioflag & IOFLAG_NONBLOCK) || (flags & MSG_DONTWAIT));
761 return read_internal(z, blocking, data, len);
762 }
763
fdio_zxio_pipe_sendto(fdio_t * io,const void * data,size_t len,int flags,const struct sockaddr * addr,socklen_t addrlen)764 static ssize_t fdio_zxio_pipe_sendto(fdio_t* io, const void* data, size_t len, int flags, const struct sockaddr* addr, socklen_t addrlen) {
765 if (flags & ~MSG_DONTWAIT) {
766 return ZX_ERR_INVALID_ARGS;
767 }
768 if (addr != NULL) {
769 return ZX_ERR_INVALID_ARGS; // should set errno to EISCONN
770 }
771 zxio_t* z = fdio_get_zxio(io);
772 bool blocking = !((io->ioflag & IOFLAG_NONBLOCK) || (flags & MSG_DONTWAIT));
773 return write_internal(z, blocking, data, len);
774 }
775
fdio_zxio_pipe_recvmsg(fdio_t * io,struct msghdr * msg,int flags)776 static ssize_t fdio_zxio_pipe_recvmsg(fdio_t* io, struct msghdr* msg, int flags) {
777 // we ignore msg_name and msg_namelen members.
778 // (this is a consistent behavior with other OS implementations for TCP protocol)
779 zxio_t* z = fdio_get_zxio(io);
780 ssize_t total = 0;
781 ssize_t n = 0;
782 bool blocking = !((io->ioflag & IOFLAG_NONBLOCK) || (flags & MSG_DONTWAIT));
783 for (int i = 0; i < msg->msg_iovlen; i++) {
784 struct iovec* iov = &msg->msg_iov[i];
785 n = read_internal(z, blocking, iov->iov_base, iov->iov_len);
786 if (n > 0) {
787 total += n;
788 }
789 if ((size_t)n != iov->iov_len) {
790 break;
791 }
792 }
793 return total > 0 ? total : n;
794 }
795
fdio_zxio_pipe_sendmsg(fdio_t * io,const struct msghdr * msg,int flags)796 static ssize_t fdio_zxio_pipe_sendmsg(fdio_t* io, const struct msghdr* msg, int flags) {
797 // Note: flags typically are used to express intent _not_ to issue SIGPIPE
798 // via MSG_NOSIGNAL. Applications use this frequently to avoid having to
799 // install additional signal handlers to handle cases where connection has
800 // been closed by remote end.
801
802 zxio_t* z = fdio_get_zxio(io);
803 ssize_t total = 0;
804 ssize_t n = 0;
805 bool blocking = !((io->ioflag & IOFLAG_NONBLOCK) || (flags & MSG_DONTWAIT));
806 for (int i = 0; i < msg->msg_iovlen; i++) {
807 struct iovec* iov = &msg->msg_iov[i];
808 if (iov->iov_len <= 0) {
809 return ZX_ERR_INVALID_ARGS;
810 }
811 n = write_internal(z, blocking, iov->iov_base, iov->iov_len);
812 if (n > 0) {
813 total += n;
814 }
815 if ((size_t)n != iov->iov_len) {
816 break;
817 }
818 }
819 return total > 0 ? total : n;
820 }
821
fdio_zxio_pipe_shutdown(fdio_t * io,int how)822 static zx_status_t fdio_zxio_pipe_shutdown(fdio_t* io, int how) {
823 uint32_t options = 0;
824 switch (how) {
825 case SHUT_RD:
826 options = ZX_SOCKET_SHUTDOWN_READ;
827 break;
828 case SHUT_WR:
829 options = ZX_SOCKET_SHUTDOWN_WRITE;
830 break;
831 case SHUT_RDWR:
832 options = ZX_SOCKET_SHUTDOWN_READ | ZX_SOCKET_SHUTDOWN_WRITE;
833 break;
834 }
835 zxio_pipe_t* pipe = fdio_get_zxio_pipe(io);
836 return zx_socket_shutdown(pipe->socket, options);
837 }
838
839 static fdio_ops_t fdio_zxio_pipe_ops = {
840 .read = fdio_zxio_pipe_read,
841 .read_at = fdio_default_read_at,
842 .write = fdio_zxio_pipe_write,
843 .write_at = fdio_default_write_at,
844 .seek = fdio_default_seek,
845 .misc = fdio_default_misc,
846 .close = fdio_zxio_close,
847 .open = fdio_default_open,
848 .clone = fdio_zxio_pipe_clone,
849 .ioctl = fdio_default_ioctl,
850 .wait_begin = fdio_zxio_wait_begin,
851 .wait_end = fdio_zxio_wait_end,
852 .unwrap = fdio_zxio_pipe_unwrap,
853 .posix_ioctl = fdio_zxio_pipe_posix_ioctl,
854 .get_vmo = fdio_default_get_vmo,
855 .get_token = fdio_default_get_token,
856 .get_attr = fdio_zxio_get_attr,
857 .set_attr = fdio_zxio_set_attr,
858 .sync = fdio_default_sync,
859 .readdir = fdio_default_readdir,
860 .rewind = fdio_default_rewind,
861 .unlink = fdio_default_unlink,
862 .truncate = fdio_zxio_truncate,
863 .rename = fdio_default_rename,
864 .link = fdio_default_link,
865 .get_flags = fdio_default_get_flags,
866 .set_flags = fdio_default_set_flags,
867 .recvfrom = fdio_zxio_pipe_recvfrom,
868 .sendto = fdio_zxio_pipe_sendto,
869 .recvmsg = fdio_zxio_pipe_recvmsg,
870 .sendmsg = fdio_zxio_pipe_sendmsg,
871 .shutdown = fdio_zxio_pipe_shutdown,
872 };
873
fdio_pipe_create(zx_handle_t socket)874 fdio_t* fdio_pipe_create(zx_handle_t socket) {
875 fdio_zxio_t* fv = fdio_alloc(sizeof(fdio_zxio_t));
876 if (fv == NULL) {
877 zx_handle_close(socket);
878 return NULL;
879 }
880 fv->io.ops = &fdio_zxio_pipe_ops;
881 fv->io.magic = FDIO_MAGIC;
882 atomic_init(&fv->io.refcount, 1);
883 zx_status_t status = zxio_pipe_init(&fv->storage, socket);
884 if (status != ZX_OK) {
885 return NULL;
886 }
887 return &fv->io;
888 }
889
fdio_socketpair_create(zx_handle_t h)890 fdio_t* fdio_socketpair_create(zx_handle_t h) {
891 return fdio_pipe_create(h);
892 }
893
fdio_pipe_pair(fdio_t ** _a,fdio_t ** _b)894 int fdio_pipe_pair(fdio_t** _a, fdio_t** _b) {
895 zx_handle_t h0, h1;
896 fdio_t *a, *b;
897 zx_status_t r;
898 if ((r = zx_socket_create(0, &h0, &h1)) < 0) {
899 return r;
900 }
901 if ((a = fdio_pipe_create(h0)) == NULL) {
902 zx_handle_close(h1);
903 return ZX_ERR_NO_MEMORY;
904 }
905 if ((b = fdio_pipe_create(h1)) == NULL) {
906 fdio_zxio_close(a);
907 return ZX_ERR_NO_MEMORY;
908 }
909 *_a = a;
910 *_b = b;
911 return 0;
912 }
913
914 __EXPORT
fdio_pipe_half(zx_handle_t * handle,uint32_t * type)915 zx_status_t fdio_pipe_half(zx_handle_t* handle, uint32_t* type) {
916 zx_handle_t h0, h1;
917 zx_status_t r;
918 fdio_t* io;
919 int fd;
920 if ((r = zx_socket_create(0, &h0, &h1)) < 0) {
921 return r;
922 }
923 if ((io = fdio_pipe_create(h0)) == NULL) {
924 r = ZX_ERR_NO_MEMORY;
925 goto fail;
926 }
927 if ((fd = fdio_bind_to_fd(io, -1, 0)) < 0) {
928 fdio_release(io);
929 r = ZX_ERR_NO_RESOURCES;
930 goto fail;
931 }
932 *handle = h1;
933 *type = PA_FDIO_SOCKET;
934 return fd;
935
936 fail:
937 zx_handle_close(h1);
938 return r;
939 }
940
941 // Debuglog --------------------------------------------------------------------
942
fdio_get_zxio_debuglog(fdio_t * io)943 static inline zxio_debuglog_t* fdio_get_zxio_debuglog(fdio_t* io) {
944 return (zxio_debuglog_t*)fdio_get_zxio(io);
945 }
946
fdio_zxio_debuglog_clone(fdio_t * io,zx_handle_t * handles,uint32_t * types)947 static zx_status_t fdio_zxio_debuglog_clone(fdio_t* io, zx_handle_t* handles,
948 uint32_t* types) {
949 zxio_debuglog_t* pipe = fdio_get_zxio_debuglog(io);
950
951 zx_status_t status = zx_handle_duplicate(pipe->handle, ZX_RIGHT_SAME_RIGHTS,
952 &handles[0]);
953 if (status != ZX_OK) {
954 return status;
955 }
956 types[0] = PA_FDIO_LOGGER;
957 return 1;
958 }
959
960 static fdio_ops_t fdio_zxio_debuglog_ops = {
961 .read = fdio_default_read,
962 .read_at = fdio_default_read_at,
963 .write = fdio_zxio_write,
964 .write_at = fdio_default_write_at,
965 .seek = fdio_default_seek,
966 .misc = fdio_default_misc,
967 .close = fdio_zxio_close,
968 .open = fdio_default_open,
969 .clone = fdio_zxio_debuglog_clone,
970 .ioctl = fdio_default_ioctl,
971 .wait_begin = fdio_default_wait_begin,
972 .wait_end = fdio_default_wait_end,
973 .unwrap = fdio_default_unwrap,
974 .posix_ioctl = fdio_default_posix_ioctl,
975 .get_vmo = fdio_default_get_vmo,
976 .get_token = fdio_default_get_token,
977 .get_attr = fdio_default_get_attr,
978 .set_attr = fdio_default_set_attr,
979 .sync = fdio_default_sync,
980 .readdir = fdio_default_readdir,
981 .rewind = fdio_default_rewind,
982 .unlink = fdio_default_unlink,
983 .truncate = fdio_default_truncate,
984 .rename = fdio_default_rename,
985 .link = fdio_default_link,
986 .get_flags = fdio_default_get_flags,
987 .set_flags = fdio_default_set_flags,
988 .recvfrom = fdio_default_recvfrom,
989 .sendto = fdio_default_sendto,
990 .recvmsg = fdio_default_recvmsg,
991 .sendmsg = fdio_default_sendmsg,
992 .shutdown = fdio_default_shutdown,
993 };
994
995 __EXPORT
fdio_logger_create(zx_handle_t handle)996 fdio_t* fdio_logger_create(zx_handle_t handle) {
997 fdio_zxio_t* fv = fdio_alloc(sizeof(fdio_zxio_t));
998 if (fv == NULL) {
999 zx_handle_close(handle);
1000 return NULL;
1001 }
1002 fv->io.ops = &fdio_zxio_debuglog_ops;
1003 fv->io.magic = FDIO_MAGIC;
1004 atomic_init(&fv->io.refcount, 1);
1005 zx_status_t status = zxio_debuglog_init(&fv->storage, handle);
1006 if (status != ZX_OK) {
1007 return NULL;
1008 }
1009 return &fv->io;
1010 }
1011