Home | History | Annotate | Download | only in nacl_io
      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