#include "nacl_io/log.h"
#include "nacl_io/memfs/mem_fs.h"
#include "nacl_io/node.h"
+#include "nacl_io/osinttypes.h"
#include "nacl_io/osmman.h"
#include "nacl_io/ossocket.h"
#include "nacl_io/osstat.h"
ScopedFilesystem root_fs;
rtn = MountInternal("", "/", "passthroughfs", 0, NULL, false, &root_fs);
if (rtn != 0)
- assert(false);
+ return rtn;
ScopedFilesystem fs;
rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs);
if (rtn != 0)
- assert(false);
+ return rtn;
dev_fs_ = sdk_util::static_scoped_ref_cast<DevFs>(fs);
// Create the filesystem nodes for / and /dev afterward. They can't be
// created the normal way because the dev filesystem didn't exist yet.
rtn = CreateFsNode(root_fs);
if (rtn != 0)
- assert(false);
+ return rtn;
rtn = CreateFsNode(dev_fs_);
if (rtn != 0)
- assert(false);
+ return rtn;
// Open the first three in order to get STDIN, STDOUT, STDERR
int fd;
fd = open("/dev/stdin", O_RDONLY, 0);
+ if (fd < 0) {
+ LOG_ERROR("failed to open /dev/stdin: %s", strerror(errno));
+ return errno;
+ }
assert(fd == 0);
- if (fd < 0)
- rtn = errno;
fd = open("/dev/stdout", O_WRONLY, 0);
+ if (fd < 0) {
+ LOG_ERROR("failed to open /dev/stdout: %s", strerror(errno));
+ return errno;
+ }
assert(fd == 1);
- if (fd < 0)
- rtn = errno;
fd = open("/dev/stderr", O_WRONLY, 0);
+ if (fd < 0) {
+ LOG_ERROR("failed to open /dev/sterr: %s", strerror(errno));
+ return errno;
+ }
assert(fd == 2);
- if (fd < 0)
- rtn = errno;
#ifdef PROVIDES_SOCKET_API
host_resolver_.Init(ppapi_);
stream_fs_.reset(new StreamFs());
int result = stream_fs_->Init(args);
if (result != 0) {
- assert(false);
- rtn = result;
+ LOG_ERROR("initializing streamfs failed: %s", strerror(result));
+ return result;
}
- return rtn;
+ return 0;
}
bool KernelProxy::RegisterFsType(const char* fs_type,
int KernelProxy::open(const char* path, int open_flags, mode_t mode) {
ScopedFilesystem fs;
ScopedNode node;
+ mode_t mask = ~GetUmask() & S_MODEBITS;
- Error error = AcquireFsAndNode(path, open_flags, mode, &fs, &node);
+ Error error = AcquireFsAndNode(path, open_flags, mode & mask, &fs, &node);
if (error) {
errno = error;
return -1;
}
int KernelProxy::chmod(const char* path, mode_t mode) {
- int fd = open(path, O_RDONLY, mode);
- if (-1 == fd)
+ ScopedFilesystem fs;
+ ScopedNode node;
+
+ Error error = AcquireFsAndNode(path, O_RDONLY, 0, &fs, &node);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ error = node->Fchmod(mode);
+ if (error) {
+ errno = error;
return -1;
+ }
- int result = fchmod(fd, mode);
- close(fd);
- return result;
+ return 0;
}
int KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
return -1;
}
- error = fs->Mkdir(rel, mode);
+ mode_t mask = ~GetUmask() & S_MODEBITS;
+ error = fs->Mkdir(rel, mode & mask);
if (error) {
errno = error;
return -1;
}
int KernelProxy::stat(const char* path, struct stat* buf) {
- int fd = open(path, O_RDONLY, 0);
- if (-1 == fd)
+ ScopedFilesystem fs;
+ ScopedNode node;
+
+ Error error = AcquireFsAndNode(path, O_RDONLY, 0, &fs, &node);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ error = node->GetStat(buf);
+ if (error) {
+ errno = error;
return -1;
+ }
- int result = fstat(fd, buf);
- close(fd);
- return result;
+ return 0;
}
int KernelProxy::mount(const char* source,
return -1;
}
+ if (handle->OpenMode() == O_RDONLY) {
+ errno = EACCES;
+ return -1;
+ }
+
error = handle->node()->FTruncate(length);
if (error) {
errno = error;
return -1;
}
- error = handle->node()->Futimens(times);
+ return FutimensInternal(handle->node(), times);
+}
+
+Error KernelProxy::FutimensInternal(const ScopedNode& node,
+ const struct timespec times[2]) {
+ Error error(0);
+ if (times == NULL) {
+ struct timespec now[2];
+ struct timeval tm;
+ error = gettimeofday(&tm, NULL);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ now[0].tv_sec = now[1].tv_sec = tm.tv_sec;
+ now[0].tv_nsec = now[1].tv_nsec = tm.tv_usec * 1000;
+ error = node->Futimens(now);
+ } else {
+ error = node->Futimens(times);
+ }
+
if (error) {
errno = error;
return -1;
}
int KernelProxy::truncate(const char* path, off_t len) {
- int fd = open(path, O_WRONLY, 0);
- if (-1 == fd)
+ ScopedFilesystem fs;
+ ScopedNode node;
+
+ Error error = AcquireFsAndNode(path, O_WRONLY, 0, &fs, &node);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+
+ // Directories cannot be truncated.
+ if (node->IsaDir()) {
+ return EISDIR;
+ }
+
+ if (!node->CanOpen(O_WRONLY)) {
+ errno = EACCES;
return -1;
+ }
+
+ error = node->FTruncate(len);
+ if (error) {
+ errno = error;
+ return -1;
+ }
- int result = ftruncate(fd, len);
- close(fd);
- return result;
+ return 0;
}
int KernelProxy::lstat(const char* path, struct stat* buf) {
return -1;
}
- error = handle->node()->Fchmod(mode);
+ error = handle->node()->Fchmod(mode & S_MODEBITS);
if (error) {
errno = error;
return -1;
}
int KernelProxy::utimens(const char* path, const struct timespec times[2]) {
- int fd = open(path, O_RDONLY, 0);
- if (-1 == fd)
+ ScopedFilesystem fs;
+ ScopedNode node;
+
+ Error error = AcquireFsAndNode(path, O_WRONLY, 0, &fs, &node);
+ if (error) {
+ errno = error;
return -1;
+ }
- int result = futimens(fd, times);
- close(fd);
- return result;
+ return FutimensInternal(node, times);
}
// TODO(noelallen): Needs implementation.
if (action && action->sa_handler != SIG_DFL) {
// Trying to set this action to anything other than SIG_DFL
// is not yet supported.
- LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", sig);
+ LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", signum);
errno = EINVAL;
return -1;
}
return -1;
}
+mode_t KernelProxy::umask(mode_t mask) {
+ return SetUmask(mask & S_MODEBITS);
+}
+
#ifdef PROVIDES_SOCKET_API
int KernelProxy::select(int nfds,
if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
(timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || (ms < 0) ||
(ms >= INT_MAX)) {
- LOG_TRACE("Invalid timeout: tv_sec=%d tv_usec=%d.",
+ LOG_TRACE("Invalid timeout: tv_sec=%" PRIi64 " tv_usec=%ld.",
timeout->tv_sec,
timeout->tv_usec);
errno = EINVAL;