1
1
/*****************************************************************************
2
* $Id: fd.c 771 2010-03-02 23:14:07Z dun $
2
* $Id: fd.c 923 2011-02-25 09:47:54Z chris.m.dunlap $
3
3
*****************************************************************************
4
4
* Written by Chris Dunlap <cdunlap@llnl.gov>.
5
* Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
5
* Copyright (C) 2007-2011 Lawrence Livermore National Security, LLC.
6
6
* Copyright (C) 2002-2007 The Regents of the University of California.
9
9
* This file is part of the MUNGE Uid 'N' Gid Emporium (MUNGE).
10
* For details, see <http://home.gna.org/munge/>.
10
* For details, see <http://munge.googlecode.com/>.
12
12
* MUNGE is free software: you can redistribute it and/or modify it under
13
13
* the terms of the GNU General Public License as published by the Free
37
37
#include <assert.h>
40
41
#include <stdlib.h>
41
42
#include <string.h>
42
45
#include <unistd.h>
46
49
/*****************************************************************************
48
51
*****************************************************************************/
53
static int _fd_get_poll_timeout (const struct timeval *when);
50
55
static int _fd_get_lock (int fd, int cmd, int type);
51
57
static pid_t _fd_test_lock (int fd, int type);
54
60
/*****************************************************************************
55
* Extern I/O Functions
61
* Public Functions for I/O
56
62
*****************************************************************************/
59
65
fd_read_n (int fd, void *buf, size_t n)
114
fd_timed_read_n (int fd, void *buf, size_t n,
115
const struct timeval *when, int do_skip_first_poll)
124
if ((fd < 0) || (buf == NULL)) {
133
if (do_skip_first_poll && (nleft > 0)) {
139
msecs = _fd_get_poll_timeout (when);
140
nfd = poll (&pfd, 1, msecs);
143
if ((errno == EINTR) || (errno == EAGAIN))
148
else if (nfd == 0) { /* timeout */
152
else if (pfd.revents & POLLNVAL) {
156
else if (pfd.revents & POLLERR) {
160
assert (pfd.revents & POLLIN);
163
nread = read (fd, p, nleft);
165
if ((errno == EINTR) || (errno == EAGAIN))
170
else if (nread == 0) { /* EOF */
185
fd_timed_write_n (int fd, const void *buf, size_t n,
186
const struct timeval *when, int do_skip_first_poll)
188
const unsigned char *p;
195
if ((fd < 0) || (buf == NULL)) {
202
pfd.events = POLLOUT;
204
if (do_skip_first_poll && (nleft > 0)) {
210
msecs = _fd_get_poll_timeout (when);
211
nfd = poll (&pfd, 1, msecs);
214
if ((errno == EINTR) || (errno == EAGAIN))
219
else if (nfd == 0) { /* timeout */
223
else if (pfd.revents & POLLHUP) {
226
else if (pfd.revents & POLLNVAL) {
230
else if (pfd.revents & POLLERR) {
234
assert (pfd.revents & POLLOUT);
237
nwritten = write (fd, p, nleft);
239
if ((errno == EINTR) || (errno == EAGAIN))
256
fd_timed_write_iov (int fd, const struct iovec *iov_orig, int iov_cnt,
257
const struct timeval *when, int do_skip_first_poll)
262
size_t n, nleft, iov_len;
268
if ((fd < 0) || (iov_orig == NULL) || (iov_cnt <= 0)) {
272
/* Create copy of iovec for modification to handle retrying short writes.
274
iov_mem_len = sizeof (struct iovec) * iov_cnt;
275
iov = malloc (iov_mem_len);
280
memcpy (iov, iov_orig, iov_mem_len);
282
for (i = 0, n = 0; i < iov_cnt; i++) {
287
pfd.events = POLLOUT;
289
if (do_skip_first_poll && (nleft > 0)) {
295
msecs = _fd_get_poll_timeout (when);
296
nfd = poll (&pfd, 1, msecs);
299
if ((errno == EINTR) || (errno == EAGAIN))
304
else if (nfd == 0) { /* timeout */
308
else if (pfd.revents & POLLHUP) {
311
else if (pfd.revents & POLLNVAL) {
315
else if (pfd.revents & POLLERR) {
319
assert (pfd.revents & POLLOUT);
322
nwritten = writev (fd, iov, iov_cnt);
324
if ((errno == EINTR) || (errno == EAGAIN))
334
for (i = 0; (i < iov_cnt) && (nwritten > 0); i++) {
335
n = (nwritten > iov[i].iov_len) ? iov[i].iov_len : nwritten;
340
iov[i].iov_base = (char *) iov[i].iov_base + n;
344
return (iov_len - nleft);
108
353
fd_read_line (int fd, void *buf, size_t maxlen)
141
386
/*****************************************************************************
142
* Extern Locking Functions
387
* Public Functions for Attributes
388
*****************************************************************************/
391
fd_set_close_on_exec (int fd)
397
if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0) {
405
fd_set_nonblocking (int fd)
413
if ((fval = fcntl (fd, F_GETFL, 0)) < 0) {
416
if (fcntl (fd, F_SETFL, fval | O_NONBLOCK) < 0) {
424
fd_is_nonblocking (int fd)
432
if ((fval = fcntl (fd, F_GETFL, 0)) < 0) {
435
return ((fval & O_NONBLOCK) ? 1 : 0);
439
/*****************************************************************************
440
* Public Functions for Locking
143
441
*****************************************************************************/
194
492
/*****************************************************************************
195
* Extern Attribute Functions
196
*****************************************************************************/
199
fd_set_close_on_exec (int fd)
203
if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
210
fd_set_nonblocking (int fd)
216
if ((fval = fcntl (fd, F_GETFL, 0)) < 0)
218
if (fcntl (fd, F_SETFL, fval | O_NONBLOCK) < 0)
224
/*****************************************************************************
226
*****************************************************************************/
494
*****************************************************************************/
497
_fd_get_poll_timeout (const struct timeval *when)
499
/* Returns the poll() timeout value for the number of milliseconds between now
500
* and [when] (which specifies an absolute time in seconds and microseconds
501
* since the Epoch), 0 if [when] is in the past, or -1 if [when] is NULL
502
* (indicating poll() should wait indefinitely).
510
if ((when->tv_sec == 0) && (when->tv_usec == 0)) {
513
/* POSIX says gettimeofday() can't fail, but just in case ...
515
if (gettimeofday (&now, NULL) < 0) {
518
/* Round up to the next millisecond.
519
* XXX: msecs can overflow/underflow if [when] is too far from now.
521
msecs = ( (when->tv_sec - now.tv_sec) * 1000 ) +
522
( (when->tv_usec - now.tv_usec + 999) / 1000 ) ;
524
* Return 0 if [when] is in the past to indicate poll() should not block.
526
return ((msecs < 0) ? 0 : msecs);
229
531
_fd_get_lock (int fd, int cmd, int type)