Mercurial > minori
annotate src/core/filesystem.cc @ 398:650a9159a0e7
filesystem: implement win32 watchers
These are really nice :)
| author | Paper <paper@tflc.us> |
|---|---|
| date | Fri, 07 Nov 2025 14:32:11 -0500 |
| parents | 963047512d34 |
| children | a0bc3ae5164a |
| rev | line source |
|---|---|
| 36 | 1 #include "core/filesystem.h" |
| 15 | 2 #include "core/config.h" |
| 62 | 3 #include "core/strings.h" |
| 250 | 4 |
| 5 #include <QStandardPaths> | |
| 6 | |
|
135
0a458cb26ff4
filesystem: move to using std::filesystem after C++17 switch
Paper <mrpapersonic@gmail.com>
parents:
134
diff
changeset
|
7 #include <filesystem> |
| 2 | 8 |
| 398 | 9 #ifdef WIN32 |
| 10 # include <windows.h> | |
| 11 #endif | |
| 12 | |
| 11 | 13 namespace Filesystem { |
| 14 | |
|
135
0a458cb26ff4
filesystem: move to using std::filesystem after C++17 switch
Paper <mrpapersonic@gmail.com>
parents:
134
diff
changeset
|
15 /* this runs fs::create_directories() on the |
|
0a458cb26ff4
filesystem: move to using std::filesystem after C++17 switch
Paper <mrpapersonic@gmail.com>
parents:
134
diff
changeset
|
16 PARENT directory. */ |
| 369 | 17 void CreateDirectories(const std::filesystem::path &path) |
| 18 { | |
|
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
138
diff
changeset
|
19 if (path.empty()) |
|
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
138
diff
changeset
|
20 return; |
|
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
138
diff
changeset
|
21 |
| 369 | 22 const auto &parent = path.parent_path(); |
|
158
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
138
diff
changeset
|
23 if (!std::filesystem::exists(parent)) |
|
80d6b28eb29f
dep/animia: fix most X11 stuff
Paper <mrpapersonic@gmail.com>
parents:
138
diff
changeset
|
24 std::filesystem::create_directories(parent); |
| 11 | 25 } |
| 26 | |
| 369 | 27 std::filesystem::path GetDotPath() |
| 28 { | |
| 250 | 29 /* |
| 30 * Windows: ~/AppData/Roaming/Minori | |
| 31 * macOS: ~/Library/Application Support/Minori | |
| 32 * ...: ~/.config/minori | |
| 33 * | |
| 34 * FIXME: are windows and mac properly cased? | |
| 258 | 35 */ |
| 9 | 36 #ifdef WIN32 |
| 250 | 37 return Strings::ToUtf8String(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); |
| 38 #else | |
| 39 return Strings::ToUtf8String(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)); | |
| 40 #endif | |
|
45
4b05bc7668eb
filesystem: split config path into dotpath and config, add anime db path
Paper <mrpapersonic@gmail.com>
parents:
44
diff
changeset
|
41 } |
|
4b05bc7668eb
filesystem: split config path into dotpath and config, add anime db path
Paper <mrpapersonic@gmail.com>
parents:
44
diff
changeset
|
42 |
| 369 | 43 std::filesystem::path GetConfigPath() |
| 44 { | |
|
135
0a458cb26ff4
filesystem: move to using std::filesystem after C++17 switch
Paper <mrpapersonic@gmail.com>
parents:
134
diff
changeset
|
45 return GetDotPath() / CONFIG_NAME; |
|
118
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
106
diff
changeset
|
46 } |
|
39521c47c7a3
*: another huge megacommit, SORRY
Paper <mrpapersonic@gmail.com>
parents:
106
diff
changeset
|
47 |
| 369 | 48 std::filesystem::path GetAnimeDBPath() |
| 49 { | |
|
135
0a458cb26ff4
filesystem: move to using std::filesystem after C++17 switch
Paper <mrpapersonic@gmail.com>
parents:
134
diff
changeset
|
50 return GetDotPath() / "anime" / "db.json"; |
|
45
4b05bc7668eb
filesystem: split config path into dotpath and config, add anime db path
Paper <mrpapersonic@gmail.com>
parents:
44
diff
changeset
|
51 } |
|
4b05bc7668eb
filesystem: split config path into dotpath and config, add anime db path
Paper <mrpapersonic@gmail.com>
parents:
44
diff
changeset
|
52 |
| 369 | 53 std::filesystem::path GetTorrentsPath() |
| 54 { | |
|
230
2f5a9247e501
torrents: implement download button
Paper <paper@paper.us.eu.org>
parents:
221
diff
changeset
|
55 return GetDotPath() / "torrents"; |
|
2f5a9247e501
torrents: implement download button
Paper <paper@paper.us.eu.org>
parents:
221
diff
changeset
|
56 } |
|
2f5a9247e501
torrents: implement download button
Paper <paper@paper.us.eu.org>
parents:
221
diff
changeset
|
57 |
| 378 | 58 std::filesystem::path GetAnimePostersPath() |
| 59 { | |
| 60 return GetDotPath() / "anime" / "posters"; | |
| 61 } | |
| 62 | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
63 /* ------------------------------------------------------------------------ */ |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
64 /* Ehhhhh */ |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
65 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
66 class Watcher : public IWatcher { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
67 public: |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
68 Watcher(void *opaque, const std::filesystem::path &path, EventHandler handler) |
| 393 | 69 : path_(path), handler_(handler), opaque_(opaque) |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
70 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
71 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
72 |
| 393 | 73 virtual ~Watcher() override {} |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
74 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
75 protected: |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
76 std::filesystem::path path_; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
77 EventHandler handler_; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
78 void *opaque_; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
79 }; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
80 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
81 /* ------------------------------------------------------------------------ */ |
|
391
c3f717b7321b
filesystem: only iterate over the list once when erasing deleted files
Paper <paper@tflc.us>
parents:
382
diff
changeset
|
82 /* Filesystem watcher. |
|
c3f717b7321b
filesystem: only iterate over the list once when erasing deleted files
Paper <paper@tflc.us>
parents:
382
diff
changeset
|
83 * This is the portable version for non-Windows (of which the Windows |
|
c3f717b7321b
filesystem: only iterate over the list once when erasing deleted files
Paper <paper@tflc.us>
parents:
382
diff
changeset
|
84 * specific version hasn't been written yet... TODO) */ |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
85 |
| 398 | 86 /* |
| 87 We can't use std::recursive_directory_iterator! | |
| 88 Why? Well, to put it blunt, it sucks. The main reason | |
| 89 being is that if it finds a single directory it cannot | |
| 90 recurse into, instead of safely recovering, it just | |
| 91 completely stops. I am dumbfounded at this behavior, but | |
| 92 nevertheless it means we simply can't use it, and must | |
| 93 resort to old-fashioned recursion. --paper | |
| 94 */ | |
| 95 static void IterateDirectory(const std::filesystem::path &path, bool recursive, | |
| 96 std::function<void(const std::filesystem::path &path)> func) | |
| 97 { | |
| 98 std::error_code ec; | |
| 99 static const std::filesystem::directory_iterator end; | |
| 100 | |
| 101 for (std::filesystem::directory_iterator item(path, ec); item != end; item.increment(ec)) { | |
| 102 if (ec) | |
| 103 continue; | |
| 104 | |
| 105 std::filesystem::path p = item->path(); | |
| 106 | |
| 107 /* Hand the path off to the listener */ | |
| 108 func(p); | |
| 109 | |
| 110 /* If we're dealing with another directory, recurse into it. */ | |
| 111 if (recursive && item->is_directory()) | |
| 112 IterateDirectory(p, true, func); | |
| 113 } | |
| 114 } | |
| 115 | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
116 class StdFilesystemWatcher : public Watcher { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
117 public: |
| 398 | 118 StdFilesystemWatcher(void *opaque, const std::filesystem::path &path, EventHandler handler, bool recursive) |
| 119 : Watcher(opaque, path, handler), recursive_(recursive) | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
120 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
121 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
122 |
| 393 | 123 virtual ~StdFilesystemWatcher() override {} |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
124 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
125 virtual void Process() override |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
126 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
127 /* Untoggle all paths. This allows us to only ever |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
128 * iterate over the directory ONCE. */ |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
129 UntoggleAllPaths(); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
130 |
| 398 | 131 /* Start iterating directories. If we're recursive, this |
| 132 * will go through the whole tree. */ | |
| 133 IterateDirectory(path_, recursive_, [this](const std::filesystem::path &p) { | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
134 if (FindAndTogglePath(p)) |
| 398 | 135 return; |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
136 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
137 handler_(opaque_, p, Event::Created); |
| 398 | 138 paths_.insert({p, true}); |
| 139 }); | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
140 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
141 DeleteUntoggledPaths(); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
142 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
143 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
144 protected: |
|
391
c3f717b7321b
filesystem: only iterate over the list once when erasing deleted files
Paper <paper@tflc.us>
parents:
382
diff
changeset
|
145 bool FindAndTogglePath(const std::filesystem::path &p) |
|
c3f717b7321b
filesystem: only iterate over the list once when erasing deleted files
Paper <paper@tflc.us>
parents:
382
diff
changeset
|
146 { |
| 398 | 147 auto it = paths_.find(p); |
| 148 if (it == paths_.end()) | |
| 149 return false; | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
150 |
| 398 | 151 it->second = true; |
| 152 return true; | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
153 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
154 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
155 void UntoggleAllPaths() |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
156 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
157 for (auto &pp : paths_) |
| 398 | 158 pp.second = false; |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
159 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
160 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
161 void DeleteUntoggledPaths() |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
162 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
163 auto it = paths_.begin(); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
164 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
165 while (it != paths_.end()) { |
| 398 | 166 if (!it->second) { |
| 167 handler_(opaque_, it->first, Event::Deleted); | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
168 it = paths_.erase(it); |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
169 } else { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
170 it++; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
171 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
172 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
173 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
174 |
| 398 | 175 /* unordered hashmap, path[found] */ |
| 176 std::unordered_map<std::filesystem::path, bool> paths_; | |
| 177 bool recursive_; | |
| 178 }; | |
| 179 | |
| 180 #ifdef WIN32 | |
| 181 /* On Windows, we can ask the OS whether the folder has changed or not. | |
| 182 * This is great for us! */ | |
| 183 class Win32Watcher : public StdFilesystemWatcher { | |
| 184 public: | |
| 185 Win32Watcher(void *opaque, const std::filesystem::path &path, IWatcher::EventHandler handler, bool recursive) | |
| 186 : StdFilesystemWatcher(opaque, path, handler, recursive), dirwatcher_(INVALID_HANDLE_VALUE), first_(true) | |
| 187 { | |
| 188 } | |
| 189 | |
| 190 virtual ~Win32Watcher() override | |
| 191 { | |
| 192 // delete handle | |
| 193 if (dirwatcher_ != INVALID_HANDLE_VALUE) | |
| 194 FindCloseChangeNotification(dirwatcher_); | |
| 195 } | |
| 196 | |
| 197 virtual void Process() override | |
| 198 { | |
| 199 if (first_ || dirwatcher_ == INVALID_HANDLE_VALUE) { | |
| 200 /* We want to create this right before iteration so | |
| 201 * we minimize possible race conditions while also | |
| 202 * reducing unnecessary processing */ | |
| 203 TryCreateDirWatcher(); | |
| 204 StdFilesystemWatcher::Process(); | |
| 205 first_ = false; | |
| 206 return; | |
| 207 } | |
| 208 | |
| 209 /* We have a valid handle */ | |
| 210 if (WaitForSingleObject(dirwatcher_, 0) != WAIT_OBJECT_0) | |
| 211 return; | |
| 212 | |
| 213 StdFilesystemWatcher::Process(); | |
| 214 FindNextChangeNotification(dirwatcher_); | |
| 215 } | |
| 216 | |
| 217 protected: | |
| 218 bool TryCreateDirWatcher() | |
| 219 { | |
| 220 dirwatcher_ = FindFirstChangeNotificationW(Watcher::path_.wstring().c_str(), recursive_, | |
| 221 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME); | |
| 222 | |
| 223 return (dirwatcher_ != INVALID_HANDLE_VALUE); | |
| 224 } | |
| 225 | |
| 226 /* variables */ | |
| 227 HANDLE dirwatcher_; | |
| 228 bool first_; | |
| 229 }; | |
| 230 | |
| 231 class Win32WatcherVista : public Win32Watcher { | |
| 232 public: | |
| 233 Win32WatcherVista(void *opaque, const std::filesystem::path &path, IWatcher::EventHandler handler, bool recursive) | |
| 234 : Win32Watcher(opaque, path, handler, recursive), dirhandle_(INVALID_HANDLE_VALUE) | |
| 235 { | |
| 236 overlapped_.hEvent = nullptr; | |
| 237 } | |
| 238 | |
| 239 virtual ~Win32WatcherVista() override | |
| 240 { | |
| 241 if (dirhandle_ != INVALID_HANDLE_VALUE) | |
| 242 CloseHandle(dirhandle_); | |
| 243 | |
| 244 if (overlapped_.hEvent != nullptr) | |
| 245 CloseHandle(overlapped_.hEvent); | |
| 246 } | |
| 247 | |
| 248 virtual void Process() override | |
| 249 { | |
| 250 if (first_) { | |
| 251 if (TryCreateHandles()) { | |
| 252 /* Queue a directory read asynchronously. On the next run, this will | |
| 253 * be waited on. */ | |
| 254 QueueDirectoryRead(); | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
255 |
| 398 | 256 /* Avoid running Win32Watcher::Process, as it will read the whole |
| 257 * directory tree into memory. Instead, iterate through the directory | |
| 258 * ourselves. */ | |
| 259 IterateDirectory(path_, recursive_, | |
| 260 [this](const std::filesystem::path &p) { handler_(opaque_, p, Event::Created); }); | |
| 261 } else { | |
| 262 /* Uh oh; we might have to fall back to Win32Watcher. Call into it to | |
| 263 * load the tree into memory. */ | |
| 264 Win32Watcher::Process(); | |
| 265 } | |
| 266 | |
| 267 first_ = false; | |
| 268 return; | |
| 269 } | |
| 270 | |
| 271 if (!HandlesAreValid()) { | |
| 272 /* If we're here, we already fell back into Win32Watcher, so just | |
| 273 * call back into again. On the slim chance TryCreateHandles() might | |
| 274 * succeed, call it as well... */ | |
| 275 if (TryCreateHandles()) | |
| 276 QueueDirectoryRead(); | |
| 277 Win32Watcher::Process(); | |
| 278 return; | |
| 279 } | |
| 280 | |
| 281 if (WaitForSingleObject(overlapped_.hEvent, 0) != WAIT_OBJECT_0) | |
| 282 return; | |
| 283 | |
| 284 FILE_NOTIFY_INFORMATION *ev = reinterpret_cast<FILE_NOTIFY_INFORMATION *>(change_buf_); | |
| 285 | |
| 286 for (;;) { | |
| 287 /* Tack on the file name to the end of our path */ | |
| 288 std::filesystem::path p = Watcher::path_ / std::wstring(ev->FileName, ev->FileNameLength / sizeof(WCHAR)); | |
| 289 | |
| 290 switch (ev->Action) { | |
| 291 case FILE_ACTION_ADDED: | |
| 292 case FILE_ACTION_RENAMED_NEW_NAME: | |
| 293 /* File was added */ | |
| 294 handler_(opaque_, p, Event::Created); | |
| 295 break; | |
| 296 case FILE_ACTION_REMOVED: | |
| 297 case FILE_ACTION_RENAMED_OLD_NAME: | |
| 298 /* File was removed */ | |
| 299 handler_(opaque_, p, Event::Deleted); | |
| 300 break; | |
| 301 } | |
| 302 | |
| 303 if (ev->NextEntryOffset) { | |
| 304 /* ugh ugh ugh ugh */ | |
| 305 ev = reinterpret_cast<FILE_NOTIFY_INFORMATION *>(reinterpret_cast<char *>(ev) + ev->NextEntryOffset); | |
| 306 } else { | |
| 307 break; | |
| 308 } | |
| 309 } | |
| 310 | |
| 311 /* Queue a directory read for the next call */ | |
| 312 QueueDirectoryRead(); | |
| 313 } | |
| 314 | |
| 315 protected: | |
| 316 bool HandlesAreValid() { return (overlapped_.hEvent && dirhandle_ != INVALID_HANDLE_VALUE); } | |
| 317 | |
| 318 bool TryCreateHandles() | |
| 319 { | |
| 320 if (!overlapped_.hEvent) { | |
| 321 overlapped_.hEvent = CreateEventW(nullptr, FALSE, 0, nullptr); | |
| 322 if (!overlapped_.hEvent) | |
| 323 return false; | |
| 324 } | |
| 325 | |
| 326 if (dirhandle_ == INVALID_HANDLE_VALUE) { | |
| 327 dirhandle_ = | |
| 328 CreateFileW(Watcher::path_.wstring().c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, | |
| 329 nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); | |
| 330 if (dirhandle_ == INVALID_HANDLE_VALUE) | |
| 331 return false; | |
| 332 } | |
| 333 | |
| 334 /* We're done here */ | |
| 335 return true; | |
| 336 } | |
| 337 | |
| 338 bool QueueDirectoryRead() | |
| 339 { | |
| 340 return ReadDirectoryChangesW(dirhandle_, change_buf_, sizeof(change_buf_), TRUE, | |
| 341 FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME, nullptr, &overlapped_, | |
| 342 nullptr); | |
| 343 } | |
| 344 | |
| 345 HANDLE dirhandle_; | |
| 346 OVERLAPPED overlapped_; | |
| 347 alignas(FILE_NOTIFY_INFORMATION) char change_buf_[4096]; | |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
348 }; |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
349 |
| 398 | 350 using DefaultWatcher = Win32WatcherVista; |
| 351 #else | |
| 352 using DefaultWatcher = StdFilesystemWatcher; | |
| 353 #endif | |
| 354 | |
| 393 | 355 IWatcher *GetRecursiveFilesystemWatcher(void *opaque, const std::filesystem::path &path, IWatcher::EventHandler handler) |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
356 { |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
357 /* .... :) */ |
| 398 | 358 return new DefaultWatcher(opaque, path, handler, true); |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
359 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
360 |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
361 IWatcher *GetFilesystemWatcher(void *opaque, const std::filesystem::path &path, IWatcher::EventHandler handler) |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
362 { |
| 398 | 363 return new DefaultWatcher(opaque, path, handler, false); |
|
382
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
364 } |
|
0265e125f680
filesystem: implement filesystem watcher
Paper <paper@tflc.us>
parents:
378
diff
changeset
|
365 |
| 15 | 366 } // namespace Filesystem |
