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