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