summaryrefslogtreecommitdiffstats
path: root/native_client_sdk/src/libraries/nacl_mounts
diff options
context:
space:
mode:
authornoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-09 22:04:01 +0000
committernoelallen@google.com <noelallen@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-09 22:04:01 +0000
commit7db56ff7801c34accc1f4589a48d3b6d42e3ac32 (patch)
tree0b047db3bd7fba75470af6e3b5db634533be9a12 /native_client_sdk/src/libraries/nacl_mounts
parente1d8ca85f00533e06abf2799781cb84cd3b051ea (diff)
downloadchromium_src-7db56ff7801c34accc1f4589a48d3b6d42e3ac32.zip
chromium_src-7db56ff7801c34accc1f4589a48d3b6d42e3ac32.tar.gz
chromium_src-7db56ff7801c34accc1f4589a48d3b6d42e3ac32.tar.bz2
Add mount sources for a MountNode (inode)
Add sources to for a base node, directory node, memory node and test files. BUG=122229 R=binji@chromium.org Review URL: https://chromiumcodereview.appspot.com/10010023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131455 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk/src/libraries/nacl_mounts')
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_mem.cc291
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_mem.h66
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_node.cc125
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_node.h71
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.cc135
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.h49
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.cc81
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.h32
-rw-r--r--native_client_sdk/src/libraries/nacl_mounts/nacl_mounts.vcproj212
9 files changed, 1062 insertions, 0 deletions
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_mem.cc b/native_client_sdk/src/libraries/nacl_mounts/mount_mem.cc
new file mode 100644
index 0000000..cb797e2
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_mem.cc
@@ -0,0 +1,291 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string>
+
+#include <vector>
+
+#include "mount_mem.h"
+#include "path.h"
+#include "util/simple_auto_lock.h"
+
+static const size_t s_blksize = 1024;
+
+class MountNodeMem {
+ public:
+ MountNodeMem(int ino) {
+ ino_ = ino;
+ ref_count_ = 0;
+ data_ = NULL;
+ memset(&stat_, 0, sizeof(stat_));
+ Resize(s_blksize);
+ };
+
+ size_t Size() const {
+ return stat_.st_size;
+ }
+
+ void Resize(size_t size) {
+ size_t cap = blocks_;
+ size_t req = (size + s_blksize - 1) / s_blksize;
+
+ if ((req > cap) || (req < (cap / 2))) {
+ char *newdata = (char *) malloc(req * s_blksize);
+ memcpy(newdata, data_, size);
+ free(data_);
+ stat_.st_size = size;
+ data_ = newdata;
+ blocks_ = req;
+ }
+ }
+
+ int ino_;
+ int ref_count_;
+ struct stat stat_;
+ void *data_;
+ size_t blocks_;
+ pthread_mutex_t lock_;
+};
+
+MountMem::MountMem() {}
+MountMem::~MountMem() {}
+
+int MountMem::AddDirEntry(MountMemNode* dir_node, MountMemNode* obj_node, const char *name) {
+ if (strlen(name > 255)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ struct dirent* d = (struct dirent *) dir_node->data_;
+ size_t cnt = dir_node->Size() / sizeof(struct dirent);
+ size_t off;
+
+ // Find a free location
+ for (off = 0; off < cnt; off++) {
+ if (d->d_name[0] == 0) break;
+ d++;
+ }
+
+ // Otherwise regrow and take the last spot.
+ if (off == cnt) {
+ dir_node->Resize(dir_node->Size() + sizeof(struct dirent));
+ d = &((struct dirent *) dir_node->data_)[off];
+ }
+
+ strcpy(d->d_name, name);
+ d->d_ino = obj_node->ino_;
+ d->d_reclen = sizeof(dirent);
+ d->d_off = off * sizeof(dirent);
+
+ // Add a ref_count_ and link count for the directory
+ obj_node->Acquire();
+ obj_node->stat_.st_nlink++;
+ return 0;
+}
+
+
+
+
+int MountMem::DelDirEntry_locked(int dir_ino, const char *name) {
+ MountMemNode* dir_node = inodes_.At(dir_ino);
+ struct dirent* d = (struct dirent *) dir_node->data_;
+ size_t cnt = dir_node->Size() / sizeof(struct dirent);
+ size_t off = 0;
+
+ // Find a free location
+ for (off = 0; off < cnt; off++) {
+ if (!strcmp(d->d_name, name)) {
+ d->d_name[0] = 0;
+ obj_node->stat_.st_nlink--;
+ if (0 == --obj_node->ref_count_) FreeNode(obj_node->ino_);
+ dir_node->ref_count_--;
+ return 0;
+ }
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+MountNodeMem* MountMem::AcquireNode(int ino) {
+ SimpleAutoLock lock(&lock_);
+ MountNodeMem *node = inodes_.At(ino);
+ if (node) node->ref_count_++;
+ return node;
+}
+
+void MountMem::ReleaseNode(MountMemNode* node) {
+ if (node) {
+ SimpleAutoLock lock(&lock_);
+ if (--node->ref_count_) inodes_.Free(node->ino_);
+ }
+}
+
+void MountMem::Init(void) {
+ int root = inodes_.Alloc();
+
+ assert(root == 0);
+ AddDirEntry(root, root, "/");
+}
+
+int MountMem::Mkdir(const std::string& path, mode_t mode, struct stat *buf) {
+ SimpleAutoLock lock(&lock_);
+
+ int ino = AcquireNode(path);
+
+ // Make sure it doesn't already exist.
+ child = GetMemNode(path);
+ if (child) {
+ errno = EEXIST;
+ return -1;
+ }
+ // Get the parent node.
+ int parent_slot = GetParentSlot(path);
+ if (parent_slot == -1) {
+ errno = ENOENT;
+ return -1;
+ }
+ parent = slots_.At(parent_slot);
+ if (!parent->is_dir()) {
+ errno = ENOTDIR;
+ return -1;
+ }
+
+ // Create a new node
+ int slot = slots_.Alloc();
+ child = slots_.At(slot);
+ child->set_slot(slot);
+ child->set_mount(this);
+ child->set_is_dir(true);
+ Path p(path);
+ child->set_name(p.Last());
+ child->set_parent(parent_slot);
+ parent->AddChild(slot);
+ if (!buf) {
+ return 0;
+ }
+
+ return Stat(slot, buf);
+}
+
+int MountMem::Rmdir(int node) {
+}
+
+int MountMem::Chmod(int ino, int mode) {
+ MountMemNode* node = AcquireNode(ino);
+
+ if (NULL == node) {
+ errno = BADF;
+ return -1;
+ }
+
+ node->stat_.st_mode = mode;
+ ReleaseNode(node);
+ return 0;
+}
+
+int MountMem::Stat(int ino, struct stat *buf) {
+ MountMemNode* node = AcquireNode(ino);
+
+ if (NULL == node) {
+ errno = BADF;
+ return -1;
+ }
+
+ memcpy(buf, node->stat_, sizeof(struct stat));
+ ReleaseNode(node);
+ return 0;
+}
+
+int MountMem::Fsync(int ino) {
+ // Acquire the node in case he node
+ MountMemNode* node = AcquireNode(ino);
+ if (node) {
+ ReleaseNode(node);
+ return 0
+ }
+
+ errno = BADF;
+ return -1;
+}
+
+int MountMem::Getdents(int ino, off_t offset, struct dirent *dirp, unsigned int count) {
+ MountMemNode* node = AcquireNode(ino);
+ if ((NULL == node) == 0) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if ((node->stat_.st_mode & S_IFDIR) == 0) {
+ errno =ENOTDIR;
+ return -1;
+ }
+
+ if (offset + count > node->Size()) {
+ count = node->Size() - offset;
+ }
+
+ memcpy(dirp, &node->data_[offset], count);
+ return count;
+}
+
+ssize_t MountMem::Write(int ino, off_t offset, const void *buf, size_t count) {
+ MountMemNode* node = AcquireNode(ino);
+
+ if (NULL == node || (node->stat_.st_mode & S_IWUSER) == 0) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (offset + count > node->Size()) {
+ int err = node->Resize();
+ if (err) {
+ errno = err;
+ ReleaseNode(node);
+ return -1;
+ }
+ }
+
+ mempcy(&node->data_[offset], buf, count);
+ ReleaseNode(node);
+ return count;
+}
+
+ssize_t MountMem::Read(int ino, off_t offset, const void *buf, size_t count) {
+ MountMemNode* node = AcquireNode(ino);
+
+ if (NULL == node || (node->stat_.st_mode & S_IRUSER) == 0) {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (offset + count > node->Size()) {
+ count = node->Size() - offset;
+ }
+
+ mempcy(buf, &node->data_[offset], count);
+ ReleaseNode(node);
+ return count;
+}
+
+int MountMem::Isatty(int ino) {
+ // Acquire the node in case he node array is in flux
+ MountMemNode* node = AcquireNode(ino);
+
+ if (node) {
+ errno = ENOTTY;
+ ReleaseNode(node);
+ }
+ else {
+ errno = BADF;
+ }
+ return 0;
+}
+
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_mem.h b/native_client_sdk/src/libraries/nacl_mounts/mount_mem.h
new file mode 100644
index 0000000..dd7ffdd
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_mem.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef LIBRARIES_NACL_MOUNTS_MOUNT_MEM_H_
+#define LIBRARIES_NACL_MOUNTS_MOUNT_MEM_H_
+
+#include <stdint.h>
+#include <map>
+#include <string>
+
+#include "mount.h"
+#include "util/macros.h"
+#include "util/SlotAllocator.h"
+
+struct dirent;
+struct stat;
+
+class MountMemNode;
+
+// Mount serves as the base mounting class that will be used by
+// the mount manager (class MountManager). The mount manager
+// relies heavily on the GetNode method as a way of directing
+// system calls that take a path as an argument. The methods
+// of this class are pure virtual. BaseMount class contains
+// stub implementations for these methods. Feel free to use
+// BaseMount if your mount does not implement all of these
+// operations.
+class MountMem : public Mount {
+ protected:
+ MountMem();
+ virtual ~MountMem();
+
+ // Init must be called by the factory before
+ void Init();
+
+ int MountMem::AddDirEntry(MountNode* node, MountNode* node, const char *name);
+
+ public:
+ // System calls that can be overridden by a mount implementation
+ virtual int Creat(const std::string& path, int mode, struct stat *st);
+ virtual int Mkdir(const std::string& path, int mode, struct stat *st);
+ virtual int Unlink(const std::string& path);
+
+ virtual int Rmdir(int node);
+ virtual int Chmod(int node, int mode);
+ virtual int Stat(int node, struct stat *buf);
+ virtual int Fsync(int node);
+
+ virtual int Getdents(int node, off_t offset, struct dirent *dirp,
+ unsigned int count);
+
+ virtual ssize_t Read(int node, off_t offset,
+ void *buf, size_t count);
+ virtual ssize_t Write(int node, off_t offset,
+ const void *buf, size_t count);
+ virtual int Isatty(int node);
+
+ private:
+ pthread_mutex_t lock_;
+ SlotAllocator<MountMemNode> inodes_;
+ DISALLOW_COPY_AND_ASSIGN(MountMem);
+};
+
+#endif // LIBRARIES_NACL_MOUNTS_MOUNT_MEM_H_
+
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_node.cc b/native_client_sdk/src/libraries/nacl_mounts/mount_node.cc
new file mode 100644
index 0000000..1aeacd1
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_node.cc
@@ -0,0 +1,125 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string>
+
+#include "auto_lock.h"
+#include "mount.h"
+#include "mount_node.h"
+
+MountNode::MountNode(Mount* mount, int ino, int dev) :
+ mount_(mount) {
+ memset(&stat_, 0, sizeof(stat_));
+ stat_.st_ino = ino;
+ stat_.st_dev = dev;
+}
+
+MountNode::~MountNode() {
+}
+
+bool MountNode::Init(int mode, short gid, short uid) {
+ stat_.st_mode = mode;
+ stat_.st_gid = gid;
+ stat_.st_uid = uid;
+ return true;
+}
+
+void MountNode::Destroy() {
+ FSync();
+ mount_->FreeNode(this);
+}
+
+int MountNode::FSync() {
+ return 0;
+}
+
+int MountNode::GetDents(size_t offs, struct dirent* pdir, size_t count) {
+ errno = ENOTDIR;
+ return -1;
+}
+
+int MountNode::GetStat(struct stat* pstat) {
+ AutoLock lock(&lock_);
+ memcpy(pstat, &stat_, sizeof(stat_));
+ return 0;
+}
+
+int MountNode::Ioctl(int request, char* arg) {
+ errno = EINVAL;
+ return -1;
+}
+int MountNode::Read(size_t offs, void* buf, size_t count) {
+ errno = EINVAL;
+ return -1;
+}
+
+int MountNode::Truncate(size_t size) {
+ errno = EINVAL;
+ return -1;
+}
+
+int MountNode::Write(size_t offs, const void* buf, size_t count) {
+ errno = EINVAL;
+ return -1;
+}
+
+int MountNode::GetLinks() const {
+ return stat_.st_nlink;
+}
+
+int MountNode::GetMode() const {
+ return stat_.st_mode & ~_S_IFMT;
+}
+
+size_t MountNode::GetSize() const {
+ return stat_.st_size;
+}
+
+int MountNode::GetType() const {
+ return stat_.st_mode & _S_IFMT;
+}
+
+bool MountNode::IsaDir() const {
+ return (stat_.st_mode & _S_IFDIR) != 0;
+}
+
+bool MountNode::IsaFile() const {
+ return (stat_.st_mode & _S_IFREG) != 0;
+}
+
+bool MountNode::IsaTTY() const {
+ return (stat_.st_mode & _S_IFCHR) != 0;
+}
+
+
+int MountNode:: AddChild(const std::string& name, MountNode* node) {
+ errno = ENOTDIR;
+ return -1;
+}
+
+int MountNode::RemoveChild(const std::string& name) {
+ errno = ENOTDIR;
+ return -1;
+}
+
+MountNode* MountNode::FindChild(const std::string& name) {
+ errno = ENOTDIR;
+ return NULL;
+}
+
+void MountNode::Link() {
+ Acquire();
+ stat_.st_nlink++;
+}
+
+void MountNode::Unlink() {
+ stat_.st_nlink--;
+ Release();
+}
+
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_node.h b/native_client_sdk/src/libraries/nacl_mounts/mount_node.h
new file mode 100644
index 0000000..dbe6c57
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_node.h
@@ -0,0 +1,71 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef LIBRARIES_NACL_MOUNTS_MOUNT_NODE_H_
+#define LIBRARIES_NACL_MOUNTS_MOUNT_NODE_H_
+
+#include <sys/stat.h>
+
+#include <string>
+#include "ref_object.h"
+
+struct dirent;
+struct stat;
+class Mount;
+class MountNode;
+
+class MountNode : public RefObject {
+ protected:
+ virtual ~MountNode();
+
+ protected:
+ MountNode(Mount* mount, int ino, int dev);
+ virtual bool Init(int mode, short uid, short gid);
+ virtual void Destroy();
+
+public:
+ // Normal OS operations on a node (file), can be called by the kernel
+ // directly so it must lock and unlock appropriately. These functions
+ // must not be called by the mount.
+ virtual int FSync();
+ virtual int GetDents(size_t offs, struct dirent* pdir, size_t count);
+ virtual int GetStat(struct stat* stat);
+ virtual int Ioctl(int request, char* arg);
+ virtual int Read(size_t offs, void* buf, size_t count);
+ virtual int Truncate(size_t size);
+ virtual int Write(size_t offs, const void* buf, size_t count);
+
+ virtual int GetLinks() const;
+ virtual int GetMode() const;
+ virtual int GetType() const;
+ virtual size_t GetSize() const;
+ virtual bool IsaDir() const;
+ virtual bool IsaFile() const;
+ virtual bool IsaTTY() const;
+
+protected:
+ // Directory operations on the node are done by the Mount. The mount's lock
+ // must be held while these calls are made.
+
+ // Adds or removes a directory entry updating the link numbers and refcount
+ virtual int AddChild(const std::string& name, MountNode *node);
+ virtual int RemoveChild(const std::string& name);
+
+ // Find a child and return it without updating the refcount
+ virtual MountNode* FindChild(const std::string& name);
+
+ // Update the link count
+ virtual void Link();
+ virtual void Unlink();
+
+protected:
+ struct stat stat_;
+ Mount* mount_;
+
+ friend class Mount;
+ friend class MountNodeDir;
+};
+
+#endif // LIBRARIES_NACL_MOUNTS_MOUNT_NODE_H_ \ No newline at end of file
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.cc b/native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.cc
new file mode 100644
index 0000000..2e43977
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.cc
@@ -0,0 +1,135 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "auto_lock.h"
+#include "mount_node_dir.h"
+
+MountNodeDir::MountNodeDir(Mount* mount, int ino, int dev) :
+ MountNode(mount, ino, dev),
+ cache_(NULL) {
+}
+
+MountNodeDir::~MountNodeDir() {
+ free(cache_);
+}
+
+bool MountNodeDir::Init(int mode, short uid, short gid) {
+ bool ok = MountNode::Init(mode, uid, gid);
+ stat_.st_mode |= _S_IFDIR;
+ return ok;
+}
+
+int MountNodeDir::Read(size_t offs, void *buf, size_t count) {
+ errno = EISDIR;
+ return -1;
+}
+
+int MountNodeDir::Truncate(size_t size) {
+ errno = EISDIR;
+ return -1;
+}
+
+int MountNodeDir::Write(size_t offs, void *buf, size_t count) {
+ errno = EISDIR;
+ return -1;
+}
+
+int MountNodeDir::GetDents(size_t offs, struct dirent* pdir, size_t size) {
+ AutoLock lock(&lock_);
+
+ // If the buffer pointer is invalid, fail
+ if (NULL == pdir) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // If the buffer is too small, fail
+ if (size < sizeof(struct dirent)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ // Force size to a multiple of dirent
+ size -= size % sizeof(struct dirent);
+ size_t max = map_.size() * sizeof(struct dirent);
+ if (cache_ == NULL) BuildCache();
+
+ if (offs >= max) return 0;
+ if (offs + size >= max) size = max - offs;
+
+ memcpy(pdir, ((char *) cache_) + offs, size);
+ return size;
+}
+
+int MountNodeDir:: AddChild(const std::string& name, MountNode* node) {
+ AutoLock lock(&lock_);
+
+ if (name.empty()) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (name.length() >= MEMBER_SIZE(struct dirent, d_name)) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ MountNodeMap_t::iterator it = map_.find(name);
+ if (it != map_.end()) {
+ errno = EEXIST;
+ return -1;
+ }
+
+ node->Link();
+ map_[name] = node;
+ ClearCache();
+ return 0;
+}
+
+int MountNodeDir::RemoveChild(const std::string& name) {
+ AutoLock lock(&lock_);
+ MountNodeMap_t::iterator it = map_.find(name);
+ if (it != map_.end()) {
+ it->second->Unlink();
+ map_.erase(it);
+ ClearCache();
+ return 0;
+ }
+ errno = ENOENT;
+ return -1;
+}
+
+MountNode* MountNodeDir::FindChild(const std::string& name) {
+ AutoLock lock(&lock_);
+ MountNodeMap_t::iterator it = map_.find(name);
+ if (it != map_.end()) {
+ return it->second;
+ }
+ errno = ENOENT;
+ return NULL;
+}
+
+void MountNodeDir::ClearCache() {
+ free(cache_);
+ cache_ = NULL;
+}
+
+void MountNodeDir::BuildCache() {
+ if (map_.size()) {
+ cache_ = (struct dirent *) malloc(sizeof(struct dirent) * map_.size());
+ MountNodeMap_t::iterator it = map_.begin();
+ for (size_t index = 0; it != map_.end(); it++, index++) {
+ MountNode* node = it->second;
+ size_t len = it->first.length();
+ cache_[index].d_ino = node->stat_.st_ino;
+ cache_[index].d_reclen = sizeof(struct dirent);
+ cache_[index].d_name[len] = 0;
+ strncpy(cache_[index].d_name, &it->first[0], len);
+ }
+ }
+}
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.h b/native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.h
new file mode 100644
index 0000000..36840b0
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_node_dir.h
@@ -0,0 +1,49 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef LIBRARIES_NACL_MOUNTS_MOUNT_NODE_DIR_H_
+#define LIBRARIES_NACL_MOUNTS_MOUNT_NODE_DIR_H_
+
+#include <dirent.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "mount_node.h"
+
+
+class MountNodeDir : public MountNode {
+ protected:
+ MountNodeDir(Mount *mount, int ino, int dev);
+ virtual ~MountNodeDir();
+ virtual bool Init(int mode, short uid, short gid);
+
+ public:
+ typedef std::map<std::string, MountNode*> MountNodeMap_t;
+
+ virtual int GetDents(size_t offs, struct dirent* pdir, size_t count);
+ virtual int Read(size_t offs, void *buf, size_t count);
+ virtual int Truncate(size_t size);
+ virtual int Write(size_t offs, void *buf, size_t count);
+
+ // Adds a finds or adds a directory entry as an INO, updating the refcount
+ virtual int AddChild(const std::string& name, MountNode *node);
+ virtual int RemoveChild(const std::string& name);
+ virtual MountNode* FindChild(const std::string& name);
+
+
+protected:
+ void ClearCache();
+ void BuildCache();
+
+private:
+ struct dirent* cache_;
+ MountNodeMap_t map_;
+ friend class Mount;
+};
+
+#endif // LIBRARIES_NACL_MOUNTS_MOUNT_NODE_DIR_H_
+
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.cc b/native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.cc
new file mode 100644
index 0000000..4a59119
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.cc
@@ -0,0 +1,81 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "auto_lock.h"
+#include "mount_node_mem.h"
+
+#define BLOCK_SIZE (1 << 16)
+#define BLOCK_MASK (BLOCK_SIZE - 1)
+
+MountNodeMem::MountNodeMem(Mount *mount, int ino, int dev) :
+ MountNode(mount, ino, dev),
+ data_(NULL),
+ capacity_(0) {
+}
+
+MountNodeMem::~MountNodeMem() {
+ free(data_);
+}
+
+bool MountNodeMem::Init(int mode, short uid, short gid) {
+ bool ok = MountNode::Init(mode, uid, gid);
+ stat_.st_mode |= _S_IFREG;
+ return ok;
+}
+
+int MountNodeMem::Read(size_t offs, void *buf, size_t count) {
+ AutoLock lock(&lock_);
+ if (count == 0) return 0;
+ if (offs + count > GetSize()) {
+ count = GetSize() - offs;
+ }
+
+ memcpy(buf, data_, count);
+ return static_cast<int>(count);
+}
+
+int MountNodeMem::Write(size_t offs, const void *buf, size_t count) {
+ AutoLock lock(&lock_);
+
+ if (count == 0) return 0;
+
+ if (count + offs > GetSize()) {
+ Truncate(count + offs);
+ count = GetSize() - offs;
+ }
+
+ memcpy(data_, buf, count);
+ return static_cast<int>(count);
+}
+
+int MountNodeMem::Truncate(size_t size) {
+ size_t need = (size + BLOCK_MASK) & ~BLOCK_MASK;
+
+ // If the current capacity is correct, just adjust and return
+ if (need == capacity_) {
+ stat_.st_size = static_cast<off_t>(size);
+ 0;
+ }
+
+ // Attempt to realloc the block
+ char *newdata = static_cast<char *>(realloc(data_, need));
+ if (newdata != NULL) {
+ data_ = newdata;
+ capacity_ = need;
+ stat_.st_size = static_cast<off_t>(size);
+ return 0;
+ }
+
+ // If we failed, then adjust size according to what we keep
+ if (size > capacity_) size = capacity_;
+
+ // Update the size and return the new size
+ stat_.st_size = static_cast<off_t>(size);
+ errno = EIO;
+ return -1;
+}
diff --git a/native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.h b/native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.h
new file mode 100644
index 0000000..63a2908
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/mount_node_mem.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef LIBRARIES_NACL_MOUNTS_MOUNT_NODE_MEM_H_
+#define LIBRARIES_NACL_MOUNTS_MOUNT_NODE_MEM_H_
+
+#include "mount_node.h"
+
+class MountNodeMem : public MountNode {
+ public:
+ MountNodeMem(Mount* mount, int ino, int dev);
+
+protected:
+ virtual ~MountNodeMem();
+ virtual bool Init(int mode, short uid, short gid);
+
+public:
+ // Normal read/write operations on a file
+ virtual int Read(size_t offs, void* buf, size_t count);
+ virtual int Write(size_t offs, const void* buf, size_t count);
+ virtual int Truncate(size_t size);
+
+ private:
+ char* data_;
+ size_t capacity_;
+ friend class Mount;
+};
+
+#endif // LIBRARIES_NACL_MOUNTS_MOUNT_NODE_MEM_H_
+
diff --git a/native_client_sdk/src/libraries/nacl_mounts/nacl_mounts.vcproj b/native_client_sdk/src/libraries/nacl_mounts/nacl_mounts.vcproj
new file mode 100644
index 0000000..875a16f
--- /dev/null
+++ b/native_client_sdk/src/libraries/nacl_mounts/nacl_mounts.vcproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="nacl_mounts"
+ ProjectGUID="{AADB97B8-EAB0-42B0-ADE0-88B76BD4745C}"
+ RootNamespace="nacl_mounts"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../win;../utils"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\mount_node.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\mount_node_dir.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\mount_node_mem.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\path.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\mount.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\mount.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mount_node.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mount_node_dir.h"
+ >
+ </File>
+ <File
+ RelativePath=".\mount_node_mem.h"
+ >
+ </File>
+ <File
+ RelativePath=".\path.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>