1*61145dc2SMartin Matuska // SPDX-License-Identifier: CDDL-1.0
2eda14cbcSMatt Macy /*
3180f8225SMatt Macy * This file is part of the ZFS Event Daemon (ZED).
4180f8225SMatt Macy *
5eda14cbcSMatt Macy * Developed at Lawrence Livermore National Laboratory (LLNL-CODE-403049).
6eda14cbcSMatt Macy * Copyright (C) 2013-2014 Lawrence Livermore National Security, LLC.
716038816SMartin Matuska * Refer to the OpenZFS git commit log for authoritative copyright attribution.
8eda14cbcSMatt Macy *
9eda14cbcSMatt Macy * The contents of this file are subject to the terms of the
10eda14cbcSMatt Macy * Common Development and Distribution License Version 1.0 (CDDL-1.0).
11eda14cbcSMatt Macy * You can obtain a copy of the license from the top-level file
12eda14cbcSMatt Macy * "OPENSOLARIS.LICENSE" or at <http://opensource.org/licenses/CDDL-1.0>.
13eda14cbcSMatt Macy * You may not use this file except in compliance with the license.
14eda14cbcSMatt Macy */
15eda14cbcSMatt Macy
1616038816SMartin Matuska #include <dirent.h>
17eda14cbcSMatt Macy #include <errno.h>
18eda14cbcSMatt Macy #include <fcntl.h>
19eda14cbcSMatt Macy #include <limits.h>
20eda14cbcSMatt Macy #include <string.h>
21eda14cbcSMatt Macy #include <sys/stat.h>
22eda14cbcSMatt Macy #include <sys/types.h>
23eda14cbcSMatt Macy #include <unistd.h>
24eda14cbcSMatt Macy #include "zed_file.h"
25eda14cbcSMatt Macy #include "zed_log.h"
26eda14cbcSMatt Macy
27eda14cbcSMatt Macy /*
28eda14cbcSMatt Macy * Set an exclusive advisory lock on the open file descriptor [fd].
29eda14cbcSMatt Macy * Return 0 on success, 1 if a conflicting lock is held by another process,
30eda14cbcSMatt Macy * or -1 on error (with errno set).
31eda14cbcSMatt Macy */
32eda14cbcSMatt Macy int
zed_file_lock(int fd)33eda14cbcSMatt Macy zed_file_lock(int fd)
34eda14cbcSMatt Macy {
35eda14cbcSMatt Macy struct flock lock;
36eda14cbcSMatt Macy
37eda14cbcSMatt Macy if (fd < 0) {
38eda14cbcSMatt Macy errno = EBADF;
39eda14cbcSMatt Macy return (-1);
40eda14cbcSMatt Macy }
41eda14cbcSMatt Macy lock.l_type = F_WRLCK;
42eda14cbcSMatt Macy lock.l_whence = SEEK_SET;
43eda14cbcSMatt Macy lock.l_start = 0;
44eda14cbcSMatt Macy lock.l_len = 0;
45eda14cbcSMatt Macy
46eda14cbcSMatt Macy if (fcntl(fd, F_SETLK, &lock) < 0) {
47eda14cbcSMatt Macy if ((errno == EACCES) || (errno == EAGAIN))
48eda14cbcSMatt Macy return (1);
49eda14cbcSMatt Macy
50eda14cbcSMatt Macy return (-1);
51eda14cbcSMatt Macy }
52eda14cbcSMatt Macy return (0);
53eda14cbcSMatt Macy }
54eda14cbcSMatt Macy
55eda14cbcSMatt Macy /*
56eda14cbcSMatt Macy * Release an advisory lock held on the open file descriptor [fd].
57eda14cbcSMatt Macy * Return 0 on success, or -1 on error (with errno set).
58eda14cbcSMatt Macy */
59eda14cbcSMatt Macy int
zed_file_unlock(int fd)60eda14cbcSMatt Macy zed_file_unlock(int fd)
61eda14cbcSMatt Macy {
62eda14cbcSMatt Macy struct flock lock;
63eda14cbcSMatt Macy
64eda14cbcSMatt Macy if (fd < 0) {
65eda14cbcSMatt Macy errno = EBADF;
66eda14cbcSMatt Macy return (-1);
67eda14cbcSMatt Macy }
68eda14cbcSMatt Macy lock.l_type = F_UNLCK;
69eda14cbcSMatt Macy lock.l_whence = SEEK_SET;
70eda14cbcSMatt Macy lock.l_start = 0;
71eda14cbcSMatt Macy lock.l_len = 0;
72eda14cbcSMatt Macy
73eda14cbcSMatt Macy if (fcntl(fd, F_SETLK, &lock) < 0)
74eda14cbcSMatt Macy return (-1);
75eda14cbcSMatt Macy
76eda14cbcSMatt Macy return (0);
77eda14cbcSMatt Macy }
78eda14cbcSMatt Macy
79eda14cbcSMatt Macy /*
80eda14cbcSMatt Macy * Test whether an exclusive advisory lock could be obtained for the open
81eda14cbcSMatt Macy * file descriptor [fd].
82eda14cbcSMatt Macy * Return 0 if the file is not locked, >0 for the PID of another process
83eda14cbcSMatt Macy * holding a conflicting lock, or -1 on error (with errno set).
84eda14cbcSMatt Macy */
85eda14cbcSMatt Macy pid_t
zed_file_is_locked(int fd)86eda14cbcSMatt Macy zed_file_is_locked(int fd)
87eda14cbcSMatt Macy {
88eda14cbcSMatt Macy struct flock lock;
89eda14cbcSMatt Macy
90eda14cbcSMatt Macy if (fd < 0) {
91eda14cbcSMatt Macy errno = EBADF;
92eda14cbcSMatt Macy return (-1);
93eda14cbcSMatt Macy }
94eda14cbcSMatt Macy lock.l_type = F_WRLCK;
95eda14cbcSMatt Macy lock.l_whence = SEEK_SET;
96eda14cbcSMatt Macy lock.l_start = 0;
97eda14cbcSMatt Macy lock.l_len = 0;
98eda14cbcSMatt Macy
99eda14cbcSMatt Macy if (fcntl(fd, F_GETLK, &lock) < 0)
100eda14cbcSMatt Macy return (-1);
101eda14cbcSMatt Macy
102eda14cbcSMatt Macy if (lock.l_type == F_UNLCK)
103eda14cbcSMatt Macy return (0);
104eda14cbcSMatt Macy
105eda14cbcSMatt Macy return (lock.l_pid);
106eda14cbcSMatt Macy }
107eda14cbcSMatt Macy
10816038816SMartin Matuska
10916038816SMartin Matuska #if __APPLE__
11016038816SMartin Matuska #define PROC_SELF_FD "/dev/fd"
11116038816SMartin Matuska #else /* Linux-compatible layout */
11216038816SMartin Matuska #define PROC_SELF_FD "/proc/self/fd"
11316038816SMartin Matuska #endif
11416038816SMartin Matuska
115eda14cbcSMatt Macy /*
116eda14cbcSMatt Macy * Close all open file descriptors greater than or equal to [lowfd].
117eda14cbcSMatt Macy * Any errors encountered while closing file descriptors are ignored.
118eda14cbcSMatt Macy */
119eda14cbcSMatt Macy void
zed_file_close_from(int lowfd)120eda14cbcSMatt Macy zed_file_close_from(int lowfd)
121eda14cbcSMatt Macy {
12216038816SMartin Matuska int errno_bak = errno;
12316038816SMartin Matuska int maxfd = 0;
124eda14cbcSMatt Macy int fd;
12516038816SMartin Matuska DIR *fddir;
12616038816SMartin Matuska struct dirent *fdent;
127eda14cbcSMatt Macy
12816038816SMartin Matuska if ((fddir = opendir(PROC_SELF_FD)) != NULL) {
12916038816SMartin Matuska while ((fdent = readdir(fddir)) != NULL) {
13016038816SMartin Matuska fd = atoi(fdent->d_name);
13116038816SMartin Matuska if (fd > maxfd && fd != dirfd(fddir))
13216038816SMartin Matuska maxfd = fd;
13316038816SMartin Matuska }
13416038816SMartin Matuska (void) closedir(fddir);
135eda14cbcSMatt Macy } else {
13616038816SMartin Matuska maxfd = sysconf(_SC_OPEN_MAX);
137eda14cbcSMatt Macy }
138eda14cbcSMatt Macy for (fd = lowfd; fd < maxfd; fd++)
139eda14cbcSMatt Macy (void) close(fd);
140eda14cbcSMatt Macy
141eda14cbcSMatt Macy errno = errno_bak;
142eda14cbcSMatt Macy }
143