1 // Copyright 2016 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 <fs/vfs.h>
6 #include <fuchsia/io/c/fidl.h>
7 #include <lib/fdio/debug.h>
8 #include <lib/fdio/vfs.h>
9 
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 
14 // Sends an 'unmount' signal on the srv handle, and waits until it is closed.
15 // Consumes 'srv'.
vfs_unmount_handle(zx_handle_t srv,zx_time_t deadline)16 zx_status_t vfs_unmount_handle(zx_handle_t srv, zx_time_t deadline) {
17     // TODO(smklein): Use C Bindings.
18     uint8_t msg[FIDL_ALIGN(sizeof(fuchsia_io_DirectoryAdminUnmountRequest)) + FDIO_CHUNK_SIZE];
19     auto request = reinterpret_cast<fuchsia_io_DirectoryAdminUnmountRequest*>(msg);
20     auto response = reinterpret_cast<fuchsia_io_DirectoryAdminUnmountResponse*>(msg);
21 
22     // the only other messages we ever send are no-reply OPEN or CLONE with
23     // txid of 0.
24     request->hdr.txid = 1;
25     request->hdr.ordinal = fuchsia_io_DirectoryAdminUnmountOrdinal;
26 
27     zx_channel_call_args_t args;
28     args.wr_bytes = request;
29     args.wr_handles = NULL;
30     args.rd_bytes = response;
31     args.rd_handles = NULL;
32     args.wr_num_bytes = FIDL_ALIGN(sizeof(fuchsia_io_DirectoryAdminUnmountRequest));
33     args.wr_num_handles = 0;
34     args.rd_num_bytes = FIDL_ALIGN(sizeof(fuchsia_io_DirectoryAdminUnmountResponse));
35     args.rd_num_handles = 0;
36 
37     uint32_t dsize;
38     uint32_t hcount;
39 
40     // At the moment, we don't actually care what the response is from the
41     // filesystem server (or even if it supports the unmount operation). As
42     // soon as ANY response comes back, either in the form of a closed handle
43     // or a visible response, shut down.
44     zx_status_t status = zx_channel_call(srv, 0, deadline, &args, &dsize, &hcount);
45     if (status == ZX_OK) {
46         // Read phase succeeded. If the target filesystem returned an error, we
47         // should parse it.
48         if (dsize < FIDL_ALIGN(sizeof(fuchsia_io_DirectoryAdminUnmountResponse))) {
49             status = ZX_ERR_IO;
50         } else {
51             status = response->s;
52         }
53     }
54     zx_handle_close(srv);
55     return status;
56 }
57