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