summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authorBen Smith <binji@chromium.org>2014-09-24 17:15:21 -0700
committerBen Smith <binji@chromium.org>2014-09-25 00:16:04 +0000
commita4ef3a9c60553b3bcc8708587ea7832fc7cac29e (patch)
treec3671a243eac0cf2ffb4b38253ba3b19aca3be40 /native_client_sdk
parent009b55e7f8532a4586fc4ab0a4df1532943f88fd (diff)
downloadchromium_src-a4ef3a9c60553b3bcc8708587ea7832fc7cac29e.zip
chromium_src-a4ef3a9c60553b3bcc8708587ea7832fc7cac29e.tar.gz
chromium_src-a4ef3a9c60553b3bcc8708587ea7832fc7cac29e.tar.bz2
[NaCl SDK] nacl_io: Add chmod/fchmod
This change includes implementation for MemFs and FuseFs. I've also reordered the fuse_operations struct to match the order used in the real FUSE implementation. BUG=414793 R=sbc@chromium.org Review URL: https://codereview.chromium.org/604513002 Cr-Commit-Position: refs/heads/master@{#296588}
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/libraries/nacl_io/dir_node.cc6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/dir_node.h1
-rw-r--r--native_client_sdk/src/libraries/nacl_io/fuse.h139
-rw-r--r--native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.cc14
-rw-r--r--native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.h1
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc9
-rw-r--r--native_client_sdk/src/libraries/nacl_io/kernel_proxy.h2
-rw-r--r--native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.cc6
-rw-r--r--native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.h1
-rw-r--r--native_client_sdk/src/libraries/nacl_io/node.cc4
-rw-r--r--native_client_sdk/src/libraries/nacl_io/node.h1
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc83
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc25
-rw-r--r--native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h2
14 files changed, 208 insertions, 86 deletions
diff --git a/native_client_sdk/src/libraries/nacl_io/dir_node.cc b/native_client_sdk/src/libraries/nacl_io/dir_node.cc
index e16c0c7..6cf0656 100644
--- a/native_client_sdk/src/libraries/nacl_io/dir_node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/dir_node.cc
@@ -69,6 +69,12 @@ Error DirNode::GetDents(size_t offs,
return cache_.GetDents(offs, pdir, size, out_bytes);
}
+Error DirNode::Fchmod(mode_t mode) {
+ AUTO_LOCK(node_lock_);
+ SetMode(mode);
+ return 0;
+}
+
Error DirNode::AddChild(const std::string& name, const ScopedNode& node) {
AUTO_LOCK(node_lock_);
diff --git a/native_client_sdk/src/libraries/nacl_io/dir_node.h b/native_client_sdk/src/libraries/nacl_io/dir_node.h
index 29d271f..3deaa33 100644
--- a/native_client_sdk/src/libraries/nacl_io/dir_node.h
+++ b/native_client_sdk/src/libraries/nacl_io/dir_node.h
@@ -43,6 +43,7 @@ class DirNode : public Node {
const void* buf,
size_t count,
int* out_bytes);
+ virtual Error Fchmod(mode_t mode);
// Adds a finds or adds a directory entry as an INO, updating the refcount
virtual Error AddChild(const std::string& name, const ScopedNode& node);
diff --git a/native_client_sdk/src/libraries/nacl_io/fuse.h b/native_client_sdk/src/libraries/nacl_io/fuse.h
index 5f79786..cbc381f 100644
--- a/native_client_sdk/src/libraries/nacl_io/fuse.h
+++ b/native_client_sdk/src/libraries/nacl_io/fuse.h
@@ -87,35 +87,35 @@ struct fuse_operations {
unsigned int flag_nopath : 1;
unsigned int flag_reserved : 31;
- // Called when a filesystem of this type is initialized.
- void* (*init)(struct fuse_conn_info* conn);
- // Called when a filesystem of this type is unmounted.
- void (*destroy)(void*);
- // Called by access()
- int (*access)(const char* path, int mode);
- // Called when O_CREAT is passed to open()
- int (*create)(const char* path, mode_t mode, struct fuse_file_info*);
- // Called by stat()/fstat(). If this function pointer is non-NULL, it is
- // called, otherwise fuse_operations.getattr will be called.
- int (*fgetattr)(const char* path, struct stat*, struct fuse_file_info*);
- // Called by fsync(). The datasync paramater is not currently supported.
- int (*fsync)(const char* path, int datasync, struct fuse_file_info*);
- // Called by ftruncate()
- int (*ftruncate)(const char* path, off_t, struct fuse_file_info*);
// Called by stat()/fstat(), but only when fuse_operations.fgetattr is NULL.
// Also called by open() to determine if the path is a directory or a regular
// file.
int (*getattr)(const char* path, struct stat*);
- // Called by mkdir()
- int (*mkdir)(const char* path, mode_t);
+ // Not called currently.
+ int (*readlink)(const char*, char*, size_t);
// Called when O_CREAT is passed to open(), but only if fuse_operations.create
// is non-NULL.
int (*mknod)(const char* path, mode_t, dev_t);
+ // Called by mkdir()
+ int (*mkdir)(const char* path, mode_t);
+ // Called by unlink()
+ int (*unlink)(const char* path);
+ // Called by rmdir()
+ int (*rmdir)(const char* path);
+ // Not called currently.
+ int (*symlink)(const char*, const char*);
+ // Called by rename()
+ int (*rename)(const char* path, const char* new_path);
+ // Not called currently.
+ int (*link)(const char*, const char*);
+ // Called by chmod()/fchmod()
+ int (*chmod)(const char*, mode_t);
+ // Not called currently.
+ int (*chown)(const char*, uid_t, gid_t);
+ // Called by truncate(), as well as open() when O_TRUNC is passed.
+ int (*truncate)(const char* path, off_t);
// Called by open()
int (*open)(const char* path, struct fuse_file_info*);
- // Called by getdents(), which is called by the more standard functions
- // opendir()/readdir().
- int (*opendir)(const char* path, struct fuse_file_info*);
// Called by read(). Note that FUSE specifies that all reads will fill the
// entire requested buffer. If this function returns less than that, the
// remainder of the buffer is zeroed.
@@ -124,6 +124,34 @@ struct fuse_operations {
size_t count,
off_t,
struct fuse_file_info*);
+ // Called by write(). Note that FUSE specifies that a write should always
+ // return the full count, unless an error occurs.
+ int (*write)(const char* path,
+ const char* buf,
+ size_t count,
+ off_t,
+ struct fuse_file_info*);
+ // Not called currently.
+ int (*statfs)(const char*, struct statvfs*);
+ // Not called currently.
+ int (*flush)(const char*, struct fuse_file_info*);
+ // Called when the last reference to this node is released. This is only
+ // called for regular files. For directories, fuse_operations.releasedir is
+ // called instead.
+ int (*release)(const char* path, struct fuse_file_info*);
+ // Called by fsync(). The datasync paramater is not currently supported.
+ int (*fsync)(const char* path, int datasync, struct fuse_file_info*);
+ // Not called currently.
+ int (*setxattr)(const char*, const char*, const char*, size_t, int);
+ // Not called currently.
+ int (*getxattr)(const char*, const char*, char*, size_t);
+ // Not called currently.
+ int (*listxattr)(const char*, char*, size_t);
+ // Not called currently.
+ int (*removexattr)(const char*, const char*);
+ // Called by getdents(), which is called by the more standard functions
+ // opendir()/readdir().
+ int (*opendir)(const char* path, struct fuse_file_info*);
// Called by getdents(), which is called by the more standard function
// readdir().
//
@@ -176,68 +204,57 @@ struct fuse_operations {
off_t,
struct fuse_file_info*);
// Called when the last reference to this node is released. This is only
- // called for regular files. For directories, fuse_operations.releasedir is
- // called instead.
- int (*release)(const char* path, struct fuse_file_info*);
- // Called when the last reference to this node is released. This is only
// called for directories. For regular files, fuse_operations.release is
// called instead.
int (*releasedir)(const char* path, struct fuse_file_info*);
- // Called by rename()
- int (*rename)(const char* path, const char* new_path);
- // Called by rmdir()
- int (*rmdir)(const char* path);
- // Called by truncate(), as well as open() when O_TRUNC is passed.
- int (*truncate)(const char* path, off_t);
- // Called by unlink()
- int (*unlink)(const char* path);
- // Called by write(). Note that FUSE specifies that a write should always
- // return the full count, unless an error occurs.
- int (*write)(const char* path,
- const char* buf,
- size_t count,
- off_t,
- struct fuse_file_info*);
+ // Not called currently.
+ int (*fsyncdir)(const char*, int, struct fuse_file_info*);
+ // Called when a filesystem of this type is initialized.
+ void* (*init)(struct fuse_conn_info* conn);
+ // Called when a filesystem of this type is unmounted.
+ void (*destroy)(void*);
+ // Called by access()
+ int (*access)(const char* path, int mode);
+ // Called when O_CREAT is passed to open()
+ int (*create)(const char* path, mode_t mode, struct fuse_file_info*);
+ // Called by ftruncate()
+ int (*ftruncate)(const char* path, off_t, struct fuse_file_info*);
+ // Called by stat()/fstat(). If this function pointer is non-NULL, it is
+ // called, otherwise fuse_operations.getattr will be called.
+ int (*fgetattr)(const char* path, struct stat*, struct fuse_file_info*);
+ // Not called currently.
+ int (*lock)(const char*, struct fuse_file_info*, int cmd, struct flock*);
// Called by utime()/utimes()/futimes()/futimens() etc.
int (*utimens)(const char*, const struct timespec tv[2]);
-
- // The following functions are not currently called by the nacl_io
- // implementation of FUSE.
+ // Not called currently.
int (*bmap)(const char*, size_t blocksize, uint64_t* idx);
- int (*chmod)(const char*, mode_t);
- int (*chown)(const char*, uid_t, gid_t);
- int (*fallocate)(const char*, int, off_t, off_t, struct fuse_file_info*);
- int (*flock)(const char*, struct fuse_file_info*, int op);
- int (*flush)(const char*, struct fuse_file_info*);
- int (*fsyncdir)(const char*, int, struct fuse_file_info*);
- int (*getxattr)(const char*, const char*, char*, size_t);
+ // Not called currently.
int (*ioctl)(const char*,
int cmd,
void* arg,
struct fuse_file_info*,
unsigned int flags,
void* data);
- int (*link)(const char*, const char*);
- int (*listxattr)(const char*, char*, size_t);
- int (*lock)(const char*, struct fuse_file_info*, int cmd, struct flock*);
+ // Not called currently.
int (*poll)(const char*,
struct fuse_file_info*,
struct fuse_pollhandle* ph,
unsigned* reventsp);
+ // Not called currently.
+ int (*write_buf)(const char*,
+ struct fuse_bufvec* buf,
+ off_t off,
+ struct fuse_file_info*);
+ // Not called currently.
int (*read_buf)(const char*,
struct fuse_bufvec** bufp,
size_t size,
off_t off,
struct fuse_file_info*);
- int (*readlink)(const char*, char*, size_t);
- int (*removexattr)(const char*, const char*);
- int (*setxattr)(const char*, const char*, const char*, size_t, int);
- int (*statfs)(const char*, struct statvfs*);
- int (*symlink)(const char*, const char*);
- int (*write_buf)(const char*,
- struct fuse_bufvec* buf,
- off_t off,
- struct fuse_file_info*);
+ // Not called currently.
+ int (*flock)(const char*, struct fuse_file_info*, int op);
+ // Not called currently.
+ int (*fallocate)(const char*, int, off_t, off_t, struct fuse_file_info*);
};
#endif // LIBRARIES_NACL_IO_FUSE_H_
diff --git a/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.cc b/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.cc
index 212f84f..d072392 100644
--- a/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.cc
@@ -261,6 +261,20 @@ Error FuseFsNode::Futimens(const struct timespec times[2]) {
return result;
}
+Error FuseFsNode::Fchmod(mode_t mode) {
+ int result;
+ if (!fuse_ops_->chmod) {
+ LOG_TRACE("fuse_ops_->chmod is NULL.");
+ return ENOSYS;
+ }
+
+ result = fuse_ops_->chmod(path_.c_str(), mode);
+ if (result < 0)
+ return -result;
+
+ return result;
+}
+
Error FuseFsNode::VIoctl(int request, va_list args) {
LOG_ERROR("Ioctl not implemented for fusefs.");
return ENOSYS;
diff --git a/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.h b/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.h
index 5bd7bc1..6097143 100644
--- a/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.h
+++ b/native_client_sdk/src/libraries/nacl_io/fusefs/fuse_fs.h
@@ -55,6 +55,7 @@ class FuseFsNode : public Node {
const struct termios* termios_p);
virtual Error GetSize(off_t* out_size);
virtual Error Futimens(const struct timespec times[2]);
+ virtual Error Fchmod(mode_t mode);
protected:
struct fuse_operations* fuse_ops_;
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
index cf6cf07..b5cf443 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -799,8 +799,7 @@ int KernelProxy::remove(const char* path) {
return 0;
}
-// TODO(noelallen): Needs implementation.
-int KernelProxy::fchmod(int fd, int mode) {
+int KernelProxy::fchmod(int fd, mode_t mode) {
ScopedKernelHandle handle;
Error error = AcquireHandle(fd, &handle);
if (error) {
@@ -808,6 +807,12 @@ int KernelProxy::fchmod(int fd, int mode) {
return -1;
}
+ error = handle->node()->Fchmod(mode);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
return 0;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
index fb11288..78a8cf8 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -107,7 +107,7 @@ class KernelProxy : protected KernelObject {
virtual ssize_t read(int fd, void* buf, size_t nbyte);
virtual ssize_t write(int fd, const void* buf, size_t nbyte);
- virtual int fchmod(int fd, int prot);
+ virtual int fchmod(int fd, mode_t mode);
virtual int fcntl(int fd, int request, va_list args);
virtual int fstat(int fd, struct stat* buf);
virtual int getdents(int fd, void* buf, unsigned int count);
diff --git a/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.cc b/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.cc
index 6eee9f0..507e5e2 100644
--- a/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.cc
@@ -122,4 +122,10 @@ Error MemFsNode::Resize(off_t new_length) {
return 0;
}
+Error MemFsNode::Fchmod(mode_t mode) {
+ AUTO_LOCK(node_lock_);
+ SetMode(mode);
+ return 0;
+}
+
} // namespace nacl_io
diff --git a/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.h b/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.h
index 77a327a..100b3ec 100644
--- a/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.h
+++ b/native_client_sdk/src/libraries/nacl_io/memfs/mem_fs_node.h
@@ -27,6 +27,7 @@ class MemFsNode : public Node {
size_t count,
int* out_bytes);
virtual Error FTruncate(off_t size);
+ virtual Error Fchmod(mode_t mode);
private:
Error Resize(off_t size);
diff --git a/native_client_sdk/src/libraries/nacl_io/node.cc b/native_client_sdk/src/libraries/nacl_io/node.cc
index 6702dc8..b91726f 100644
--- a/native_client_sdk/src/libraries/nacl_io/node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/node.cc
@@ -180,6 +180,10 @@ Error Node::Futimens(const struct timespec times[2]) {
return 0;
}
+Error Node::Fchmod(mode_t mode) {
+ return EINVAL;
+}
+
int Node::GetLinks() {
return stat_.st_nlink;
}
diff --git a/native_client_sdk/src/libraries/nacl_io/node.h b/native_client_sdk/src/libraries/nacl_io/node.h
index c30c796..8fb4ab9 100644
--- a/native_client_sdk/src/libraries/nacl_io/node.h
+++ b/native_client_sdk/src/libraries/nacl_io/node.h
@@ -90,6 +90,7 @@ class Node : public sdk_util::RefObject {
virtual Error Tcsetattr(int optional_actions,
const struct termios* termios_p);
virtual Error Futimens(const struct timespec times[2]);
+ virtual Error Fchmod(mode_t mode);
virtual int GetLinks();
virtual int GetMode();
diff --git a/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc b/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
index dffc1ba..e0833ce 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
@@ -31,18 +31,16 @@ class FuseFsForTesting : public FuseFs {
// Implementation of a simple flat memory filesystem.
struct File {
- File() {
- memset(&times, 0, sizeof(times));
- }
+ File() : mode(0666) { memset(&times, 0, sizeof(times)); }
std::string name;
std::vector<uint8_t> data;
+ mode_t mode;
timespec times[2];
};
typedef std::vector<File> Files;
Files g_files;
-mode_t last_create_mode = 0666;
bool IsValidPath(const char* path) {
if (path == NULL)
@@ -81,7 +79,7 @@ int testfs_getattr(const char* path, struct stat* stbuf) {
if (file == NULL)
return -ENOENT;
- stbuf->st_mode = S_IFREG | last_create_mode;
+ stbuf->st_mode = S_IFREG | file->mode;
stbuf->st_size = file->data.size();
stbuf->st_atime = file->times[0].tv_sec;
stbuf->st_atimensec = file->times[0].tv_nsec;
@@ -119,7 +117,7 @@ int testfs_create(const char* path, mode_t mode, struct fuse_file_info* fi) {
file = &g_files.back();
file->name = &path[1]; // Skip initial /
}
- last_create_mode = mode;
+ file->mode = mode;
return 0;
}
@@ -180,33 +178,62 @@ int testfs_utimens(const char* path, const struct timespec times[2]) {
return 0;
}
+int testfs_chmod(const char* path, mode_t mode) {
+ File* file = FindFile(path);
+ if (file == NULL)
+ return -ENOENT;
+
+ file->mode = mode;
+ return 0;
+}
+
const char hello_world[] = "Hello, World!\n";
fuse_operations g_fuse_operations = {
0, // flag_nopath
0, // flag_reserved
- NULL, // init
- NULL, // destroy
- NULL, // access
- testfs_create, // create
- NULL, // fgetattr
- NULL, // fsync
- NULL, // ftruncate
testfs_getattr, // getattr
- NULL, // mkdir
+ NULL, // readlink
NULL, // mknod
+ NULL, // mkdir
+ NULL, // unlink
+ NULL, // rmdir
+ NULL, // symlink
+ NULL, // rename
+ NULL, // link
+ testfs_chmod, // chmod
+ NULL, // chown
+ NULL, // truncate
testfs_open, // open
- NULL, // opendir
testfs_read, // read
- testfs_readdir, // readdir
+ testfs_write, // write
+ NULL, // statfs
+ NULL, // flush
NULL, // release
+ NULL, // fsync
+ NULL, // setxattr
+ NULL, // getxattr
+ NULL, // listxattr
+ NULL, // removexattr
+ NULL, // opendir
+ testfs_readdir, // readdir
NULL, // releasedir
- NULL, // rename
- NULL, // rmdir
- NULL, // truncate
- NULL, // unlink
- testfs_write, // write
+ NULL, // fsyncdir
+ NULL, // init
+ NULL, // destroy
+ NULL, // access
+ testfs_create, // create
+ NULL, // ftruncate
+ NULL, // fgetattr
+ NULL, // lock
testfs_utimens, // utimens
+ NULL, // bmap
+ NULL, // ioctl
+ NULL, // poll
+ NULL, // write_buf
+ NULL, // read_buf
+ NULL, // flock
+ NULL, // fallocate
};
class FuseFsTest : public ::testing::Test {
@@ -361,6 +388,20 @@ TEST_F(FuseFsTest, Utimens) {
EXPECT_EQ(times[1].tv_nsec, statbuf.st_mtimensec);
}
+TEST_F(FuseFsTest, Fchmod) {
+ struct stat statbuf;
+ ScopedNode node;
+
+ ASSERT_EQ(0, fs_.Open(Path("/hello"), O_RDONLY, &node));
+ ASSERT_EQ(0, node->GetStat(&statbuf));
+ EXPECT_EQ(0666, statbuf.st_mode & ~S_IFMT);
+
+ ASSERT_EQ(0, node->Fchmod(0777));
+
+ ASSERT_EQ(0, node->GetStat(&statbuf));
+ EXPECT_EQ(0777, statbuf.st_mode & ~S_IFMT);
+}
+
namespace {
class KernelProxyFuseTest : public ::testing::Test {
diff --git a/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc b/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc
index f2259d7..9b6e347 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc
@@ -127,6 +127,25 @@ TEST(MemFsNodeTest, File) {
EXPECT_EQ(NULL_NODE, result_node.get());
}
+TEST(MemFsNodeTest, Fchmod) {
+ MemFsNodeForTesting file;
+
+ ASSERT_EQ(0, file.Init(0));
+ EXPECT_EQ(S_IRALL | S_IWALL, file.GetMode());
+
+ struct stat s;
+ ASSERT_EQ(0, file.GetStat(&s));
+ EXPECT_EQ(S_IFREG | S_IRALL | S_IWALL, s.st_mode);
+
+ // Change to read-only.
+ EXPECT_EQ(0, file.Fchmod(S_IRALL));
+
+ EXPECT_EQ(S_IRALL, file.GetMode());
+
+ ASSERT_EQ(0, file.GetStat(&s));
+ EXPECT_EQ(S_IFREG | S_IRALL, s.st_mode);
+}
+
TEST(MemFsNodeTest, FTruncate) {
MemFsNodeForTesting file;
off_t result_size = 0;
@@ -229,6 +248,12 @@ TEST(MemFsNodeTest, Directory) {
EXPECT_EQ(EISDIR, root.Read(attr, buf1, sizeof(buf1), &result_bytes));
EXPECT_EQ(EISDIR, root.Write(attr, buf1, sizeof(buf1), &result_bytes));
+ // Chmod test
+ EXPECT_EQ(0, root.Fchmod(S_IRALL | S_IWALL));
+ EXPECT_EQ(S_IRALL | S_IWALL, root.GetMode());
+ // Change it back.
+ EXPECT_EQ(0, root.Fchmod(S_IRALL | S_IWALL | S_IXALL));
+
// Test directory operations
MemFsNodeForTesting* raw_file = new MemFsNodeForTesting;
EXPECT_EQ(0, raw_file->Init(0));
diff --git a/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h b/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
index b29fe6a..e121c6c 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
+++ b/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
@@ -26,7 +26,7 @@ class MockKernelProxy : public nacl_io::KernelProxy {
MOCK_METHOD1(dup, int(int));
MOCK_METHOD2(dup2, int(int, int));
MOCK_METHOD1(fchdir, int(int));
- MOCK_METHOD2(fchmod, int(int, int));
+ MOCK_METHOD2(fchmod, int(int, mode_t));
MOCK_METHOD3(fchown, int(int, uid_t, gid_t));
MOCK_METHOD3(fcntl, int(int, int, va_list));
MOCK_METHOD1(fdatasync, int(int));