| 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 |