kernel_proxy.cc revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
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
8#include <assert.h>
9#include <errno.h>
10#include <fcntl.h>
11#include <limits.h>
12#include <poll.h>
13#include <pthread.h>
14#include <stdio.h>
15#include <string.h>
16#include <sys/time.h>
17
18#include <iterator>
19#include <string>
20
21#include "nacl_io/host_resolver.h"
22#include "nacl_io/kernel_handle.h"
23#include "nacl_io/kernel_wrap_real.h"
24#include "nacl_io/mount.h"
25#include "nacl_io/mount_dev.h"
26#include "nacl_io/mount_html5fs.h"
27#include "nacl_io/mount_http.h"
28#include "nacl_io/mount_mem.h"
29#include "nacl_io/mount_node.h"
30#include "nacl_io/mount_passthrough.h"
31#include "nacl_io/osmman.h"
32#include "nacl_io/ossocket.h"
33#include "nacl_io/osstat.h"
34#include "nacl_io/path.h"
35#include "nacl_io/pepper_interface.h"
36#include "nacl_io/typed_mount_factory.h"
37#include "sdk_util/auto_lock.h"
38#include "sdk_util/ref_object.h"
39
40#ifndef MAXPATHLEN
41#define MAXPATHLEN 256
42#endif
43
44namespace nacl_io {
45
46KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL) {
47}
48
49KernelProxy::~KernelProxy() {
50  // Clean up the MountFactories.
51  for (MountFactoryMap_t::iterator i = factories_.begin();
52       i != factories_.end();
53       ++i) {
54    delete i->second;
55  }
56
57  delete ppapi_;
58}
59
60void KernelProxy::Init(PepperInterface* ppapi) {
61  ppapi_ = ppapi;
62  dev_ = 1;
63
64  factories_["memfs"] = new TypedMountFactory<MountMem>;
65  factories_["dev"] = new TypedMountFactory<MountDev>;
66  factories_["html5fs"] = new TypedMountFactory<MountHtml5Fs>;
67  factories_["httpfs"] = new TypedMountFactory<MountHttp>;
68  factories_["passthroughfs"] = new TypedMountFactory<MountPassthrough>;
69
70  int result;
71  result = mount("", "/", "passthroughfs", 0, NULL);
72  assert(result == 0);
73
74  result = mount("", "/dev", "dev", 0, NULL);
75  assert(result == 0);
76
77  // Open the first three in order to get STDIN, STDOUT, STDERR
78  open("/dev/stdin", O_RDONLY);
79  open("/dev/stdout", O_WRONLY);
80  open("/dev/stderr", O_WRONLY);
81
82#ifdef PROVIDES_SOCKET_API
83  host_resolver_.Init(ppapi_);
84#endif
85}
86
87int KernelProxy::open_resource(const char* path) {
88  ScopedMount mnt;
89  Path rel;
90
91  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
92  if (error) {
93    errno = error;
94    return -1;
95  }
96
97  ScopedMountNode node;
98  error = mnt->OpenResource(rel, &node);
99  if (error) {
100    // OpenResource failed, try Open().
101    error = mnt->Open(rel, O_RDONLY, &node);
102    if (error) {
103      errno = error;
104      return -1;
105    }
106  }
107
108  ScopedKernelHandle handle(new KernelHandle(mnt, node));
109  error = handle->Init(O_RDONLY);
110  if (error) {
111    errno = error;
112    return -1;
113  }
114
115  return AllocateFD(handle);
116}
117
118int KernelProxy::open(const char* path, int oflags) {
119  ScopedMount mnt;
120  ScopedMountNode node;
121
122  Error error = AcquireMountAndNode(path, oflags, &mnt, &node);
123  if (error) {
124    errno = error;
125    return -1;
126  }
127
128  ScopedKernelHandle handle(new KernelHandle(mnt, node));
129  error = handle->Init(oflags);
130  if (error) {
131    errno = error;
132    return -1;
133  }
134
135  return AllocateFD(handle);
136}
137
138int KernelProxy::close(int fd) {
139  ScopedKernelHandle handle;
140  Error error = AcquireHandle(fd, &handle);
141  if (error) {
142    errno = error;
143    return -1;
144  }
145
146  // Remove the FD from the process open file descriptor map
147  FreeFD(fd);
148  return 0;
149}
150
151int KernelProxy::dup(int oldfd) {
152  ScopedKernelHandle handle;
153  Error error = AcquireHandle(oldfd, &handle);
154  if (error) {
155    errno = error;
156    return -1;
157  }
158
159  return AllocateFD(handle);
160}
161
162int KernelProxy::dup2(int oldfd, int newfd) {
163  // If it's the same file handle, just return
164  if (oldfd == newfd)
165    return newfd;
166
167  ScopedKernelHandle old_handle;
168  Error error = AcquireHandle(oldfd, &old_handle);
169  if (error) {
170    errno = error;
171    return -1;
172  }
173
174  FreeAndReassignFD(newfd, old_handle);
175  return newfd;
176}
177
178int KernelProxy::chdir(const char* path) {
179  Error error = SetCWD(path);
180  if (error) {
181    errno = error;
182    return -1;
183  }
184  return 0;
185}
186
187char* KernelProxy::getcwd(char* buf, size_t size) {
188  std::string cwd = GetCWD();
189
190  if (size <= 0) {
191    errno = EINVAL;
192    return NULL;
193  }
194
195  // If size is 0, allocate as much as we need.
196  if (size == 0) {
197    size = cwd.size() + 1;
198  }
199
200  // Verify the buffer is large enough
201  if (size <= cwd.size()) {
202    errno = ERANGE;
203    return NULL;
204  }
205
206  // Allocate the buffer if needed
207  if (buf == NULL) {
208    buf = static_cast<char*>(malloc(size));
209  }
210
211  strcpy(buf, cwd.c_str());
212  return buf;
213}
214
215char* KernelProxy::getwd(char* buf) {
216  if (NULL == buf) {
217    errno = EFAULT;
218    return NULL;
219  }
220  return getcwd(buf, MAXPATHLEN);
221}
222
223int KernelProxy::chmod(const char* path, mode_t mode) {
224  int fd = KernelProxy::open(path, O_RDONLY);
225  if (-1 == fd)
226    return -1;
227
228  int result = fchmod(fd, mode);
229  close(fd);
230  return result;
231}
232
233int KernelProxy::chown(const char* path, uid_t owner, gid_t group) {
234  return 0;
235}
236
237int KernelProxy::fchown(int fd, uid_t owner, gid_t group) {
238  return 0;
239}
240
241int KernelProxy::lchown(const char* path, uid_t owner, gid_t group) {
242  return 0;
243}
244
245int KernelProxy::utime(const char* filename, const struct utimbuf* times) {
246  return 0;
247}
248
249int KernelProxy::mkdir(const char* path, mode_t mode) {
250  ScopedMount mnt;
251  Path rel;
252
253  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
254  if (error) {
255    errno = error;
256    return -1;
257  }
258
259  error = mnt->Mkdir(rel, mode);
260  if (error) {
261    errno = error;
262    return -1;
263  }
264
265  return 0;
266}
267
268int KernelProxy::rmdir(const char* path) {
269  ScopedMount mnt;
270  Path rel;
271
272  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
273  if (error) {
274    errno = error;
275    return -1;
276  }
277
278  error = mnt->Rmdir(rel);
279  if (error) {
280    errno = error;
281    return -1;
282  }
283
284  return 0;
285}
286
287int KernelProxy::stat(const char* path, struct stat* buf) {
288  int fd = open(path, O_RDONLY);
289  if (-1 == fd)
290    return -1;
291
292  int result = fstat(fd, buf);
293  close(fd);
294  return result;
295}
296
297
298int KernelProxy::mount(const char* source,
299                       const char* target,
300                       const char* filesystemtype,
301                       unsigned long mountflags,
302                       const void* data) {
303  std::string abs_path = GetAbsParts(target).Join();
304
305  // Find a factory of that type
306  MountFactoryMap_t::iterator factory = factories_.find(filesystemtype);
307  if (factory == factories_.end()) {
308    errno = ENODEV;
309    return -1;
310  }
311
312  // Create a map of settings
313  StringMap_t smap;
314  smap["SOURCE"] = source;
315  smap["TARGET"] = abs_path;
316
317  if (data) {
318    char* str = strdup(static_cast<const char*>(data));
319    char* ptr = strtok(str, ",");
320    char* val;
321    while (ptr != NULL) {
322      val = strchr(ptr, '=');
323      if (val) {
324        *val = 0;
325        smap[ptr] = val + 1;
326      } else {
327        smap[ptr] = "TRUE";
328      }
329      ptr = strtok(NULL, ",");
330    }
331    free(str);
332  }
333
334  ScopedMount mnt;
335  Error error = factory->second->CreateMount(dev_++, smap, ppapi_, &mnt);
336  if (error) {
337    errno = error;
338    return -1;
339  }
340
341  error = AttachMountAtPath(mnt, abs_path);
342  if (error) {
343    errno = error;
344    return -1;
345  }
346
347  return 0;
348}
349
350int KernelProxy::umount(const char* path) {
351  Error error = DetachMountAtPath(path);
352  if (error) {
353    errno = error;
354    return -1;
355  }
356  return 0;
357}
358
359ssize_t KernelProxy::read(int fd, void* buf, size_t nbytes) {
360  ScopedKernelHandle handle;
361  Error error = AcquireHandle(fd, &handle);
362  if (error) {
363    errno = error;
364    return -1;
365  }
366
367  int cnt = 0;
368  error = handle->Read(buf, nbytes, &cnt);
369  if (error) {
370    errno = error;
371    return -1;
372  }
373
374  return cnt;
375}
376
377ssize_t KernelProxy::write(int fd, const void* buf, size_t nbytes) {
378  ScopedKernelHandle handle;
379  Error error = AcquireHandle(fd, &handle);
380  if (error) {
381    errno = error;
382    return -1;
383  }
384
385  int cnt = 0;
386  error = handle->Write(buf, nbytes, &cnt);
387  if (error) {
388    errno = error;
389    return -1;
390  }
391
392  return cnt;
393}
394
395int KernelProxy::fstat(int fd, struct stat* buf) {
396  ScopedKernelHandle handle;
397  Error error = AcquireHandle(fd, &handle);
398  if (error) {
399    errno = error;
400    return -1;
401  }
402
403  error = handle->node()->GetStat(buf);
404  if (error) {
405    errno = error;
406    return -1;
407  }
408
409  return 0;
410}
411
412int KernelProxy::getdents(int fd, void* buf, unsigned int count) {
413  ScopedKernelHandle handle;
414  Error error = AcquireHandle(fd, &handle);
415  if (error) {
416    errno = error;
417    return -1;
418  }
419
420  int cnt = 0;
421  error = handle->GetDents(static_cast<dirent*>(buf), count, &cnt);
422  if (error)
423    errno = error;
424
425  return cnt;
426}
427
428int KernelProxy::ftruncate(int fd, off_t length) {
429  ScopedKernelHandle handle;
430  Error error = AcquireHandle(fd, &handle);
431  if (error) {
432    errno = error;
433    return -1;
434  }
435
436  error = handle->node()->FTruncate(length);
437  if (error) {
438    errno = error;
439    return -1;
440  }
441
442  return 0;
443}
444
445int KernelProxy::fsync(int fd) {
446  ScopedKernelHandle handle;
447  Error error = AcquireHandle(fd, &handle);
448  if (error) {
449    errno = error;
450    return -1;
451  }
452
453  error = handle->node()->FSync();
454  if (error) {
455    errno = error;
456    return -1;
457  }
458
459  return 0;
460}
461
462int KernelProxy::isatty(int fd) {
463  ScopedKernelHandle handle;
464  Error error = AcquireHandle(fd, &handle);
465  if (error) {
466    errno = error;
467    return -1;
468  }
469
470  error = handle->node()->IsaTTY();
471  if (error) {
472    errno = error;
473    return -1;
474  }
475
476  return 0;
477}
478
479int KernelProxy::ioctl(int fd, int request, char* argp) {
480  ScopedKernelHandle handle;
481  Error error = AcquireHandle(fd, &handle);
482  if (error) {
483    errno = error;
484    return -1;
485  }
486
487  error = handle->node()->Ioctl(request, argp);
488  if (error) {
489    errno = error;
490    return -1;
491  }
492
493  return 0;
494}
495
496off_t KernelProxy::lseek(int fd, off_t offset, int whence) {
497  ScopedKernelHandle handle;
498  Error error = AcquireHandle(fd, &handle);
499  if (error) {
500    errno = error;
501    return -1;
502  }
503
504  off_t new_offset;
505  error = handle->Seek(offset, whence, &new_offset);
506  if (error) {
507    errno = error;
508    return -1;
509  }
510
511  return new_offset;
512}
513
514int KernelProxy::unlink(const char* path) {
515  ScopedMount mnt;
516  Path rel;
517
518  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
519  if (error) {
520    errno = error;
521    return -1;
522  }
523
524  error = mnt->Unlink(rel);
525  if (error) {
526    errno = error;
527    return -1;
528  }
529
530  return 0;
531}
532
533int KernelProxy::remove(const char* path) {
534  ScopedMount mnt;
535  Path rel;
536
537  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
538  if (error) {
539    errno = error;
540    return -1;
541  }
542
543  error = mnt->Remove(rel);
544  if (error) {
545    errno = error;
546    return -1;
547  }
548
549  return 0;
550}
551
552// TODO(noelallen): Needs implementation.
553int KernelProxy::fchmod(int fd, int mode) {
554  ScopedKernelHandle handle;
555  Error error = AcquireHandle(fd, &handle);
556  if (error) {
557    errno = error;
558    return -1;
559  }
560
561  return 0;
562}
563
564int KernelProxy::access(const char* path, int amode) {
565  ScopedMount mnt;
566  Path rel;
567
568  Error error = AcquireMountAndRelPath(path, &mnt, &rel);
569  if (error) {
570    errno = error;
571    return -1;
572  }
573
574  error = mnt->Access(rel, amode);
575  if (error) {
576    errno = error;
577    return -1;
578  }
579  return 0;
580}
581
582// TODO(noelallen): Needs implementation.
583int KernelProxy::link(const char* oldpath, const char* newpath) {
584  errno = EINVAL;
585  return -1;
586}
587
588int KernelProxy::symlink(const char* oldpath, const char* newpath) {
589  errno = EINVAL;
590  return -1;
591}
592
593void* KernelProxy::mmap(void* addr,
594                        size_t length,
595                        int prot,
596                        int flags,
597                        int fd,
598                        size_t offset) {
599  // We shouldn't be getting anonymous mmaps here.
600  assert((flags & MAP_ANONYMOUS) == 0);
601  assert(fd != -1);
602
603  ScopedKernelHandle handle;
604  Error error = AcquireHandle(fd, &handle);
605  if (error) {
606    errno = error;
607    return MAP_FAILED;
608  }
609
610  void* new_addr;
611  error = handle->node()->MMap(addr, length, prot, flags, offset, &new_addr);
612  if (error) {
613    errno = error;
614    return MAP_FAILED;
615  }
616
617  return new_addr;
618}
619
620int KernelProxy::munmap(void* addr, size_t length) {
621  // NOTE: The comment below is from a previous discarded implementation that
622  // tracks mmap'd regions. For simplicity, we no longer do this; because we
623  // "snapshot" the contents of the file in mmap(), and don't support
624  // write-back or updating the mapped region when the file is written, holding
625  // on to the KernelHandle is pointless.
626  //
627  // If we ever do, these threading issues should be considered.
628
629  //
630  // WARNING: this function may be called by free().
631  //
632  // There is a potential deadlock scenario:
633  // Thread 1: open() -> takes lock1 -> free() -> takes lock2
634  // Thread 2: free() -> takes lock2 -> munmap() -> takes lock1
635  //
636  // Note that open() above could be any function that takes a lock that is
637  // shared with munmap (this includes munmap!)
638  //
639  // To prevent this, we avoid taking locks in munmap() that are used by other
640  // nacl_io functions that may call free. Specifically, we only take the
641  // mmap_lock, which is only shared with mmap() above. There is still a
642  // possibility of deadlock if mmap() or munmap() calls free(), so this is not
643  // allowed.
644  //
645  // Unfortunately, munmap still needs to acquire other locks; see the call to
646  // ReleaseHandle below which takes the process lock. This is safe as long as
647  // this is never executed from free() -- we can be reasonably sure this is
648  // true, because malloc only makes anonymous mmap() requests, and should only
649  // be munmapping those allocations. We never add to mmap_info_list_ for
650  // anonymous maps, so the unmap_list should always be empty when called from
651  // free().
652  return 0;
653}
654
655int KernelProxy::tcflush(int fd, int queue_selector) {
656  ScopedKernelHandle handle;
657  Error error = AcquireHandle(fd, &handle);
658  if (error) {
659    errno = error;
660    return -1;
661  }
662
663  error = handle->node()->Tcflush(queue_selector);
664  if (error) {
665    errno = error;
666    return -1;
667  }
668
669  return 0;
670}
671
672int KernelProxy::tcgetattr(int fd, struct termios* termios_p) {
673  ScopedKernelHandle handle;
674  Error error = AcquireHandle(fd, &handle);
675  if (error) {
676    errno = error;
677    return -1;
678  }
679
680  error = handle->node()->Tcgetattr(termios_p);
681  if (error) {
682    errno = error;
683    return -1;
684  }
685
686  return 0;
687}
688
689int KernelProxy::tcsetattr(int fd, int optional_actions,
690                           const struct termios *termios_p) {
691  ScopedKernelHandle handle;
692  Error error = AcquireHandle(fd, &handle);
693  if (error) {
694    errno = error;
695    return -1;
696  }
697
698  error = handle->node()->Tcsetattr(optional_actions, termios_p);
699  if (error) {
700    errno = error;
701    return -1;
702  }
703
704  return 0;
705}
706
707#ifdef PROVIDES_SOCKET_API
708
709int KernelProxy::select(int nfds, fd_set* readfds, fd_set* writefds,
710                        fd_set* exceptfds, struct timeval* timeout) {
711  ScopedEventListener listener(new EventListener);
712  std::vector<struct pollfd> fds;
713
714  fd_set readout, writeout, exceptout;
715
716  FD_ZERO(&readout);
717  FD_ZERO(&writeout);
718  FD_ZERO(&exceptout);
719
720  int fd;
721  size_t event_cnt = 0;
722  int event_track = 0;
723  for (fd = 0; fd < nfds; fd++) {
724    int events = 0;
725
726    if (readfds != NULL && FD_ISSET(fd, readfds))
727      events |= POLLIN;
728
729    if (writefds != NULL && FD_ISSET(fd, writefds))
730      events |= POLLOUT;
731
732    if (exceptfds != NULL && FD_ISSET(fd, exceptfds))
733      events |= POLLERR | POLLHUP;
734
735    // If we are not interested in this FD, skip it
736    if (0 == events) continue;
737
738    ScopedKernelHandle handle;
739    Error err = AcquireHandle(fd, &handle);
740
741    // Select will return immediately if there are bad FDs.
742    if (err != 0) {
743      errno = EBADF;
744      return -1;
745    }
746
747    int status = handle->node()->GetEventStatus() & events;
748    if (status & POLLIN) {
749      FD_SET(fd, &readout);
750      event_cnt++;
751    }
752
753    if (status & POLLOUT) {
754      FD_SET(fd, &writeout);
755      event_cnt++;
756    }
757
758    if (status & (POLLERR | POLLHUP)) {
759      FD_SET(fd, &exceptout);
760      event_cnt++;
761    }
762
763    // Otherwise track it.
764    if (0 == status) {
765      err = listener->Track(fd, handle->node(), events, fd);
766      if (err != 0) {
767        errno = EBADF;
768        return -1;
769      }
770      event_track++;
771    }
772  }
773
774  // If nothing is signaled, then we must wait.
775  if (event_cnt == 0) {
776    std::vector<EventData> events;
777    int ready_cnt;
778    int ms_timeout;
779
780    // NULL timeout signals wait forever.
781    if (timeout == NULL) {
782      ms_timeout = -1;
783    } else {
784      int64_t ms = timeout->tv_sec * 1000 + ((timeout->tv_usec + 500) / 1000);
785
786      // If the timeout is invalid or too long (larger than signed 32 bit).
787      if ((timeout->tv_sec < 0) || (timeout->tv_sec >= (INT_MAX / 1000)) ||
788          (timeout->tv_usec < 0) || (timeout->tv_usec >= 1000) ||
789          (ms < 0) || (ms >= INT_MAX)) {
790        errno = EINVAL;
791        return -1;
792      }
793
794      ms_timeout = static_cast<int>(ms);
795    }
796
797    events.resize(event_track);
798    listener->Wait(events.data(), event_track, ms_timeout, &ready_cnt);
799    for (fd = 0; static_cast<int>(fd) < ready_cnt; fd++) {
800      if (events[fd].events & POLLIN) {
801        FD_SET(events[fd].user_data, &readout);
802        event_cnt++;
803      }
804
805      if (events[fd].events & POLLOUT) {
806        FD_SET(events[fd].user_data, &writeout);
807        event_cnt++;
808      }
809
810      if (events[fd].events & (POLLERR | POLLHUP)) {
811        FD_SET(events[fd].user_data, &exceptout);
812        event_cnt++;
813      }
814    }
815  }
816
817  // Copy out the results
818  if (readfds != NULL)
819    *readfds = readout;
820
821  if (writefds != NULL)
822    *writefds = writeout;
823
824  if (exceptfds != NULL)
825    *exceptfds = exceptout;
826
827  return event_cnt;
828}
829
830int KernelProxy::poll(struct pollfd *fds, nfds_t nfds, int timeout) {
831  ScopedEventListener listener(new EventListener);
832
833  int index;
834  size_t event_cnt = 0;
835  size_t event_track = 0;
836  for (index = 0; static_cast<nfds_t>(index) < nfds; index++) {
837    ScopedKernelHandle handle;
838    struct pollfd* info = &fds[index];
839    Error err = AcquireHandle(info->fd, &handle);
840
841    // If the node isn't open, or somehow invalid, mark it so.
842    if (err != 0) {
843      info->revents = POLLNVAL;
844      event_cnt++;
845      continue;
846    }
847
848    // If it's already signaled, then just capture the event
849    if (handle->node()->GetEventStatus() & info->events) {
850      info->revents = info->events & handle->node()->GetEventStatus();
851      event_cnt++;
852      continue;
853    }
854
855    // Otherwise try to track it.
856    err = listener->Track(info->fd, handle->node(), info->events, index);
857    if (err != 0) {
858      info->revents = POLLNVAL;
859      event_cnt++;
860      continue;
861    }
862    event_track++;
863  }
864
865  // If nothing is signaled, then we must wait.
866  if (0 == event_cnt) {
867    std::vector<EventData> events;
868    int ready_cnt;
869
870    events.resize(event_track);
871    listener->Wait(events.data(), event_track, timeout, &ready_cnt);
872    for (index = 0; index < ready_cnt; index++) {
873      struct pollfd* info = &fds[events[index].user_data];
874
875      info->revents = events[index].events;
876      event_cnt++;
877    }
878  }
879
880  return event_cnt;
881}
882
883
884
885// Socket Functions
886int KernelProxy::accept(int fd, struct sockaddr* addr, socklen_t* len) {
887  if (NULL == addr || NULL == len) {
888    errno = EFAULT;
889    return -1;
890  }
891
892  ScopedKernelHandle handle;
893  if (AcquireSocketHandle(fd, &handle) == -1)
894    return -1;
895
896  errno = EINVAL;
897  return -1;
898}
899
900int KernelProxy::bind(int fd, const struct sockaddr* addr, socklen_t len) {
901  if (NULL == addr) {
902    errno = EFAULT;
903    return -1;
904  }
905
906  ScopedKernelHandle handle;
907  if (AcquireSocketHandle(fd, &handle) == -1)
908    return -1;
909
910  errno = EINVAL;
911  return -1;
912}
913
914int KernelProxy::connect(int fd, const struct sockaddr* addr, socklen_t len) {
915  if (NULL == addr) {
916    errno = EFAULT;
917    return -1;
918  }
919
920  ScopedKernelHandle handle;
921  if (AcquireSocketHandle(fd, &handle) == -1)
922    return -1;
923
924  errno = EACCES;
925  return -1;
926}
927
928struct hostent* KernelProxy::gethostbyname(const char* name) {
929  return host_resolver_.gethostbyname(name);
930}
931
932int KernelProxy::getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
933  if (NULL == addr || NULL == len) {
934    errno = EFAULT;
935    return -1;
936  }
937
938  ScopedKernelHandle handle;
939  if (AcquireSocketHandle(fd, &handle) == -1)
940    return -1;
941
942  errno = EINVAL;
943  return -1;
944}
945
946int KernelProxy::getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
947  if (NULL == addr || NULL == len) {
948    errno = EFAULT;
949    return -1;
950  }
951
952  ScopedKernelHandle handle;
953  if (AcquireSocketHandle(fd, &handle) == -1)
954    return -1;
955
956  errno = EINVAL;
957  return -1;
958}
959
960int KernelProxy::getsockopt(int fd,
961                         int lvl,
962                         int optname,
963                         void* optval,
964                         socklen_t* len) {
965  if (NULL == optval || NULL == len) {
966    errno = EFAULT;
967    return -1;
968  }
969
970  ScopedKernelHandle handle;
971  if (AcquireSocketHandle(fd, &handle) == -1)
972    return -1;
973
974  errno = EINVAL;
975  return -1;
976}
977
978int KernelProxy::listen(int fd, int backlog) {
979  ScopedKernelHandle handle;
980  if (AcquireSocketHandle(fd, &handle) == -1)
981    return -1;
982
983  errno = EOPNOTSUPP;
984  return -1;
985}
986
987ssize_t KernelProxy::recv(int fd,
988                          void* buf,
989                          size_t len,
990                          int flags) {
991  if (NULL == buf) {
992    errno = EFAULT;
993    return -1;
994  }
995
996  ScopedKernelHandle handle;
997  if (AcquireSocketHandle(fd, &handle) == -1)
998    return -1;
999
1000  errno = EINVAL;
1001  return -1;
1002}
1003
1004ssize_t KernelProxy::recvfrom(int fd,
1005                              void* buf,
1006                              size_t len,
1007                              int flags,
1008                              struct sockaddr* addr,
1009                              socklen_t* addrlen) {
1010  // According to the manpage, recvfrom with a null addr is identical to recv.
1011  if (NULL == addr) {
1012    return recv(fd, buf, len, flags);
1013  }
1014
1015  if (NULL == buf || NULL == addrlen) {
1016    errno = EFAULT;
1017    return -1;
1018  }
1019
1020  ScopedKernelHandle handle;
1021  if (AcquireSocketHandle(fd, &handle) == -1)
1022    return -1;
1023
1024  errno = EINVAL;
1025  return -1;
1026}
1027
1028ssize_t KernelProxy::recvmsg(int fd, struct msghdr* msg, int flags) {
1029  if (NULL == msg ) {
1030    errno = EFAULT;
1031    return -1;
1032  }
1033
1034  ScopedKernelHandle handle;
1035  if (AcquireSocketHandle(fd, &handle) == -1)
1036    return -1;
1037
1038  errno = EOPNOTSUPP;
1039  return -1;
1040}
1041
1042ssize_t KernelProxy::send(int fd, const void* buf, size_t len, int flags) {
1043  if (NULL == buf) {
1044    errno = EFAULT;
1045    return -1;
1046  }
1047
1048  ScopedKernelHandle handle;
1049  if (AcquireSocketHandle(fd, &handle) == -1)
1050    return -1;
1051
1052  errno = EINVAL;
1053  return -1;
1054}
1055
1056ssize_t KernelProxy::sendto(int fd,
1057                            const void* buf,
1058                            size_t len,
1059                            int flags,
1060                            const struct sockaddr* addr,
1061                            socklen_t addrlen) {
1062  // According to the manpage, sendto with a null addr is identical to send.
1063  if (NULL == addr) {
1064    return send(fd, buf, len, flags);
1065  }
1066
1067  if (NULL == buf) {
1068    errno = EFAULT;
1069    return -1;
1070  }
1071
1072  ScopedKernelHandle handle;
1073  if (AcquireSocketHandle(fd, &handle) == -1)
1074    return -1;
1075
1076  errno = EINVAL;
1077  return -1;
1078}
1079
1080ssize_t KernelProxy::sendmsg(int fd, const struct msghdr* msg, int flags) {
1081  if (NULL == msg) {
1082    errno = EFAULT;
1083    return -1;
1084  }
1085
1086  ScopedKernelHandle handle;
1087  if (AcquireSocketHandle(fd, &handle) == -1)
1088    return -1;
1089
1090  errno = EOPNOTSUPP;
1091  return -1;
1092}
1093
1094int KernelProxy::setsockopt(int fd,
1095                            int lvl,
1096                            int optname,
1097                            const void* optval,
1098                            socklen_t len) {
1099  if (NULL == optval) {
1100    errno = EFAULT;
1101    return -1;
1102  }
1103
1104  ScopedKernelHandle handle;
1105  if (AcquireSocketHandle(fd, &handle) == -1)
1106    return -1;
1107
1108  errno = EINVAL;
1109  return -1;
1110}
1111
1112int KernelProxy::shutdown(int fd, int how) {
1113  ScopedKernelHandle handle;
1114  if (AcquireSocketHandle(fd, &handle) == -1)
1115    return -1;
1116
1117  errno = EINVAL;
1118  return -1;
1119}
1120
1121int KernelProxy::socket(int domain, int type, int protocol) {
1122  if (AF_INET != domain && AF_INET6 != domain) {
1123    errno = EAFNOSUPPORT;
1124    return -1;
1125  }
1126
1127  if (SOCK_STREAM != type && SOCK_DGRAM != type) {
1128    errno = EPROTONOSUPPORT;
1129    return -1;
1130  }
1131
1132  errno = EACCES;
1133  return -1;
1134}
1135
1136int KernelProxy::socketpair(int domain, int type, int protocol, int* sv) {
1137  if (NULL == sv) {
1138    errno = EFAULT;
1139    return -1;
1140  }
1141
1142  // Catch-22: We don't support AF_UNIX, but any other AF doesn't support
1143  // socket pairs. Thus, this function always fails.
1144  if (AF_UNIX != domain) {
1145    errno = EPROTONOSUPPORT;
1146    return -1;
1147  }
1148
1149  if (AF_INET != domain && AF_INET6 != domain) {
1150    errno = EAFNOSUPPORT;
1151    return -1;
1152  }
1153
1154  // We cannot reach this point.
1155  errno = ENOSYS;
1156  return -1;
1157}
1158
1159int KernelProxy::AcquireSocketHandle(int fd, ScopedKernelHandle* handle) {
1160  Error error = AcquireHandle(fd, handle);
1161
1162  if (error) {
1163    errno = error;
1164    return -1;
1165  }
1166
1167  if ((handle->get()->node_->GetType() & S_IFSOCK) == 0) {
1168    errno = ENOTSOCK;
1169    return -1;
1170  }
1171
1172  return 0;
1173}
1174
1175#endif  // PROVIDES_SOCKET_API
1176
1177}  // namespace_nacl_io
1178