blob: ba7192e8504b9fa1032754c7f15ac92186123fa8 [file] [log] [blame] [edit]
// 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.
#ifndef LIB_VFS_CPP_INTERNAL_DIRECTORY_H_
#define LIB_VFS_CPP_INTERNAL_DIRECTORY_H_
#include <fuchsia/io/cpp/fidl.h>
#include <lib/vfs/cpp/internal/node.h>
#include <lib/zx/channel.h>
#include <lib/zx/result.h>
#include <stdint.h>
#include <zircon/types.h>
#include <optional>
#include <string>
#include <string_view>
namespace vfs {
namespace internal {
// A directory object in a file system.
//
// Implements the |fuchsia.io.Directory| interface. Incoming connections are
// owned by this object and will be destroyed when this object is destroyed.
//
// Subclass to implement specific directory semantics.
//
// See also:
//
// * File, which represents file objects.
class Directory : public Node {
public:
Directory();
~Directory() override;
// |Node| implementation
zx_status_t Lookup(std::string_view name, Node** out_node) const override;
void Describe(fuchsia::io::NodeInfoDeprecated* out_info) override;
// Enumerates Directory
//
// |offset| will start with 0 and then implementation can set offset as it
// pleases.
//
// Returns |ZX_OK| if able to read at least one dentry else returns
// |ZX_ERR_INVALID_ARGS| with |out_actual| as 0 and |out_offset| as |offset|.
virtual zx_status_t Readdir(uint64_t offset, void* data, uint64_t len, uint64_t* out_offset,
uint64_t* out_actual) = 0;
// Parses path and opens correct node.
//
// Called from |fuchsia.io.Directory#Open|.
void Open(fuchsia::io::OpenFlags open_flags, fuchsia::io::OpenFlags parent_flags,
fuchsia::io::ModeType mode, std::string_view path, zx::channel request,
async_dispatcher_t* dispatcher);
// Validates passed path
//
// Returns |false| if |path| is longer than |NAME_MAX| or if
// |path| starts with ".." or "/".
// Returns |true| on valid path.
static bool ValidatePath(std::string_view path);
struct WalkPathResult {
std::optional<std::string_view> current_node_name;
std::string_view remaining_path;
};
// Walks provided path to find the first node name in |path| and returns
// remaining path and current node name if not self.
//
// Calls |ValidatePath| and returns |ZX_ERR_INVALID_ARGS| on failure.
//
// Supports paths like "a/./b//."
// Supports repetitive "/"
// Doesn't support "a/../a/b"
//
// eg:
// path ="a/b/c/d", |WalkPathResult::remaining_path| would be "b/c/d"
// path =".", |WalkPathResult::remaining_path| would be empty
// path ="./", |WalkPathResult::remaining_path| would be empty
// path ="a/b/", |WalkPathResult::remaining_path| would be "b/"
static zx::result<WalkPathResult> WalkPath(std::string_view path);
// |Node| implementation
zx_status_t GetAttr(fuchsia::io::NodeAttributes* out_attributes) const override;
bool IsDirectory() const override;
protected:
// |Node| implementations
zx_status_t CreateConnection(fuchsia::io::OpenFlags flags,
std::unique_ptr<Connection>* connection) override;
fuchsia::io::OpenFlags GetAllowedFlags() const override;
fuchsia::io::OpenFlags GetProhibitiveFlags() const override;
struct LookupPathResult {
Node& node;
std::string_view remaining_path;
bool is_dir;
};
// Walks |path| until the node corresponding to |path| is found, or a remote
// filesystem was encountered during traversal. In the latter case, this
// function will return an intermediate node, on which |IsRemote| returns
// true, and will return the remaining path.
//
// For example: if path is "a/b/c/d/f/g" and c is a remote node, it will return
// {
// node: c,
// remaining_path: "d/f/g",
// is_dir: false,
// }
//
// |is_dir| is true if path has '/' or '/.' at the end.
//
// Calls |WalkPath| in loop and returns status on error. Returns
// |ZX_ERR_NOT_DIR| if an intermediate component of |path| is not a directory.
zx::result<LookupPathResult> LookupPath(std::string_view path);
};
} // namespace internal
} // namespace vfs
#endif // LIB_VFS_CPP_INTERNAL_DIRECTORY_H_