| |
| // 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 <stdint.h> |
| |
| #include <string> |
| |
| 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(const std::string& name, Node** out_node) const override; |
| |
| // Override that describes this object as a directory. |
| void Describe(fuchsia::io::NodeInfo* 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(uint32_t open_flags, uint32_t parent_flags, uint32_t mode, const char* path, |
| size_t path_len, zx::channel request, async_dispatcher_t* dispatcher); |
| |
| // Validates passed path |
| // |
| // Returns |ZX_ERR_INVALID_ARGS| if path_len is more than |NAME_MAX| or if |
| // |path| starts with ".." or "/". |
| // Returns |ZX_OK| on valid path. |
| static zx_status_t ValidatePath(const char* path, size_t path_len); |
| |
| // Walks provided path to find the first node name in |path| and then |
| // sets |out_path| and |out_len| to correct position in |path| beyond current |
| // node name and sets |out_key| to node name. |
| // |
| // Calls |ValidatePath| and returns |status| on error. |
| // Sets |out_is_self| to true if path is empty or '.' or './' |
| // |
| // Supports paths like 'a/./b//.' |
| // Supports repetitive '/' |
| // Doesn't support 'a/../a/b' |
| // |
| // eg: |
| // path ="a/b/c/d", out_path would be "b/c/d" |
| // path =".", out_path would be "" |
| // path ="./", out_path would be "" |
| // path ="a/b/", out_path would be "b/" |
| static zx_status_t WalkPath(const char* path, size_t path_len, const char** out_path, |
| size_t* out_len, std::string* out_key, bool* out_is_self); |
| |
| // |Node| implementation |
| zx_status_t GetAttr(fuchsia::io::NodeAttributes* out_attributes) const override; |
| |
| protected: |
| // |Node| implementations |
| zx_status_t CreateConnection(uint32_t flags, std::unique_ptr<Connection>* connection) override; |
| |
| // Markes directory with |NODE_KIND_DIRECTORY| and also marks it readable and |
| // writable. |
| NodeKind::Type GetKind() const override; |
| |
| // 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 set |out_path| and |out_len| to be the remaining path. |
| // |
| // For example: if path is /a/b/c/d/f/g and c is a remote node, it will return |
| // c in |out_node|, "d/f/g" in |out_path| and |out_len|. |
| // |
| // Sets |out_is_dir| to 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_status_t LookupPath(const char* path, size_t path_len, bool* out_is_dir, Node** out_node, |
| const char** out_path, size_t* out_len); |
| }; |
| |
| } // namespace internal |
| } // namespace vfs |
| |
| #endif // LIB_VFS_CPP_INTERNAL_DIRECTORY_H_ |