]> granicus.if.org Git - zfs/blob - cmd/zed/zed_file.c
Replace zed_file_create_dirs() with mkdirp()
[zfs] / 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  * FIXME: No longer needed?
207  */
208 int
209 zed_file_close_on_exec(int fd)
210 {
211         int flags;
212
213         if (fd < 0) {
214                 errno = EBADF;
215                 return (-1);
216         }
217         flags = fcntl(fd, F_GETFD);
218         if (flags == -1)
219                 return (-1);
220
221         flags |= FD_CLOEXEC;
222
223         if (fcntl(fd, F_SETFD, flags) == -1)
224                 return (-1);
225
226         return (0);
227 }