1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "nacl_io/kernel_proxy.h"
6
7#include <assert.h>
8#include <errno.h>
9#include <fcntl.h>
10#include <limits.h>
11#include <poll.h>
12#include <pthread.h>
13#include <stdio.h>
14#include <string.h>
15#include <sys/time.h>
16#include <unistd.h>
17
18#include <iterator>
19#include <string>
20
21#include "nacl_io/devfs/dev_fs.h"
22#include "nacl_io/filesystem.h"
23#include "nacl_io/fusefs/fuse_fs_factory.h"
24#include "nacl_io/host_resolver.h"
25#include "nacl_io/html5fs/html5_fs.h"
26#include "nacl_io/httpfs/http_fs.h"
27#include "nacl_io/kernel_handle.h"
28#include "nacl_io/kernel_wrap_real.h"
29#include "nacl_io/log.h"
30#include "nacl_io/memfs/mem_fs.h"
31#include "nacl_io/node.h"
32#include "nacl_io/osmman.h"
33#include "nacl_io/ossocket.h"
34#include "nacl_io/osstat.h"
35#include "nacl_io/passthroughfs/passthrough_fs.h"
36#include "nacl_io/path.h"
37#include "nacl_io/pepper_interface.h"
38#include "nacl_io/pipe/pipe_node.h"
39#include "nacl_io/socket/tcp_node.h"
40#include "nacl_io/socket/udp_node.h"
41#include "nacl_io/stream/stream_fs.h"
42#include "nacl_io/typed_fs_factory.h"
43#include "sdk_util/auto_lock.h"
44#include "sdk_util/ref_object.h"
45#include "sdk_util/string_util.h"
46
47#ifndef MAXPATHLEN
48#define MAXPATHLEN 256
49#endif
50
51namespace nacl_io {
52
53KernelProxy::KernelProxy()
54    : dev_(0),
55      ppapi_(NULL),
56      exit_callback_(NULL),
57      exit_callback_user_data_(NULL),
58      mount_callback_(NULL),
59      mount_callback_user_data_(NULL),
60      signal_emitter_(new EventEmitter) {
61  memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
62  sigwinch_handler_.sa_handler = SIG_DFL;
63}
64
65KernelProxy::~KernelProxy() {
66  // Clean up the FsFactories.
67  for (FsFactoryMap_t::iterator i = factories_.begin(); i != factories_.end();
68       ++i) {
69    delete i->second;
70  }
71}
72
73Error KernelProxy::Init(PepperInterface* ppapi) {
74  Error rtn = 0;
75  ppapi_ = ppapi;
76  dev_ = 1;
77
78  factories_["memfs"] = new TypedFsFactory<MemFs>;
79  factories_["dev"] = new TypedFsFactory<DevFs>;
80  factories_["html5fs"] = new TypedFsFactory<Html5Fs>;
81  factories_["httpfs"] = new TypedFsFactory<HttpFs>;
82  factories_["passthroughfs"] = new TypedFsFactory<PassthroughFs>;
83
84  ScopedFilesystem root_fs;
85  rtn = MountInternal("", "/", "passthroughfs", 0, NULL, false, &root_fs);
86  if (rtn != 0)
87    assert(false);
88
89  ScopedFilesystem fs;
90  rtn = MountInternal("", "/dev", "dev", 0, NULL, false, &fs);
91  if (rtn != 0)
92    assert(false);
93  dev_fs_ = sdk_util::static_scoped_ref_cast<DevFs>(fs);
94
95  // Create the filesystem nodes for / and /dev afterward. They can't be
96  // created the normal way because the dev filesystem didn't exist yet.
97  rtn = CreateFsNode(root_fs);
98  if (rtn != 0)
99    assert(false);
100
101  rtn = CreateFsNode(dev_fs_);
102  if (rtn != 0)
103    assert(false);
104
105  // Open the first three in order to get STDIN, STDOUT, STDERR
106  int fd;
107  fd = open("/dev/stdin", O_RDONLY, 0);
108  assert(fd == 0);
109  if (fd < 0)
110    rtn = errno;
111
112  fd = open("/dev/stdout", O_WRONLY, 0);
113  assert(fd == 1);
114  if (fd < 0)
115    rtn = errno;
116
117  fd = open("/dev/stderr", O_WRONLY, 0);
118  assert(fd == 2);
119  if (fd < 0)
120    rtn = errno;
121
122#ifdef PROVIDES_SOCKET_API
123  host_resolver_.Init(ppapi_);
124#endif
125
126  FsInitArgs args;
127  args.dev = dev_++;
128  args.ppapi = ppapi_;
129  stream_fs_.reset(new StreamFs());
130  int result = stream_fs_->Init(args);
131  if (result != 0) {
132    assert(false);
133    rtn = result;
134  }
135
136  return rtn;
137}
138
139bool KernelProxy::RegisterFsType(const char* fs_type,
140                                 fuse_operations* fuse_ops) {
141  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
142  if (iter != factories_.end())
143    return false;
144
145  factories_[fs_type] = new FuseFsFactory(fuse_ops);
146  return true;
147}
148
149bool KernelProxy::UnregisterFsType(const char* fs_type) {
150  FsFactoryMap_t::iterator iter = factories_.find(fs_type);
151  if (iter == factories_.end())
152    return false;
153
154  delete iter->second;
155  factories_.erase(iter);
156  return true;
157}
158
159void KernelProxy::SetExitCallback(nacl_io_exit_callback_t exit_callback,
160                                  void* user_data) {
161  exit_callback_ = exit_callback;
162  exit_callback_user_data_ = user_data;
163}
164
165void KernelProxy::SetMountCallback(nacl_io_mount_callback_t mount_callback,
166                                   void* user_data) {
167  mount_callback_ = mount_callback;
168  mount_callback_user_data_ = user_data;
169}
170
171int KernelProxy::open_resource(const char* path) {
172  ScopedFilesystem fs;
173  Path rel;
174
175  Error error = AcquireFsAndRelPath(path, &fs, &rel);
176  if (error) {
177    errno = error;
178    return -1;
179  }
180
181  ScopedNode node;
182  error = fs->OpenResource(rel, &node);
183  if (error) {
184    // OpenResource failed, try Open().
185    error = fs->Open(rel, O_RDONLY, &node);
186    if (error) {
187      errno = error;
188      return -1;
189    }
190  }
191
192  ScopedKernelHandle handle(new KernelHandle(fs, node));
193  error = handle->Init(O_RDONLY);
194  if (error) {
195    errno = error;
196    return -1;
197  }
198
199  return AllocateFD(handle, path);
200}
201
202int KernelProxy::open(const char* path, int open_flags, mode_t mode) {
203  ScopedFilesystem fs;
204  ScopedNode node;
205
206  Error error = AcquireFsAndNode(path, open_flags, mode, &fs, &node);
207  if (error) {
208    errno = error;
209    return -1;
210  }
211
212  ScopedKernelHandle handle(new KernelHandle(fs, node));
213  error = handle->Init(open_flags);
214  if (error) {
215    errno = error;
216    return -1;
217  }
218
219  return AllocateFD(handle, path);
220}
221
222int KernelProxy::pipe(int pipefds[2]) {
223  PipeNode* pipe = new PipeNode(stream_fs_.get());
224  ScopedNode node(pipe);
225
226  if (pipe->Init(O_RDWR) == 0) {
227    ScopedKernelHandle handle0(new KernelHandle(stream_fs_, node));
228    ScopedKernelHandle handle1(new KernelHandle(stream_fs_, node));
229
230    // Should never fail, but...
231    if (handle0->Init(O_RDONLY) || handle1->Init(O_WRONLY)) {
232      errno = EACCES;
233      return -1;
234    }
235
236    pipefds[0] = AllocateFD(handle0);
237    pipefds[1] = AllocateFD(handle1);
238    return 0;
239  }
240
241  errno = ENOSYS;
242  return -1;
243}
244
245int KernelProxy::close(int fd) {
246  ScopedKernelHandle handle;
247  Error error = AcquireHandle(fd, &handle);
248  if (error) {
249    errno = error;
250    return -1;
251  }
252
253  // Remove the FD from the process open file descriptor map
254  FreeFD(fd);
255  return 0;
256}
257
258int KernelProxy::dup(int oldfd) {
259  ScopedKernelHandle handle;
260  std::string path;
261  Error error = AcquireHandleAndPath(oldfd, &handle, &path);
262  if (error) {
263    errno = error;
264    return -1;
265  }
266  return AllocateFD(handle, path);
267}
268
269int KernelProxy::dup2(int oldfd, int newfd) {
270  // If it's the same file handle, just return
271  if (oldfd == newfd)
272    return newfd;
273
274  ScopedKernelHandle old_handle;
275  std::string old_path;
276  Error error = AcquireHandleAndPath(oldfd, &old_handle, &old_path);
277  if (error) {
278    errno = error;
279    return -1;
280  }
281
282  FreeAndReassignFD(newfd, old_handle, old_path);
283  return newfd;
284}
285
286int KernelProxy::chdir(const char* path) {
287  Error error = SetCWD(path);
288  if (error) {
289    errno = error;
290    return -1;
291  }
292  return 0;
293}
294
295void KernelProxy::exit(int status) {
296  if (exit_callback_)
297    exit_callback_(status, exit_callback_user_data_);
298}
299
300char* KernelProxy::getcwd(char* buf, size_t size) {
301  if (NULL == buf) {
302    errno = EFAULT;
303    return NULL;
304  }
305
306  std::string cwd = GetCWD();
307
308  // Verify the buffer is large enough
309  if (size <= cwd.size()) {
310    errno = ERANGE;
311    return NULL;
312  }
313
314  strcpy(buf, cwd.c_str());
315  return buf;
316}
317
318char* KernelProxy::getwd(char* buf) {
319  if (NULL == buf) {
320    errno = EFAULT;
321    return NULL;
322  }
323  return getcwd(buf, MAXPATHLEN);
324}
325
326int KernelProxy::chmod(const char* path, mode_t mode) {
327  int fd = open(path, O_RDONLY, mode);
328  if (-1 == fd)
329    return -1;
330
331  int result = fchmod(fd, mode);
332  close(fd);
333  return result;
334}
335
336int KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
337  return 0;
338}
339
340int KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
341  return 0;
342}
343
344int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
345  return 0;
346}
347
348int KernelProxy::mkdir(const char* path, mode_t mode) {
349  ScopedFilesystem fs;
350  Path rel;
351
352  Error error = AcquireFsAndRelPath(path, &fs, &rel);
353  if (error) {
354    errno = error;
355    return -1;
356  }
357
358  error = fs->Mkdir(rel, mode);
359  if (error) {
360    errno = error;
361    return -1;
362  }
363
364  return 0;
365}
366
367int KernelProxy::rmdir(const char* path) {
368  ScopedFilesystem fs;
369  Path rel;
370
371  Error error = AcquireFsAndRelPath(path, &fs, &rel);
372  if (error) {
373    errno = error;
374    return -1;
375  }
376
377  error = fs->Rmdir(rel);
378  if (error) {
379    errno = error;
380    return -1;
381  }
382
383  return 0;
384}
385
386int KernelProxy::stat(const char* path, struct stat* buf) {
387  int fd = open(path, O_RDONLY, 0);
388  if (-1 == fd)
389    return -1;
390
391  int result = fstat(fd, buf);
392  close(fd);
393  return result;
394}
395
396int KernelProxy::mount(const char* source,
397                       const char* target,
398                       const char* filesystemtype,
399                       unsigned long mountflags,
400                       const void* data) {
401  ScopedFilesystem fs;
402  Error error = MountInternal(
403      source, target, filesystemtype, mountflags, data, true, &fs);
404  if (error) {
405    errno = error;
406    return -1;
407  }
408
409  return 0;
410}
411
412Error KernelProxy::MountInternal(const char* source,
413                                 const char* target,
414                                 const char* filesystemtype,
415                                 unsigned long mountflags,
416                                 const void* data,
417                                 bool create_fs_node,
418                                 ScopedFilesystem* out_filesystem) {
419  std::string abs_path = GetAbsParts(target).Join();
420
421  // Find a factory of that type
422  FsFactoryMap_t::iterator factory = factories_.find(filesystemtype);
423  if (factory == factories_.end()) {
424    LOG_ERROR("Unknown filesystem type: %s", filesystemtype);
425    return ENODEV;
426  }
427
428  // Create a map of settings
429  StringMap_t smap;
430  smap["SOURCE"] = source;
431
432  if (data) {
433    std::vector<std::string> elements;
434    sdk_util::SplitString(static_cast<const char*>(data), ',', &elements);
435
436    for (std::vector<std::string>::const_iterator it = elements.begin();
437         it != elements.end();
438         ++it) {
439      size_t location = it->find('=');
440      if (location != std::string::npos) {
441        std::string key = it->substr(0, location);
442        std::string val = it->substr(location + 1);
443        smap[key] = val;
444      } else {
445        smap[*it] = "TRUE";
446      }
447    }
448  }
449
450  FsInitArgs args;
451  args.dev = dev_++;
452  args.string_map = smap;
453  args.ppapi = ppapi_;
454
455  ScopedFilesystem fs;
456  Error error = factory->second->CreateFilesystem(args, &fs);
457  if (error)
458    return error;
459
460  error = AttachFsAtPath(fs, abs_path);
461  if (error)
462    return error;
463
464  if (create_fs_node) {
465    error = CreateFsNode(fs);
466    if (error) {
467      DetachFsAtPath(abs_path, &fs);
468      return error;
469    }
470  }
471
472  *out_filesystem = fs;
473
474  if (mount_callback_) {
475    mount_callback_(source,
476                    target,
477                    filesystemtype,
478                    mountflags,
479                    data,
480                    fs->dev(),
481                    mount_callback_user_data_);
482  }
483
484  return 0;
485}
486
487Error KernelProxy::CreateFsNode(const ScopedFilesystem& fs) {
488  assert(dev_fs_);
489
490  return dev_fs_->CreateFsNode(fs.get());
491}
492
493int KernelProxy::umount(const char* path) {
494  ScopedFilesystem fs;
495  Error error = DetachFsAtPath(path, &fs);
496  if (error) {
497    errno = error;
498    return -1;
499  }
500
501  error = dev_fs_->DestroyFsNode(fs.get());
502  if (error) {
503    // Ignore any errors here, just log.
504    LOG_ERROR("Unable to destroy FsNode: %s", strerror(error));
505  }
506  return 0;
507}
508
509ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
510  ScopedKernelHandle handle;
511  Error error = AcquireHandle(fd, &handle);
512  if (error) {
513    errno = error;
514    return -1;
515  }
516
517  int cnt = 0;
518  error = handle->Read(buf, nbytes, &cnt);
519  if (error) {
520    errno = error;
521    return -1;
522  }
523
524  return cnt;
525}
526
527ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
528  ScopedKernelHandle handle;
529  Error error = AcquireHandle(fd, &handle);
530  if (error) {
531    errno = error;
532    return -1;
533  }
534
535  int cnt = 0;
536  error = handle->Write(buf, nbytes, &cnt);
537  if (error) {
538    errno = error;
539    return -1;
540  }
541
542  return cnt;
543}
544
545int KernelProxy::fstat(int fd, struct stat* buf) {
546  ScopedKernelHandle handle;
547  Error error = AcquireHandle(fd, &handle);
548  if (error) {
549    errno = error;
550    return -1;
551  }
552
553  error = handle->node()->GetStat(buf);
554  if (error) {
555    errno = error;
556    return -1;
557  }
558
559  return 0;
560}
561
562int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
563  ScopedKernelHandle handle;
564  Error error = AcquireHandle(fd, &handle);
565  if (error) {
566    errno = error;
567    return -1;
568  }
569
570  int cnt = 0;
571  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
572  if (error)
573    errno = error;
574
575  return cnt;
576}
577
578int KernelProxy::fchdir(int fd) {
579  ScopedKernelHandle handle;
580  std::string path;
581  Error error = AcquireHandleAndPath(fd, &handle, &path);
582  if (error) {
583    errno = error;
584    return -1;
585  }
586
587  if (!handle->node()->IsaDir()) {
588    errno = ENOTDIR;
589    return -1;
590  }
591
592  if (path.empty()) {
593    errno = EBADF;
594    return -1;
595  }
596
597  error = SetCWD(path);
598  if (error) {
599    // errno is return value from SetCWD
600    errno = error;
601    return -1;
602  }
603  return 0;
604}
605
606int KernelProxy::ftruncate(int fd, off_t length) {
607  ScopedKernelHandle handle;
608  Error error = AcquireHandle(fd, &handle);
609  if (error) {
610    errno = error;
611    return -1;
612  }
613
614  error = handle->node()->FTruncate(length);
615  if (error) {
616    errno = error;
617    return -1;
618  }
619
620  return 0;
621}
622
623int KernelProxy::fsync(int fd) {
624  ScopedKernelHandle handle;
625  Error error = AcquireHandle(fd, &handle);
626  if (error) {
627    errno = error;
628    return -1;
629  }
630
631  error = handle->node()->FSync();
632  if (error) {
633    errno = error;
634    return -1;
635  }
636
637  return 0;
638}
639
640int KernelProxy::fdatasync(int fd) {
641  errno = ENOSYS;
642  return -1;
643}
644
645int KernelProxy::isatty(int fd) {
646  ScopedKernelHandle handle;
647  Error error = AcquireHandle(fd, &handle);
648  if (error) {
649    errno = error;
650    return 0;
651  }
652
653  error = handle->node()->Isatty();
654  if (error) {
655    errno = error;
656    return 0;
657  }
658
659  return 1;
660}
661
662int KernelProxy::ioctl(int fd, int request, va_list args) {
663  ScopedKernelHandle handle;
664  Error error = AcquireHandle(fd, &handle);
665  if (error) {
666    errno = error;
667    return -1;
668  }
669
670  error = handle->node()->VIoctl(request, args);
671  if (error) {
672    errno = error;
673    return -1;
674  }
675
676  return 0;
677}
678
679int KernelProxy::futimens(int fd, const struct timespec times[2]) {
680  ScopedKernelHandle handle;
681  Error error = AcquireHandle(fd, &handle);
682  if (error) {
683    errno = error;
684    return -1;
685  }
686
687  error = handle->node()->Futimens(times);
688  if (error) {
689    errno = error;
690    return -1;
691  }
692
693  return 0;
694}
695
696off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
697  ScopedKernelHandle handle;
698  Error error = AcquireHandle(fd, &handle);
699  if (error) {
700    errno = error;
701    return -1;
702  }
703
704  off_t new_offset;
705  error = handle->Seek(offset, whence, &new_offset);
706  if (error) {
707    errno = error;
708    return -1;
709  }
710
711  return new_offset;
712}
713
714int KernelProxy::unlink(const char* path) {
715  ScopedFilesystem fs;
716  Path rel;
717
718  Error error = AcquireFsAndRelPath(path, &fs, &rel);
719  if (error) {
720    errno = error;
721    return -1;
722  }
723
724  error = fs->Unlink(rel);
725  if (error) {
726    errno = error;
727    return -1;
728  }
729
730  return 0;
731}
732
733int KernelProxy::truncate(const char* path, off_t len) {
734  int fd = open(path, O_WRONLY, 0);
735  if (-1 == fd)
736    return -1;
737
738  int result = ftruncate(fd, len);
739  close(fd);
740  return result;
741}
742
743int KernelProxy::lstat(const char* path, struct stat* buf) {
744  return stat(path, buf);
745}
746
747int KernelProxy::rename(const char* path, const char* newpath) {
748  ScopedFilesystem fs;
749  Path rel;
750  Error error = AcquireFsAndRelPath(path, &fs, &rel);
751  if (error) {
752    errno = error;
753    return -1;
754  }
755
756  ScopedFilesystem newfs;
757  Path newrel;
758  error = AcquireFsAndRelPath(newpath, &newfs, &newrel);
759  if (error) {
760    errno = error;
761    return -1;
762  }
763
764  if (newfs.get() != fs.get()) {
765    // Renaming accross mountpoints is not allowed
766    errno = EXDEV;
767    return -1;
768  }
769
770  // They already point to the same path
771  if (rel == newrel)
772    return 0;
773
774  error = fs->Rename(rel, newrel);
775  if (error) {
776    errno = error;
777    return -1;
778  }
779
780  return 0;
781}
782
783int KernelProxy::remove(const char* path) {
784  ScopedFilesystem fs;
785  Path rel;
786
787  Error error = AcquireFsAndRelPath(path, &fs, &rel);
788  if (error) {
789    errno = error;
790    return -1;
791  }
792
793  error = fs->Remove(rel);
794  if (error) {
795    errno = error;
796    return -1;
797  }
798
799  return 0;
800}
801
802int KernelProxy::fchmod(int fd, mode_t mode) {
803  ScopedKernelHandle handle;
804  Error error = AcquireHandle(fd, &handle);
805  if (error) {
806    errno = error;
807    return -1;
808  }
809
810  error = handle->node()->Fchmod(mode);
811  if (error) {
812    errno = error;
813    return -1;
814  }
815
816  return 0;
817}
818
819int KernelProxy::fcntl(int fd, int request, va_list args) {
820  Error error = 0;
821
822  // F_GETFD and F_SETFD are descriptor specific flags that
823  // are stored in the KernelObject's decriptor map unlike
824  // F_GETFL and F_SETFL which are handle specific.
825  switch (request) {
826    case F_GETFD: {
827      int rtn = -1;
828      error = GetFDFlags(fd, &rtn);
829      if (error) {
830        errno = error;
831        return -1;
832      }
833      return rtn;
834    }
835    case F_SETFD: {
836      int flags = va_arg(args, int);
837      error = SetFDFlags(fd, flags);
838      if (error) {
839        errno = error;
840        return -1;
841      }
842      return 0;
843    }
844  }
845
846  ScopedKernelHandle handle;
847  error = AcquireHandle(fd, &handle);
848  if (error) {
849    errno = error;
850    return -1;
851  }
852
853  int rtn = 0;
854  error = handle->VFcntl(request, &rtn, args);
855  if (error) {
856    errno = error;
857    return -1;
858  }
859
860  return rtn;
861}
862
863int KernelProxy::access(const char* path, int amode) {
864  struct stat buf;
865  int rtn = stat(path, &buf);
866  if (rtn != 0)
867    return rtn;
868
869  if (((amode & R_OK) && !(buf.st_mode & S_IREAD)) ||
870      ((amode & W_OK) && !(buf.st_mode & S_IWRITE)) ||
871      ((amode & X_OK) && !(buf.st_mode & S_IEXEC))) {
872    errno = EACCES;
873    return -1;
874  }
875
876  return 0;
877}
878
879int KernelProxy::readlink(const char* path, char* buf, size_t count) {
880  LOG_TRACE("readlink is not implemented.");
881  errno = EINVAL;
882  return -1;
883}
884
885int KernelProxy::utimens(const char* path, const struct timespec times[2]) {
886  int fd = open(path, O_RDONLY, 0);
887  if (-1 == fd)
888    return -1;
889
890  int result = futimens(fd, times);
891  close(fd);
892  return result;
893}
894
895// TODO(noelallen): Needs implementation.
896int KernelProxy::link(const char* oldpath, const char* newpath) {
897  LOG_TRACE("link is not implemented.");
898  errno = EINVAL;
899  return -1;
900}
901
902int KernelProxy::symlink(const char* oldpath, const char* newpath) {
903  LOG_TRACE("symlink is not implemented.");
904  errno = EINVAL;
905  return -1;
906}
907
908void* KernelProxy::mmap(void* addr,
909                        size_t length,
910                        int prot,
911                        int flags,
912                        int fd,
913                        size_t offset) {
914  // We shouldn't be getting anonymous mmaps here.
915  assert((flags & MAP_ANONYMOUS) == 0);
916  assert(fd != -1);
917
918  ScopedKernelHandle handle;
919  Error error = AcquireHandle(fd, &handle);
920  if (error) {
921    errno = error;
922    return MAP_FAILED;
923  }
924
925  void* new_addr;
926  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
927  if (error) {
928    errno = error;
929    return MAP_FAILED;
930  }
931
932  return new_addr;
933}
934
935int KernelProxy::munmap(void* addr, size_t length) {
936  // NOTE: The comment below is from a previous discarded implementation that
937  // tracks mmap'd regions. For simplicity, we no longer do this; because we
938  // "snapshot" the contents of the file in mmap(), and don't support
939  // write-back or updating the mapped region when the file is written, holding
940  // on to the KernelHandle is pointless.
941  //
942  // If we ever do, these threading issues should be considered.
943
944  //
945  // WARNING: this function may be called by free().
946  //
947  // There is a potential deadlock scenario:
948  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
949  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
950  //
951  // Note that open() above could be any function that takes a lock that is
952  // shared with munmap (this includes munmap!)
953  //
954  // To prevent this, we avoid taking locks in munmap() that are used by other
955  // nacl_io functions that may call free. Specifically, we only take the
956  // mmap_lock, which is only shared with mmap() above. There is still a
957  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
958  // allowed.
959  //
960  // Unfortunately, munmap still needs to acquire other locks; see the call to
961  // ReleaseHandle below which takes the process lock. This is safe as long as
962  // this is never executed from free() -- we can be reasonably sure this is
963  // true, because malloc only makes anonymous mmap() requests, and should only
964  // be munmapping those allocations. We never add to mmap_info_list_ for
965  // anonymous maps, so the unmap_list should always be empty when called from
966  // free().
967  return 0;
968}
969
970int KernelProxy::tcflush(int fd, int queue_selector) {
971  ScopedKernelHandle handle;
972  Error error = AcquireHandle(fd, &handle);
973  if (error) {
974    errno = error;
975    return -1;
976  }
977
978  error = handle->node()->Tcflush(queue_selector);
979  if (error) {
980    errno = error;
981    return -1;
982  }
983
984  return 0;
985}
986
987int KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
988  ScopedKernelHandle handle;
989  Error error = AcquireHandle(fd, &handle);
990  if (error) {
991    errno = error;
992    return -1;
993  }
994
995  error = handle->node()->Tcgetattr(termios_p);
996  if (error) {
997    errno = error;
998    return -1;
999  }
1000
1001  return 0;
1002}
1003
1004int KernelProxy::tcsetattr(int fd,
1005                           int optional_actions,
1006                           const struct termios* termios_p) {
1007  ScopedKernelHandle handle;
1008  Error error = AcquireHandle(fd, &handle);
1009  if (error) {
1010    errno = error;
1011    return -1;
1012  }
1013
1014  error = handle->node()->Tcsetattr(optional_actions, termios_p);
1015  if (error) {
1016    errno = error;
1017    return -1;
1018  }
1019
1020  return 0;
1021}
1022
1023int KernelProxy::kill(pid_t pid, int sig) {
1024  // Currently we don't even pretend that other processes exist
1025  // so we can only send a signal to outselves.  For kill(2)
1026  // pid 0 means the current process group and -1 means all the
1027  // processes we have permission to send signals to.
1028  if (pid != getpid() && pid != -1 && pid != 0) {
1029    errno = ESRCH;
1030    return -1;
1031  }
1032
1033  // Raise an event so that select/poll get interrupted.
1034  AUTO_LOCK(signal_emitter_->GetLock())
1035  signal_emitter_->RaiseEvents_Locked(POLLERR);
1036  switch (sig) {
1037    case SIGWINCH:
1038      if (sigwinch_handler_.sa_handler != SIG_IGN &&
1039          sigwinch_handler_.sa_handler != SIG_DFL) {
1040        sigwinch_handler_.sa_handler(SIGWINCH);
1041      }
1042      break;
1043
1044    case SIGUSR1:
1045    case SIGUSR2:
1046      break;
1047
1048    default:
1049      LOG_TRACE("Unsupported signal: %d", sig);
1050      errno = EINVAL;
1051      return -1;
1052  }
1053  return 0;
1054}
1055
1056int KernelProxy::sigaction(int signum,
1057                           const struct sigaction* action,
1058                           struct sigaction* oaction) {
1059  if (action && action->sa_flags & SA_SIGINFO) {
1060    // We don't support SA_SIGINFO (sa_sigaction field) yet
1061    errno = EINVAL;
1062    return -1;
1063  }
1064
1065  switch (signum) {
1066    // Handled signals.
1067    case SIGWINCH: {
1068      if (oaction)
1069        *oaction = sigwinch_handler_;
1070      if (action) {
1071        sigwinch_handler_ = *action;
1072      }
1073      return 0;
1074    }
1075
1076    // Known signals
1077    case SIGHUP:
1078    case SIGINT:
1079    case SIGPIPE:
1080    case SIGPOLL:
1081    case SIGPROF:
1082    case SIGTERM:
1083    case SIGCHLD:
1084    case SIGURG:
1085    case SIGFPE:
1086    case SIGILL:
1087    case SIGQUIT:
1088    case SIGSEGV:
1089    case SIGTRAP:
1090      if (action && action->sa_handler != SIG_DFL) {
1091        // Trying to set this action to anything other than SIG_DFL
1092        // is not yet supported.
1093        LOG_TRACE("sigaction on signal %d != SIG_DFL not supported.", sig);
1094        errno = EINVAL;
1095        return -1;
1096      }
1097
1098      if (oaction) {
1099        memset(oaction, 0, sizeof(*oaction));
1100        oaction->sa_handler = SIG_DFL;
1101      }
1102      return 0;
1103
1104    // KILL and STOP cannot be handled
1105    case SIGKILL:
1106    case SIGSTOP:
1107      LOG_TRACE("sigaction on SIGKILL/SIGSTOP not supported.");
1108      errno = EINVAL;
1109      return -1;
1110  }
1111
1112  // Unknown signum
1113  errno = EINVAL;
1114  return -1;
1115}
1116
1117#ifdef PROVIDES_SOCKET_API
1118
1119int KernelProxy::select(int nfds,
1120                        fd_set* readfds,
1121                        fd_set* writefds,
1122                        fd_set* exceptfds,
1123                        struct timeval* timeout) {
1124  std::vector<pollfd> pollfds;
1125
1126  for (int fd = 0; fd < nfds; fd++) {
1127    int events = 0;
1128    if (readfds && FD_ISSET(fd, readfds)) {
1129      events |= POLLIN;
1130      FD_CLR(fd, readfds);
1131    }
1132
1133    if (writefds && FD_ISSET(fd, writefds)) {
1134      events |= POLLOUT;
1135      FD_CLR(fd, writefds);
1136    }
1137
1138    if (exceptfds && FD_ISSET(fd, exceptfds)) {
1139      events |= POLLERR | POLLHUP;
1140      FD_CLR(fd, exceptfds);
1141    }
1142
1143    if (events) {
1144      pollfd info;
1145      info.fd = fd;
1146      info.events = events;
1147      pollfds.push_back(info);
1148    }
1149  }
1150
1151  // NULL timeout signals wait forever.
1152  int ms_timeout = -1;
1153  if (timeout != NULL) {
1154    int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
1155
1156    // If the timeout is invalid or too long (larger than signed 32 bit).
1157    if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
1158        (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000000) || (ms < 0) ||
1159        (ms >= INT_MAX)) {
1160      LOG_TRACE("Invalid timeout: tv_sec=%d tv_usec=%d.",
1161                timeout->tv_sec,
1162                timeout->tv_usec);
1163      errno = EINVAL;
1164      return -1;
1165    }
1166
1167    ms_timeout = static_cast<int>(ms);
1168  }
1169
1170  int result = poll(&pollfds[0], pollfds.size(), ms_timeout);
1171  if (result == -1)
1172    return -1;
1173
1174  int event_cnt = 0;
1175  for (size_t index = 0; index < pollfds.size(); index++) {
1176    pollfd* info = &pollfds[index];
1177    if (info->revents & POLLIN) {
1178      FD_SET(info->fd, readfds);
1179      event_cnt++;
1180    }
1181    if (info->revents & POLLOUT) {
1182      FD_SET(info->fd, writefds);
1183      event_cnt++;
1184    }
1185    if (info->revents & (POLLHUP | POLLERR)) {
1186      FD_SET(info->fd, exceptfds);
1187      event_cnt++;
1188    }
1189  }
1190
1191  return event_cnt;
1192}
1193
1194struct PollInfo {
1195  PollInfo() : index(-1) {};
1196
1197  std::vector<struct pollfd*> fds;
1198  int index;
1199};
1200
1201typedef std::map<EventEmitter*, PollInfo> EventPollMap_t;
1202
1203int KernelProxy::poll(struct pollfd* fds, nfds_t nfds, int timeout) {
1204  EventPollMap_t event_map;
1205
1206  std::vector<EventRequest> requests;
1207  size_t event_cnt = 0;
1208
1209  for (int index = 0; static_cast<nfds_t>(index) < nfds; index++) {
1210    ScopedKernelHandle handle;
1211    struct pollfd* fd_info = &fds[index];
1212    Error err = AcquireHandle(fd_info->fd, &handle);
1213
1214    fd_info->revents = 0;
1215
1216    // If the node isn't open, or somehow invalid, mark it so.
1217    if (err != 0) {
1218      fd_info->revents = POLLNVAL;
1219      event_cnt++;
1220      continue;
1221    }
1222
1223    // If it's already signaled, then just capture the event
1224    ScopedEventEmitter emitter(handle->node()->GetEventEmitter());
1225    int events = POLLIN | POLLOUT;
1226    if (emitter)
1227      events = emitter->GetEventStatus();
1228
1229    if (events & fd_info->events) {
1230      fd_info->revents = events & fd_info->events;
1231      event_cnt++;
1232      continue;
1233    }
1234
1235    if (NULL == emitter) {
1236      fd_info->revents = POLLNVAL;
1237      event_cnt++;
1238      continue;
1239    }
1240
1241    // Otherwise try to track it.
1242    PollInfo* info = &event_map[emitter.get()];
1243    if (info->index == -1) {
1244      EventRequest request;
1245      request.emitter = emitter;
1246      request.filter = fd_info->events;
1247      request.events = 0;
1248
1249      info->index = requests.size();
1250      requests.push_back(request);
1251    }
1252    info->fds.push_back(fd_info);
1253    requests[info->index].filter |= fd_info->events;
1254  }
1255
1256  // If nothing is signaled, then we must wait on the event map
1257  if (0 == event_cnt) {
1258    EventListenerPoll wait;
1259    Error err = wait.WaitOnAny(&requests[0], requests.size(), timeout);
1260    if ((err != 0) && (err != ETIMEDOUT)) {
1261      errno = err;
1262      return -1;
1263    }
1264
1265    for (size_t rindex = 0; rindex < requests.size(); rindex++) {
1266      EventRequest* request = &requests[rindex];
1267      if (request->events) {
1268        PollInfo* poll_info = &event_map[request->emitter.get()];
1269        for (size_t findex = 0; findex < poll_info->fds.size(); findex++) {
1270          struct pollfd* fd_info = poll_info->fds[findex];
1271          uint32_t events = fd_info->events & request->events;
1272          if (events) {
1273            fd_info->revents = events;
1274            event_cnt++;
1275          }
1276        }
1277      }
1278    }
1279  }
1280
1281  return event_cnt;
1282}
1283
1284// Socket Functions
1285int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
1286  if (NULL == addr || NULL == len) {
1287    errno = EFAULT;
1288    return -1;
1289  }
1290
1291  ScopedKernelHandle handle;
1292  Error error = AcquireHandle(fd, &handle);
1293  if (error) {
1294    errno = error;
1295    return -1;
1296  }
1297
1298  PP_Resource new_sock = 0;
1299  error = handle->Accept(&new_sock, addr, len);
1300  if (error != 0) {
1301    errno = error;
1302    return -1;
1303  }
1304
1305  SocketNode* sock = new TcpNode(stream_fs_.get(), new_sock);
1306
1307  // The SocketNode now holds a reference to the new socket
1308  // so we release ours.
1309  ppapi_->ReleaseResource(new_sock);
1310  error = sock->Init(O_RDWR);
1311  if (error != 0) {
1312    errno = error;
1313    return -1;
1314  }
1315
1316  ScopedNode node(sock);
1317  ScopedKernelHandle new_handle(new KernelHandle(stream_fs_, node));
1318  error = new_handle->Init(O_RDWR);
1319  if (error != 0) {
1320    errno = error;
1321    return -1;
1322  }
1323
1324  return AllocateFD(new_handle);
1325}
1326
1327int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
1328  if (NULL == addr) {
1329    errno = EFAULT;
1330    return -1;
1331  }
1332
1333  ScopedKernelHandle handle;
1334  if (AcquireSocketHandle(fd, &handle) == -1)
1335    return -1;
1336
1337  Error err = handle->socket_node()->Bind(addr, len);
1338  if (err != 0) {
1339    errno = err;
1340    return -1;
1341  }
1342
1343  return 0;
1344}
1345
1346int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
1347  if (NULL == addr) {
1348    errno = EFAULT;
1349    return -1;
1350  }
1351
1352  ScopedKernelHandle handle;
1353  Error error = AcquireHandle(fd, &handle);
1354  if (error) {
1355    errno = error;
1356    return -1;
1357  }
1358
1359  error = handle->Connect(addr, len);
1360  if (error != 0) {
1361    errno = error;
1362    return -1;
1363  }
1364
1365  return 0;
1366}
1367
1368void KernelProxy::freeaddrinfo(struct addrinfo* res) {
1369  return host_resolver_.freeaddrinfo(res);
1370}
1371
1372int KernelProxy::getaddrinfo(const char* node,
1373                             const char* service,
1374                             const struct addrinfo* hints,
1375                             struct addrinfo** res) {
1376  return host_resolver_.getaddrinfo(node, service, hints, res);
1377}
1378
1379int KernelProxy::getnameinfo(const struct sockaddr *sa,
1380                             socklen_t salen,
1381                             char *host,
1382                             size_t hostlen,
1383                             char *serv,
1384                             size_t servlen,
1385                             int flags) {
1386  return host_resolver_.getnameinfo(sa, salen, host, hostlen, serv, servlen,
1387                                    flags);
1388}
1389
1390struct hostent* KernelProxy::gethostbyname(const char* name) {
1391  return host_resolver_.gethostbyname(name);
1392}
1393
1394int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
1395  if (NULL == addr || NULL == len) {
1396    errno = EFAULT;
1397    return -1;
1398  }
1399
1400  ScopedKernelHandle handle;
1401  if (AcquireSocketHandle(fd, &handle) == -1)
1402    return -1;
1403
1404  Error err = handle->socket_node()->GetPeerName(addr, len);
1405  if (err != 0) {
1406    errno = err;
1407    return -1;
1408  }
1409
1410  return 0;
1411}
1412
1413int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
1414  if (NULL == addr || NULL == len) {
1415    errno = EFAULT;
1416    return -1;
1417  }
1418
1419  ScopedKernelHandle handle;
1420  if (AcquireSocketHandle(fd, &handle) == -1)
1421    return -1;
1422
1423  Error err = handle->socket_node()->GetSockName(addr, len);
1424  if (err != 0) {
1425    errno = err;
1426    return -1;
1427  }
1428
1429  return 0;
1430}
1431
1432int KernelProxy::getsockopt(int fd,
1433                            int lvl,
1434                            int optname,
1435                            void* optval,
1436                            socklen_t* len) {
1437  if (NULL == optval || NULL == len) {
1438    errno = EFAULT;
1439    return -1;
1440  }
1441
1442  ScopedKernelHandle handle;
1443  if (AcquireSocketHandle(fd, &handle) == -1)
1444    return -1;
1445
1446  Error err = handle->socket_node()->GetSockOpt(lvl, optname, optval, len);
1447  if (err != 0) {
1448    errno = err;
1449    return -1;
1450  }
1451
1452  return 0;
1453}
1454
1455int KernelProxy::listen(int fd, int backlog) {
1456  ScopedKernelHandle handle;
1457  if (AcquireSocketHandle(fd, &handle) == -1)
1458    return -1;
1459
1460  Error err = handle->socket_node()->Listen(backlog);
1461  if (err != 0) {
1462    errno = err;
1463    return -1;
1464  }
1465
1466  return 0;
1467}
1468
1469ssize_t KernelProxy::recv(int fd, void* buf, size_t len, int flags) {
1470  if (NULL == buf) {
1471    errno = EFAULT;
1472    return -1;
1473  }
1474
1475  ScopedKernelHandle handle;
1476  Error error = AcquireHandle(fd, &handle);
1477  if (error) {
1478    errno = error;
1479    return -1;
1480  }
1481
1482  int out_len = 0;
1483  error = handle->Recv(buf, len, flags, &out_len);
1484  if (error != 0) {
1485    errno = error;
1486    return -1;
1487  }
1488
1489  return static_cast<ssize_t>(out_len);
1490}
1491
1492ssize_t KernelProxy::recvfrom(int fd,
1493                              void* buf,
1494                              size_t len,
1495                              int flags,
1496                              struct sockaddr* addr,
1497                              socklen_t* addrlen) {
1498  // According to the manpage, recvfrom with a null addr is identical to recv.
1499  if (NULL == addr) {
1500    return recv(fd, buf, len, flags);
1501  }
1502
1503  if (NULL == buf || NULL == addrlen) {
1504    errno = EFAULT;
1505    return -1;
1506  }
1507
1508  ScopedKernelHandle handle;
1509  Error error = AcquireHandle(fd, &handle);
1510  if (error) {
1511    errno = error;
1512    return -1;
1513  }
1514
1515  int out_len = 0;
1516  error = handle->RecvFrom(buf, len, flags, addr, addrlen, &out_len);
1517  if (error != 0) {
1518    errno = error;
1519    return -1;
1520  }
1521
1522  return static_cast<ssize_t>(out_len);
1523}
1524
1525ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1526  if (NULL == msg) {
1527    errno = EFAULT;
1528    return -1;
1529  }
1530
1531  ScopedKernelHandle handle;
1532  if (AcquireSocketHandle(fd, &handle) == -1)
1533    return -1;
1534
1535  errno = EOPNOTSUPP;
1536  return -1;
1537}
1538
1539ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1540  if (NULL == buf) {
1541    errno = EFAULT;
1542    return -1;
1543  }
1544
1545  ScopedKernelHandle handle;
1546  Error error = AcquireHandle(fd, &handle);
1547  if (error) {
1548    errno = error;
1549    return -1;
1550  }
1551
1552  int out_len = 0;
1553  error = handle->Send(buf, len, flags, &out_len);
1554  if (error != 0) {
1555    errno = error;
1556    return -1;
1557  }
1558
1559  return static_cast<ssize_t>(out_len);
1560}
1561
1562ssize_t KernelProxy::sendto(int fd,
1563                            const void* buf,
1564                            size_t len,
1565                            int flags,
1566                            const struct sockaddr* addr,
1567                            socklen_t addrlen) {
1568  // According to the manpage, sendto with a null addr is identical to send.
1569  if (NULL == addr) {
1570    return send(fd, buf, len, flags);
1571  }
1572
1573  if (NULL == buf) {
1574    errno = EFAULT;
1575    return -1;
1576  }
1577
1578  ScopedKernelHandle handle;
1579  Error error = AcquireHandle(fd, &handle);
1580  if (error) {
1581    errno = error;
1582    return -1;
1583  }
1584
1585  int out_len = 0;
1586  error = handle->SendTo(buf, len, flags, addr, addrlen, &out_len);
1587  if (error != 0) {
1588    errno = error;
1589    return -1;
1590  }
1591
1592  return static_cast<ssize_t>(out_len);
1593}
1594
1595ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1596  if (NULL == msg) {
1597    errno = EFAULT;
1598    return -1;
1599  }
1600
1601  ScopedKernelHandle handle;
1602  if (AcquireSocketHandle(fd, &handle) == -1)
1603    return -1;
1604
1605  errno = EOPNOTSUPP;
1606  return -1;
1607}
1608
1609int KernelProxy::setsockopt(int fd,
1610                            int lvl,
1611                            int optname,
1612                            const void* optval,
1613                            socklen_t len) {
1614  if (NULL == optval) {
1615    errno = EFAULT;
1616    return -1;
1617  }
1618
1619  ScopedKernelHandle handle;
1620  if (AcquireSocketHandle(fd, &handle) == -1)
1621    return -1;
1622
1623  Error err = handle->socket_node()->SetSockOpt(lvl, optname, optval, len);
1624  if (err != 0) {
1625    errno = err;
1626    return -1;
1627  }
1628
1629  return 0;
1630}
1631
1632int KernelProxy::shutdown(int fd, int how) {
1633  ScopedKernelHandle handle;
1634  if (AcquireSocketHandle(fd, &handle) == -1)
1635    return -1;
1636
1637  Error err = handle->socket_node()->Shutdown(how);
1638  if (err != 0) {
1639    errno = err;
1640    return -1;
1641  }
1642
1643  return 0;
1644}
1645
1646int KernelProxy::socket(int domain, int type, int protocol) {
1647  if (AF_INET != domain && AF_INET6 != domain) {
1648    errno = EAFNOSUPPORT;
1649    return -1;
1650  }
1651
1652  int open_flags = O_RDWR;
1653
1654  if (type & SOCK_CLOEXEC) {
1655#ifdef O_CLOEXEC
1656    // The NaCl newlib version of fcntl.h doesn't currently define
1657    // O_CLOEXEC.
1658    // TODO(sbc): remove this guard once it gets added.
1659    open_flags |= O_CLOEXEC;
1660#endif
1661    type &= ~SOCK_CLOEXEC;
1662  }
1663
1664  if (type & SOCK_NONBLOCK) {
1665    open_flags |= O_NONBLOCK;
1666    type &= ~SOCK_NONBLOCK;
1667  }
1668
1669  SocketNode* sock = NULL;
1670  switch (type) {
1671    case SOCK_DGRAM:
1672      sock = new UdpNode(stream_fs_.get());
1673      break;
1674
1675    case SOCK_STREAM:
1676      sock = new TcpNode(stream_fs_.get());
1677      break;
1678
1679    case SOCK_SEQPACKET:
1680    case SOCK_RDM:
1681    case SOCK_RAW:
1682      errno = EPROTONOSUPPORT;
1683      return -1;
1684
1685    default:
1686      errno = EINVAL;
1687      return -1;
1688  }
1689
1690  ScopedNode node(sock);
1691  Error rtn = sock->Init(O_RDWR);
1692  if (rtn != 0) {
1693    errno = rtn;
1694    return -1;
1695  }
1696
1697  ScopedKernelHandle handle(new KernelHandle(stream_fs_, node));
1698  rtn = handle->Init(open_flags);
1699  if (rtn != 0) {
1700    errno = rtn;
1701    return -1;
1702  }
1703
1704  return AllocateFD(handle);
1705}
1706
1707int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1708  if (NULL == sv) {
1709    errno = EFAULT;
1710    return -1;
1711  }
1712
1713  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1714  // socket pairs. Thus, this function always fails.
1715  if (AF_UNIX != domain) {
1716    errno = EPROTONOSUPPORT;
1717    return -1;
1718  }
1719
1720  if (AF_INET != domain && AF_INET6 != domain) {
1721    errno = EAFNOSUPPORT;
1722    return -1;
1723  }
1724
1725  // We cannot reach this point.
1726  errno = ENOSYS;
1727  return -1;
1728}
1729
1730int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1731  Error error = AcquireHandle(fd, handle);
1732
1733  if (error) {
1734    errno = error;
1735    return -1;
1736  }
1737
1738  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1739    errno = ENOTSOCK;
1740    return -1;
1741  }
1742
1743  return 0;
1744}
1745
1746#endif  // PROVIDES_SOCKET_API
1747
1748}  // namespace_nacl_io
1749