1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef OHOS_FILE_FS_WATCHER_IMPL_H
17#define OHOS_FILE_FS_WATCHER_IMPL_H
18
19#include <mutex>
20#include <sys/inotify.h>
21#include <unordered_map>
22#include <unordered_set>
23
24#include "uni_error.h"
25#include "ffi_remote_data.h"
26#include "cj_common_ffi.h"
27#include "cj_lambda.h"
28#include "singleton.h"
29
30namespace OHOS {
31namespace CJSystemapi {
32constexpr int BUF_SIZE = 1024;
33
34struct CWatchEvent {
35    char* fileName;
36    uint32_t event;
37    uint32_t cookie;
38};
39struct WatcherInfoArg {
40    std::string fileName = "";
41    uint32_t events = 0;
42    int wd = -1;
43    int64_t callbackId = -1;
44    std::function<void(CWatchEvent)> watchCallback_;
45    explicit WatcherInfoArg(void (*callback)(CWatchEvent))
46    {
47        watchCallback_ = CJLambda::Create(callback);
48        callbackId = reinterpret_cast<int64_t>(callback);
49    }
50    ~WatcherInfoArg() = default;
51};
52
53class WatcherImpl : public OHOS::FFI::FFIData {
54public:
55    std::shared_ptr<WatcherInfoArg> data_;
56    OHOS::FFI::RuntimeType* GetRuntimeType() override { return GetClassType(); }
57private:
58    friend class OHOS::FFI::RuntimeType;
59    friend class OHOS::FFI::TypeBase;
60    static OHOS::FFI::RuntimeType* GetClassType()
61    {
62        static OHOS::FFI::RuntimeType runtimeType = OHOS::FFI::RuntimeType::Create<OHOS::FFI::FFIData>("WatcherImpl");
63        return &runtimeType;
64    }
65};
66
67class FileWatcherManager : public Singleton<FileWatcherManager> {
68public:
69    FileWatcherManager();
70    ~FileWatcherManager();
71    FileWatcherManager(FileWatcherManager const &) = delete;
72    void operator=(FileWatcherManager const &) = delete;
73
74    int32_t GetNotifyId();
75    bool InitNotify();
76    bool AddWatcherInfo(const std::string &fileName, std::shared_ptr<WatcherInfoArg> arg);
77    bool CheckEventValid(const uint32_t &event);
78    int32_t StartNotify(std::shared_ptr<WatcherInfoArg> arg);
79    void GetNotifyEvent(std::shared_ptr<WatcherInfoArg> arg);
80    void ReadNotifyEvent(std::function<void(CWatchEvent)> callback);
81    int32_t StopNotify(std::shared_ptr<WatcherInfoArg> arg);
82
83private:
84    uint32_t RemoveWatcherInfo(std::shared_ptr<WatcherInfoArg> arg);
85    std::tuple<bool, int> CheckEventWatched(const std::string &fileName, const uint32_t &event);
86    void NotifyEvent(const struct inotify_event *event, std::function<void(CWatchEvent)> callback);
87    int CloseNotifyFd();
88    int NotifyToWatchNewEvents(const std::string &fileName, const int &wd, const uint32_t &watchEvents);
89
90private:
91    static std::mutex watchMutex_;
92    bool run_ = false;
93    int32_t notifyFd_ = -1;
94    int32_t eventFd_ = -1;
95    std::unordered_set<std::shared_ptr<WatcherInfoArg>> watcherInfoSet_;
96    std::unordered_map<std::string, std::pair<int, uint32_t>> wdFileNameMap_;
97};
98} // OHOS::FileManagement::ModuleFileIO
99}
100
101#endif // OHOS_FILE_FS_IMPL_H