blob: e5be6a9bb90e21d24850e48c6bff13b366b9968c [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/vfs.h>
#include <lib/fit/function.h>
#include <fs/vfs_types.h>
namespace fio = ::llcpp::fuchsia::io;
namespace fs {
VnodeConnectionOptions VnodeConnectionOptions::FromIoV1Flags(uint32_t fidl_flags) {
VnodeConnectionOptions options;
// Flags:
if (fidl_flags & fio::OPEN_FLAG_CREATE) {
options.flags.create = true;
}
if (fidl_flags & fio::OPEN_FLAG_CREATE_IF_ABSENT) {
options.flags.fail_if_exists = true;
}
if (fidl_flags & fio::OPEN_FLAG_TRUNCATE) {
options.flags.truncate = true;
}
if (fidl_flags & fio::OPEN_FLAG_DIRECTORY) {
options.flags.directory = true;
}
if (fidl_flags & fio::OPEN_FLAG_APPEND) {
options.flags.append = true;
}
if (fidl_flags & fio::OPEN_FLAG_NO_REMOTE) {
options.flags.no_remote = true;
}
if (fidl_flags & fio::OPEN_FLAG_NODE_REFERENCE) {
options.flags.node_reference = true;
}
if (fidl_flags & fio::OPEN_FLAG_DESCRIBE) {
options.flags.describe = true;
}
if (fidl_flags & fio::OPEN_FLAG_POSIX) {
options.flags.posix = true;
}
if (fidl_flags & fio::OPEN_FLAG_NOT_DIRECTORY) {
options.flags.not_directory = true;
}
if (fidl_flags & fio::CLONE_FLAG_SAME_RIGHTS) {
options.flags.clone_same_rights = true;
}
// Rights (these are smushed into |fidl_flags| in fuchsia.io v1):
if (fidl_flags & fio::OPEN_RIGHT_READABLE) {
options.rights.read = true;
}
if (fidl_flags & fio::OPEN_RIGHT_WRITABLE) {
options.rights.write = true;
}
if (fidl_flags & fio::OPEN_RIGHT_ADMIN) {
options.rights.admin = true;
}
if (fidl_flags & fio::OPEN_RIGHT_EXECUTABLE) {
options.rights.execute = true;
}
return options;
}
uint32_t VnodeConnectionOptions::ToIoV1Flags() const {
uint32_t fidl_flags = 0;
// Flags:
if (flags.create) {
fidl_flags |= fio::OPEN_FLAG_CREATE;
}
if (flags.fail_if_exists) {
fidl_flags |= fio::OPEN_FLAG_CREATE_IF_ABSENT;
}
if (flags.truncate) {
fidl_flags |= fio::OPEN_FLAG_TRUNCATE;
}
if (flags.directory) {
fidl_flags |= fio::OPEN_FLAG_DIRECTORY;
}
if (flags.append) {
fidl_flags |= fio::OPEN_FLAG_APPEND;
}
if (flags.no_remote) {
fidl_flags |= fio::OPEN_FLAG_NO_REMOTE;
}
if (flags.node_reference) {
fidl_flags |= fio::OPEN_FLAG_NODE_REFERENCE;
}
if (flags.describe) {
fidl_flags |= fio::OPEN_FLAG_DESCRIBE;
}
if (flags.posix) {
fidl_flags |= fio::OPEN_FLAG_POSIX;
}
if (flags.not_directory) {
fidl_flags |= fio::OPEN_FLAG_NOT_DIRECTORY;
}
if (flags.clone_same_rights) {
fidl_flags |= fio::CLONE_FLAG_SAME_RIGHTS;
}
// Rights (these are smushed into |fidl_flags| in fuchsia.io v1):
if (rights.read) {
fidl_flags |= fio::OPEN_RIGHT_READABLE;
}
if (rights.write) {
fidl_flags |= fio::OPEN_RIGHT_WRITABLE;
}
if (rights.admin) {
fidl_flags |= fio::OPEN_RIGHT_ADMIN;
}
if (rights.execute) {
fidl_flags |= fio::OPEN_RIGHT_EXECUTABLE;
}
return fidl_flags;
}
VnodeConnectionOptions VnodeConnectionOptions::FilterForNewConnection(
VnodeConnectionOptions options) {
VnodeConnectionOptions result;
result.flags.append = options.flags.append;
result.flags.node_reference = options.flags.node_reference;
result.rights = options.rights;
return result;
}
fio::NodeAttributes VnodeAttributes::ToIoV1NodeAttributes() const {
return fio::NodeAttributes{.mode = mode,
.id = inode,
.content_size = content_size,
.storage_size = storage_size,
.link_count = link_count,
.creation_time = creation_time,
.modification_time = modification_time};
}
void ConvertToIoV1NodeInfo(VnodeRepresentation representation,
fit::callback<void(fio::NodeInfo&&)> callback) {
representation.visit([&](auto&& repr) {
using T = std::decay_t<decltype(repr)>;
fio::NodeInfo info;
if constexpr (std::is_same_v<T, fs::VnodeRepresentation::Connector>) {
fidl::aligned<fio::Service> service;
info.set_service(fidl::unowned_ptr(&service));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::File>) {
fio::FileObject file = {.event = std::move(repr.observer)};
info.set_file(fidl::unowned_ptr(&file));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::Directory>) {
fidl::aligned<fio::DirectoryObject> directory;
info.set_directory(fidl::unowned_ptr(&directory));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::Pipe>) {
fio::Pipe pipe = {.socket = std::move(repr.socket)};
info.set_pipe(fidl::unowned_ptr(&pipe));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::Memory>) {
fio::Vmofile vmofile = {
.vmo = std::move(repr.vmo), .offset = repr.offset, .length = repr.length};
info.set_vmofile(fidl::unowned_ptr(&vmofile));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::Device>) {
fio::Device device = {.event = std::move(repr.event)};
info.set_device(fidl::unowned_ptr(&device));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::Tty>) {
fio::Tty tty = {.event = std::move(repr.event)};
info.set_tty(fidl::unowned_ptr(&tty));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::DatagramSocket>) {
fio::DatagramSocket datagram_socket = {.event = std::move(repr.event)};
info.set_datagram_socket(fidl::unowned_ptr(&datagram_socket));
callback(std::move(info));
} else if constexpr (std::is_same_v<T, fs::VnodeRepresentation::StreamSocket>) {
fio::StreamSocket stream_socket = {.socket = std::move(repr.socket)};
info.set_stream_socket(fidl::unowned_ptr(&stream_socket));
callback(std::move(info));
} else {
ZX_PANIC("Representation variant is not initialized");
}
});
}
} // namespace fs