OLD | NEW |
| (Empty) |
1 /* Copyright (c) 2012 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_mounts/mount_node_dir.h" | |
6 | |
7 #include <errno.h> | |
8 #include <string.h> | |
9 | |
10 #include "nacl_mounts/osdirent.h" | |
11 #include "nacl_mounts/osstat.h" | |
12 #include "utils/macros.h" | |
13 #include "utils/auto_lock.h" | |
14 | |
15 MountNodeDir::MountNodeDir(Mount* mount) | |
16 : MountNode(mount), | |
17 cache_(NULL) { | |
18 stat_.st_mode |= S_IFDIR; | |
19 } | |
20 | |
21 MountNodeDir::~MountNodeDir() { | |
22 free(cache_); | |
23 } | |
24 | |
25 int MountNodeDir::Read(size_t offs, void *buf, size_t count) { | |
26 errno = EISDIR; | |
27 return -1; | |
28 } | |
29 | |
30 int MountNodeDir::Truncate(size_t size) { | |
31 errno = EISDIR; | |
32 return -1; | |
33 } | |
34 | |
35 int MountNodeDir::Write(size_t offs, void *buf, size_t count) { | |
36 errno = EISDIR; | |
37 return -1; | |
38 } | |
39 | |
40 int MountNodeDir::GetDents(size_t offs, struct dirent* pdir, size_t size) { | |
41 AutoLock lock(&lock_); | |
42 | |
43 // If the buffer pointer is invalid, fail | |
44 if (NULL == pdir) { | |
45 errno = EINVAL; | |
46 return -1; | |
47 } | |
48 | |
49 // If the buffer is too small, fail | |
50 if (size < sizeof(struct dirent)) { | |
51 errno = EINVAL; | |
52 return -1; | |
53 } | |
54 | |
55 // Force size to a multiple of dirent | |
56 size -= size % sizeof(struct dirent); | |
57 size_t max = map_.size() * sizeof(struct dirent); | |
58 if (cache_ == NULL) BuildCache(); | |
59 | |
60 if (offs >= max) return 0; | |
61 if (offs + size >= max) size = max - offs; | |
62 | |
63 memcpy(pdir, ((char *) cache_) + offs, size); | |
64 return size; | |
65 } | |
66 | |
67 int MountNodeDir::AddChild(const std::string& name, MountNode* node) { | |
68 AutoLock lock(&lock_); | |
69 | |
70 if (name.empty()) { | |
71 errno = ENOENT; | |
72 return -1; | |
73 } | |
74 if (name.length() >= MEMBER_SIZE(struct dirent, d_name)) { | |
75 errno = ENAMETOOLONG; | |
76 return -1; | |
77 } | |
78 | |
79 MountNodeMap_t::iterator it = map_.find(name); | |
80 if (it != map_.end()) { | |
81 errno = EEXIST; | |
82 return -1; | |
83 } | |
84 | |
85 node->Link(); | |
86 map_[name] = node; | |
87 ClearCache(); | |
88 return 0; | |
89 } | |
90 | |
91 int MountNodeDir::RemoveChild(const std::string& name) { | |
92 AutoLock lock(&lock_); | |
93 MountNodeMap_t::iterator it = map_.find(name); | |
94 if (it != map_.end()) { | |
95 it->second->Unlink(); | |
96 map_.erase(it); | |
97 ClearCache(); | |
98 return 0; | |
99 } | |
100 errno = ENOENT; | |
101 return -1; | |
102 } | |
103 | |
104 MountNode* MountNodeDir::FindChild(const std::string& name) { | |
105 AutoLock lock(&lock_); | |
106 MountNodeMap_t::iterator it = map_.find(name); | |
107 if (it != map_.end()) { | |
108 return it->second; | |
109 } | |
110 errno = ENOENT; | |
111 return NULL; | |
112 } | |
113 | |
114 int MountNodeDir::ChildCount() { | |
115 AutoLock lock(&lock_); | |
116 return map_.size(); | |
117 } | |
118 | |
119 void MountNodeDir::ClearCache() { | |
120 free(cache_); | |
121 cache_ = NULL; | |
122 } | |
123 | |
124 void MountNodeDir::BuildCache() { | |
125 if (map_.size()) { | |
126 cache_ = (struct dirent *) malloc(sizeof(struct dirent) * map_.size()); | |
127 MountNodeMap_t::iterator it = map_.begin(); | |
128 for (size_t index = 0; it != map_.end(); it++, index++) { | |
129 MountNode* node = it->second; | |
130 size_t len = it->first.length(); | |
131 cache_[index].d_ino = node->stat_.st_ino; | |
132 cache_[index].d_reclen = sizeof(struct dirent); | |
133 cache_[index].d_name[len] = 0; | |
134 strncpy(cache_[index].d_name, &it->first[0], len); | |
135 } | |
136 } | |
137 } | |
OLD | NEW |