15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file. 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "nacl_io/dir_node.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "nacl_io/log.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osdirent.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "nacl_io/osinttypes.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osstat.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/macros.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io { 18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace { 2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// TODO(binji): For now, just use a dummy value for the parent ino. 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const ino_t kParentDirIno = -1; 2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DirNode::DirNode(Filesystem* filesystem) 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : Node(filesystem), 2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cache_(stat_.st_ino, kParentDirIno), 2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cache_built_(false) { 298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SetType(S_IFDIR); 308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Directories are raadable, writable and executable by default. 318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) stat_.st_mode |= S_IRALL | S_IWALL | S_IXALL; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)DirNode::~DirNode() { 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (NodeMap_t::iterator it = map_.begin(); it != map_.end(); ++it) { 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it->second->Unlink(); 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error DirNode::Read(const HandleAttr& attr, 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void* buf, 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t count, 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* out_bytes) { 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_bytes = 0; 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_TRACE("Can't read a directory."); 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return EISDIR; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Error DirNode::FTruncate(off_t size) { 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_TRACE("Can't truncate a directory."); 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return EISDIR; 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error DirNode::Write(const HandleAttr& attr, 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const void* buf, 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t count, 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* out_bytes) { 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_bytes = 0; 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_TRACE("Can't write to a directory."); 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return EISDIR; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error DirNode::GetDents(size_t offs, 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) dirent* pdir, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t size, 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int* out_bytes) { 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AUTO_LOCK(node_lock_); 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) BuildCache_Locked(); 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return cache_.GetDents(offs, pdir, size, out_bytes); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciError DirNode::Fchmod(mode_t mode) { 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AUTO_LOCK(node_lock_); 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetMode(mode); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return 0; 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error DirNode::AddChild(const std::string& name, const ScopedNode& node) { 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AUTO_LOCK(node_lock_); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (name.empty()) { 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Can't add child with no name."); 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ENOENT; 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (name.length() >= MEMBER_SIZE(dirent, d_name)) { 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_ERROR("Child name is too long: %" PRIuS " >= %" PRIuS, 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch name.length(), 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MEMBER_SIZE(dirent, d_name)); 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ENAMETOOLONG; 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NodeMap_t::iterator it = map_.find(name); 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (it != map_.end()) { 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch LOG_TRACE("Can't add child \"%s\", it already exists.", name); 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return EEXIST; 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->Link(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) map_[name] = node; 10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ClearCache_Locked(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error DirNode::RemoveChild(const std::string& name) { 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AUTO_LOCK(node_lock_); 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NodeMap_t::iterator it = map_.find(name); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != map_.end()) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second->Unlink(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) map_.erase(it); 11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ClearCache_Locked(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ENOENT; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Error DirNode::FindChild(const std::string& name, ScopedNode* out_node) { 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch out_node->reset(NULL); 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AUTO_LOCK(node_lock_); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NodeMap_t::iterator it = map_.find(name); 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (it == map_.end()) 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ENOENT; 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *out_node = it->second; 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return 0; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int DirNode::ChildCount() { 1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AUTO_LOCK(node_lock_); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return map_.size(); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DirNode::BuildCache_Locked() { 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (cache_built_) 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (NodeMap_t::iterator it = map_.begin(), end = map_.end(); it != end; 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& name = it->first; 14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ino_t ino = it->second->stat_.st_ino; 14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cache_.AddDirent(ino, name.c_str(), name.length()); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cache_built_ = true; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DirNode::ClearCache_Locked() { 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cache_built_ = false; 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) cache_.Reset(); 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} // namespace nacl_io 154