| // 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_NODE_H_ |
| #define LIB_VFS_CPP_INTERNAL_NODE_H_ |
| |
| #include <fuchsia/io/cpp/fidl.h> |
| #include <lib/async/dispatcher.h> |
| #include <lib/fidl/cpp/binding.h> |
| #include <lib/vfs/cpp/node_kind.h> |
| #include <limits.h> |
| |
| namespace vfs { |
| namespace internal { |
| |
| bool IsValidName(const std::string& name); |
| |
| class Connection; |
| |
| // An object in a file system. |
| // |
| // Implements the |fuchsia.io.Node| interface. Incoming connections are owned by |
| // this object and will be destroyed when this object is destroyed. |
| // |
| // Subclass to implement a particular kind of file system object. |
| // |
| // See also: |
| // |
| // * File, which is a subclass for file objects. |
| // * Directory, which is a subclass for directory objects. |
| class Node { |
| public: |
| Node(); |
| virtual ~Node(); |
| |
| Node(const Node&) = delete; |
| Node& operator=(const Node&) = delete; |
| |
| // Notifies |Node| that it should remove and return |
| // |connection| from its list as it is getting closed. |
| virtual std::unique_ptr<Connection> Close(Connection* connection); |
| |
| // This function is called before |Close| is called and status is passed to |
| // fuchsia::io::Node#Close| call. |
| // Please note |Node| is closed even if this function returns error, so Node |
| // should be ready a |Close| call. |
| // Default implementation returns |ZX_OK|. |
| virtual zx_status_t PreClose(Connection* connection); |
| |
| // Implementation of |fuchsia.io.Node/Describe|. |
| // |
| // Subclass must override this method to describe themselves accurately. |
| virtual void Describe(fuchsia::io::NodeInfo* out_info) = 0; |
| |
| // Implementation of |fuchsia.io.Node/Sync|. |
| virtual zx_status_t Sync(); |
| |
| // Implementation of |fuchsia.io.Node/GetAttr|. |
| virtual zx_status_t GetAttr(fuchsia::io::NodeAttributes* out_attributes) const; |
| |
| // Implementation of |fuchsia.io.Node/SetAttr|. |
| virtual zx_status_t SetAttr(uint32_t flags, const fuchsia::io::NodeAttributes& attributes); |
| |
| // Implementation of |fuchsia.io.Node/Clone|. |
| virtual void Clone(uint32_t flags, uint32_t parent_flags, zx::channel request, |
| async_dispatcher_t* dispatcher); |
| |
| // Establishes a connection for |request| using the given |flags|. |
| // |
| // Waits for messages asynchronously on the |request| channel using |
| // |dispatcher|. If |dispatcher| is |nullptr|, the implementation will call |
| // |async_get_default_dispatcher| to obtain the default dispatcher for the |
| // current thread. |
| // |
| // Calls |Connect| after validating flags and modes. |
| zx_status_t Serve(uint32_t flags, zx::channel request, async_dispatcher_t* dispatcher = nullptr); |
| |
| // Validates |mode| and passes request to serve |
| // |
| // Would be called by |Open|. |
| zx_status_t ServeWithMode(uint32_t flags, uint32_t mode, zx::channel request, |
| async_dispatcher_t* dispatcher = nullptr); |
| |
| // Find an entry in this directory with the given |name|. |
| // |
| // The entry is returned via |out_node|. The returned entry is owned by this |
| // directory. |
| // |
| // Returns |ZX_ERR_NOT_FOUND| if no entry exists. |
| // Default implementation in this class return |ZX_ERR_NOT_DIR| if |
| // |IsDirectory| is false, else throws error with |ZX_ASSERT|. |
| // |
| // All directory types which are not remote should implement this method. |
| virtual zx_status_t Lookup(const std::string& name, Node** out_node) const; |
| |
| // Return true if |Node| is a remote node. |
| // This function is used in |Directory::Open| to correctly open those kind of |
| // nodes. |
| bool IsRemote() const { return NodeKind::IsRemote(GetKind()); } |
| |
| // Return true if |Node| is a directory. |
| // This function is used in |ValidateFlags| and |Lookup| to return correct |
| // error. |
| bool IsDirectory() const { return NodeKind::IsDirectory(GetKind()); } |
| |
| // Return true if |Node| is a file. |
| bool IsFile() const { return NodeKind::IsFile(GetKind()); } |
| |
| // Return true if |Node| is a service. |
| bool IsService() const { return NodeKind::IsService(GetKind()); } |
| |
| // Return true if |Node| is a VMO. |
| bool IsVMO() const { return NodeKind::IsVMO(GetKind()); } |
| |
| protected: |
| // Return |Kind| of implementing |Node|. |
| virtual NodeKind::Type GetKind() const = 0; |
| |
| // Returns total number of active connections |
| uint64_t GetConnectionCount() const; |
| |
| // Called by |Serve| after validating flags and modes. |
| // This should be implemented by sub classes which doesn't create a |
| // connection class. |
| // |
| // Default implementation: |
| // Uses |CreateConnection| to create a connection appropriate for the |
| // concrete type of this object. |
| virtual zx_status_t Connect(uint32_t flags, zx::channel request, async_dispatcher_t* dispatcher); |
| |
| // Sends OnOpen event on error status if |OPEN_FLAG_DESCRIBE| is set. |
| static void SendOnOpenEventOnError(uint32_t flags, zx::channel request, zx_status_t status); |
| |
| // Store given connection. |
| void AddConnection(std::unique_ptr<Connection> connection); |
| |
| // Creates a |Connection| appropriate for the concrete type of this object. |
| // |
| // Subclasses must override this method to create an appropriate connection. |
| // The returned connection should be in an "unbound" state. |
| // |
| // Typically called by |Serve|. |
| virtual zx_status_t CreateConnection(uint32_t flags, std::unique_ptr<Connection>* connection) = 0; |
| |
| private: |
| // Validate flags on |Serve|. |
| // |
| // If the caller specified an invalid combination of flags as per io.fidl, |
| // returns |ZX_ERR_INVALID_ARGS|. |
| // |
| // Returns |ZX_ERR_NOT_DIR| if |OPEN_FLAG_DIRECTORY| is set and |
| // |IsDirectory| returns false. |
| // |
| // Calls |GetProhibitiveFlags| flags and if one of the flag is in |
| // prohibitive list, returns |ZX_ERR_INVALID_ARGS|. |
| // |
| // Calls |GetAllowedFlags|, appends |OPEN_FLAG_DESCRIBE|, |
| // |OPEN_FLAG_NODE_REFERENCE|, |OPEN_FLAG_DIRECTORY| (only if |
| // |IsDirectory| returns true) to those flags and returns |
| // |ZX_ERR_NOT_SUPPORTED| if flags are not found in allowed list. |
| // |
| // Returns ZX_OK if none of the above cases are true. |
| zx_status_t ValidateFlags(uint32_t flags) const; |
| |
| // Validate flags on |ServeWithMode|. |
| // |
| // Calls |GetAttr| and checks that mode should not be anything other than |
| // |MODE_PROTECTION_MASK| and one in attr. Returns |ZX_ERR_INVALID_ARGS| if it |
| // is, else returns |ZX_OK|. |
| zx_status_t ValidateMode(uint32_t mode) const; |
| |
| // Filters out flags that are invalid when combined with |
| // |OPEN_FLAG_NODE_REFERENCE|. |
| // Allowed flags are |OPEN_FLAG_DIRECTORY| and |OPEN_FLAG_DESCRIBE|. |
| uint32_t FilterRefFlags(uint32_t flags); |
| |
| // Allowed flags for use in |ValidateFlags|. |
| // |
| // Uses a internal map to map |Kind| to flags and retuns flags based on kind |
| // returned by |GetKind()|. |
| // |
| // See documentation of |ValidateFlags| for exact details. |
| uint32_t GetAllowedFlags() const; |
| |
| // Prohibitive flags use in |ValidateFlags|. |
| // |
| // Checks if |Node| is a directory and returns flags which cannot be |
| // applied to a directory. |
| // |
| // See documentation of |ValidateFlags| for exact details. |
| uint32_t GetProhibitiveFlags() const; |
| |
| // guards connection_ |
| mutable std::mutex mutex_; |
| // The active connections associated with this object. |
| std::vector<std::unique_ptr<Connection>> connections_ __TA_GUARDED(mutex_); |
| }; |
| |
| } // namespace internal |
| } // namespace vfs |
| |
| #endif // LIB_VFS_CPP_INTERNAL_NODE_H_ |