• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DirNode(Filesystem * filesystem)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 
~DirNode()32 DirNode::~DirNode() {
33   for (NodeMap_t::iterator it = map_.begin(); it != map_.end(); ++it) {
34     it->second->Unlink();
35   }
36 }
37 
Read(const HandleAttr & attr,void * buf,size_t count,int * out_bytes)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 
FTruncate(off_t size)46 Error DirNode::FTruncate(off_t size) {
47   return EISDIR;
48 }
49 
Write(const HandleAttr & attr,const void * buf,size_t count,int * out_bytes)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 
GetDents(size_t offs,dirent * pdir,size_t size,int * out_bytes)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 
AddChild(const std::string & name,const ScopedNode & node)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 
RemoveChild(const std::string & name)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 
FindChild(const std::string & name,ScopedNode * out_node)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 
ChildCount()110 int DirNode::ChildCount() {
111   AUTO_LOCK(node_lock_);
112   return map_.size();
113 }
114 
BuildCache_Locked()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 
ClearCache_Locked()129 void DirNode::ClearCache_Locked() {
130   cache_built_ = false;
131   cache_.Reset();
132 }
133 
134 }  // namespace nacl_io
135