shim_fcntl.c 7.7 KB

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