2 * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "launchpad-process-pool/file_monitor.hh"
19 #include "lib/common/inc/launchpad_common.h"
23 namespace fs = std::filesystem;
25 gboolean FileMonitor::OnEventReceived(GIOChannel* channel,
28 char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event))));
31 struct inotify_event* event;
32 auto event_listener = reinterpret_cast<FileMonitor*>(user_data);
33 int fd = g_io_channel_unix_get_fd(channel);
35 while ((len = read(fd, buf, sizeof(buf))) > 0) {
36 for (ptr = buf; ptr < buf + len;
37 ptr += sizeof(struct inotify_event) + event->len) {
38 event = reinterpret_cast<struct inotify_event*>(ptr);
39 char* nptr = ptr + sizeof(struct inotify_event) + event->len;
43 if (!event->len || event_listener->file_name_ != event->name)
46 if (event->mask & IN_CREATE) {
47 if (event_listener->listener_)
48 event_listener->listener_->OnFileChanged(FileMonitorEvent::Created);
49 } else if (event->mask & IN_MODIFY) {
50 if (event_listener->listener_)
51 event_listener->listener_->OnFileChanged(FileMonitorEvent::Modified);
52 } else if (event->mask & IN_DELETE) {
53 if (event_listener->listener_)
54 event_listener->listener_->OnFileChanged(FileMonitorEvent::Deleted);
57 return G_SOURCE_CONTINUE;
61 return G_SOURCE_CONTINUE;
64 FileMonitor::FileMonitor(const std::string_view file_path,
65 FileMonitor::IEvent* listener)
66 : listener_(listener) {
67 fs::path path(file_path);
68 parent_path_ = path.parent_path();
69 file_name_ = path.filename();
70 if (!fs::exists(parent_path_)) {
71 if (!fs::create_directories(parent_path_)) {
72 _E("Failed to create directory. %s", parent_path_.c_str());
77 if (fs::exists(path)) {
79 listener_->OnFileChanged(FileMonitor::FileMonitorEvent::Created);
82 fd_ = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
85 _E("Failed to inotify_init. errno: %d", ret);
90 wd_ = inotify_add_watch(fd_, parent_path_.c_str(),
91 IN_CREATE | IN_MODIFY | IN_DELETE);
94 _E("Failed to inotify_add_watch. errno: %d", ret);
99 channel_ = g_io_channel_unix_new(fd_);
100 if (channel_ == nullptr) {
101 _E("Failed to create GIO channel");
106 g_io_channel_set_close_on_unref(channel_, false);
107 tag_ = g_io_add_watch(channel_, G_IO_IN, OnEventReceived, this);
109 _E("Failed to add watch");
117 FileMonitor::~FileMonitor() {
121 void FileMonitor::Dispose() {
126 g_source_remove(tag_);
130 if (channel_ != nullptr) {
131 g_io_channel_unref(channel_);
136 inotify_rm_watch(fd_, wd_);
148 } // namespace launchpad