shim_fcntl.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * shim_fcntl.c
  17. *
  18. * Implementation of system call "fcntl".
  19. */
  20. #include <shim_internal.h>
  21. #include <shim_utils.h>
  22. #include <shim_table.h>
  23. #include <shim_handle.h>
  24. #include <shim_thread.h>
  25. #include <shim_fs.h>
  26. #include <pal.h>
  27. #include <pal_error.h>
  28. #include <errno.h>
  29. #include <linux/fcntl.h>
  30. int shim_do_fcntl (int fd, int cmd, unsigned long arg)
  31. {
  32. struct shim_handle_map * handle_map = get_cur_handle_map(NULL);
  33. int flags;
  34. int ret = -ENOSYS;
  35. struct shim_handle * hdl = get_fd_handle(fd, &flags, handle_map);
  36. if (!hdl)
  37. return -EBADF;
  38. switch (cmd) {
  39. /* F_DUPFD (long)
  40. * Find the lowest numbered available file descriptor greater than or
  41. * equal to arg and make it be a copy of fd. This is different from
  42. * dup2(2), which uses exactly the descriptor specified.
  43. * On success, the new descriptor is returned.
  44. */
  45. case F_DUPFD: {
  46. int vfd = arg;
  47. while(1) {
  48. if (set_new_fd_handle_by_fd(vfd, hdl, flags, handle_map) == vfd)
  49. break;
  50. vfd++;
  51. };
  52. ret = vfd;
  53. break;
  54. }
  55. /* F_DUPFD_CLOEXEC (long; since Linux 2.6.24)
  56. * As for F_DUPFD, but additionally set the close-on-exec flag for
  57. * the duplicate descriptor. Specifying this flag permits a
  58. * program to avoid an additional fcntl() F_SETFD operation to set
  59. * the FD_CLOEXEC flag. For an explanation of why this flag is
  60. * useful, see the description of O_CLOEXEC in open(2).
  61. */
  62. case F_DUPFD_CLOEXEC: {
  63. int vfd = arg;
  64. flags |= FD_CLOEXEC;
  65. while(1) {
  66. if (set_new_fd_handle_by_fd(vfd, hdl, flags, handle_map) == vfd)
  67. break;
  68. vfd++;
  69. };
  70. ret = vfd;
  71. break;
  72. }
  73. /* File descriptor flags
  74. * The following commands manipulate the flags associated with a file
  75. * descriptor. Currently, only one such flag is defined: FD_CLOEXEC,
  76. * the close-on-exec flag. If the FD_CLOEXEC bit is 0, the file
  77. * descriptor will
  78. * remain open across an execve(2), otherwise it will be closed.
  79. *
  80. * F_GETFD (void)
  81. * Read the file descriptor flags; arg is ignored.
  82. */
  83. case F_GETFD:
  84. ret = flags & FD_CLOEXEC;
  85. break;
  86. /* F_SETFD (long)
  87. * Set the file descriptor flags to the value specified by arg.
  88. */
  89. case F_SETFD:
  90. lock(handle_map->lock);
  91. if (HANDLE_ALLOCATED(handle_map->map[fd]))
  92. handle_map->map[fd]->flags = arg & FD_CLOEXEC;
  93. unlock(handle_map->lock);
  94. ret = 0;
  95. break;
  96. /* File status flags
  97. * Each open file description has certain associated status flags,
  98. * initialized by open(2) and possibly modified by fcntl().
  99. * Duplicated file descriptors (made with dup(2), fcntl(F_DUPFD),
  100. * fork(2), etc.) refer to the same open file description, and thus
  101. * share the same file status flags.
  102. * The file status flags and their semantics are described in open(2).
  103. *
  104. * F_GETFL (void)
  105. * Read the file status flags; arg is ignored.
  106. */
  107. case F_GETFL:
  108. lock(hdl->lock);
  109. flags = hdl->flags;
  110. unlock(hdl->lock);
  111. ret = flags;
  112. break;
  113. /* F_SETFL (long)
  114. * Set the file status flags to the value specified by arg. File
  115. * access mode (O_RDONLY, O_WRONLY, O_RDWR) and file creation flags
  116. * (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in arg are ignored. On
  117. * Linux this command can only change the O_APPEND, O_DIRECT,
  118. * O_NOATIME, and O_NONBLOCK flags.
  119. */
  120. #define FCNTL_SETFL_MASK (O_APPEND|O_NONBLOCK)
  121. case F_SETFL:
  122. lock(hdl->lock);
  123. if (hdl->fs && hdl->fs->fs_ops &&
  124. hdl->fs->fs_ops->setflags)
  125. hdl->fs->fs_ops->setflags(hdl, arg & FCNTL_SETFL_MASK);
  126. hdl->flags = (hdl->flags & ~FCNTL_SETFL_MASK) |
  127. (arg & FCNTL_SETFL_MASK);
  128. unlock(hdl->lock);
  129. ret = 0;
  130. break;
  131. /* Advisory locking
  132. * F_GETLK, F_SETLK and F_SETLKW are used to acquire, release, and
  133. * test for the existence of record locks (also known as file-segment
  134. * or file-region locks). The third argument, lock, is a pointer to
  135. * a structure that has at least the following fields (in unspecified
  136. * order).
  137. *
  138. * F_SETLK (struct flock *)
  139. * Acquire a lock (when l_type is F_RDLCK or F_WRLCK) or release a
  140. * lock (when l_type is F_UNLCK) on the bytes specified by the
  141. * l_whence, l_start, and l_len fields of lock. If a conflicting lock
  142. * is held by another process, this call returns -1 and sets errno to
  143. * EACCES or EAGAIN.
  144. */
  145. case F_SETLK:
  146. ret = -ENOSYS;
  147. break;
  148. /* F_SETLKW (struct flock *)
  149. * As for F_SETLK, but if a conflicting lock is held on the file,
  150. * then wait for that lock to be released. If a signal is caught while
  151. * waiting, then the call is interrupted and (after the signal handler
  152. * has returned) returns immediately (with return value -1 and errno
  153. * set to EINTR; see signal(7)).
  154. */
  155. case F_SETLKW:
  156. ret = -ENOSYS;
  157. break;
  158. /* F_GETLK (struct flock *)
  159. * On input to this call, lock describes a lock we would like to place
  160. * on the file. If the lock could be placed, fcntl() does not
  161. * actually place it, but returns F_UNLCK in the l_type field of lock
  162. * and leaves the other fields of the structure unchanged. If one or
  163. * more incompatible locks would prevent this lock being placed, then
  164. * fcntl() returns details about one of these locks in the l_type,
  165. * l_whence, l_start, and l_len fields of lock and sets l_pid to be
  166. * the PID of the process holding that lock.
  167. */
  168. case F_GETLK:
  169. ret = -ENOSYS;
  170. break;
  171. /* F_SETOWN (int)
  172. * Set the process ID or process group ID that will receive SIGIO
  173. * and SIGURG signals for events on file descriptor fd to the ID given
  174. * in arg. A process ID is specified as a positive value; a process
  175. * group ID is specified as a negative value. Most commonly, the
  176. * calling process specifies itself as the owner (that is, arg is
  177. * specified as getpid(2)).
  178. */
  179. case F_SETOWN:
  180. ret = 0;
  181. /* XXX: DUMMY for now */
  182. break;
  183. }
  184. put_handle(hdl);
  185. return ret;
  186. }