diff options
Diffstat (limited to 'sys/contrib/openzfs/cmd/zed/zed_file.c')
-rw-r--r-- | sys/contrib/openzfs/cmd/zed/zed_file.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/cmd/zed/zed_file.c b/sys/contrib/openzfs/cmd/zed/zed_file.c new file mode 100644 index 000000000000..c706398cdf99 --- /dev/null +++ b/sys/contrib/openzfs/cmd/zed/zed_file.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: CDDL-1.0 +/* + * This file is part of the ZFS Event Daemon (ZED). + * + * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049). + * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC. + * Refer to the OpenZFS git commit log for authoritative copyright attribution. + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License Version 1.0 (CDDL-1.0). + * You can obtain a copy of the license from the top-level file + * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>. + * You may not use this file except in compliance with the license. + */ + +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include "zed_file.h" +#include "zed_log.h" + +/* + * Set an exclusive advisory lock on the open file descriptor [fd]. + * Return 0 on success, 1 if a conflicting lock is held by another process, + * or -1 on error (with errno set). + */ +int +zed_file_lock(int fd) +{ + struct flock lock; + + if (fd < 0) { + errno = EBADF; + return (-1); + } + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + + if (fcntl(fd, F_SETLK, &lock) < 0) { + if ((errno == EACCES) || (errno == EAGAIN)) + return (1); + + return (-1); + } + return (0); +} + +/* + * Release an advisory lock held on the open file descriptor [fd]. + * Return 0 on success, or -1 on error (with errno set). + */ +int +zed_file_unlock(int fd) +{ + struct flock lock; + + if (fd < 0) { + errno = EBADF; + return (-1); + } + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + + if (fcntl(fd, F_SETLK, &lock) < 0) + return (-1); + + return (0); +} + +/* + * Test whether an exclusive advisory lock could be obtained for the open + * file descriptor [fd]. + * Return 0 if the file is not locked, >0 for the PID of another process + * holding a conflicting lock, or -1 on error (with errno set). + */ +pid_t +zed_file_is_locked(int fd) +{ + struct flock lock; + + if (fd < 0) { + errno = EBADF; + return (-1); + } + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + + if (fcntl(fd, F_GETLK, &lock) < 0) + return (-1); + + if (lock.l_type == F_UNLCK) + return (0); + + return (lock.l_pid); +} + + +#if __APPLE__ +#define PROC_SELF_FD "/dev/fd" +#else /* Linux-compatible layout */ +#define PROC_SELF_FD "/proc/self/fd" +#endif + +/* + * Close all open file descriptors greater than or equal to [lowfd]. + * Any errors encountered while closing file descriptors are ignored. + */ +void +zed_file_close_from(int lowfd) +{ + int errno_bak = errno; + int maxfd = 0; + int fd; + DIR *fddir; + struct dirent *fdent; + + if ((fddir = opendir(PROC_SELF_FD)) != NULL) { + while ((fdent = readdir(fddir)) != NULL) { + fd = atoi(fdent->d_name); + if (fd > maxfd && fd != dirfd(fddir)) + maxfd = fd; + } + (void) closedir(fddir); + } else { + maxfd = sysconf(_SC_OPEN_MAX); + } + for (fd = lowfd; fd < maxfd; fd++) + (void) close(fd); + + errno = errno_bak; +} |