1 /*
2  * Copyright (c) 2022 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 "n_error.h"
17 
18 #include <cstring>
19 
20 #include "filemgmt_libhilog.h"
21 #include "n_val.h"
22 #include "uv.h"
23 
24 namespace OHOS {
25 namespace FileManagement {
26 namespace LibN {
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     napi_status status;
35     code = NVal::CreateInt32(env, errCode).val_;
36     msg = NVal::CreateUTF8String(env, errMsg).val_;
37     status = napi_create_error(env, nullptr, msg, &businessError);
38     if (status != napi_ok) {
39         HILOGE("Failed to create a BusinessError, error message is %{public}s", errMsg.c_str());
40         return nullptr;
41     }
42     status = napi_set_named_property(env, businessError, FILEIO_TAG_ERR_CODE.c_str(), code);
43     if (status != napi_ok) {
44         HILOGE("Failed to set code property on Error, error message is %{public}s", errMsg.c_str());
45         return nullptr;
46     }
47     return businessError;
48 }
49 
ConvertUVCode2ErrCode(int errCode)50 static int ConvertUVCode2ErrCode(int errCode)
51 {
52     if (errCode >= 0) {
53         return errCode;
54     }
55     auto uvCode = string_view(uv_err_name(errCode));
56     if (uvCode2ErrCodeTable.find(uvCode) != uvCode2ErrCodeTable.end()) {
57         return uvCode2ErrCodeTable.at(uvCode);
58     }
59     return UNKROWN_ERR;
60 }
61 
NError()62 NError::NError() {}
63 
NError(int errCode)64 NError::NError(int errCode)
65 {
66     int genericCode = ConvertUVCode2ErrCode(errCode);
67     auto it = errCodeTable.find(genericCode);
68     if (it != errCodeTable.end()) {
69         errno_ = it->second.first;
70         errMsg_ = it->second.second;
71     } else {
72         errno_ = errCodeTable.at(UNKROWN_ERR).first;
73         errMsg_ = errCodeTable.at(UNKROWN_ERR).second + ", errno is " + to_string(abs(errCode));
74     }
75 }
76 
NError(std::function<std::tuple<uint32_t,std::string> ()> errGen)77 NError::NError(std::function<std::tuple<uint32_t, std::string>()> errGen)
78 {
79     tie(errno_, errMsg_) = errGen();
80 }
81 
82 NError::operator bool() const
83 {
84     return errno_ != ERRNO_NOERR;
85 }
86 
GetNapiErr(napi_env env)87 napi_value NError::GetNapiErr(napi_env env)
88 {
89     if (errno_ == ERRNO_NOERR) {
90         return nullptr;
91     }
92     return GenerateBusinessError(env, errno_, errMsg_);
93 }
94 
GetNapiErr(napi_env env,int errCode)95 napi_value NError::GetNapiErr(napi_env env, int errCode)
96 {
97     if (errCode == ERRNO_NOERR) {
98         return nullptr;
99     }
100     int32_t code = 0;
101     string msg;
102     auto it = errCodeTable.find(errCode);
103     if (it != errCodeTable.end()) {
104         code = it->second.first;
105         msg = it->second.second;
106     } else {
107         code = errCodeTable.at(UNKROWN_ERR).first;
108         msg = errCodeTable.at(UNKROWN_ERR).second;
109     }
110     errno_ = code;
111     errMsg_ = msg;
112     return GenerateBusinessError(env, code, msg);
113 }
114 
GetNapiErrAddData(napi_env env,int errCode,napi_value data)115 napi_value NError::GetNapiErrAddData(napi_env env, int errCode, napi_value data)
116 {
117     if (errCode == ERRNO_NOERR) {
118         return nullptr;
119     }
120     int32_t code = 0;
121     string msg;
122     if (errCodeTable.find(errCode) != errCodeTable.end()) {
123         code = errCodeTable.at(errCode).first;
124         msg = errCodeTable.at(errCode).second;
125     } else {
126         code = errCodeTable.at(UNKROWN_ERR).first;
127         msg = errCodeTable.at(UNKROWN_ERR).second;
128     }
129     errno_ = code;
130     errMsg_ = msg;
131     napi_value businessError = GenerateBusinessError(env, code, msg);
132     napi_status status = napi_set_named_property(env, businessError, FILEIO_TAG_ERR_DATA.c_str(), data);
133     if (status != napi_ok) {
134         HILOGE("Failed to set data property on Error, error message is %{public}s", msg.c_str());
135         return nullptr;
136     }
137     return businessError;
138 }
139 
ThrowErr(napi_env env,int errCode)140 void NError::ThrowErr(napi_env env, int errCode)
141 {
142     int32_t code = 0;
143     string msg;
144     if (errCodeTable.find(errCode) != errCodeTable.end()) {
145         code = errCodeTable.at(errCode).first;
146         msg = errCodeTable.at(errCode).second;
147     } else {
148         code = errCodeTable.at(UNKROWN_ERR).first;
149         msg = errCodeTable.at(UNKROWN_ERR).second;
150     }
151     errno_ = code;
152     errMsg_ = msg;
153     napi_status status = napi_throw(env, GenerateBusinessError(env, code, msg));
154     if (status != napi_ok) {
155         HILOGE("Failed to throw a BusinessError, error message is %{public}s", msg.c_str());
156     }
157 }
158 
ThrowErr(napi_env env,string errMsg)159 void NError::ThrowErr(napi_env env, string errMsg)
160 {
161     napi_value tmp = nullptr;
162     napi_get_and_clear_last_exception(env, &tmp);
163     // Note that ace engine cannot thow errors created by napi_create_error so far
164     napi_status throwStatus = napi_throw_error(env, nullptr, errMsg.c_str());
165     if (throwStatus != napi_ok) {
166         HILOGE("Failed to throw an Error, error message is %{public}s", errMsg.c_str());
167     }
168 }
169 
ThrowErrAddData(napi_env env,int errCode,napi_value data)170 void NError::ThrowErrAddData(napi_env env, int errCode, napi_value data)
171 {
172     int32_t code = 0;
173     string msg;
174     if (errCodeTable.find(errCode) != errCodeTable.end()) {
175         code = errCodeTable.at(errCode).first;
176         msg = errCodeTable.at(errCode).second;
177     } else {
178         code = errCodeTable.at(UNKROWN_ERR).first;
179         msg = errCodeTable.at(UNKROWN_ERR).second;
180     }
181     errno_ = code;
182     errMsg_ = msg;
183     napi_value businessError = GenerateBusinessError(env, code, msg);
184     napi_status status = napi_set_named_property(env, businessError, FILEIO_TAG_ERR_DATA.c_str(), data);
185     if (status != napi_ok) {
186         HILOGE("Failed to set data property on Error, error message is %{public}s", msg.c_str());
187         return;
188     }
189     status = napi_throw(env, businessError);
190     if (status != napi_ok) {
191         HILOGE("Failed to throw a BusinessError, error message is %{public}s", msg.c_str());
192         return;
193     }
194 }
195 
ThrowErr(napi_env env)196 void NError::ThrowErr(napi_env env)
197 {
198     napi_value tmp = nullptr;
199     napi_get_and_clear_last_exception(env, &tmp);
200     napi_status status = napi_throw(env, GenerateBusinessError(env, errno_, errMsg_));
201     if (status != napi_ok) {
202         HILOGE("Failed to throw a BusinessError, error message is %{public}s", errMsg_.c_str());
203     }
204 }
205 } // namespace LibN
206 } // namespace FileManagement
207 } // namespace OHOS