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
zed_file_read_n(int fd,void * buf,size_t n)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
zed_file_write_n(int fd,void * buf,size_t n)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
zed_file_lock(int fd)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
zed_file_unlock(int fd)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
zed_file_is_locked(int fd)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
zed_file_close_from(int lowfd)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
zed_file_close_on_exec(int fd)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