fs_fcntl.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /****************************************************************************
  2. * fs/vfs/fs_fcntl.c
  3. *
  4. * Copyright (C) 2009, 2012-2014, 2016-2017 Gregory Nutt. All rights
  5. * reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. * 3. Neither the name NuttX nor the names of its contributors may be
  19. * used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ****************************************************************************/
  36. /****************************************************************************
  37. * Included Files
  38. ****************************************************************************/
  39. #include <nuttx/config.h>
  40. #include <stdarg.h>
  41. #include <fcntl.h>
  42. #include <errno.h>
  43. #include <assert.h>
  44. #include <nuttx/sched.h>
  45. #include <nuttx/cancelpt.h>
  46. #include <nuttx/fs/fs.h>
  47. #include <nuttx/net/net.h>
  48. #include "inode/inode.h"
  49. /****************************************************************************
  50. * Public Functions
  51. ****************************************************************************/
  52. /****************************************************************************
  53. * Name: file_vfcntl
  54. *
  55. * Description:
  56. * Similar to the standard vfcntl function except that is accepts a struct
  57. * struct file instance instead of a file descriptor.
  58. *
  59. * Input Parameters:
  60. * filep - Instance for struct file for the opened file.
  61. * cmd - Identifies the operation to be performed.
  62. * ap - Variable argument following the command.
  63. *
  64. * Returned Value:
  65. * The nature of the return value depends on the command. Non-negative
  66. * values indicate success. Failures are reported as negated errno
  67. * values.
  68. *
  69. ****************************************************************************/
  70. int file_vfcntl(FAR struct file *filep, int cmd, va_list ap)
  71. {
  72. int ret = -EINVAL;
  73. /* Was this file opened ? */
  74. if (!filep->f_inode)
  75. {
  76. return -EBADF;
  77. }
  78. switch (cmd)
  79. {
  80. case F_DUPFD:
  81. /* Return a new file descriptor which shall be the lowest numbered
  82. * available (that is, not already open) file descriptor greater than
  83. * or equal to the third argument, arg, taken as an integer of type
  84. * int. The new file descriptor shall refer to the same open file
  85. * description as the original file descriptor, and shall share any
  86. * locks. The FD_CLOEXEC flag associated with the new file
  87. * descriptor shall be cleared to keep the file open across calls to
  88. * one of the exec functions.
  89. */
  90. {
  91. /* Does not set the errno variable in the event of a failure */
  92. ret = file_dup(filep, va_arg(ap, int));
  93. }
  94. break;
  95. case F_GETFD:
  96. /* Get the file descriptor flags defined in <fcntl.h> that are
  97. * associated with the file descriptor fd. File descriptor flags are
  98. * associated with a single file descriptor and do not affect other
  99. * file descriptors that refer to the same file.
  100. */
  101. {
  102. ret = filep->f_oflags & O_CLOEXEC ? FD_CLOEXEC : 0;
  103. }
  104. break;
  105. case F_SETFD:
  106. /* Set the file descriptor flags defined in <fcntl.h>, that are
  107. * associated with fd, to the third argument, arg, taken as type int.
  108. * If the FD_CLOEXEC flag in the third argument is 0, the file shall
  109. * remain open across the exec functions; otherwise, the file shall
  110. * be closed upon successful execution of one of the exec functions.
  111. */
  112. {
  113. int oflags = va_arg(ap, int);
  114. if (oflags & ~FD_CLOEXEC)
  115. {
  116. ret = -ENOSYS;
  117. break;
  118. }
  119. if (oflags & FD_CLOEXEC)
  120. {
  121. filep->f_oflags |= O_CLOEXEC;
  122. }
  123. else
  124. {
  125. filep->f_oflags &= ~O_CLOEXEC;
  126. }
  127. ret = OK;
  128. }
  129. break;
  130. case F_GETFL:
  131. /* Get the file status flags and file access modes, defined in
  132. * <fcntl.h>, for the file description associated with fd. The file
  133. * access modes can be extracted from the return value using the
  134. * mask O_ACCMODE, which is defined in <fcntl.h>. File status flags
  135. * and file access modes are associated with the file description
  136. * and do not affect other file descriptors that refer to the same
  137. * file with different open file descriptions.
  138. */
  139. {
  140. ret = filep->f_oflags;
  141. }
  142. break;
  143. case F_SETFL:
  144. /* Set the file status flags, defined in <fcntl.h>, for the file
  145. * description associated with fd from the corresponding bits in
  146. * the third argument, arg, taken as type int. Bits corresponding
  147. * to the file access mode and the file creation flags, as defined
  148. * in <fcntl.h>, that are set in arg shall be ignored. If any bits
  149. * in arg other than those mentioned here are changed by the
  150. * application, the result is unspecified.
  151. */
  152. {
  153. int oflags = va_arg(ap, int);
  154. oflags &= FFCNTL;
  155. filep->f_oflags &= ~FFCNTL;
  156. filep->f_oflags |= oflags;
  157. ret = OK;
  158. }
  159. break;
  160. case F_GETOWN:
  161. /* If fd refers to a socket, get the process or process group ID
  162. * specified to receive SIGURG signals when out-of-band data is
  163. * available. Positive values indicate a process ID; negative
  164. * values, other than -1, indicate a process group ID. If fd does
  165. * not refer to a socket, the results are unspecified.
  166. */
  167. case F_SETOWN:
  168. /* If fd refers to a socket, set the process or process group ID
  169. * specified to receive SIGURG signals when out-of-band data is
  170. * available, using the value of the third argument, arg, taken as
  171. * type int. Positive values indicate a process ID; negative values,
  172. * other than -1, indicate a process group ID. If fd does not refer
  173. * to a socket, the results are unspecified.
  174. */
  175. ret = -EBADF; /* Only valid on socket descriptors */
  176. break;
  177. case F_GETLK:
  178. /* Get the first lock which blocks the lock description pointed to
  179. * by the third argument, arg, taken as a pointer to type struct
  180. * flock, defined in <fcntl.h>. The information retrieved shall
  181. * overwrite the information passed to fcntl() in the structure
  182. * flock. If no lock is found that would prevent this lock from
  183. * being created, then the structure shall be left unchanged except
  184. * for the lock type which shall be set to F_UNLCK.
  185. */
  186. case F_SETLK:
  187. /* Set or clear a file segment lock according to the lock
  188. * description pointed to by the third argument, arg, taken as a
  189. * pointer to type struct flock, defined in <fcntl.h>. F_SETLK can
  190. * establish shared (or read) locks (F_RDLCK) or exclusive (or
  191. * write) locks (F_WRLCK), as well as to remove either type of lock
  192. * (F_UNLCK). F_RDLCK, F_WRLCK, and F_UNLCK are defined in
  193. * <fcntl.h>. If a shared or exclusive lock cannot be set, fcntl()
  194. * shall return immediately with a return value of -1.
  195. */
  196. case F_SETLKW:
  197. /* This command shall be equivalent to F_SETLK except that if a
  198. * shared or exclusive lock is blocked by other locks, the thread
  199. * shall wait until the request can be satisfied. If a signal that
  200. * is to be caught is received while fcntl() is waiting for a
  201. * region, fcntl() shall be interrupted. Upon return from the signal
  202. * handler, fcntl() shall return -1 with errno set to [EINTR], and
  203. * the lock operation shall not be done.
  204. */
  205. ret = -ENOSYS; /* Not implemented */
  206. break;
  207. default:
  208. break;
  209. }
  210. return ret;
  211. }
  212. /****************************************************************************
  213. * Name: file_fcntl
  214. *
  215. * Description:
  216. * Similar to the standard fcntl function except that is accepts a struct
  217. * struct file instance instead of a file descriptor.
  218. *
  219. * Input Parameters:
  220. * filep - Instance for struct file for the opened file.
  221. * cmd - Identifies the operation to be performed. Command specific
  222. * arguments may follow.
  223. *
  224. * Returned Value:
  225. * The nature of the return value depends on the command. Non-negative
  226. * values indicate success. Failures are reported as negated errno
  227. * values.
  228. *
  229. ****************************************************************************/
  230. int file_fcntl(FAR struct file *filep, int cmd, ...)
  231. {
  232. va_list ap;
  233. int ret;
  234. /* Setup to access the variable argument list */
  235. va_start(ap, cmd);
  236. /* Let file_vfcntl() do the real work. The errno is not set on
  237. * failures.
  238. */
  239. ret = file_vfcntl(filep, cmd, ap);
  240. va_end(ap);
  241. return ret;
  242. }
  243. /****************************************************************************
  244. * Name: nx_fcntl and nx_vfcntl
  245. *
  246. * Description:
  247. * nx_fcntl() is similar to the standard 'fcntl' interface except that is
  248. * not a cancellation point and it does not modify the errno variable.
  249. *
  250. * nx_vfcntl() is identical except that it accepts a va_list as an argument
  251. * versus taking a variable length list of arguments.
  252. *
  253. * nx_fcntl() and nx_vfcntl are internal NuttX interface and should not be
  254. * called from applications.
  255. *
  256. * Returned Value:
  257. * Returns a non-negative number on success; A negated errno value is
  258. * returned on any failure (see comments fcntl() for a list of appropriate
  259. * errno values).
  260. *
  261. ****************************************************************************/
  262. int nx_vfcntl(int fd, int cmd, va_list ap)
  263. {
  264. FAR struct file *filep;
  265. int ret;
  266. /* Did we get a valid file descriptor? */
  267. if (fd < CONFIG_NFILE_DESCRIPTORS)
  268. {
  269. /* Get the file structure corresponding to the file descriptor. */
  270. ret = fs_getfilep(fd, &filep);
  271. if (ret >= 0)
  272. {
  273. DEBUGASSERT(filep != NULL);
  274. /* Let file_vfcntl() do the real work. The errno is not set on
  275. * failures.
  276. */
  277. ret = file_vfcntl(filep, cmd, ap);
  278. }
  279. }
  280. else
  281. {
  282. /* No... check for operations on a socket descriptor */
  283. #ifdef CONFIG_NET
  284. if (fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS))
  285. {
  286. /* Yes.. defer socket descriptor operations to net_vfcntl(). The
  287. * errno is not set on failures.
  288. */
  289. ret = net_vfcntl(fd, cmd, ap);
  290. }
  291. else
  292. #endif
  293. {
  294. /* No.. this descriptor number is out of range */
  295. ret = -EBADF;
  296. }
  297. }
  298. return ret;
  299. }
  300. int nx_fcntl(int fd, int cmd, ...)
  301. {
  302. va_list ap;
  303. int ret;
  304. /* Setup to access the variable argument list */
  305. va_start(ap, cmd);
  306. /* Let nx_vfcntl() do the real work. The errno is not set on
  307. * failures.
  308. */
  309. ret = nx_vfcntl(fd, cmd, ap);
  310. va_end(ap);
  311. return ret;
  312. }
  313. /****************************************************************************
  314. * Name: fcntl
  315. *
  316. * Description:
  317. * fcntl() will perform the operation specified by 'cmd' on an open file.
  318. *
  319. * Input Parameters:
  320. * fd - File descriptor of the open file
  321. * cmd - Identifies the operation to be performed. Command specific
  322. * arguments may follow.
  323. *
  324. * Returned Value:
  325. * The returned value depends on the nature of the command but for all
  326. * commands the return value of -1 (ERROR) indicates that an error has
  327. * occurred and, in this case, the errno variable will be set
  328. * appropriately
  329. *
  330. ****************************************************************************/
  331. int fcntl(int fd, int cmd, ...)
  332. {
  333. va_list ap;
  334. int ret;
  335. /* fcntl() is a cancellation point */
  336. enter_cancellation_point();
  337. /* Setup to access the variable argument list */
  338. va_start(ap, cmd);
  339. /* Let nx_vfcntl() do the real work. The errno is not set on
  340. * failures.
  341. */
  342. ret = nx_vfcntl(fd, cmd, ap);
  343. va_end(ap);
  344. if (ret < 0)
  345. {
  346. set_errno(-ret);
  347. ret = ERROR;
  348. }
  349. leave_cancellation_point();
  350. return ret;
  351. }