blob: a4ea6e01592a3c46031a68b783d5c8e08a9cab33 [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.
#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_