/src/common/fd.c

https://code.google.com/ · C · 273 lines · 194 code · 49 blank · 30 comment · 41 complexity · 7193be502f226542bc5f9baf93e35493 MD5 · raw file

  1. /*****************************************************************************
  2. * $Id$
  3. *****************************************************************************
  4. * This file is part of the Munge Uid 'N' Gid Emporium (MUNGE).
  5. * For details, see <http://www.llnl.gov/linux/munge/>.
  6. * UCRL-CODE-2003-???.
  7. *
  8. * Copyright (C) 2001-2003 The Regents of the University of California.
  9. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  10. * Written by Chris Dunlap <cdunlap@llnl.gov>.
  11. *
  12. * This is free software; you can redistribute it and/or modify it
  13. * under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This is distributed in the hope that it will be useful, but WITHOUT
  18. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  20. * for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License;
  23. * if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  24. * Suite 330, Boston, MA 02111-1307 USA.
  25. *****************************************************************************
  26. * Refer to "fd.h" for documentation on public functions.
  27. *****************************************************************************/
  28. #if HAVE_CONFIG_H
  29. # include "config.h"
  30. #endif /* HAVE_CONFIG_H */
  31. #include <assert.h>
  32. #include <errno.h>
  33. #include <fcntl.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include "fd.h"
  38. static int _fd_get_lock (int fd, int cmd, int type);
  39. static pid_t _fd_test_lock (int fd, int type);
  40. int
  41. fd_set_close_on_exec (int fd)
  42. {
  43. assert (fd >= 0);
  44. if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
  45. return (-1);
  46. return (0);
  47. }
  48. int
  49. fd_set_nonblocking (int fd)
  50. {
  51. int fval;
  52. assert (fd >= 0);
  53. if ((fval = fcntl (fd, F_GETFL, 0)) < 0)
  54. return (-1);
  55. if (fcntl (fd, F_SETFL, fval | O_NONBLOCK) < 0)
  56. return (-1);
  57. return (0);
  58. }
  59. int
  60. fd_get_read_lock (int fd)
  61. {
  62. return (_fd_get_lock (fd, F_SETLK, F_RDLCK));
  63. }
  64. int
  65. fd_get_readw_lock (int fd)
  66. {
  67. return (_fd_get_lock (fd, F_SETLKW, F_RDLCK));
  68. }
  69. int
  70. fd_get_write_lock (int fd)
  71. {
  72. return (_fd_get_lock (fd, F_SETLK, F_WRLCK));
  73. }
  74. int
  75. fd_get_writew_lock (int fd)
  76. {
  77. return (_fd_get_lock (fd, F_SETLKW, F_WRLCK));
  78. }
  79. int
  80. fd_release_lock (int fd)
  81. {
  82. return (_fd_get_lock (fd, F_SETLK, F_UNLCK));
  83. }
  84. pid_t
  85. fd_is_read_lock_blocked (int fd)
  86. {
  87. return (_fd_test_lock (fd, F_RDLCK));
  88. }
  89. pid_t
  90. fd_is_write_lock_blocked (int fd)
  91. {
  92. return (_fd_test_lock (fd, F_WRLCK));
  93. }
  94. static int
  95. _fd_get_lock (int fd, int cmd, int type)
  96. {
  97. struct flock lock;
  98. assert (fd >= 0);
  99. lock.l_type = type;
  100. lock.l_start = 0;
  101. lock.l_whence = SEEK_SET;
  102. lock.l_len = 0;
  103. return (fcntl (fd, cmd, &lock));
  104. }
  105. static pid_t
  106. _fd_test_lock (int fd, int type)
  107. {
  108. struct flock lock;
  109. assert (fd >= 0);
  110. lock.l_type = type;
  111. lock.l_start = 0;
  112. lock.l_whence = SEEK_SET;
  113. lock.l_len = 0;
  114. if (fcntl (fd, F_GETLK, &lock) < 0)
  115. return (-1);
  116. if (lock.l_type == F_UNLCK)
  117. return (0);
  118. return (lock.l_pid);
  119. }
  120. ssize_t
  121. fd_read_n (int fd, void *buf, size_t n)
  122. {
  123. size_t nleft;
  124. ssize_t nread;
  125. unsigned char *p;
  126. p = buf;
  127. nleft = n;
  128. while (nleft > 0) {
  129. if ((nread = read (fd, p, nleft)) < 0) {
  130. if (errno == EINTR)
  131. continue;
  132. else
  133. return (-1);
  134. }
  135. else if (nread == 0) { /* EOF */
  136. break;
  137. }
  138. nleft -= nread;
  139. p += nread;
  140. }
  141. return (n - nleft);
  142. }
  143. ssize_t
  144. fd_write_n (int fd, void *buf, size_t n)
  145. {
  146. size_t nleft;
  147. ssize_t nwritten;
  148. unsigned char *p;
  149. p = buf;
  150. nleft = n;
  151. while (nleft > 0) {
  152. if ((nwritten = write (fd, p, nleft)) < 0) {
  153. if (errno == EINTR)
  154. continue;
  155. else
  156. return (-1);
  157. }
  158. nleft -= nwritten;
  159. p += nwritten;
  160. }
  161. return (n);
  162. }
  163. ssize_t
  164. fd_read_line (int fd, void *buf, size_t maxlen)
  165. {
  166. ssize_t n, rc;
  167. unsigned char c, *p;
  168. n = 0;
  169. p = buf;
  170. while (n < (ssize_t) maxlen - 1) { /* reserve space for NUL-termination */
  171. if ((rc = read (fd, &c, 1)) == 1) {
  172. n++;
  173. *p++ = c;
  174. if (c == '\n')
  175. break; /* store newline, like fgets() */
  176. }
  177. else if (rc == 0) {
  178. if (n == 0) /* EOF, no data read */
  179. return (0);
  180. else /* EOF, some data read */
  181. break;
  182. }
  183. else {
  184. if (errno == EINTR)
  185. continue;
  186. return (-1);
  187. }
  188. }
  189. *p = '\0'; /* NUL-terminate, like fgets() */
  190. return (n);
  191. }
  192. /*
  193. * Following added by Mike Haskell <mhaskell@llnl.gov>
  194. */
  195. ssize_t
  196. fd_null_read_n (int fd, void *buf, size_t n)
  197. {
  198. unsigned char *mp;
  199. size_t nleft;
  200. ssize_t nread;
  201. unsigned char *p;
  202. unsigned char *q;
  203. q = p = (unsigned char *)buf;
  204. nleft = n;
  205. while (nleft > 0) {
  206. if ((nread = read (fd, p, nleft)) < 0) {
  207. if (errno == EINTR)
  208. continue;
  209. else
  210. return (-1);
  211. }
  212. else if (nread == 0) { /* EOF */
  213. break;
  214. }
  215. nleft -= nread;
  216. p += nread;
  217. mp = (unsigned char *) memchr(q, '\0', (n - nleft));
  218. if (mp <= &q[ (n - nleft - 1)]) {
  219. if (mp != NULL)
  220. break;
  221. }
  222. }
  223. return (n - nleft);
  224. }