1 /* 2 * This file is part of the ZFS Event Daemon (ZED). 3 * 4 * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). 5 * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. 6 * Refer to the ZoL git commit log for authoritative copyright attribution. 7 * 8 * The contents of this file are subject to the terms of the 9 * Common Development and Distribution License Version 1.0 (CDDL-1.0). 10 * You can obtain a copy of the license from the top-level file 11 * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>. 12 * You may not use this file except in compliance with the license. 13 */ 14 15 #include <errno.h> 16 #include <fcntl.h> 17 #include <limits.h> 18 #include <string.h> 19 #include <sys/resource.h> 20 #include <sys/stat.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 #include "zed_file.h" 24 #include "zed_log.h" 25 26 /* 27 * Read up to [n] bytes from [fd] into [buf]. 28 * Return the number of bytes read, 0 on EOF, or -1 on error. 29 */ 30 ssize_t 31 zed_file_read_n(int fd, void *buf, size_t n) 32 { 33 unsigned char *p; 34 size_t n_left; 35 ssize_t n_read; 36 37 p = buf; 38 n_left = n; 39 while (n_left > 0) { 40 if ((n_read = read(fd, p, n_left)) < 0) { 41 if (errno == EINTR) 42 continue; 43 else 44 return (-1); 45 46 } else if (n_read == 0) { 47 break; 48 } 49 n_left -= n_read; 50 p += n_read; 51 } 52 return (n - n_left); 53 } 54 55 /* 56 * Write [n] bytes from [buf] out to [fd]. 57 * Return the number of bytes written, or -1 on error. 58 */ 59 ssize_t 60 zed_file_write_n(int fd, void *buf, size_t n) 61 { 62 const unsigned char *p; 63 size_t n_left; 64 ssize_t n_written; 65 66 p = buf; 67 n_left = n; 68 while (n_left > 0) { 69 if ((n_written = write(fd, p, n_left)) < 0) { 70 if (errno == EINTR) 71 continue; 72 else 73 return (-1); 74 75 } 76 n_left -= n_written; 77 p += n_written; 78 } 79 return (n); 80 } 81 82 /* 83 * Set an exclusive advisory lock on the open file descriptor [fd]. 84 * Return 0 on success, 1 if a conflicting lock is held by another process, 85 * or -1 on error (with errno set). 86 */ 87 int 88 zed_file_lock(int fd) 89 { 90 struct flock lock; 91 92 if (fd < 0) { 93 errno = EBADF; 94 return (-1); 95 } 96 lock.l_type = F_WRLCK; 97 lock.l_whence = SEEK_SET; 98 lock.l_start = 0; 99 lock.l_len = 0; 100 101 if (fcntl(fd, F_SETLK, &lock) < 0) { 102 if ((errno == EACCES) || (errno == EAGAIN)) 103 return (1); 104 105 return (-1); 106 } 107 return (0); 108 } 109 110 /* 111 * Release an advisory lock held on the open file descriptor [fd]. 112 * Return 0 on success, or -1 on error (with errno set). 113 */ 114 int 115 zed_file_unlock(int fd) 116 { 117 struct flock lock; 118 119 if (fd < 0) { 120 errno = EBADF; 121 return (-1); 122 } 123 lock.l_type = F_UNLCK; 124 lock.l_whence = SEEK_SET; 125 lock.l_start = 0; 126 lock.l_len = 0; 127 128 if (fcntl(fd, F_SETLK, &lock) < 0) 129 return (-1); 130 131 return (0); 132 } 133 134 /* 135 * Test whether an exclusive advisory lock could be obtained for the open 136 * file descriptor [fd]. 137 * Return 0 if the file is not locked, >0 for the PID of another process 138 * holding a conflicting lock, or -1 on error (with errno set). 139 */ 140 pid_t 141 zed_file_is_locked(int fd) 142 { 143 struct flock lock; 144 145 if (fd < 0) { 146 errno = EBADF; 147 return (-1); 148 } 149 lock.l_type = F_WRLCK; 150 lock.l_whence = SEEK_SET; 151 lock.l_start = 0; 152 lock.l_len = 0; 153 154 if (fcntl(fd, F_GETLK, &lock) < 0) 155 return (-1); 156 157 if (lock.l_type == F_UNLCK) 158 return (0); 159 160 return (lock.l_pid); 161 } 162 163 /* 164 * Close all open file descriptors greater than or equal to [lowfd]. 165 * Any errors encountered while closing file descriptors are ignored. 166 */ 167 void 168 zed_file_close_from(int lowfd) 169 { 170 const int maxfd_def = 256; 171 int errno_bak; 172 struct rlimit rl; 173 int maxfd; 174 int fd; 175 176 errno_bak = errno; 177 178 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 179 maxfd = maxfd_def; 180 } else if (rl.rlim_max == RLIM_INFINITY) { 181 maxfd = maxfd_def; 182 } else { 183 maxfd = rl.rlim_max; 184 } 185 for (fd = lowfd; fd < maxfd; fd++) 186 (void) close(fd); 187 188 errno = errno_bak; 189 } 190 191 /* 192 * Set the CLOEXEC flag on file descriptor [fd] so it will be automatically 193 * closed upon successful execution of one of the exec functions. 194 * Return 0 on success, or -1 on error. 195 * 196 * FIXME: No longer needed? 197 */ 198 int 199 zed_file_close_on_exec(int fd) 200 { 201 int flags; 202 203 if (fd < 0) { 204 errno = EBADF; 205 return (-1); 206 } 207 flags = fcntl(fd, F_GETFD); 208 if (flags == -1) 209 return (-1); 210 211 flags |= FD_CLOEXEC; 212 213 if (fcntl(fd, F_SETFD, flags) == -1) 214 return (-1); 215 216 return (0); 217 } 218