[fdio][ns] Convert namespace to C++
TEST=/boot/test/sys/namespace-test
Change-Id: I44df3c92ea7577a040a99ea25041a7c26616a9f7
diff --git a/zircon/system/ulib/fdio/fdio.c b/zircon/system/ulib/fdio/fdio.c
index 194ffa4..1e88be3 100644
--- a/zircon/system/ulib/fdio/fdio.c
+++ b/zircon/system/ulib/fdio/fdio.c
@@ -14,7 +14,7 @@
#include "private.h"
struct fdio {
- fdio_ops_t* ops;
+ const fdio_ops_t* ops;
atomic_int_fast32_t refcount;
int32_t dupcount;
uint32_t ioflag;
@@ -70,7 +70,7 @@
return &io->storage;
}
-fdio_t* fdio_alloc(fdio_ops_t* ops) {
+fdio_t* fdio_alloc(const fdio_ops_t* ops) {
fdio_t* io = (fdio_t*) calloc(1, sizeof(fdio_t));
LOG(5, "fdio: io: alloc: %p\n", io);
io->ops = ops;
diff --git a/zircon/system/ulib/fdio/namespace.c b/zircon/system/ulib/fdio/namespace.cpp
similarity index 83%
rename from zircon/system/ulib/fdio/namespace.c
rename to zircon/system/ulib/fdio/namespace.cpp
index 7b4b919..528bdb6 100644
--- a/zircon/system/ulib/fdio/namespace.c
+++ b/zircon/system/ulib/fdio/namespace.cpp
@@ -4,11 +4,13 @@
#include <errno.h>
#include <fcntl.h>
-#include <stdatomic.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
+#include <atomic>
+#include <new>
+
#include <zircon/types.h>
#include <zircon/listnode.h>
#include <zircon/syscalls.h>
@@ -74,9 +76,15 @@
// readdir sequence number
// TODO: rewind support (when we have rewinddir)
- atomic_int_fast32_t seq;
+ std::atomic<int32_t> seq;
};
+static_assert(offsetof(zxio_dir, io) == 0,
+ "zxio_dir must be castable to zxio_t");
+
+static_assert(std::is_trivially_destructible<zxio_dir>::value,
+ "zxio_dir must have trivial destructor to be freed");
+
static_assert(sizeof(zxio_dir_t) <= sizeof(zxio_storage_t),
"zxio_dir_t must fit inside zxio_storage_t.");
@@ -119,12 +127,12 @@
*out = vn;
return ZX_OK;
}
- if ((vn = calloc(1, sizeof(*vn) + len + 1)) == NULL) {
+ if ((vn = static_cast<mxvn_t*>(calloc(1, sizeof(*vn) + len + 1))) == NULL) {
return ZX_ERR_NO_MEMORY;
}
memcpy(vn->name, name, len);
vn->name[len] = 0;
- vn->namelen = len;
+ vn->namelen = static_cast<uint32_t>(len);
vn->parent = dir;
vn->remote = remote;
vn->next = dir->child;
@@ -181,7 +189,7 @@
}
static zxio_dir_t* fdio_get_zxio_dir(fdio_t* io) {
- return (zxio_dir_t*)fdio_get_zxio(io);
+ return reinterpret_cast<zxio_dir_t*>(fdio_get_zxio(io));
}
static zx_status_t zxio_dir_close(fdio_t* io) {
@@ -243,6 +251,8 @@
}
}
+__BEGIN_CDECLS
+
__EXPORT
zx_status_t fdio_ns_connect(fdio_ns_t* ns, const char* path,
uint32_t flags, zx_handle_t h) {
@@ -296,9 +306,8 @@
// Expects a canonical path (no ..) with no leading
// slash and no trailing slash
-static zx_status_t zxio_dir_open(fdio_t* io, const char* path,
- uint32_t flags, uint32_t mode,
- fdio_t** out) {
+static zx_status_t zxio_dir_open(fdio_t* io, const char* path, uint32_t flags, uint32_t mode,
+ fdio_t** out) {
zxio_dir_t* dir = fdio_get_zxio_dir(io);
mxvn_t* vn = dir->vn;
zx_status_t r = ZX_OK;
@@ -332,39 +341,56 @@
return r;
}
-static zx_status_t fill_dirent(vdirent_t* de, size_t delen,
- const char* name, size_t len, uint32_t type) {
- size_t sz = sizeof(vdirent_t) + len;
+__END_CDECLS
- if (sz > delen || len > NAME_MAX) {
- return ZX_ERR_INVALID_ARGS;
+class DirentFiller {
+public:
+ explicit DirentFiller(void* buffer, size_t length) :
+ start_(buffer), buffer_(buffer), length_(length) {}
+
+ zx_status_t Add(const char* name, size_t len, uint32_t type) {
+ size_t sz = sizeof(vdirent_t) + len;
+
+ if (sz > length_ || len > NAME_MAX) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+ vdirent_t* de = static_cast<vdirent_t*>(buffer_);
+ de->ino = fuchsia_io_INO_UNKNOWN;
+ de->size = static_cast<uint8_t>(len);
+ de->type = static_cast<uint8_t>(type);
+ memcpy(de->name, name, len);
+
+ buffer_ = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(buffer_) + sz);
+ length_ -= sz;
+ return ZX_OK;
}
- de->ino = fuchsia_io_INO_UNKNOWN;
- de->size = len;
- de->type = type;
- memcpy(de->name, name, len);
- return sz;
-}
+
+ size_t Used() const {
+ return reinterpret_cast<uintptr_t>(buffer_) - reinterpret_cast<uintptr_t>(start_);
+ }
+
+private:
+ void* start_;
+ void* buffer_;
+ size_t length_;
+};
static zx_status_t zxio_dir_readdir_locked(zxio_dir_t* dir, void* buf, size_t len) {
- void *ptr = buf;
+ DirentFiller dirents(buf, len);
- zx_status_t r = fill_dirent(ptr, len, ".", 1, VTYPE_TO_DTYPE(V_TYPE_DIR));
- if (r < 0) {
+ zx_status_t status = dirents.Add(".", 1, VTYPE_TO_DTYPE(V_TYPE_DIR));
+ if (status != ZX_OK) {
return 0;
}
- ptr += r;
- len -= r;
+
for (mxvn_t* vn = dir->vn->child; vn; vn = vn->next) {
- if ((r = fill_dirent(ptr, len, vn->name, vn->namelen, VTYPE_TO_DTYPE(V_TYPE_DIR))) < 0) {
+ if ((status = dirents.Add(vn->name, vn->namelen, VTYPE_TO_DTYPE(V_TYPE_DIR))) != ZX_OK) {
break;
}
- ptr += r;
- len -= r;
}
- return ptr - buf;
+ return static_cast<zx_status_t>(dirents.Used());
}
static zx_status_t zxio_dir_get_attr(fdio_t* io, fuchsia_io_NodeAttributes* attr) {
@@ -382,7 +408,7 @@
static zx_status_t zxio_dir_readdir(fdio_t* io, void* ptr, size_t max, size_t* actual) {
zxio_dir_t* dir = fdio_get_zxio_dir(io);
mtx_lock(&dir->ns->lock);
- int n = atomic_fetch_add(&dir->seq, 1);
+ int n = dir->seq.fetch_add(1);
if (n == 0) {
*actual = zxio_dir_readdir_locked(dir, ptr, max);
} else {
@@ -396,51 +422,58 @@
return ZX_ERR_UNAVAILABLE;
}
-static fdio_ops_t dir_ops = {
- .get_attr = zxio_dir_get_attr,
- .close = zxio_dir_close,
- .open = zxio_dir_open,
- .clone = fdio_default_clone,
- .ioctl = fdio_default_ioctl,
- .wait_begin = fdio_default_wait_begin,
- .wait_end = fdio_default_wait_end,
- .unwrap = fdio_default_unwrap,
- .posix_ioctl = fdio_default_posix_ioctl,
- .get_vmo = fdio_default_get_vmo,
- .get_token = fdio_default_get_token,
- .set_attr = fdio_default_set_attr,
- .readdir = zxio_dir_readdir,
- .rewind = zxio_dir_rewind,
- .unlink = zxio_dir_unlink,
- .truncate = fdio_default_truncate,
- .rename = fdio_default_rename,
- .link = fdio_default_link,
- .get_flags = fdio_default_get_flags,
- .set_flags = fdio_default_set_flags,
- .recvfrom = fdio_default_recvfrom,
- .sendto = fdio_default_sendto,
- .recvmsg = fdio_default_recvmsg,
- .sendmsg = fdio_default_sendmsg,
- .shutdown = fdio_default_shutdown,
-};
+constexpr fdio_ops_t dir_ops = []() {
+ fdio_ops_t ops = {};
+ ops.get_attr = zxio_dir_get_attr;
+ ops.close = zxio_dir_close;
+ ops.open = zxio_dir_open;
+ ops.clone = fdio_default_clone;
+ ops.ioctl = fdio_default_ioctl;
+ ops.wait_begin = fdio_default_wait_begin;
+ ops.wait_end = fdio_default_wait_end;
+ ops.unwrap = fdio_default_unwrap;
+ ops.posix_ioctl = fdio_default_posix_ioctl;
+ ops.get_vmo = fdio_default_get_vmo;
+ ops.get_token = fdio_default_get_token;
+ ops.set_attr = fdio_default_set_attr;
+ ops.readdir = zxio_dir_readdir;
+ ops.rewind = zxio_dir_rewind;
+ ops.unlink = zxio_dir_unlink;
+ ops.truncate = fdio_default_truncate;
+ ops.rename = fdio_default_rename;
+ ops.link = fdio_default_link;
+ ops.get_flags = fdio_default_get_flags;
+ ops.set_flags = fdio_default_set_flags;
+ ops.recvfrom = fdio_default_recvfrom;
+ ops.sendto = fdio_default_sendto;
+ ops.recvmsg = fdio_default_recvmsg;
+ ops.sendmsg = fdio_default_sendmsg;
+ ops.shutdown = fdio_default_shutdown;
+ return ops;
+}();
static fdio_t* fdio_dir_create_locked(fdio_ns_t* ns, mxvn_t* vn) {
fdio_t* io = fdio_alloc(&dir_ops);
if (io == NULL) {
return NULL;
}
+ // Invoke placement new on the new zxio_dir_t. Since the object is trivially
+ // destructible, we can avoid invoking the destructor.
+ char* storage = reinterpret_cast<char*>(fdio_get_zxio_dir(io));
+ zxio_dir_t* dir = new (storage) zxio_dir_t();
zxio_null_init(&(fdio_get_zxio_storage(io)->io));
- zxio_dir_t* dir = fdio_get_zxio_dir(io);
+
dir->ns = ns;
dir->vn = vn;
- atomic_init(&dir->seq, 0);
return io;
}
+__BEGIN_CDECLS
+
__EXPORT
zx_status_t fdio_ns_create(fdio_ns_t** out) {
// +1 is for the "" name
- fdio_ns_t* ns = calloc(1, sizeof(fdio_ns_t) + 1);
+ fdio_ns_t* ns = static_cast<fdio_ns_t*>(calloc(1, sizeof(fdio_ns_t) + 1));
if (ns == NULL) {
return ZX_ERR_NO_MEMORY;
}
@@ -665,7 +698,7 @@
static zx_status_t ns_export_count(void* cookie, const char* path,
size_t len, zx_handle_t h) {
- export_state_t* es = cookie;
+ export_state_t* es = static_cast<export_state_t*>(cookie);
// Each entry needs one slot in the handle table,
// one slot in the type table, and one slot in the
// path table, plus storage for the path and NUL
@@ -679,11 +712,11 @@
if ((h = fdio_service_clone(h)) == ZX_HANDLE_INVALID) {
return ZX_ERR_BAD_STATE;
}
- export_state_t* es = cookie;
+ export_state_t* es = static_cast<export_state_t*>(cookie);
memcpy(es->buffer, path, len + 1);
es->path[es->count] = es->buffer;
es->handle[es->count] = h;
- es->type[es->count] = PA_HND(PA_NS_DIR, es->count);
+ es->type[es->count] = PA_HND(PA_NS_DIR, static_cast<uint32_t>(es->count));
es->buffer += (len + 1);
es->count++;
return ZX_OK;
@@ -699,7 +732,7 @@
ns_enumerate(&ns->root, &es, ns_export_count);
- fdio_flat_namespace_t* flat = malloc(es.bytes);
+ fdio_flat_namespace_t* flat = static_cast<fdio_flat_namespace_t*>(malloc(es.bytes));
if (flat == NULL) {
mtx_unlock(&ns->lock);
return ZX_ERR_NO_MEMORY;
@@ -748,7 +781,9 @@
}
__EXPORT
-void fdio_ns_free_flat_namesapce(fdio_flat_namespace_t* ns) {
+void fdio_ns_free_flat_namespace(fdio_flat_namespace_t* ns) {
zx_handle_close_many(ns->handle, ns->count);
free(ns);
}
+
+__END_CDECLS
diff --git a/zircon/system/ulib/fdio/private-remoteio.h b/zircon/system/ulib/fdio/private-remoteio.h
index dca4f0c..64ef7c73 100644
--- a/zircon/system/ulib/fdio/private-remoteio.h
+++ b/zircon/system/ulib/fdio/private-remoteio.h
@@ -6,6 +6,10 @@
#include "private.h"
+__BEGIN_CDECLS
+
// open operation directly on remoteio handle
zx_status_t zxrio_open_handle(zx_handle_t h, const char* path, uint32_t flags,
uint32_t mode, fdio_t** out);
+
+__END_CDECLS
diff --git a/zircon/system/ulib/fdio/private.h b/zircon/system/ulib/fdio/private.h
index 67fa49b..fc01071 100644
--- a/zircon/system/ulib/fdio/private.h
+++ b/zircon/system/ulib/fdio/private.h
@@ -60,7 +60,7 @@
zx_status_t (*get_flags)(fdio_t* io, uint32_t* out_flags);
zx_status_t (*set_flags)(fdio_t* io, uint32_t flags);
ssize_t (*recvfrom)(fdio_t* io, void* data, size_t len, int flags,
- struct sockaddr* restrict addr, socklen_t* restrict addrlen);
+ struct sockaddr* __restrict addr, socklen_t* __restrict addrlen);
ssize_t (*sendto)(fdio_t* io, const void* data, size_t len, int flags,
const struct sockaddr* addr, socklen_t addrlen);
ssize_t (*recvmsg)(fdio_t* io, struct msghdr* msg, int flags);
@@ -83,6 +83,8 @@
typedef struct fdio fdio_t;
+__BEGIN_CDECLS
+
// Acquire a reference to a globally shared "fdio_t" object
// acts as a sentinel value for reservation.
//
@@ -97,7 +99,7 @@
//
// Initializes the refcount to one. The refcount may be altered with the |fdio_acquire| and
// |fdio_release| functions. When the refcount reaches zero, the object is destroyed.
-fdio_t* fdio_alloc(fdio_ops_t* ops);
+fdio_t* fdio_alloc(const fdio_ops_t* ops);
// Increases the refcount of |io| by one.
void fdio_acquire(fdio_t* io);
@@ -226,8 +228,8 @@
ssize_t fdio_default_write(fdio_t* io, const void* _data, size_t len);
ssize_t fdio_default_write_at(fdio_t* io, const void* _data, size_t len, off_t offset);
ssize_t fdio_default_recvfrom(fdio_t* io, void* _data, size_t len, int flags,
- struct sockaddr* restrict addr,
- socklen_t* restrict addrlen);
+ struct sockaddr* __restrict addr,
+ socklen_t* __restrict addrlen);
ssize_t fdio_default_sendto(fdio_t* io, const void* _data, size_t len,
int flags, const struct sockaddr* addr,
socklen_t addrlen);
@@ -307,3 +309,5 @@
// Unassign the reservation at |fd|. If |fd| does not resolve to a reservation
// then -1 is returned and errno is set to EINVAL, otherwise |fd| is returned.
int fdio_release_reserved(int fd);
+
+__END_CDECLS
diff --git a/zircon/system/ulib/fdio/rules.mk b/zircon/system/ulib/fdio/rules.mk
index f08278a..d8272e8 100644
--- a/zircon/system/ulib/fdio/rules.mk
+++ b/zircon/system/ulib/fdio/rules.mk
@@ -17,7 +17,7 @@
$(LOCAL_DIR)/debug.c \
$(LOCAL_DIR)/get-vmo.c \
$(LOCAL_DIR)/fdio.c \
- $(LOCAL_DIR)/namespace.c \
+ $(LOCAL_DIR)/namespace.cpp \
$(LOCAL_DIR)/null.c \
$(LOCAL_DIR)/remoteio.c \
$(LOCAL_DIR)/socket.c \