Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libc/port/sys/inotify.c
+++ new/usr/src/lib/libc/port/sys/inotify.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
14 14 */
15 15
16 16 #include <sys/inotify.h>
17 17 #include <sys/stat.h>
18 18 #include <unistd.h>
19 19 #include <errno.h>
20 20 #include <fcntl.h>
21 21 #include <strings.h>
22 22 #include <dirent.h>
23 23
24 24 int
25 25 inotify_init()
26 26 {
27 27 return (open("/dev/inotify", O_RDWR));
28 28 }
29 29
30 30 int
31 31 inotify_init1(int flags)
32 32 {
33 33 int oflags = O_RDWR;
34 34
35 35 if (flags & IN_NONBLOCK)
36 36 oflags |= O_NONBLOCK;
37 37
38 38 if (flags & IN_CLOEXEC)
39 39 oflags |= O_CLOEXEC;
40 40
41 41 return (open("/dev/inotify", oflags));
42 42 }
43 43
44 44 int
45 45 inotify_add_watch(int fd, const char *pathname, uint32_t mask)
46 46 {
47 47 inotify_addwatch_t ioc;
48 48 inotify_addchild_t cioc;
49 49 struct stat buf;
50 50 int dirfd, wd;
51 51 DIR *dir;
52 52 struct dirent *dp;
53 53 int oflags = O_RDONLY;
54 54
55 55 if (mask & IN_DONT_FOLLOW)
56 56 oflags |= O_NOFOLLOW;
57 57
58 58 if ((dirfd = open(pathname, oflags)) < 0)
59 59 return (-1);
60 60
61 61 if (fstat(dirfd, &buf) != 0) {
62 62 (void) close(dirfd);
63 63 return (-1);
64 64 }
65 65
66 66 if ((mask & IN_ONLYDIR) && !(buf.st_mode & S_IFDIR)) {
67 67 (void) close(dirfd);
68 68 errno = ENOTDIR;
69 69 return (-1);
70 70 }
71 71
72 72 bzero(&ioc, sizeof (ioc));
73 73 ioc.inaw_fd = dirfd;
74 74 ioc.inaw_mask = mask;
75 75
76 76 if ((wd = ioctl(fd, INOTIFYIOC_ADD_WATCH, &ioc)) < 0) {
77 77 (void) close(dirfd);
78 78 return (-1);
79 79 }
80 80
81 81 if (!(buf.st_mode & S_IFDIR) || !(mask & IN_CHILD_EVENTS)) {
82 82 (void) close(dirfd);
83 83 (void) ioctl(fd, INOTIFYIOC_ACTIVATE, wd);
84 84 return (wd);
85 85 }
86 86
87 87 /*
88 88 * If we have a directory and we have a mask that denotes child events,
89 89 * we need to manually add a child watch to every directory entry.
90 90 * (Because our watch is in place, it will automatically be added to
91 91 * files that are newly created after this point.)
92 92 */
93 93 if ((dir = fdopendir(dirfd)) == NULL) {
94 94 (void) inotify_rm_watch(fd, wd);
95 95 (void) close(dirfd);
96 96 return (-1);
97 97 }
98 98
99 99 bzero(&cioc, sizeof (cioc));
100 100 cioc.inac_fd = dirfd;
101 101
102 102 while ((dp = readdir(dir)) != NULL) {
103 103 if (strcmp(dp->d_name, ".") == 0)
104 104 continue;
105 105
106 106 if (strcmp(dp->d_name, "..") == 0)
107 107 continue;
108 108
109 109 cioc.inac_name = dp->d_name;
110 110
111 111 if (ioctl(fd, INOTIFYIOC_ADD_CHILD, &cioc) != 0) {
112 112 /*
113 113 * If we get an error that indicates clear internal
114 114 * malfunctioning, we propagate the error. Otherwise
115 115 * we eat it: this could be a file that no longer
116 116 * exists or a symlink or something else that we
117 117 * can't lookup.
118 118 */
119 119 switch (errno) {
120 120 case ENXIO:
121 121 case EFAULT:
122 122 case EBADF:
123 123 (void) closedir(dir);
124 124 (void) inotify_rm_watch(fd, wd);
125 125 return (-1);
126 126 default:
127 127 break;
128 128 }
129 129 }
130 130 }
131 131
132 132 (void) closedir(dir);
133 133 (void) ioctl(fd, INOTIFYIOC_ACTIVATE, wd);
134 134
135 135 return (wd);
136 136 }
137 137
138 138 int
139 139 inotify_rm_watch(int fd, int wd)
140 140 {
141 141 return (ioctl(fd, INOTIFYIOC_RM_WATCH, wd));
142 142 }
|
↓ open down ↓ |
142 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX