// Copyright 2016 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. #pragma once #include #include #include #include #include #include #include #include #include namespace memfs { class VnodeMemfs; constexpr size_t kDnodeNameMax = NAME_MAX; static_assert(NAME_MAX == 255, "NAME_MAX must be 255"); // Assert that kDnodeNameMax can be used as a bitmask static_assert(((kDnodeNameMax + 1) & kDnodeNameMax) == 0, "Expected kDnodeNameMax to be one less than a power of two"); class Dnode : public fbl::RefCounted { public: DISALLOW_COPY_ASSIGN_AND_MOVE(Dnode); using NodeState = fbl::DoublyLinkedListNodeState>; // ChildTraits is the state used for a Dnode to appear as the child // of another dnode. struct TypeChildTraits { static NodeState& node_state(Dnode& dn) { return dn.type_child_state_; }}; using ChildList = fbl::DoublyLinkedList, Dnode::TypeChildTraits>; // Allocates a dnode, attached to a vnode static fbl::RefPtr Create(fbl::StringPiece name, fbl::RefPtr vn); // Takes a parent-less node and makes it a child of the parent node. // // Increments child link count by one. // If the child is a directory, increments the parent link count by one. static void AddChild(fbl::RefPtr parent, fbl::RefPtr child); // Removes a dnode from its parent (if dnode has a parent) // Decrements parent link count by one. void RemoveFromParent(); // Detaches a dnode from its parent / vnode. // Decrements dn->vnode link count by one (if it exists). void Detach(); bool HasChildren() const { return !children_.is_empty(); } // Look up the child dnode (within a parent directory) by name. // Returns ZX_OK if the child is found. // // If the looked up child is the current node, "out" is nullptr, and // ZX_OK is still returned. // If "out" is provided as "nullptr", the returned status appears the // same, but the "out" argument is not touched. zx_status_t Lookup(fbl::StringPiece name, fbl::RefPtr* out) const; // Acquire a pointer to the vnode underneath this dnode. // Acquires a reference to the underlying vnode. fbl::RefPtr AcquireVnode() const; // Returns ZX_OK if the dnode may be unlinked zx_status_t CanUnlink() const; // Read dirents (up to len bytes worth) into data. // ReaddirStart reads the canned "." and ".." entries that should appear // at the beginning of a directory. // On success, return the number of bytes read. static zx_status_t ReaddirStart(fs::DirentFiller* df, void* cookie); void Readdir(fs::DirentFiller* df, void* cookie) const; // Answers the question: "Is dn a subdirectory of this?" bool IsSubdirectory(fbl::RefPtr dn) const; // Functions to take / steal the allocated dnode name. fbl::unique_ptr TakeName(); void PutName(fbl::unique_ptr name, size_t len); bool IsDirectory() const; private: friend struct TypeChildTraits; Dnode(fbl::RefPtr vn, fbl::unique_ptr name, uint32_t flags); size_t NameLen() const; bool NameMatch(fbl::StringPiece name) const; NodeState type_child_state_; fbl::RefPtr vnode_; fbl::RefPtr parent_; // Used to impose an absolute order on dnodes within a directory. size_t ordering_token_; ChildList children_; uint32_t flags_; fbl::unique_ptr name_; }; } // namespace memfs