OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_LINUX) | 6 #if defined(TARGET_OS_LINUX) |
7 | 7 |
8 #include "bin/file_system_watcher.h" | 8 #include "bin/file_system_watcher.h" |
9 | 9 |
10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
11 #include <sys/inotify.h> // NOLINT | 11 #include <sys/inotify.h> // NOLINT |
12 | 12 |
13 #include "bin/fdutils.h" | 13 #include "bin/fdutils.h" |
14 #include "bin/socket.h" | 14 #include "bin/socket.h" |
15 | |
16 #include "platform/signal_blocker.h" | 15 #include "platform/signal_blocker.h" |
17 | 16 |
18 | |
19 namespace dart { | 17 namespace dart { |
20 namespace bin { | 18 namespace bin { |
21 | 19 |
22 bool FileSystemWatcher::IsSupported() { | 20 bool FileSystemWatcher::IsSupported() { |
23 return true; | 21 return true; |
24 } | 22 } |
25 | 23 |
26 | 24 |
27 intptr_t FileSystemWatcher::Init() { | 25 intptr_t FileSystemWatcher::Init() { |
28 int id = NO_RETRY_EXPECTED(inotify_init1(IN_CLOEXEC)); | 26 int id = NO_RETRY_EXPECTED(inotify_init1(IN_CLOEXEC)); |
29 if (id < 0) return -1; | 27 if (id < 0) { |
| 28 return -1; |
| 29 } |
30 // Some systems dosn't support setting this as non-blocking. Since watching | 30 // Some systems dosn't support setting this as non-blocking. Since watching |
31 // internals are kept away from the user, we know it's possible to continue, | 31 // internals are kept away from the user, we know it's possible to continue, |
32 // even if setting non-blocking fails. | 32 // even if setting non-blocking fails. |
33 FDUtils::SetNonBlocking(id); | 33 FDUtils::SetNonBlocking(id); |
34 return id; | 34 return id; |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 void FileSystemWatcher::Close(intptr_t id) { | 38 void FileSystemWatcher::Close(intptr_t id) { |
39 USE(id); | 39 USE(id); |
40 } | 40 } |
41 | 41 |
42 | 42 |
43 intptr_t FileSystemWatcher::WatchPath(intptr_t id, | 43 intptr_t FileSystemWatcher::WatchPath(intptr_t id, |
44 const char* path, | 44 const char* path, |
45 int events, | 45 int events, |
46 bool recursive) { | 46 bool recursive) { |
47 int list_events = IN_DELETE_SELF | IN_MOVE_SELF; | 47 int list_events = IN_DELETE_SELF | IN_MOVE_SELF; |
48 if (events & kCreate) list_events |= IN_CREATE; | 48 if (events & kCreate) { |
49 if (events & kModifyContent) list_events |= IN_CLOSE_WRITE | IN_ATTRIB; | 49 list_events |= IN_CREATE; |
50 if (events & kDelete) list_events |= IN_DELETE; | 50 } |
51 if (events & kMove) list_events |= IN_MOVE; | 51 if (events & kModifyContent) { |
| 52 list_events |= IN_CLOSE_WRITE | IN_ATTRIB; |
| 53 } |
| 54 if (events & kDelete) { |
| 55 list_events |= IN_DELETE; |
| 56 } |
| 57 if (events & kMove) { |
| 58 list_events |= IN_MOVE; |
| 59 } |
52 int path_id = NO_RETRY_EXPECTED(inotify_add_watch(id, path, list_events)); | 60 int path_id = NO_RETRY_EXPECTED(inotify_add_watch(id, path, list_events)); |
53 if (path_id < 0) { | 61 if (path_id < 0) { |
54 return -1; | 62 return -1; |
55 } | 63 } |
56 return path_id; | 64 return path_id; |
57 } | 65 } |
58 | 66 |
59 | 67 |
60 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) { | 68 void FileSystemWatcher::UnwatchPath(intptr_t id, intptr_t path_id) { |
61 VOID_NO_RETRY_EXPECTED(inotify_rm_watch(id, path_id)); | 69 VOID_NO_RETRY_EXPECTED(inotify_rm_watch(id, path_id)); |
62 } | 70 } |
63 | 71 |
64 | 72 |
65 intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) { | 73 intptr_t FileSystemWatcher::GetSocketId(intptr_t id, intptr_t path_id) { |
66 USE(path_id); | 74 USE(path_id); |
67 return id; | 75 return id; |
68 } | 76 } |
69 | 77 |
70 | 78 |
| 79 static int InotifyEventToMask(struct inotify_event* e) { |
| 80 int mask = 0; |
| 81 if (e->mask & IN_CLOSE_WRITE) { |
| 82 mask |= FileSystemWatcher::kModifyContent; |
| 83 } |
| 84 if (e->mask & IN_ATTRIB) { |
| 85 mask |= FileSystemWatcher::kModefyAttribute; |
| 86 } |
| 87 if (e->mask & IN_CREATE) { |
| 88 mask |= FileSystemWatcher::kCreate; |
| 89 } |
| 90 if (e->mask & IN_MOVE) { |
| 91 mask |= FileSystemWatcher::kMove; |
| 92 } |
| 93 if (e->mask & IN_DELETE) { |
| 94 mask |= FileSystemWatcher::kDelete; |
| 95 } |
| 96 if (e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) { |
| 97 mask |= FileSystemWatcher::kDeleteSelf; |
| 98 } |
| 99 if (e->mask & IN_ISDIR) { |
| 100 mask |= FileSystemWatcher::kIsDir; |
| 101 } |
| 102 return mask; |
| 103 } |
| 104 |
| 105 |
71 Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) { | 106 Dart_Handle FileSystemWatcher::ReadEvents(intptr_t id, intptr_t path_id) { |
72 USE(path_id); | 107 USE(path_id); |
73 const intptr_t kEventSize = sizeof(struct inotify_event); | 108 const intptr_t kEventSize = sizeof(struct inotify_event); |
74 const intptr_t kBufferSize = kEventSize + NAME_MAX + 1; | 109 const intptr_t kBufferSize = kEventSize + NAME_MAX + 1; |
75 uint8_t buffer[kBufferSize]; | 110 uint8_t buffer[kBufferSize]; |
76 intptr_t bytes = Socket::Read(id, buffer, kBufferSize); | 111 intptr_t bytes = Socket::Read(id, buffer, kBufferSize); |
77 if (bytes < 0) { | 112 if (bytes < 0) { |
78 return DartUtils::NewDartOSError(); | 113 return DartUtils::NewDartOSError(); |
79 } | 114 } |
80 const intptr_t kMaxCount = bytes / kEventSize; | 115 const intptr_t kMaxCount = bytes / kEventSize; |
81 Dart_Handle events = Dart_NewList(kMaxCount); | 116 Dart_Handle events = Dart_NewList(kMaxCount); |
82 intptr_t offset = 0; | 117 intptr_t offset = 0; |
83 intptr_t i = 0; | 118 intptr_t i = 0; |
84 while (offset < bytes) { | 119 while (offset < bytes) { |
85 struct inotify_event* e = | 120 struct inotify_event* e = |
86 reinterpret_cast<struct inotify_event*>(buffer + offset); | 121 reinterpret_cast<struct inotify_event*>(buffer + offset); |
87 if ((e->mask & IN_IGNORED) == 0) {; | 122 if ((e->mask & IN_IGNORED) == 0) {; |
88 Dart_Handle event = Dart_NewList(5); | 123 Dart_Handle event = Dart_NewList(5); |
89 int mask = 0; | 124 int mask = InotifyEventToMask(e); |
90 if (e->mask & IN_CLOSE_WRITE) mask |= kModifyContent; | |
91 if (e->mask & IN_ATTRIB) mask |= kModefyAttribute; | |
92 if (e->mask & IN_CREATE) mask |= kCreate; | |
93 if (e->mask & IN_MOVE) mask |= kMove; | |
94 if (e->mask & IN_DELETE) mask |= kDelete; | |
95 if (e->mask & (IN_DELETE_SELF | IN_MOVE_SELF)) mask |= kDeleteSelf; | |
96 if (e->mask & IN_ISDIR) mask |= kIsDir; | |
97 Dart_ListSetAt(event, 0, Dart_NewInteger(mask)); | 125 Dart_ListSetAt(event, 0, Dart_NewInteger(mask)); |
98 Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie)); | 126 Dart_ListSetAt(event, 1, Dart_NewInteger(e->cookie)); |
99 if (e->len > 0) { | 127 if (e->len > 0) { |
100 Dart_ListSetAt(event, 2, Dart_NewStringFromUTF8( | 128 Dart_ListSetAt(event, 2, Dart_NewStringFromUTF8( |
101 reinterpret_cast<uint8_t*>(e->name), strlen(e->name))); | 129 reinterpret_cast<uint8_t*>(e->name), strlen(e->name))); |
102 } else { | 130 } else { |
103 Dart_ListSetAt(event, 2, Dart_Null()); | 131 Dart_ListSetAt(event, 2, Dart_Null()); |
104 } | 132 } |
105 Dart_ListSetAt(event, 3, Dart_NewBoolean(e->mask & IN_MOVED_TO)); | 133 Dart_ListSetAt(event, 3, Dart_NewBoolean(e->mask & IN_MOVED_TO)); |
106 Dart_ListSetAt(event, 4, Dart_NewInteger(e->wd)); | 134 Dart_ListSetAt(event, 4, Dart_NewInteger(e->wd)); |
107 Dart_ListSetAt(events, i, event); | 135 Dart_ListSetAt(events, i, event); |
108 i++; | 136 i++; |
109 } | 137 } |
110 offset += kEventSize + e->len; | 138 offset += kEventSize + e->len; |
111 } | 139 } |
112 ASSERT(offset == bytes); | 140 ASSERT(offset == bytes); |
113 return events; | 141 return events; |
114 } | 142 } |
115 | 143 |
116 } // namespace bin | 144 } // namespace bin |
117 } // namespace dart | 145 } // namespace dart |
118 | 146 |
119 #endif // defined(TARGET_OS_LINUX) | 147 #endif // defined(TARGET_OS_LINUX) |
OLD | NEW |