]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/openzfs/cmd/zed/zed_file.c
Update OpenZFS to 2.0.0-rc3-gfc5966
[FreeBSD/FreeBSD.git] / sys / contrib / openzfs / cmd / zed / zed_file.c
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 }