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