Esempio n. 1
0
static int apipe_write(
    const char* path,
    const char* buf,
    size_t count,
    off_t offset,
    struct fuse_file_info* info) {
  if (count == 0) return 0;

  struct PP_Var req_var = nspawn_dict_create();
  nspawn_dict_setstring(req_var, "command", "nacl_apipe_write");
  nspawn_dict_setint(req_var, "pipe_id", info->fh);
  struct PP_Var data = PSInterfaceVarArrayBuffer()->Create(count);
  if (data.type == PP_VARTYPE_NULL) return -EIO;
  void *p = PSInterfaceVarArrayBuffer()->Map(data);
  if (count > 0 && !p) {
    nspawn_var_release(data);
    nspawn_var_release(req_var);
    return -EIO;
  }
  memcpy(p, buf, count);
  PSInterfaceVarArrayBuffer()->Unmap(data);
  nspawn_dict_set(req_var, "data", data);

  struct PP_Var result_var = nspawn_send_request(req_var);
  int ret = nspawn_dict_getint(result_var, "count");
  nspawn_var_release(result_var);

  return ret;
}
Esempio n. 2
0
struct PP_Var nspawn_send_request(struct PP_Var req_var) {
  /*
   * naclprocess.js is required in order send requests to JavaScript.
   * If NACL_PROCESS is not set in the environment then we assume it is
   * not present and exit early. Without this check we would block forever
   * waiting for a response for the JavaScript side.
   *
   * Only check this once per process, as some programs (emacs)
   * engage in manipulation of the environment that may not be safely
   * read at all times.
   */
  static int checked_for_nacl_process = 0;
  if (!checked_for_nacl_process) {
    const char* naclprocess = getenv("NACL_PROCESS");
    if (naclprocess == NULL) {
      fprintf(stderr, "nspawn_send_request called without NACL_PROCESS set\n");
      return PP_MakeNull();
    }
    checked_for_nacl_process = 1;
  }

  int64_t id = get_request_id();
  char req_id[64];
  sprintf(req_id, "%lld", id);
  nspawn_dict_setstring(req_var, "id", req_id);

  struct NaClSpawnReply reply;
  pthread_mutex_init(&reply.mu, NULL);
  pthread_cond_init(&reply.cond, NULL);
  PSEventRegisterMessageHandler(req_id, &handle_reply, &reply);

  PSInterfaceMessaging()->PostMessage(PSGetInstanceId(), req_var);
  nspawn_var_release(req_var);

  pthread_mutex_lock(&reply.mu);
  /*
   * Wait for response for JavaScript.  This can block for an unbounded amount
   * of time (e.g. waiting for a response to waitpid).
   */
  int error = pthread_cond_wait(&reply.cond, &reply.mu);
  pthread_mutex_unlock(&reply.mu);

  pthread_cond_destroy(&reply.cond);
  pthread_mutex_destroy(&reply.mu);

  PSEventRegisterMessageHandler(req_id, NULL, &reply);

  if (error != 0) {
    fprintf(stderr, "nspawn_send_request: pthread_cond_timedwait: %s\n",
          strerror(error));
    return PP_MakeNull();
  }

  return reply.result_var;
}
Esempio n. 3
0
static int apipe_release(const char* path, struct fuse_file_info* info) {
  struct PP_Var req_var = nspawn_dict_create();
  nspawn_dict_setstring(req_var, "command", "nacl_apipe_close");
  nspawn_dict_setint(req_var, "pipe_id", info->fh);
  nspawn_dict_setint(req_var, "writer", (info->flags & O_WRONLY) == O_WRONLY);

  struct PP_Var result_var = nspawn_send_request(req_var);
  int ret = nspawn_dict_getint(result_var, "result");
  nspawn_var_release(result_var);

  return ret;
}
Esempio n. 4
0
static int apipe_read(
    const char* path, char* buf, size_t count, off_t offset,
    struct fuse_file_info* info) {
  struct PP_Var req_var = nspawn_dict_create();
  nspawn_dict_setstring(req_var, "command", "nacl_apipe_read");
  nspawn_dict_setint(req_var, "pipe_id", info->fh);
  nspawn_dict_setint(req_var, "count", count);
  nspawn_dict_setint(req_var, "nonblock",
                     (info->flags & O_NONBLOCK) == O_NONBLOCK);

  struct PP_Var result_var = nspawn_send_request(req_var);
  int err = nspawn_dict_getint(result_var, "error");
  if (err != 0) {
    nspawn_var_release(result_var);
    return -err;
  }
  struct PP_Var data = nspawn_dict_get(result_var, "data");
  assert(data.type == PP_VARTYPE_ARRAY_BUFFER);
  uint32_t len;
  if (!PSInterfaceVarArrayBuffer()->ByteLength(data, &len)) {
    nspawn_var_release(data);
    nspawn_var_release(result_var);
    return -EIO;
  }
  void *p = PSInterfaceVarArrayBuffer()->Map(data);
  if (len > 0 && !p) {
    nspawn_var_release(data);
    nspawn_var_release(result_var);
    return -EIO;
  }
  assert(len <= count);
  memcpy(buf, p, len);
  PSInterfaceVarArrayBuffer()->Unmap(data);
  nspawn_var_release(data);
  nspawn_var_release(result_var);

  return len;
}
Esempio n. 5
0
int nspawn_dict_getint_release(struct PP_Var dict_var, const char* key) {
    int ret = nspawn_dict_getint(dict_var, key);
    nspawn_var_release(dict_var);
    return ret;
}