1 /*
2  * Copyright (c) 2022-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  * 本部件处理错误的原则:
18  *     原则1:使用异常表示错误,但只有无法处理的问题才算得上是错误,否则只是普通的边界分支;
19  *     原则2:仅在模块内部使用异常,而在界面层Catch所有异常,从而防止异常扩散;
20  *     原则3:在注释里通过throw关键字注明可能抛出的异常,通报使用风险。
21  */
22 #ifndef OHOS_FILEMGMT_BACKUP_B_ERROR_H
23 #define OHOS_FILEMGMT_BACKUP_B_ERROR_H
24 
25 #include <errors.h>
26 #include <functional>
27 #include <map>
28 #include <string>
29 #include <string_view>
30 #include <system_error>
31 #include <vector>
32 
33 #if __has_builtin(__builtin_FILE) && __has_builtin(__builtin_LINE) && __has_builtin(__builtin_FUNCTION)
34 #define DEFINE_SOURCE_LOCATION                                              \
35     int lineNo = __builtin_LINE(), const char *fileName = __builtin_FILE(), \
36         const char *functionName = __builtin_FUNCTION()
37 #else
38 #define DEFINE_SOURCE_LOCATION int lineNo = -1, const char *fileName = "NA", const char *functionName = "NA"
39 #endif
40 
41 namespace OHOS::FileManagement::Backup {
42 using ErrCode = int;
43 using ErrParam = std::function<std::tuple<uint32_t, std::string>()>;
44 
45 class BError : public std::exception {
46 public:
47     /**
48      * @brief 错误码,新增错误码时需要同步补充默认错误信息
49      *
50      */
51     enum class Codes : ErrCode {
52         // 0 无错误
53         OK = 0x0,
54 
55         // 1~999 标准平台错误
56 
57         // 0x1000~0x1999 backup_utils错误
58         UTILS_INVAL_JSON_ENTITY = 0x1000,
59         UTILS_INVAL_FILE_HANDLE = 0x1001,
60         UTILS_INVAL_TARBALL_ARG = 0x1002,
61         UTILS_INVAL_PROCESS_ARG = 0x1003,
62         UTILS_INTERRUPTED_PROCESS = 0x1004,
63 
64         // 0x2000~0x2999 backup_tool错误
65         TOOL_INVAL_ARG = 0x2000,
66 
67         // 0x3000~0x3999 backup_sa错误
68         SA_INVAL_ARG = 0x3000,
69         SA_BROKEN_IPC = 0x3001,
70         SA_REFUSED_ACT = 0x3002,
71         SA_BROKEN_ROOT_DIR = 0x3003,
72         SA_FORBID_BACKUP_RESTORE = 0x3004,
73         SA_BOOT_EXT_TIMEOUT = 0x3005,
74         SA_BUNDLE_INFO_EMPTY = 0x3006,
75         SA_BOOT_EXT_FAIL = 0x3007,
76 
77         // 0x4000~0x4999 backup_SDK错误
78         SDK_INVAL_ARG = 0x4000,
79         SDK_BROKEN_IPC = 0x4001,
80         SDK_MIXED_SCENARIO = 0x4002,
81 
82         // 0x5000~0x5999 backup_ext错误
83         EXT_INVAL_ARG = 0x5000,
84         EXT_BROKEN_FRAMEWORK = 0x5001,
85         EXT_BROKEN_BACKUP_SA = 0x5002,
86         EXT_BROKEN_IPC = 0x5003,
87         EXT_ABILITY_DIED = 0x5004,
88         EXT_ABILITY_TIMEOUT = 0x5005,
89         EXT_FORBID_BACKUP_RESTORE = 0x5006,
90         EXT_BACKUP_PACKET_ERROR = 0x5007,
91         EXT_METHOD_NOT_EXIST = 0x5008,
92         EXT_THROW_EXCEPTION = 0x5009,
93         EXT_BACKUP_UNPACKET_ERROR = 0x5010,
94 
95         // 0x6000~0x6999 sa_ext错误
96         SA_EXT_ERR_CALL = 0x6000,
97         SA_EXT_ERR_SAMGR = 0x6001,
98         SA_EXT_RELOAD_FAIL = 0x6002,
99     };
100 
101     enum BackupErrorCode {
102         E_IPCSS = 13600001,
103         E_PERM = 13900001,
104         E_NOTEXIST = 13900002,
105         E_IO = 13900005,
106         E_NOMEM = 13900011,
107         E_INVAL = 13900020,
108         E_NOSPC = 13900025,
109         E_UKERR = 13900042,
110         E_FORBID = 13500001,
111         E_BTO = 13500002,
112         E_ETO = 13500003,
113         E_DIED = 13500004,
114         E_EMPTY = 13500005,
115         E_PACKET = 13500006,
116         E_EXCEPTION = 13500007,
117         E_UNPACKET = 13500008,
118         E_BEF = 13500009,
119         E_TASKFAIL = 13500010,
120     };
121 
122 public:
123     /**
124      * @brief 返回OHOS标准错误码
125      *
126      * @return int 标注错误码
127      */
128     int GetCode() const;
129 
130     /**
131      * @brief 根据系统的errno返回OHOS标准错误码
132      *
133      * @return int 标注错误码
134      */
135     static int32_t GetCodeByErrno(int32_t errnoSys);
136 
137     /**
138      * @brief 返回原始错误码
139      *
140      * @return Codes 原始错误码
141      */
GetRawCode()142     Codes GetRawCode() const
143     {
144         return code_;
145     }
146 
147     /**
148      * @brief 返回错误信息
149      *
150      * @return const char* 错误信息
151      */
what()152     const char *what() const noexcept override
153     {
154         return msg_.c_str();
155     }
156 
157     /**
158      * @brief 归一返回备份恢复错误码
159      *
160      * @return ErrCode 备份恢复错误码
161      */
162     static ErrCode GetBackupCodeByErrno(ErrCode err);
163 
164     /**
165      * @brief 归一返回备份恢复错误信息
166      *
167      * @return string 备份恢复错误信息
168      */
169     static std::string GetBackupMsgByErrno(ErrCode err);
170 public:
171     /**
172      * @brief 重载bool操作符,判断当前错误是否是错误
173      *
174      * @return true 是错误
175      * @return false 不是错误
176      */
177     explicit operator bool() const
178     {
179         return code_ != Codes::OK;
180     }
181 
182     /**
183      * @brief 返回OHOS标准错误码
184      *
185      * @return int 标准错误码
186      */
187     operator int() const
188     {
189         return GetCode();
190     }
191 
192 public:
193     /**
194      * @brief 构造错误对象
195      *
196      * @param code 备份系统标准错误码,取自本类中的Codes
197      * @param lineNo 构造错误对象的行号(不要自己填写)
198      * @param fileName 构造错误对象的文件(不要自己填写)
199      * @param functionName 构造错误对象的函数(不要自己填写)
200      */
201     explicit BError(Codes code = Codes::OK, DEFINE_SOURCE_LOCATION) : code_(code)
202     {
203         msg_ = WrapMessageWithExtraInfos(fileName, lineNo, functionName, code_, {mpErrToMsg_.at(code_)});
204     }
205 
206     /**
207      * @brief 构造错误对象
208      *
209      * @param code 备份系统标准错误码,取自本类中的Codes
210      * @param extraMsg 追加的详细错误信息
211      * @param lineNo 构造错误对象的行号(不要自己填写)
212      * @param fileName 构造错误对象的文件(不要自己填写)
213      * @param functionName 构造错误对象的函数(不要自己填写)
214      */
BError(Codes code,const std::string_view & extraMsg,DEFINE_SOURCE_LOCATION)215     BError(Codes code, const std::string_view &extraMsg, DEFINE_SOURCE_LOCATION) : code_(code)
216     {
217         msg_ = WrapMessageWithExtraInfos(fileName, lineNo, functionName, code_, {mpErrToMsg_.at(code_), extraMsg});
218     }
219 
220     /**
221      * @brief 构造错误对象
222      *
223      * @param stdErrno 失败的LIBC调用通过errno返回的错误码
224      * @param lineNo 构造错误对象的行号(不要自己填写)
225      * @param fileName 构造错误对象的文件(不要自己填写)
226      * @param functionName 构造错误对象的函数(不要自己填写)
227      */
BError(int stdErrno,DEFINE_SOURCE_LOCATION)228     explicit BError(int stdErrno, DEFINE_SOURCE_LOCATION) : code_ {stdErrno}
229     {
230         std::string rawMsg = std::generic_category().message(stdErrno);
231         msg_ = WrapMessageWithExtraInfos(fileName, lineNo, functionName, code_, {rawMsg});
232     }
233 
234 private:
235     static inline const std::map<Codes, std::string_view> mpErrToMsg_ = {
236         {Codes::OK, "No error"},
237         {Codes::UTILS_INVAL_JSON_ENTITY, "Json utils operated on an invalid file"},
238         {Codes::UTILS_INVAL_FILE_HANDLE, "File utils received an invalid file handle"},
239         {Codes::UTILS_INVAL_TARBALL_ARG, "Tarball utils received an invalid argument"},
240         {Codes::UTILS_INVAL_PROCESS_ARG, "Process utils received an invalid argument"},
241         {Codes::UTILS_INTERRUPTED_PROCESS, "Can't launch a process or the process was corrupted"},
242         {Codes::TOOL_INVAL_ARG, "TOOL received invalid arguments"},
243         {Codes::SA_INVAL_ARG, "SA received invalid arguments"},
244         {Codes::SA_BROKEN_IPC, "SA failed to issue a IPC"},
245         {Codes::SA_REFUSED_ACT, "SA refuse to act"},
246         {Codes::SA_BROKEN_ROOT_DIR, "SA failed to operate on the given root dir"},
247         {Codes::SA_FORBID_BACKUP_RESTORE, "SA forbid backup or restore"},
248         {Codes::SA_BOOT_EXT_TIMEOUT, "SA boot application extension time out"},
249         {Codes::SA_BUNDLE_INFO_EMPTY, "SA the bundle info for backup/restore is empty"},
250         {Codes::SA_BOOT_EXT_FAIL, "SA failed to boot application extension"},
251         {Codes::SDK_INVAL_ARG, "SDK received invalid arguments"},
252         {Codes::SDK_BROKEN_IPC, "SDK failed to do IPC"},
253         {Codes::SDK_MIXED_SCENARIO, "SDK involed backup/restore when doing the contrary"},
254         {Codes::EXT_INVAL_ARG, "Extension received an invalid argument"},
255         {Codes::EXT_BROKEN_FRAMEWORK, "Extension found the appex framework is broken"},
256         {Codes::EXT_BROKEN_BACKUP_SA, "Extension found the backup SA died"},
257         {Codes::EXT_BROKEN_IPC, "Extension failed to do IPC"},
258         {Codes::EXT_ABILITY_TIMEOUT, "Extension process timeout"},
259         {Codes::EXT_ABILITY_DIED, "Extension process died"},
260         {Codes::EXT_FORBID_BACKUP_RESTORE, "forbid backup or restore"},
261         {Codes::EXT_BACKUP_PACKET_ERROR, "Backup packet error"},
262         {Codes::EXT_METHOD_NOT_EXIST, "Extension method not exist"},
263         {Codes::EXT_THROW_EXCEPTION, "Extension throw exception"},
264         {Codes::EXT_BACKUP_UNPACKET_ERROR, "Backup unpacket error"},
265         {Codes::SA_EXT_ERR_CALL, "SA Extension received invalid arguments"},
266         {Codes::SA_EXT_ERR_SAMGR, "SA Extension get samgr failed"},
267         {Codes::SA_EXT_RELOAD_FAIL, "SA Extension reload failed"},
268     };
269 
270     static inline const std::map<int, int> errCodeTable_ {
271         {static_cast<int>(Codes::OK), static_cast<int>(Codes::OK)},
272         {static_cast<int>(Codes::UTILS_INVAL_JSON_ENTITY), BackupErrorCode::E_INVAL},
273         {static_cast<int>(Codes::UTILS_INVAL_FILE_HANDLE), BackupErrorCode::E_INVAL},
274         {static_cast<int>(Codes::UTILS_INVAL_TARBALL_ARG), BackupErrorCode::E_UKERR},
275         {static_cast<int>(Codes::UTILS_INVAL_PROCESS_ARG), BackupErrorCode::E_UKERR},
276         {static_cast<int>(Codes::UTILS_INTERRUPTED_PROCESS), BackupErrorCode::E_UKERR},
277         {static_cast<int>(Codes::TOOL_INVAL_ARG), BackupErrorCode::E_UKERR},
278         {static_cast<int>(Codes::SA_INVAL_ARG), BackupErrorCode::E_INVAL},
279         {static_cast<int>(Codes::SA_BROKEN_IPC), BackupErrorCode::E_IPCSS},
280         {static_cast<int>(Codes::SA_REFUSED_ACT), BackupErrorCode::E_PERM},
281         {static_cast<int>(Codes::SA_BROKEN_ROOT_DIR), BackupErrorCode::E_UKERR},
282         {static_cast<int>(Codes::SA_FORBID_BACKUP_RESTORE), BackupErrorCode::E_FORBID},
283         {static_cast<int>(Codes::SA_BOOT_EXT_TIMEOUT), BackupErrorCode::E_BTO},
284         {static_cast<int>(Codes::SA_BUNDLE_INFO_EMPTY), BackupErrorCode::E_EMPTY},
285         {static_cast<int>(Codes::SA_BOOT_EXT_FAIL), BackupErrorCode::E_BEF},
286         {static_cast<int>(Codes::SDK_INVAL_ARG), BackupErrorCode::E_INVAL},
287         {static_cast<int>(Codes::SDK_BROKEN_IPC), BackupErrorCode::E_IPCSS},
288         {static_cast<int>(Codes::SDK_MIXED_SCENARIO), BackupErrorCode::E_INVAL},
289         {static_cast<int>(Codes::EXT_INVAL_ARG), BackupErrorCode::E_INVAL},
290         {static_cast<int>(Codes::EXT_BROKEN_FRAMEWORK), BackupErrorCode::E_UKERR},
291         {static_cast<int>(Codes::EXT_BROKEN_BACKUP_SA), BackupErrorCode::E_IPCSS},
292         {static_cast<int>(Codes::EXT_BROKEN_IPC), BackupErrorCode::E_IPCSS},
293         {static_cast<int>(Codes::EXT_ABILITY_DIED), BackupErrorCode::E_DIED},
294         {static_cast<int>(Codes::EXT_ABILITY_TIMEOUT), BackupErrorCode::E_ETO},
295         {static_cast<int>(Codes::EXT_FORBID_BACKUP_RESTORE), BackupErrorCode::E_FORBID},
296         {static_cast<int>(Codes::EXT_BACKUP_PACKET_ERROR), BackupErrorCode::E_PACKET},
297         {static_cast<int>(Codes::EXT_METHOD_NOT_EXIST), BackupErrorCode::E_INVAL},
298         {static_cast<int>(Codes::EXT_THROW_EXCEPTION), BackupErrorCode::E_EXCEPTION},
299         {static_cast<int>(Codes::EXT_BACKUP_UNPACKET_ERROR), BackupErrorCode::E_UNPACKET},
300         {static_cast<int>(Codes::SA_EXT_ERR_CALL), BackupErrorCode::E_INVAL},
301         {static_cast<int>(Codes::SA_EXT_ERR_SAMGR), BackupErrorCode::E_IPCSS},
302         {static_cast<int>(Codes::SA_EXT_RELOAD_FAIL), BackupErrorCode::E_BEF},
303         {BackupErrorCode::E_IPCSS, BackupErrorCode::E_IPCSS},
304         {BackupErrorCode::E_INVAL, BackupErrorCode::E_INVAL},
305         {BackupErrorCode::E_NOTEXIST, BackupErrorCode::E_NOTEXIST},
306         {BackupErrorCode::E_UKERR, BackupErrorCode::E_UKERR},
307         {BackupErrorCode::E_PERM, BackupErrorCode::E_PERM},
308         {BackupErrorCode::E_NOMEM, BackupErrorCode::E_NOMEM},
309         {BackupErrorCode::E_NOSPC, BackupErrorCode::E_NOSPC},
310         {BackupErrorCode::E_IO, BackupErrorCode::E_IO},
311         {BackupErrorCode::E_FORBID, BackupErrorCode::E_FORBID},
312         {BackupErrorCode::E_BTO, BackupErrorCode::E_BTO},
313         {BackupErrorCode::E_ETO, BackupErrorCode::E_ETO},
314         {BackupErrorCode::E_DIED, BackupErrorCode::E_DIED},
315         {BackupErrorCode::E_EMPTY, BackupErrorCode::E_EMPTY},
316         {BackupErrorCode::E_PACKET, BackupErrorCode::E_PACKET},
317         {BackupErrorCode::E_EXCEPTION, BackupErrorCode::E_EXCEPTION},
318         {BackupErrorCode::E_UNPACKET, BackupErrorCode::E_UNPACKET},
319         {BackupErrorCode::E_BEF, BackupErrorCode::E_BEF},
320     };
321 
322     static inline const std::map<int, int> sysErrnoCodeTable_ {
323         {EPERM, BackupErrorCode::E_PERM},
324         {EIO, BackupErrorCode::E_IO},
325         {EBADF, BackupErrorCode::E_IO},
326         {EACCES, BackupErrorCode::E_IO},
327         {EFBIG, BackupErrorCode::E_IO},
328         {ENOMEM, BackupErrorCode::E_NOMEM},
329         {EMFILE, BackupErrorCode::E_NOMEM},
330         {ENOENT, BackupErrorCode::E_INVAL},
331         {ENOTDIR, BackupErrorCode::E_INVAL},
332         {EISDIR, BackupErrorCode::E_INVAL},
333         {ENAMETOOLONG, BackupErrorCode::E_INVAL},
334         {ENOSPC, BackupErrorCode::E_NOSPC},
335     };
336 
337     static inline const std::map<int, std::string> backupErrorMsgTable_ {
338         {BackupErrorCode::E_IPCSS, "IPC error"},
339         {BackupErrorCode::E_INVAL, "Invalid argument"},
340         {BackupErrorCode::E_NOTEXIST, "Method not exist"},
341         {BackupErrorCode::E_UKERR, "Unknown error"},
342         {BackupErrorCode::E_PERM, "Operation not permitted"},
343         {BackupErrorCode::E_NOMEM, "Out of memory"},
344         {BackupErrorCode::E_NOSPC, "No space left on device"},
345         {BackupErrorCode::E_IO, "I/O error"},
346         {BackupErrorCode::E_FORBID, "Not support backup/restore"},
347         {BackupErrorCode::E_BTO, "SA boot extension timeout"},
348         {BackupErrorCode::E_ETO, "Extension process timeout"},
349         {BackupErrorCode::E_DIED, "Extension process died"},
350         {BackupErrorCode::E_EMPTY, "SA the bundle info for backup/restore is empty"},
351         {BackupErrorCode::E_PACKET, "Tar failed"},
352         {BackupErrorCode::E_EXCEPTION, "Extension throw exception"},
353         {BackupErrorCode::E_UNPACKET, "Untar failed"},
354         {BackupErrorCode::E_BEF, "SA failed to boot application extension"},
355     };
356 
357 private:
358     Codes code_ {Codes::OK};
359     std::string msg_;
360 
361 private:
362     /**
363      * @brief 生成如下格式的打印信息 → [文件名:行号->函数名] 默认错误信息. 补充错误信息
364      *
365      * @param fileName 构造错误对象的文件
366      * @param lineNo 构造错误对象的行号
367      * @param functionName 构造错误对象的函数
368      * @param msgs 所有待追加的错误信息
369      * @return std::string 打印信息
370      */
371     std::string WrapMessageWithExtraInfos(const char *fileName,
372                                           int lineNo,
373                                           const char *functionName,
374                                           Codes code,
375                                           const std::vector<std::string_view> &msgs) const;
376 };
377 } // namespace OHOS::FileManagement::Backup
378 
379 #endif // OHOS_FILEMGMT_BACKUP_B_ERROR_H