]> granicus.if.org Git - zfs/blob - cmd/zed/zed_file.c
Merge branch 'zfsonlinux/merge-spl'
[zfs] / cmd / zed / zed_file.c
1 /*
2  * This file is part of the ZFS Event Daemon (ZED)
3  * for ZFS on Linux (ZoL) <http://zfsonlinux.org/>.
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_log.h"
24
25 /*
26  * Read up to [n] bytes from [fd] into [buf].
27  * Return the number of bytes read, 0 on EOF, or -1 on error.
28  */
29 ssize_t
30 zed_file_read_n(int fd, void *buf, size_t n)
31 {
32         unsigned char *p;
33         size_t n_left;
34         ssize_t n_read;
35
36         p = buf;
37         n_left = n;
38         while (n_left > 0) {
39                 if ((n_read = read(fd, p, n_left)) < 0) {
40                         if (errno == EINTR)
41                                 continue;
42                         else
43                                 return (-1);
44
45                 } else if (n_read == 0) {
46                         break;
47                 }
48                 n_left -= n_read;
49                 p += n_read;
50         }
51         return (n - n_left);
52 }
53
54 /*
55  * Write [n] bytes from [buf] out to [fd].
56  * Return the number of bytes written, or -1 on error.
57  */
58 ssize_t
59 zed_file_write_n(int fd, void *buf, size_t n)
60 {
61         const unsigned char *p;
62         size_t n_left;
63         ssize_t n_written;
64
65         p = buf;
66         n_left = n;
67         while (n_left > 0) {
68                 if ((n_written = write(fd, p, n_left)) < 0) {
69                         if (errno == EINTR)
70                                 continue;
71                         else
72                                 return (-1);
73
74                 }
75                 n_left -= n_written;
76                 p += n_written;
77         }
78         return (n);
79 }
80
81 /*
82  * Set an exclusive advisory lock on the open file descriptor [fd].
83  * Return 0 on success, 1 if a conflicting lock is held by another process,
84  * or -1 on error (with errno set).
85  */
86 int
87 zed_file_lock(int fd)
88 {
89         struct flock lock;
90
91         if (fd < 0) {
92                 errno = EBADF;
93                 return (-1);
94         }
95         lock.l_type = F_WRLCK;
96         lock.l_whence = SEEK_SET;
97         lock.l_start = 0;
98         lock.l_len = 0;
99
100         if (fcntl(fd, F_SETLK, &lock) < 0) {
101                 if ((errno == EACCES) || (errno == EAGAIN))
102                         return (1);
103
104                 return (-1);
105         }
106         return (0);
107 }
108
109 /*
110  * Release an advisory lock held on the open file descriptor [fd].
111  * Return 0 on success, or -1 on error (with errno set).
112  */
113 int
114 zed_file_unlock(int fd)
115 {
116         struct flock lock;
117
118         if (fd < 0) {
119                 errno = EBADF;
120                 return (-1);
121         }
122         lock.l_type = F_UNLCK;
123         lock.l_whence = SEEK_SET;
124         lock.l_start = 0;
125         lock.l_len = 0;
126
127         if (fcntl(fd, F_SETLK, &lock) < 0)
128                 return (-1);
129
130         return (0);
131 }
132
133 /*
134  * Test whether an exclusive advisory lock could be obtained for the open
135  * file descriptor [fd].
136  * Return 0 if the file is not locked, >0 for the PID of another process
137  * holding a conflicting lock, or -1 on error (with errno set).
138  */
139 pid_t
140 zed_file_is_locked(int fd)
141 {
142         struct flock lock;
143
144         if (fd < 0) {
145                 errno = EBADF;
146                 return (-1);
147         }
148         lock.l_type = F_WRLCK;
149         lock.l_whence = SEEK_SET;
150         lock.l_start = 0;
151         lock.l_len = 0;
152
153         if (fcntl(fd, F_GETLK, &lock) < 0)
154                 return (-1);
155
156         if (lock.l_type == F_UNLCK)
157                 return (0);
158
159         return (lock.l_pid);
160 }
161
162 /*
163  * Close all open file descriptors greater than or equal to [lowfd].
164  * Any errors encountered while closing file descriptors are ignored.
165  */
166 void
167 zed_file_close_from(int lowfd)
168 {
169         const int maxfd_def = 256;
170         int errno_bak;
171         struct rlimit rl;
172         int maxfd;
173         int fd;
174
175         errno_bak = errno;
176
177         if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
178                 maxfd = maxfd_def;
179         } else if (rl.rlim_max == RLIM_INFINITY) {
180                 maxfd = maxfd_def;
181         } else {
182                 maxfd = rl.rlim_max;
183         }
184         for (fd = lowfd; fd < maxfd; fd++)
185                 (void) close(fd);
186
187         errno = errno_bak;
188 }
189
190 /*
191  * Set the CLOEXEC flag on file descriptor [fd] so it will be automatically
192  * closed upon successful execution of one of the exec functions.
193  * Return 0 on success, or -1 on error.
194  *
195  * FIXME: No longer needed?
196  */
197 int
198 zed_file_close_on_exec(int fd)
199 {
200         int flags;
201
202         if (fd < 0) {
203                 errno = EBADF;
204                 return (-1);
205         }
206         flags = fcntl(fd, F_GETFD);
207         if (flags == -1)
208                 return (-1);
209
210         flags |= FD_CLOEXEC;
211
212         if (fcntl(fd, F_SETFD, flags) == -1)
213                 return (-1);
214
215         return (0);
216 }