1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount_node_html5fs.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <ppapi/c/pp_completion_callback.h>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <ppapi/c/pp_directory_entry.h>
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <ppapi/c/pp_errors.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <ppapi/c/pp_file_info.h>
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <ppapi/c/ppb_file_io.h>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h>
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/mount.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/osdirent.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nacl_io/pepper_interface.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "sdk_util/auto_lock.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io {
22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct OutputBuffer {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void* data;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int element_count;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void* GetOutputBuffer(void* user_data, uint32_t count, uint32_t size) {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OutputBuffer* output = static_cast<OutputBuffer*>(user_data);
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output->element_count = count;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (count) {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    output->data = malloc(count * size);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!output->data)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      output->element_count = 0;
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    output->data = NULL;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return output->data;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32_t ModeToOpenFlags(int mode) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int32_t open_flags = 0;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (mode & 3) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case O_RDONLY:
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      open_flags = PP_FILEOPENFLAG_READ;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case O_WRONLY:
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      open_flags = PP_FILEOPENFLAG_WRITE;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case O_RDWR:
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      open_flags = PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (mode & O_CREAT)
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    open_flags |= PP_FILEOPENFLAG_CREATE;
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (mode & O_TRUNC)
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    open_flags |= PP_FILEOPENFLAG_TRUNCATE;
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (mode & O_EXCL)
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    open_flags |= PP_FILEOPENFLAG_EXCLUSIVE;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return open_flags;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::FSync() {
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Cannot call Flush on a directory; simply do nothing.
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDirectory())
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t result = mount_->ppapi()->GetFileIoInterface()
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ->Flush(fileio_resource_, PP_BlockUntilComplete());
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result != PP_OK)
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(result);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::GetDents(size_t offs,
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 struct dirent* pdir,
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 size_t size,
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 int* out_bytes) {
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_bytes = 0;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the buffer pointer is invalid, fail
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (NULL == pdir)
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return EINVAL;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the buffer is too small, fail
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (size < sizeof(struct dirent))
95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return EINVAL;
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If this is not a directory, fail
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!IsDirectory())
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return ENOTDIR;
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OutputBuffer output_buf = {NULL, 0};
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PP_ArrayOutput output = {&GetOutputBuffer, &output_buf};
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t result = mount_->ppapi()->GetFileRefInterface()->ReadDirectoryEntries(
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fileref_resource_, output, PP_BlockUntilComplete());
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result != PP_OK)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(result);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<struct dirent> dirents;
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PP_DirectoryEntry* entries = static_cast<PP_DirectoryEntry*>(output_buf.data);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < output_buf.element_count; ++i) {
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PP_Var file_name_var =
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        mount_->ppapi()->GetFileRefInterface()->GetName(entries[i].file_ref);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Release the file reference.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mount_->ppapi()->ReleaseResource(entries[i].file_ref);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (file_name_var.type != PP_VARTYPE_STRING)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    uint32_t file_name_length;
122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const char* file_name = mount_->ppapi()->GetVarInterface()
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        ->VarToUtf8(file_name_var, &file_name_length);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!file_name)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_name_length = std::min(
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<size_t>(file_name_length),
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        sizeof(static_cast<struct dirent*>(0)->d_name) - 1);  // -1 for NULL.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dirents.push_back(dirent());
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    struct dirent& direntry = dirents.back();
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    direntry.d_ino = 1;  // Must be > 0.
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    direntry.d_off = sizeof(struct dirent);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    direntry.d_reclen = sizeof(struct dirent);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    strncpy(direntry.d_name, file_name, file_name_length);
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    direntry.d_name[file_name_length] = 0;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Release the output buffer.
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  free(output_buf.data);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Force size to a multiple of dirent
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size -= size % sizeof(struct dirent);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t max = dirents.size() * sizeof(struct dirent);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (offs >= max)
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (offs + size >= max)
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    size = max - offs;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memcpy(pdir, reinterpret_cast<char*>(dirents.data()) + offs, size);
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_bytes = size;
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::GetStat(struct stat* stat) {
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AUTO_LOCK(node_lock_);
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_FileInfo info;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t result = mount_->ppapi()->GetFileRefInterface()->Query(
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fileref_resource_, &info, PP_BlockUntilComplete());
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result != PP_OK)
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(result);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fill in known info here.
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memcpy(stat, &stat_, sizeof(stat_));
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fill in the additional info from ppapi.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (info.type) {
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case PP_FILETYPE_REGULAR:
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      stat->st_mode |= S_IFREG;
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    case PP_FILETYPE_DIRECTORY:
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      stat->st_mode |= S_IFDIR;
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case PP_FILETYPE_OTHER:
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    default:
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      break;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stat->st_size = static_cast<off_t>(info.size);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stat->st_atime = info.last_access_time;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stat->st_mtime = info.last_modified_time;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  stat->st_ctime = info.creation_time;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::Read(size_t offs,
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             void* buf,
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             size_t count,
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                             int* out_bytes) {
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_bytes = 0;
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDirectory())
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return EISDIR;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t result =
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mount_->ppapi()->GetFileIoInterface()->Read(fileio_resource_,
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  offs,
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  static_cast<char*>(buf),
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  static_cast<int32_t>(count),
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  PP_BlockUntilComplete());
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result < 0)
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(result);
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_bytes = result;
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::FTruncate(off_t size) {
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDirectory())
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return EISDIR;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t result = mount_->ppapi()->GetFileIoInterface()
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ->SetLength(fileio_resource_, size, PP_BlockUntilComplete());
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result != PP_OK)
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(result);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return 0;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::Write(size_t offs,
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              const void* buf,
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              size_t count,
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              int* out_bytes) {
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_bytes = 0;
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (IsDirectory())
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return EISDIR;
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t result = mount_->ppapi()->GetFileIoInterface()
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ->Write(fileio_resource_,
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              offs,
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              static_cast<const char*>(buf),
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              static_cast<int32_t>(count),
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)              PP_BlockUntilComplete());
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result < 0)
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(result);
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_bytes = result;
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::GetSize(size_t* out_size) {
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_size = 0;
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AUTO_LOCK(node_lock_);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_FileInfo info;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t result = mount_->ppapi()->GetFileIoInterface()
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ->Query(fileio_resource_, &info, PP_BlockUntilComplete());
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (result != PP_OK)
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(result);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *out_size = static_cast<size_t>(info.size);
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MountNodeHtml5Fs::MountNodeHtml5Fs(Mount* mount, PP_Resource fileref_resource)
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : MountNode(mount),
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fileref_resource_(fileref_resource),
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fileio_resource_(0) {}
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Error MountNodeHtml5Fs::Init(int perm) {
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Error error = MountNode::Init(Mount::OpenModeToPermission(perm));
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (error)
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return error;
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // First query the FileRef to see if it is a file or directory.
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PP_FileInfo file_info;
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  int32_t query_result =
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      mount_->ppapi()->GetFileRefInterface()->Query(fileref_resource_,
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                    &file_info,
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                                    PP_BlockUntilComplete());
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // If this is a directory, do not get a FileIO.
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (query_result == PP_OK && file_info.type == PP_FILETYPE_DIRECTORY)
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return 0;
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fileio_resource_ = mount_->ppapi()->GetFileIoInterface()
281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ->Create(mount_->ppapi()->GetInstance());
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!fileio_resource_)
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return ENOSYS;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int32_t open_result =
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mount_->ppapi()->GetFileIoInterface()->Open(fileio_resource_,
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  fileref_resource_,
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  ModeToOpenFlags(perm),
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                  PP_BlockUntilComplete());
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (open_result != PP_OK)
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return PPErrorToErrno(open_result);
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return 0;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MountNodeHtml5Fs::Destroy() {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FSync();
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (fileio_resource_) {
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mount_->ppapi()->GetFileIoInterface()->Close(fileio_resource_);
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mount_->ppapi()->ReleaseResource(fileio_resource_);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  mount_->ppapi()->ReleaseResource(fileref_resource_);
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fileio_resource_ = 0;
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fileref_resource_ = 0;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MountNode::Destroy();
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace nacl_io
310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
311