1 /*
2 * Copyright (c) 2021-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 #include "uni_error.h"
17
18 #include <cstring>
19 #include <string>
20 #include <unordered_map>
21
22 #include "log.h"
23 #include "napi/n_val.h"
24
25 namespace OHOS {
26 namespace DistributedFS {
27 using namespace std;
28
GenerateBusinessError(napi_env env,int32_t errCode,string errMsg)29 static napi_value GenerateBusinessError(napi_env env, int32_t errCode, string errMsg)
30 {
31 napi_value businessError = nullptr;
32 napi_value code = nullptr;
33 napi_value msg = nullptr;
34 code = NVal::CreateInt32(env, errCode).val_;
35 msg = NVal::CreateUTF8String(env, errMsg).val_;
36 napi_create_error(env, nullptr, msg, &businessError);
37 napi_set_named_property(env, businessError, FILEIO_TAG_ERR_CODE.c_str(), code);
38 napi_set_named_property(env, businessError, FILEIO_TAG_ERR_MSG.c_str(), msg);
39 return businessError;
40 }
41
UniError()42 UniError::UniError() {}
43
UniError(ELegacy eLegacy)44 UniError::UniError(ELegacy eLegacy) : errno_(eLegacy), codingSystem_(ERR_CODE_SYSTEM_LEGACY) {}
45
UniError(int ePosix)46 UniError::UniError(int ePosix) : errno_(ePosix), codingSystem_(ERR_CODE_SYSTEM_POSIX) {}
47
UniError(int ePosix,bool throwCode)48 UniError::UniError(int ePosix, bool throwCode) : errno_(ePosix), codingSystem_(ERR_CODE_SYSTEM_POSIX),
49 throwCode_(throwCode) {}
50
51 UniError::operator bool() const
52 {
53 return errno_ != ERRNO_NOERR;
54 }
55
GetErrno(ErrCodeSystem cs)56 int UniError::GetErrno(ErrCodeSystem cs)
57 {
58 if (errno_ == ERRNO_NOERR) {
59 return ERRNO_NOERR;
60 }
61
62 if (cs == codingSystem_) {
63 return errno_;
64 }
65
66 if (cs == ERR_CODE_SYSTEM_POSIX) {
67 // Note that we should support more codes here
68 return EINVAL;
69 }
70
71 // Note that this shall be done properly
72 return ELEGACY_INVAL;
73 }
74
SetErrno(ELegacy eLegacy)75 void UniError::SetErrno(ELegacy eLegacy)
76 {
77 errno_ = eLegacy;
78 codingSystem_ = ERR_CODE_SYSTEM_LEGACY;
79 }
80
SetErrno(int ePosix)81 void UniError::SetErrno(int ePosix)
82 {
83 errno_ = ePosix;
84 codingSystem_ = ERR_CODE_SYSTEM_POSIX;
85 }
86
GetDefaultErrstr()87 std::string UniError::GetDefaultErrstr()
88 {
89 if (codingSystem_ != ERR_CODE_SYSTEM_POSIX && codingSystem_ != ERR_CODE_SYSTEM_LEGACY) {
90 return "BUG: Curious coding system";
91 }
92 return strerror(GetErrno(ERR_CODE_SYSTEM_POSIX));
93 }
94
GetNapiErr(napi_env env)95 napi_value UniError::GetNapiErr(napi_env env)
96 {
97 int errCode = GetErrno(codingSystem_);
98 if (errCode == ERRNO_NOERR) {
99 return nullptr;
100 }
101 if (!throwCode_) {
102 return GetNapiErr(env, GetDefaultErrstr());
103 }
104 int32_t code;
105 string msg;
106 auto it = errCodeTable.find(errCode);
107 if (it != errCodeTable.end()) {
108 code = it->second.first;
109 msg = it->second.second;
110 } else {
111 code = errCodeTable.at(-1).first;
112 msg = errCodeTable.at(-1).second;
113 }
114 return GenerateBusinessError(env, code, msg);
115 }
116
GetNapiErr(napi_env env,string errMsg)117 napi_value UniError::GetNapiErr(napi_env env, string errMsg)
118 {
119 napi_value msg = NVal::CreateUTF8String(env, errMsg).val_;
120 napi_value res = nullptr;
121 napi_status createRes = napi_create_error(env, nullptr, msg, &res);
122 if (createRes) {
123 HILOGE("Failed to create an exception, msg = %{public}s", errMsg.c_str());
124 }
125 return res;
126 }
127
ThrowErr(napi_env env)128 void UniError::ThrowErr(napi_env env)
129 {
130 napi_value tmp = nullptr;
131 napi_get_and_clear_last_exception(env, &tmp);
132 int32_t code;
133 string msg;
134 napi_status throwStatus = napi_ok;
135 auto it = errCodeTable.find(errno_);
136 if (it != errCodeTable.end()) {
137 code = it->second.first;
138 msg = it->second.second;
139 } else {
140 code = errCodeTable.at(-1).first;
141 msg = errCodeTable.at(-1).second;
142 }
143 if (!throwCode_) {
144 throwStatus = napi_throw_error(env, nullptr, msg.c_str());
145 } else {
146 throwStatus = napi_throw(env, GenerateBusinessError(env, code, msg));
147 }
148
149 if (throwStatus != napi_ok) {
150 HILOGE("Failed to throw an exception, %{public}d, code = %{public}s", throwStatus, msg.c_str());
151 }
152 }
153
ThrowErr(napi_env env,int code)154 void UniError::ThrowErr(napi_env env, int code)
155 {
156 napi_value tmp = nullptr;
157 napi_get_and_clear_last_exception(env, &tmp);
158 if (errCodeTable.find(code) == errCodeTable.end()) {
159 code = -1;
160 }
161 napi_status throwStatus = napi_throw(env, GenerateBusinessError(env, errCodeTable.at(code).first,
162 errCodeTable.at(code).second));
163 if (throwStatus != napi_ok) {
164 HILOGE("Failed to throw an exception, %{public}d, code = %{public}s", throwStatus,
165 errCodeTable.at(code).second.c_str());
166 }
167 }
168
ThrowErr(napi_env env,string errMsg)169 void UniError::ThrowErr(napi_env env, string errMsg)
170 {
171 napi_value tmp = nullptr;
172 napi_get_and_clear_last_exception(env, &tmp);
173 // Note that ace engine cannot throw errors created by napi_create_error so far
174 napi_status throwStatus = napi_throw_error(env, nullptr, errMsg.c_str());
175 if (throwStatus != napi_ok) {
176 HILOGE("Failed to throw an exception, %{public}d, code = %{public}s", throwStatus, errMsg.c_str());
177 }
178 }
179 } // namespace DistributedFS
180 } // namespace OHOS