This source file includes following definitions.
- GetOutputBuffer
- OpenFlagsToPPAPIOpenFlags
- FSync
- GetDents
- GetStat
- Read
- FTruncate
- Write
- GetType
- GetSize
- IsaDir
- IsaFile
- fileio_resource_
- Init
- Destroy
#include "nacl_io/html5fs/html5_fs_node.h"
#include <errno.h>
#include <fcntl.h>
#include <ppapi/c/pp_completion_callback.h>
#include <ppapi/c/pp_directory_entry.h>
#include <ppapi/c/pp_errors.h>
#include <ppapi/c/pp_file_info.h>
#include <ppapi/c/ppb_file_io.h>
#include <string.h>
#include <vector>
#include "nacl_io/filesystem.h"
#include "nacl_io/getdents_helper.h"
#include "nacl_io/kernel_handle.h"
#include "nacl_io/osdirent.h"
#include "nacl_io/pepper_interface.h"
#include "sdk_util/auto_lock.h"
namespace nacl_io {
namespace {
struct OutputBuffer {
void* data;
int element_count;
};
void* GetOutputBuffer(void* user_data, uint32_t count, uint32_t size) {
OutputBuffer* output = static_cast<OutputBuffer*>(user_data);
output->element_count = count;
if (count) {
output->data = malloc(count * size);
if (!output->data)
output->element_count = 0;
} else {
output->data = NULL;
}
return output->data;
}
int32_t OpenFlagsToPPAPIOpenFlags(int open_flags) {
int32_t ppapi_flags = 0;
switch (open_flags & 3) {
default:
case O_RDONLY:
ppapi_flags = PP_FILEOPENFLAG_READ;
break;
case O_WRONLY:
ppapi_flags = PP_FILEOPENFLAG_WRITE;
break;
case O_RDWR:
ppapi_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
break;
}
if (open_flags & O_CREAT)
ppapi_flags |= PP_FILEOPENFLAG_CREATE;
if (open_flags & O_TRUNC)
ppapi_flags |= PP_FILEOPENFLAG_TRUNCATE;
if (open_flags & O_EXCL)
ppapi_flags |= PP_FILEOPENFLAG_EXCLUSIVE;
return ppapi_flags;
}
}
Error Html5FsNode::FSync() {
if (IsaDir())
return 0;
int32_t result = filesystem_->ppapi()->GetFileIoInterface()->Flush(
fileio_resource_, PP_BlockUntilComplete());
if (result != PP_OK)
return PPErrorToErrno(result);
return 0;
}
Error Html5FsNode::GetDents(size_t offs,
struct dirent* pdir,
size_t size,
int* out_bytes) {
*out_bytes = 0;
if (!IsaDir())
return ENOTDIR;
const ino_t kCurDirIno = -1;
const ino_t kParentDirIno = -2;
GetDentsHelper helper(kCurDirIno, kParentDirIno);
OutputBuffer output_buf = {NULL, 0};
PP_ArrayOutput output = {&GetOutputBuffer, &output_buf};
int32_t result =
filesystem_->ppapi()->GetFileRefInterface()->ReadDirectoryEntries(
fileref_resource_, output, PP_BlockUntilComplete());
if (result != PP_OK)
return PPErrorToErrno(result);
PP_DirectoryEntry* entries = static_cast<PP_DirectoryEntry*>(output_buf.data);
for (int i = 0; i < output_buf.element_count; ++i) {
PP_Var file_name_var = filesystem_->ppapi()->GetFileRefInterface()->GetName(
entries[i].file_ref);
filesystem_->ppapi()->ReleaseResource(entries[i].file_ref);
if (file_name_var.type != PP_VARTYPE_STRING)
continue;
uint32_t file_name_length;
const char* file_name = filesystem_->ppapi()->GetVarInterface()->VarToUtf8(
file_name_var, &file_name_length);
if (file_name) {
file_name_length =
std::min(static_cast<size_t>(file_name_length),
MEMBER_SIZE(dirent, d_name) - 1);
helper.AddDirent(1, file_name, file_name_length);
}
filesystem_->ppapi()->GetVarInterface()->Release(file_name_var);
}
free(output_buf.data);
return helper.GetDents(offs, pdir, size, out_bytes);
}
Error Html5FsNode::GetStat(struct stat* stat) {
AUTO_LOCK(node_lock_);
PP_FileInfo info;
int32_t result = filesystem_->ppapi()->GetFileRefInterface()->Query(
fileref_resource_, &info, PP_BlockUntilComplete());
if (result != PP_OK)
return PPErrorToErrno(result);
memcpy(stat, &stat_, sizeof(stat_));
switch (info.type) {
case PP_FILETYPE_REGULAR:
stat->st_mode |= S_IFREG;
break;
case PP_FILETYPE_DIRECTORY:
stat->st_mode |= S_IFDIR;
break;
case PP_FILETYPE_OTHER:
default:
break;
}
stat->st_size = static_cast<off_t>(info.size);
stat->st_atime = info.last_access_time;
stat->st_mtime = info.last_modified_time;
stat->st_ctime = info.creation_time;
return 0;
}
Error Html5FsNode::Read(const HandleAttr& attr,
void* buf,
size_t count,
int* out_bytes) {
*out_bytes = 0;
if (IsaDir())
return EISDIR;
int32_t result = filesystem_->ppapi()->GetFileIoInterface()->Read(
fileio_resource_,
attr.offs,
static_cast<char*>(buf),
static_cast<int32_t>(count),
PP_BlockUntilComplete());
if (result < 0)
return PPErrorToErrno(result);
*out_bytes = result;
return 0;
}
Error Html5FsNode::FTruncate(off_t size) {
if (IsaDir())
return EISDIR;
int32_t result = filesystem_->ppapi()->GetFileIoInterface()->SetLength(
fileio_resource_, size, PP_BlockUntilComplete());
if (result != PP_OK)
return PPErrorToErrno(result);
return 0;
}
Error Html5FsNode::Write(const HandleAttr& attr,
const void* buf,
size_t count,
int* out_bytes) {
*out_bytes = 0;
if (IsaDir())
return EISDIR;
int32_t result = filesystem_->ppapi()->GetFileIoInterface()->Write(
fileio_resource_,
attr.offs,
static_cast<const char*>(buf),
static_cast<int32_t>(count),
PP_BlockUntilComplete());
if (result < 0)
return PPErrorToErrno(result);
*out_bytes = result;
return 0;
}
int Html5FsNode::GetType() { return fileio_resource_ ? S_IFREG : S_IFDIR; }
Error Html5FsNode::GetSize(size_t* out_size) {
*out_size = 0;
if (IsaDir())
return 0;
AUTO_LOCK(node_lock_);
PP_FileInfo info;
int32_t result = filesystem_->ppapi()->GetFileIoInterface()->Query(
fileio_resource_, &info, PP_BlockUntilComplete());
if (result != PP_OK)
return PPErrorToErrno(result);
*out_size = static_cast<size_t>(info.size);
return 0;
}
bool Html5FsNode::IsaDir() { return !fileio_resource_; }
bool Html5FsNode::IsaFile() { return fileio_resource_; }
Html5FsNode::Html5FsNode(Filesystem* filesystem, PP_Resource fileref_resource)
: Node(filesystem),
fileref_resource_(fileref_resource),
fileio_resource_(0) {}
Error Html5FsNode::Init(int open_flags) {
Error error = Node::Init(open_flags);
if (error)
return error;
PP_FileInfo file_info;
int32_t query_result = filesystem_->ppapi()->GetFileRefInterface()->Query(
fileref_resource_, &file_info, PP_BlockUntilComplete());
if (query_result == PP_OK && file_info.type == PP_FILETYPE_DIRECTORY)
return 0;
FileIoInterface* file_io = filesystem_->ppapi()->GetFileIoInterface();
fileio_resource_ = file_io->Create(filesystem_->ppapi()->GetInstance());
if (!fileio_resource_)
return ENOSYS;
int32_t open_result = file_io->Open(fileio_resource_,
fileref_resource_,
OpenFlagsToPPAPIOpenFlags(open_flags),
PP_BlockUntilComplete());
if (open_result != PP_OK)
return PPErrorToErrno(open_result);
return 0;
}
void Html5FsNode::Destroy() {
FSync();
if (fileio_resource_) {
filesystem_->ppapi()->GetFileIoInterface()->Close(fileio_resource_);
filesystem_->ppapi()->ReleaseResource(fileio_resource_);
}
filesystem_->ppapi()->ReleaseResource(fileref_resource_);
fileio_resource_ = 0;
fileref_resource_ = 0;
Node::Destroy();
}
}