/src/common/fd.c
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 29 30#if HAVE_CONFIG_H 31# include "config.h" 32#endif /* HAVE_CONFIG_H */ 33 34#include <assert.h> 35#include <errno.h> 36#include <fcntl.h> 37#include <stdlib.h> 38#include <string.h> 39#include <unistd.h> 40#include "fd.h" 41 42 43static int _fd_get_lock (int fd, int cmd, int type); 44static pid_t _fd_test_lock (int fd, int type); 45 46 47int 48fd_set_close_on_exec (int fd) 49{ 50 assert (fd >= 0); 51 52 if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0) 53 return (-1); 54 return (0); 55} 56 57 58int 59fd_set_nonblocking (int fd) 60{ 61 int fval; 62 63 assert (fd >= 0); 64 65 if ((fval = fcntl (fd, F_GETFL, 0)) < 0) 66 return (-1); 67 if (fcntl (fd, F_SETFL, fval | O_NONBLOCK) < 0) 68 return (-1); 69 return (0); 70} 71 72 73int 74fd_get_read_lock (int fd) 75{ 76 return (_fd_get_lock (fd, F_SETLK, F_RDLCK)); 77} 78 79 80int 81fd_get_readw_lock (int fd) 82{ 83 return (_fd_get_lock (fd, F_SETLKW, F_RDLCK)); 84} 85 86 87int 88fd_get_write_lock (int fd) 89{ 90 return (_fd_get_lock (fd, F_SETLK, F_WRLCK)); 91} 92 93 94int 95fd_get_writew_lock (int fd) 96{ 97 return (_fd_get_lock (fd, F_SETLKW, F_WRLCK)); 98} 99 100 101int 102fd_release_lock (int fd) 103{ 104 return (_fd_get_lock (fd, F_SETLK, F_UNLCK)); 105} 106 107 108pid_t 109fd_is_read_lock_blocked (int fd) 110{ 111 return (_fd_test_lock (fd, F_RDLCK)); 112} 113 114 115pid_t 116fd_is_write_lock_blocked (int fd) 117{ 118 return (_fd_test_lock (fd, F_WRLCK)); 119} 120 121 122static int 123_fd_get_lock (int fd, int cmd, int type) 124{ 125 struct flock lock; 126 127 assert (fd >= 0); 128 129 lock.l_type = type; 130 lock.l_start = 0; 131 lock.l_whence = SEEK_SET; 132 lock.l_len = 0; 133 134 return (fcntl (fd, cmd, &lock)); 135} 136 137 138static pid_t 139_fd_test_lock (int fd, int type) 140{ 141 struct flock lock; 142 143 assert (fd >= 0); 144 145 lock.l_type = type; 146 lock.l_start = 0; 147 lock.l_whence = SEEK_SET; 148 lock.l_len = 0; 149 150 if (fcntl (fd, F_GETLK, &lock) < 0) 151 return (-1); 152 if (lock.l_type == F_UNLCK) 153 return (0); 154 return (lock.l_pid); 155} 156 157 158ssize_t 159fd_read_n (int fd, void *buf, size_t n) 160{ 161 size_t nleft; 162 ssize_t nread; 163 unsigned char *p; 164 165 p = buf; 166 nleft = n; 167 while (nleft > 0) { 168 if ((nread = read (fd, p, nleft)) < 0) { 169 if (errno == EINTR) 170 continue; 171 else 172 return (-1); 173 } 174 else if (nread == 0) { /* EOF */ 175 break; 176 } 177 nleft -= nread; 178 p += nread; 179 } 180 return (n - nleft); 181} 182 183 184ssize_t 185fd_write_n (int fd, void *buf, size_t n) 186{ 187 size_t nleft; 188 ssize_t nwritten; 189 unsigned char *p; 190 191 p = buf; 192 nleft = n; 193 while (nleft > 0) { 194 if ((nwritten = write (fd, p, nleft)) < 0) { 195 if (errno == EINTR) 196 continue; 197 else 198 return (-1); 199 } 200 nleft -= nwritten; 201 p += nwritten; 202 } 203 return (n); 204} 205 206 207ssize_t 208fd_read_line (int fd, void *buf, size_t maxlen) 209{ 210 ssize_t n, rc; 211 unsigned char c, *p; 212 213 n = 0; 214 p = buf; 215 while (n < (ssize_t) maxlen - 1) { /* reserve space for NUL-termination */ 216 217 if ((rc = read (fd, &c, 1)) == 1) { 218 n++; 219 *p++ = c; 220 if (c == '\n') 221 break; /* store newline, like fgets() */ 222 } 223 else if (rc == 0) { 224 if (n == 0) /* EOF, no data read */ 225 return (0); 226 else /* EOF, some data read */ 227 break; 228 } 229 else { 230 if (errno == EINTR) 231 continue; 232 return (-1); 233 } 234 } 235 236 *p = '\0'; /* NUL-terminate, like fgets() */ 237 return (n); 238} 239 240/* 241 * Following added by Mike Haskell <mhaskell@llnl.gov> 242 */ 243ssize_t 244fd_null_read_n (int fd, void *buf, size_t n) 245{ 246 unsigned char *mp; 247 size_t nleft; 248 ssize_t nread; 249 unsigned char *p; 250 unsigned char *q; 251 252 q = p = (unsigned char *)buf; 253 nleft = n; 254 while (nleft > 0) { 255 if ((nread = read (fd, p, nleft)) < 0) { 256 if (errno == EINTR) 257 continue; 258 else 259 return (-1); 260 } 261 else if (nread == 0) { /* EOF */ 262 break; 263 } 264 nleft -= nread; 265 p += nread; 266 mp = (unsigned char *) memchr(q, '\0', (n - nleft)); 267 if (mp <= &q[ (n - nleft - 1)]) { 268 if (mp != NULL) 269 break; 270 } 271 } 272 return (n - nleft); 273}