shim_fcntl.c 7.6 KB

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