1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/jsfs/js_fs.h"
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <assert.h>
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <errno.h>
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <fcntl.h>
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <limits.h>
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string.h>
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/ioctl.h"
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/jsfs/js_fs_node.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/kernel_handle.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/log.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/osdirent.h"
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "nacl_io/pepper_interface.h"
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "sdk_util/macros.h"
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace nacl_io {
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)JsFs::JsFs()
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : messaging_iface_(NULL),
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      array_iface_(NULL),
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      buffer_iface_(NULL),
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      dict_iface_(NULL),
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      var_iface_(NULL),
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      request_id_(0) {
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::Init(const FsInitArgs& args) {
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Error error = Filesystem::Init(args);
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (error)
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return error;
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pthread_cond_init(&response_cond_, NULL);
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  messaging_iface_ = ppapi_->GetMessagingInterface();
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  array_iface_ = ppapi_->GetVarArrayInterface();
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  buffer_iface_ = ppapi_->GetVarArrayBufferInterface();
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  dict_iface_ = ppapi_->GetVarDictionaryInterface();
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  var_iface_ = ppapi_->GetVarInterface();
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!messaging_iface_ || !array_iface_ || !buffer_iface_ || !dict_iface_ ||
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      !var_iface_) {
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Got 1+ NULL interface(s): %s%s%s%s%s",
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              messaging_iface_ ? "" : "Messaging ",
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              array_iface_ ? "" : "VarArray ",
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              buffer_iface_ ? "" : "VarArrayBuffer ",
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              dict_iface_ ? "" : "VarDictionary ",
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              var_iface_ ? "" : "Var ");
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return ENOSYS;
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return 0;
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void JsFs::Destroy() {
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pthread_cond_destroy(&response_cond_);
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFs::SetDictVar(PP_Var dict, const char* key, PP_Var value) {
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PP_Var key_var = var_iface_->VarFromUtf8(key, strlen(key));
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar scoped_key(ppapi_, key_var);
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (key_var.type != PP_VARTYPE_STRING) {
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Unable to create string key \"%s\".", key);
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PP_Bool success = dict_iface_->Set(dict, key_var, value);
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!success) {
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Unable to set \"%s\" key of dictionary.", key);
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)PP_Var JsFs::GetDictVar(PP_Var dict, const char* key) {
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PP_Var key_var = var_iface_->VarFromUtf8(key, strlen(key));
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar scoped_key(ppapi_, key_var);
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (key_var.type != PP_VARTYPE_STRING) {
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Unable to create string key \"%s\".", key);
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return PP_MakeUndefined();
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return dict_iface_->Get(dict, key_var);
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFs::GetVarInt32(PP_Var var, int32_t* out_value) {
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  switch (var.type) {
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PP_VARTYPE_INT32:
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *out_value = var.value.as_int;
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PP_VARTYPE_DOUBLE:
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *out_value = static_cast<int32_t>(var.value.as_double);
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    default:
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFs::GetVarUint32(PP_Var var, uint32_t* out_value) {
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  switch (var.type) {
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PP_VARTYPE_INT32:
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *out_value = static_cast<uint32_t>(var.value.as_int);
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PP_VARTYPE_DOUBLE:
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *out_value = static_cast<uint32_t>(var.value.as_double);
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    default:
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFs::GetVarInt64(PP_Var var, int64_t* out_value) {
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  switch (var.type) {
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PP_VARTYPE_INT32:
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *out_value = var.value.as_int;
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PP_VARTYPE_DOUBLE:
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *out_value = static_cast<int64_t>(var.value.as_double);
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    case PP_VARTYPE_ARRAY: {
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      uint32_t len = array_iface_->GetLength(var);
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (len != 2) {
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        LOG_ERROR("Expected int64 array type to have 2 elements, not %d", len);
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return false;
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      PP_Var high_int_var = array_iface_->Get(var, 0);
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ScopedVar scoped_high_int_var(ppapi_, high_int_var);
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      uint32_t high_int;
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!GetVarUint32(high_int_var, &high_int))
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return false;
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      PP_Var low_int_var = array_iface_->Get(var, 1);
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ScopedVar scoped_low_int_var(ppapi_, low_int_var);
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      uint32_t low_int;
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!GetVarUint32(low_int_var, &low_int))
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return false;
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      *out_value = static_cast<int64_t>(
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          (static_cast<uint64_t>(high_int) << 32) | low_int);
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return true;
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    default:
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return false;
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)PP_Var JsFs::VMakeRequest(RequestId request_id,
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          const char* format,
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          va_list args) {
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PP_Var dict = dict_iface_->Create();
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar scoped_dict(ppapi_, dict);
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!SetDictVar(dict, "id", PP_MakeInt32(request_id)))
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return PP_MakeNull();
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* p = format;
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (*p) {
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    assert(*p == '%');
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ++p;
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const char* key = va_arg(args, const char*);
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    PP_Var value_var = PP_MakeUndefined();
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    switch(*p) {
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'd':
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        value_var = PP_MakeInt32(va_arg(args, int32_t));
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'u':
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        value_var = PP_MakeInt32(va_arg(args, uint32_t));
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 's': {
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        const char* value = va_arg(args, const char*);
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        value_var = var_iface_->VarFromUtf8(value, strlen(value));
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (value_var.type != PP_VARTYPE_STRING) {
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          LOG_ERROR("Unable to create \"%s\" string var.", value);
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          return PP_MakeNull();
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'p':
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        value_var = *va_arg(args, const PP_Var*);
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        var_iface_->AddRef(value_var);
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'l': {
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // Only '%lld' is supported.
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ++p;
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        assert(*p == 'l');
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ++p;
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        assert(*p == 'd');
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        int64_t value = va_arg(args, int64_t);
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (value >= INT_MIN && value <= INT_MAX) {
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          // Send as an int.
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          value_var = PP_MakeInt32(static_cast<int32_t>(value));
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        } else {
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          // Send as an array of two ints: [high int32, low int32].
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          value_var = array_iface_->Create();
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          if (!array_iface_->SetLength(value_var, 2)) {
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            LOG_ERROR("Unable to set length of s64 array.");
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            return PP_MakeNull();
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          }
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          if (!array_iface_->Set(value_var, 0, PP_MakeInt32(value >> 32))) {
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            LOG_ERROR("Unable to set of high int32 of s64 array.");
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            return PP_MakeNull();
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          }
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          if (!array_iface_->Set(
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                  value_var, 1, PP_MakeInt32(value & 0xffffffff))) {
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            LOG_ERROR("Unable to set of low int32 of s64 array.");
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            return PP_MakeNull();
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          }
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      default:
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        LOG_ERROR("Unknown format specifier %%\"%s\"", p);
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        assert(0);
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        return PP_MakeNull();
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ++p;
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!SetDictVar(dict, key, value_var))
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return PP_MakeNull();
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Unconditionally release the value var. It is legal to do this even for
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // non-refcounted types.
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    var_iface_->Release(value_var);
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return scoped_dict.Release();
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)JsFs::RequestId JsFs::VSendRequest(const char* format, va_list args) {
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AUTO_LOCK(lock_);
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RequestId id = ++request_id_;
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Skip 0 (the invalid request id) in the very unlikely case that the request
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // id wraps.
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (id == 0)
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    id = ++request_id_;
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PP_Var dict_var = VMakeRequest(id, format, args);
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar scoped_dict_var(ppapi_, dict_var);
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (dict_var.type != PP_VARTYPE_DICTIONARY)
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return 0;
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  messaging_iface_->PostMessage(ppapi_->GetInstance(), dict_var);
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return id;
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFs::VSendRequestAndWait(ScopedVar* out_response,
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               const char* format,
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                               va_list args) {
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RequestId id = VSendRequest(format, args);
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (id == 0)
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return false;
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  out_response->Reset(WaitForResponse(id));
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return true;
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool JsFs::SendRequestAndWait(ScopedVar* out_response,
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              const char* format,
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              ...) {
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_list args;
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_start(args, format);
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  bool result = VSendRequestAndWait(out_response, format, args);
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_end(args);
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return result;
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::ErrorFromResponse(const ScopedVar& response) {
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int32_t error;
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (ScanVar(response.pp_var(), "%d", "error", &error) != 1) {
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Expected \"error\" field in response.");
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return error;
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)int JsFs::ScanVar(PP_Var var, const char* format, ...) {
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_list args;
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_start(args, format);
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int result = VScanVar(var, format, args);
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_end(args);
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return result;
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)int JsFs::VScanVar(PP_Var dict_var, const char* format, va_list args) {
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (dict_var.type != PP_VARTYPE_DICTIONARY) {
307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Expected var of type dictionary, not %d.", dict_var.type);
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return 0;
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int num_values = 0;
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* p = format;
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (*p) {
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    assert(*p == '%');
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ++p;
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const char* key = va_arg(args, const char*);
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    PP_Var value_var = GetDictVar(dict_var, key);
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ScopedVar scoped_value_var(ppapi_, value_var);
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (value_var.type == PP_VARTYPE_UNDEFINED)
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool ok = true;
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    switch (*p) {
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'd': {
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        int32_t* value = va_arg(args, int32_t*);
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (!GetVarInt32(value_var, value)) {
331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          LOG_ERROR("Expected int32_t value for key \"%s\"", key);
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          ok = false;
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'u': {
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        uint32_t* value = va_arg(args, uint32_t*);
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (!GetVarUint32(value_var, value)) {
339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          LOG_ERROR("Expected uint32_t value for key \"%s\"", key);
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          ok = false;
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'l': {
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // Only '%lld' is supported.
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ++p;
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        assert(*p == 'l');
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ++p;
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        assert(*p == 'd');
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        int64_t* value = va_arg(args, int64_t*);
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (!GetVarInt64(value_var, value)) {
353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          LOG_ERROR("Expected int64_t value for key \"%s\"", key);
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          ok = false;
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        }
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      case 'p': {
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        PP_Var* value = va_arg(args, PP_Var*);
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        *value = scoped_value_var.Release();
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      default:
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        LOG_ERROR("Unknown format specifier %%\"%s\"", p);
365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        assert(0);
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ok = false;
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!ok)
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    p++;
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    num_values++;
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return num_values;
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)PP_Var JsFs::WaitForResponse(RequestId request_id) {
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AUTO_LOCK(lock_);
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (1) {
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ResponseMap_t::iterator iter = responses_.find(request_id);
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (iter != responses_.end()) {
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      PP_Var response = iter->second;
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      responses_.erase(iter);
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return response;
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    pthread_cond_wait(&response_cond_, lock_.mutex());
391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciError JsFs::OpenWithMode(const Path& path, int open_flags, mode_t t,
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         ScopedNode* out_node) {
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  out_node->reset(NULL);
397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar response(ppapi_);
398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!SendRequestAndWait(&response, "%s%s%d",
399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "cmd", "open",
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "path", path.Join().c_str(),
401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "oflag", open_flags)) {
402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Failed to send request.");
403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int32_t error;
407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int32_t fd;
408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int result = ScanVar(response.pp_var(), "%d%d", "error", &error, "fd", &fd);
409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (result >= 1 && error)
410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return error;
411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (result != 2) {
413116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Expected \"error\" and \"fd\" fields in response.");
414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  out_node->reset(new JsFsNode(this, fd));
418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return 0;
419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::Unlink(const Path& path) {
422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar response(ppapi_);
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!SendRequestAndWait(
424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          &response, "%s%s", "cmd", "unlink", "path", path.Join().c_str())) {
425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Failed to send request.");
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ErrorFromResponse(response);
430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::Mkdir(const Path& path, int perm) {
433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar response(ppapi_);
434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!SendRequestAndWait(&response, "%s%s%d",
435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "cmd", "mkdir",
436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "path", path.Join().c_str(),
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "mode", perm)) {
438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Failed to send request.");
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ErrorFromResponse(response);
443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::Rmdir(const Path& path) {
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar response(ppapi_);
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!SendRequestAndWait(
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          &response, "%s%s", "cmd", "rmdir", "path", path.Join().c_str())) {
449116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Failed to send request.");
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ErrorFromResponse(response);
454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::Remove(const Path& path) {
457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar response(ppapi_);
458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!SendRequestAndWait(
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          &response, "%s%s", "cmd", "remove", "path", path.Join().c_str())) {
460116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Failed to send request.");
461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
464f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ErrorFromResponse(response);
465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::Rename(const Path& path, const Path& newpath) {
468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedVar response(ppapi_);
469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!SendRequestAndWait(&response, "%s%s%s",
470f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "cmd", "rename",
471f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "old", path.Join().c_str(),
472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                          "new", newpath.Join().c_str())) {
473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Failed to send request.");
474f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
475f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
476f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
477f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return ErrorFromResponse(response);
478f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
479f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Error JsFs::Filesystem_VIoctl(int request, va_list args) {
481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (request != NACL_IOC_HANDLEMESSAGE) {
482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_ERROR("Unknown ioctl: %#x", request);
483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  PP_Var response = *va_arg(args, PP_Var*);
487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  AUTO_LOCK(lock_);
489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RequestId response_id;
491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (ScanVar(response, "%d", "id", &response_id) != 1) {
492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    LOG_TRACE("ioctl with no \"id\", ignoring.\n");
493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return EINVAL;
494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  responses_.insert(ResponseMap_t::value_type(response_id, response));
497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pthread_cond_broadcast(&response_cond_);
498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return 0;
499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace nacl_io
502