1/*
2 * Copyright (c) 2023 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/**
17 * @file mapped_file.h
18 *
19 * @brief Provides classes for memory-mapped files implemented in c_utils.
20 */
21
22#ifndef UTILS_BASE_MAPPED_FILE_H
23#define UTILS_BASE_MAPPED_FILE_H
24
25#include <cstdint>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <string>
29#include <unistd.h>
30#include "errors.h"
31
32namespace OHOS {
33namespace Utils {
34
35enum class MapMode : uint8_t {
36    DEFAULT = 0,
37    PRIVATE = 2,
38    SHARED = DEFAULT,
39    READ_ONLY = 4,
40    READ_WRITE = DEFAULT,
41    CREATE_IF_ABSENT = 8
42};
43
44class MappedFile {
45public:
46    static constexpr off_t DEFAULT_LENGTH = -1LL;
47
48    // constructors and assignment operators
49    explicit MappedFile(std::string& path,
50                        MapMode mode = MapMode::DEFAULT,
51                        off_t offset = 0,
52                        off_t size = DEFAULT_LENGTH,
53                        const char *hint = nullptr);
54
55    MappedFile(const MappedFile& other) = delete;
56    MappedFile(MappedFile&& other) noexcept;
57    MappedFile& operator=(const MappedFile& other) = delete;
58    MappedFile& operator=(MappedFile&& other) noexcept;
59    virtual ~MappedFile();
60
61    // mapping
62    ErrCode Normalize();
63    ErrCode Map();
64    ErrCode Unmap();
65    ErrCode TurnNext();
66    ErrCode Resize();
67    ErrCode Resize(off_t newSize, bool sync = false);
68    ErrCode Clear(bool force = false);
69
70    // info
71    inline off_t Size() const
72    {
73        return size_;
74    }
75
76    inline off_t StartOffset() const
77    {
78        return offset_;
79    }
80
81    inline off_t EndOffset() const
82    {
83        return size_ == DEFAULT_LENGTH ? -1LL : offset_ + size_ - 1LL;
84    }
85
86    inline static off_t PageSize()
87    {
88        return pageSize_;
89    }
90
91    inline char* Begin() const
92    {
93        return data_;
94    }
95
96    inline char* End() const
97    {
98        return data_ == nullptr ? nullptr : data_ + size_ - 1;
99    }
100
101    inline char* RegionStart() const
102    {
103        return rStart_;
104    }
105
106    inline char* RegionEnd() const
107    {
108        return rEnd_;
109    }
110
111    inline bool IsMapped() const
112    {
113        return isMapped_;
114    }
115
116    inline bool IsNormed() const
117    {
118        return isNormed_;
119    }
120
121    inline const std::string& GetPath() const
122    {
123        return path_;
124    }
125
126    inline const char* GetHint() const
127    {
128        return hint_;
129    }
130
131    inline MapMode GetMode() const
132    {
133        return mode_;
134    }
135
136    inline int GetFd() const
137    {
138        return fd_;
139    }
140
141    bool ChangeOffset(off_t offset);
142    bool ChangeSize(off_t size);
143    bool ChangePath(const std::string& path);
144    bool ChangeHint(const char* hint);
145    bool ChangeMode(MapMode mode);
146
147private:
148    inline static off_t RoundSize(off_t input)
149    {
150        return (input % PageSize() == 0) ? input : (input / PageSize() + 1) * PageSize();
151    }
152
153    bool ValidMappedSize(off_t& targetSize, const struct stat& stat);
154    bool NormalizePath();
155    bool NormalizeSize();
156    void NormalizeMode();
157    bool OpenFile();
158    bool SyncFileSize(off_t newSize);
159    void Reset();
160
161    char* data_ = nullptr;
162    char* rStart_ = nullptr;
163    char* rEnd_ = nullptr;
164    bool isMapped_ = false;
165    bool isNormed_ = false;
166    bool isNewFile_ = false;
167
168    std::string path_;
169    off_t size_;
170    static off_t pageSize_;
171    off_t offset_;
172    MapMode mode_;
173    int fd_ = -1;
174    int mapProt_ = 0;
175    int mapFlag_ = 0;
176    int openFlag_ = 0;
177    const char *hint_;
178};
179
180inline MapMode operator&(MapMode a, MapMode b)
181{
182    return static_cast<MapMode>(static_cast<uint8_t>(a) & static_cast<uint8_t>(b));
183}
184
185inline MapMode operator|(MapMode a, MapMode b)
186{
187    return static_cast<MapMode>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
188}
189
190inline MapMode operator^(MapMode a, MapMode b)
191{
192    return static_cast<MapMode>(static_cast<uint8_t>(a) ^ static_cast<uint8_t>(b));
193}
194
195inline MapMode operator~(MapMode a)
196{
197    return static_cast<MapMode>(~static_cast<uint8_t>(a));
198}
199
200inline MapMode& operator|=(MapMode& a, MapMode b)
201{
202    return a = a | b;
203}
204
205inline MapMode& operator&=(MapMode& a, MapMode b)
206{
207    return a = a & b;
208}
209
210inline MapMode& operator^=(MapMode& a, MapMode b)
211{
212    return a = a ^ b;
213}
214
215} // namespace Utils
216} // namespace OHOS
217#endif