1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "nacl_io/dir_node.h" 6 7 #include <errno.h> 8 #include <string.h> 9 10 #include "nacl_io/osdirent.h" 11 #include "nacl_io/osstat.h" 12 #include "sdk_util/auto_lock.h" 13 #include "sdk_util/macros.h" 14 15 namespace nacl_io { 16 17 namespace { 18 19 // TODO(binji): For now, just use a dummy value for the parent ino. 20 const ino_t kParentDirIno = -1; 21 } 22 23 DirNode::DirNode(Filesystem* filesystem) 24 : Node(filesystem), 25 cache_(stat_.st_ino, kParentDirIno), 26 cache_built_(false) { 27 SetType(S_IFDIR); 28 // Directories are raadable, writable and executable by default. 29 stat_.st_mode |= S_IRALL | S_IWALL | S_IXALL; 30 } 31 32 DirNode::~DirNode() { 33 for (NodeMap_t::iterator it = map_.begin(); it != map_.end(); ++it) { 34 it->second->Unlink(); 35 } 36 } 37 38 Error DirNode::Read(const HandleAttr& attr, 39 void* buf, 40 size_t count, 41 int* out_bytes) { 42 *out_bytes = 0; 43 return EISDIR; 44 } 45 46 Error DirNode::FTruncate(off_t size) { 47 return EISDIR; 48 } 49 50 Error DirNode::Write(const HandleAttr& attr, 51 const void* buf, 52 size_t count, 53 int* out_bytes) { 54 *out_bytes = 0; 55 return EISDIR; 56 } 57 58 Error DirNode::GetDents(size_t offs, 59 dirent* pdir, 60 size_t size, 61 int* out_bytes) { 62 AUTO_LOCK(node_lock_); 63 BuildCache_Locked(); 64 return cache_.GetDents(offs, pdir, size, out_bytes); 65 } 66 67 Error DirNode::AddChild(const std::string& name, const ScopedNode& node) { 68 AUTO_LOCK(node_lock_); 69 70 if (name.empty()) 71 return ENOENT; 72 73 if (name.length() >= MEMBER_SIZE(dirent, d_name)) 74 return ENAMETOOLONG; 75 76 NodeMap_t::iterator it = map_.find(name); 77 if (it != map_.end()) 78 return EEXIST; 79 80 node->Link(); 81 map_[name] = node; 82 ClearCache_Locked(); 83 return 0; 84 } 85 86 Error DirNode::RemoveChild(const std::string& name) { 87 AUTO_LOCK(node_lock_); 88 NodeMap_t::iterator it = map_.find(name); 89 if (it != map_.end()) { 90 it->second->Unlink(); 91 map_.erase(it); 92 ClearCache_Locked(); 93 return 0; 94 } 95 return ENOENT; 96 } 97 98 Error DirNode::FindChild(const std::string& name, ScopedNode* out_node) { 99 out_node->reset(NULL); 100 101 AUTO_LOCK(node_lock_); 102 NodeMap_t::iterator it = map_.find(name); 103 if (it == map_.end()) 104 return ENOENT; 105 106 *out_node = it->second; 107 return 0; 108 } 109 110 int DirNode::ChildCount() { 111 AUTO_LOCK(node_lock_); 112 return map_.size(); 113 } 114 115 void DirNode::BuildCache_Locked() { 116 if (cache_built_) 117 return; 118 119 for (NodeMap_t::iterator it = map_.begin(), end = map_.end(); it != end; 120 ++it) { 121 const std::string& name = it->first; 122 ino_t ino = it->second->stat_.st_ino; 123 cache_.AddDirent(ino, name.c_str(), name.length()); 124 } 125 126 cache_built_ = true; 127 } 128 129 void DirNode::ClearCache_Locked() { 130 cache_built_ = false; 131 cache_.Reset(); 132 } 133 134 } // namespace nacl_io 135