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 OpenZFS 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 <dirent.h> 16 #include <errno.h> 17 #include <fcntl.h> 18 #include <limits.h> 19 #include <string.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 * Set an exclusive advisory lock on the open file descriptor [fd]. 28 * Return 0 on success, 1 if a conflicting lock is held by another process, 29 * or -1 on error (with errno set). 30 */ 31 int 32 zed_file_lock(int fd) 33 { 34 struct flock lock; 35 36 if (fd < 0) { 37 errno = EBADF; 38 return (-1); 39 } 40 lock.l_type = F_WRLCK; 41 lock.l_whence = SEEK_SET; 42 lock.l_start = 0; 43 lock.l_len = 0; 44 45 if (fcntl(fd, F_SETLK, &lock) < 0) { 46 if ((errno == EACCES) || (errno == EAGAIN)) 47 return (1); 48 49 return (-1); 50 } 51 return (0); 52 } 53 54 /* 55 * Release an advisory lock held on the open file descriptor [fd]. 56 * Return 0 on success, or -1 on error (with errno set). 57 */ 58 int 59 zed_file_unlock(int fd) 60 { 61 struct flock lock; 62 63 if (fd < 0) { 64 errno = EBADF; 65 return (-1); 66 } 67 lock.l_type = F_UNLCK; 68 lock.l_whence = SEEK_SET; 69 lock.l_start = 0; 70 lock.l_len = 0; 71 72 if (fcntl(fd, F_SETLK, &lock) < 0) 73 return (-1); 74 75 return (0); 76 } 77 78 /* 79 * Test whether an exclusive advisory lock could be obtained for the open 80 * file descriptor [fd]. 81 * Return 0 if the file is not locked, >0 for the PID of another process 82 * holding a conflicting lock, or -1 on error (with errno set). 83 */ 84 pid_t 85 zed_file_is_locked(int fd) 86 { 87 struct flock lock; 88 89 if (fd < 0) { 90 errno = EBADF; 91 return (-1); 92 } 93 lock.l_type = F_WRLCK; 94 lock.l_whence = SEEK_SET; 95 lock.l_start = 0; 96 lock.l_len = 0; 97 98 if (fcntl(fd, F_GETLK, &lock) < 0) 99 return (-1); 100 101 if (lock.l_type == F_UNLCK) 102 return (0); 103 104 return (lock.l_pid); 105 } 106 107 108 #if __APPLE__ 109 #define PROC_SELF_FD "/dev/fd" 110 #else /* Linux-compatible layout */ 111 #define PROC_SELF_FD "/proc/self/fd" 112 #endif 113 114 /* 115 * Close all open file descriptors greater than or equal to [lowfd]. 116 * Any errors encountered while closing file descriptors are ignored. 117 */ 118 void 119 zed_file_close_from(int lowfd) 120 { 121 int errno_bak = errno; 122 int maxfd = 0; 123 int fd; 124 DIR *fddir; 125 struct dirent *fdent; 126 127 if ((fddir = opendir(PROC_SELF_FD)) != NULL) { 128 while ((fdent = readdir(fddir)) != NULL) { 129 fd = atoi(fdent->d_name); 130 if (fd > maxfd && fd != dirfd(fddir)) 131 maxfd = fd; 132 } 133 (void) closedir(fddir); 134 } else { 135 maxfd = sysconf(_SC_OPEN_MAX); 136 } 137 for (fd = lowfd; fd < maxfd; fd++) 138 (void) close(fd); 139 140 errno = errno_bak; 141 } 142