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 
32 namespace OHOS {
33 namespace Utils {
34 
35 enum 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 
44 class MappedFile {
45 public:
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
Size()71     inline off_t Size() const
72     {
73         return size_;
74     }
75 
StartOffset()76     inline off_t StartOffset() const
77     {
78         return offset_;
79     }
80 
EndOffset()81     inline off_t EndOffset() const
82     {
83         return size_ == DEFAULT_LENGTH ? -1LL : offset_ + size_ - 1LL;
84     }
85 
PageSize()86     inline static off_t PageSize()
87     {
88         return pageSize_;
89     }
90 
Begin()91     inline char* Begin() const
92     {
93         return data_;
94     }
95 
End()96     inline char* End() const
97     {
98         return data_ == nullptr ? nullptr : data_ + size_ - 1;
99     }
100 
RegionStart()101     inline char* RegionStart() const
102     {
103         return rStart_;
104     }
105 
RegionEnd()106     inline char* RegionEnd() const
107     {
108         return rEnd_;
109     }
110 
IsMapped()111     inline bool IsMapped() const
112     {
113         return isMapped_;
114     }
115 
IsNormed()116     inline bool IsNormed() const
117     {
118         return isNormed_;
119     }
120 
GetPath()121     inline const std::string& GetPath() const
122     {
123         return path_;
124     }
125 
GetHint()126     inline const char* GetHint() const
127     {
128         return hint_;
129     }
130 
GetMode()131     inline MapMode GetMode() const
132     {
133         return mode_;
134     }
135 
GetFd()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 
147 private:
RoundSize(off_t input)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 
180 inline MapMode operator&(MapMode a, MapMode b)
181 {
182     return static_cast<MapMode>(static_cast<uint8_t>(a) & static_cast<uint8_t>(b));
183 }
184 
185 inline MapMode operator|(MapMode a, MapMode b)
186 {
187     return static_cast<MapMode>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
188 }
189 
190 inline MapMode operator^(MapMode a, MapMode b)
191 {
192     return static_cast<MapMode>(static_cast<uint8_t>(a) ^ static_cast<uint8_t>(b));
193 }
194 
195 inline MapMode operator~(MapMode a)
196 {
197     return static_cast<MapMode>(~static_cast<uint8_t>(a));
198 }
199 
200 inline MapMode& operator|=(MapMode& a, MapMode b)
201 {
202     return a = a | b;
203 }
204 
205 inline MapMode& operator&=(MapMode& a, MapMode b)
206 {
207     return a = a & b;
208 }
209 
210 inline MapMode& operator^=(MapMode& a, MapMode b)
211 {
212     return a = a ^ b;
213 }
214 
215 } // namespace Utils
216 } // namespace OHOS
217 #endif