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.
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.
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]
23 * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
24 * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
31 #include <sys/resource.h>
33 #include <sys/types.h>
38 * Read up to [n] bytes from [fd] into [buf].
39 * Return the number of bytes read, 0 on EOF, or -1 on error.
42 zed_file_read_n(int fd, void *buf, size_t n)
51 if ((n_read = read(fd, p, n_left)) < 0) {
57 } else if (n_read == 0) {
67 * Write [n] bytes from [buf] out to [fd].
68 * Return the number of bytes written, or -1 on error.
71 zed_file_write_n(int fd, void *buf, size_t n)
73 const unsigned char *p;
80 if ((n_written = write(fd, p, n_left)) < 0) {
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).
107 lock.l_type = F_WRLCK;
108 lock.l_whence = SEEK_SET;
112 if (fcntl(fd, F_SETLK, &lock) < 0) {
113 if ((errno == EACCES) || (errno == EAGAIN))
122 * Release an advisory lock held on the open file descriptor [fd].
123 * Return 0 on success, or -1 on error (with errno set).
126 zed_file_unlock(int fd)
134 lock.l_type = F_UNLCK;
135 lock.l_whence = SEEK_SET;
139 if (fcntl(fd, F_SETLK, &lock) < 0)
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).
152 zed_file_is_locked(int fd)
160 lock.l_type = F_WRLCK;
161 lock.l_whence = SEEK_SET;
165 if (fcntl(fd, F_GETLK, &lock) < 0)
168 if (lock.l_type == F_UNLCK)
175 * Close all open file descriptors greater than or equal to [lowfd].
176 * Any errors encountered while closing file descriptors are ignored.
179 zed_file_close_from(int lowfd)
181 const int maxfd_def = 256;
189 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
191 } else if (rl.rlim_max == RLIM_INFINITY) {
196 for (fd = lowfd; fd < maxfd; fd++)
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?
209 zed_file_close_on_exec(int fd)
217 flags = fcntl(fd, F_GETFD);
223 if (fcntl(fd, F_SETFD, flags) == -1)
230 * Create the directory [dir_name] and any missing parent directories.
231 * Directories will be created with permissions 0755 modified by the umask.
232 * Return 0 on success, or -1 on error.
233 * FIXME: Deprecate in favor of mkdirp(). (lib/libspl/mkdirp.c)
236 zed_file_create_dirs(const char *dir_name)
239 char dir_buf[PATH_MAX];
240 mode_t dir_mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
243 if ((dir_name == NULL) || (dir_name[0] == '\0')) {
244 zed_log_msg(LOG_WARNING,
245 "Failed to create directory: no directory specified");
249 if (dir_name[0] != '/') {
250 zed_log_msg(LOG_WARNING,
251 "Failed to create directory \"%s\": not absolute path",
256 /* Check if directory already exists. */
257 if (stat(dir_name, &st) == 0) {
258 if (S_ISDIR(st.st_mode))
262 zed_log_msg(LOG_WARNING,
263 "Failed to create directory \"%s\": %s",
264 dir_name, strerror(errno));
267 /* Create copy for modification. */
268 if (strlen(dir_name) >= sizeof (dir_buf)) {
269 errno = ENAMETOOLONG;
270 zed_log_msg(LOG_WARNING,
271 "Failed to create directory \"%s\": %s",
272 dir_name, strerror(errno));
275 strncpy(dir_buf, dir_name, sizeof (dir_buf));
277 /* Remove trailing slashes. */
278 p = dir_buf + strlen(dir_buf) - 1;
279 while ((p > dir_buf) && (*p == '/'))
282 /* Process directory components starting from the root dir. */
287 /* Skip over adjacent slashes. */
291 /* Advance to the next path component. */
296 /* Create directory. */
297 if (mkdir(dir_buf, dir_mode) < 0) {
299 int mkdir_errno = errno;
301 if ((mkdir_errno == EEXIST) ||
302 (stat(dir_buf, &st) < 0) ||
303 (!S_ISDIR(st.st_mode))) {
304 zed_log_msg(LOG_WARNING,
305 "Failed to create directory \"%s\": %s",
306 dir_buf, strerror(mkdir_errno));