• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 <map>
17 #include "loglibrary_ani_util.h"
18 #include "hiview_service_agent.h"
19 #include "ipc_skeleton.h"
20 #include "tokenid_kit.h"
21 
22 using namespace OHOS::HiviewDFX;
23 namespace {
24 DEFINE_LOG_LABEL(0xD002D10, "LogLibraryAniUtil");
25 static constexpr int32_t SUCCESS = 0;
26 }
27 
ParseStringValue(ani_env * env,ani_string aniStrRef)28 std::string LogLibraryAniUtil::ParseStringValue(ani_env *env, ani_string aniStrRef)
29 {
30     ani_size strSize = 0;
31     if (ANI_OK != env->String_GetUTF8Size(aniStrRef, &strSize)) {
32         HILOG_ERROR(LOG_CORE, "String_GetUTF8Size Failed");
33         return "";
34     }
35     std::vector<char> buffer(strSize + 1);
36     char* utf8Buffer = buffer.data();
37     ani_size bytesWritten = 0;
38     if (ANI_OK != env->String_GetUTF8(aniStrRef, utf8Buffer, strSize + 1, &bytesWritten)) {
39         HILOG_ERROR(LOG_CORE, "String_GetUTF8 Failed");
40         return "";
41     }
42     utf8Buffer[bytesWritten] = '\0';
43     std::string content = std::string(utf8Buffer);
44     return content;
45 }
46 
CreateLogEntryArray(ani_env * env,const std::vector<HiviewFileInfo> & fileInfos,ani_array_ref & logEntryArray)47 bool LogLibraryAniUtil::CreateLogEntryArray(ani_env *env,
48     const std::vector<HiviewFileInfo>& fileInfos, ani_array_ref &logEntryArray)
49 {
50     ani_size index = 0;
51     for (const auto& value: fileInfos) {
52         std::string name = value.name;
53         ani_string name_string{};
54         env->String_NewUTF8(name.c_str(), name.size(), &name_string);
55         ani_object logEntryObj = LogLibraryAniUtil::CreateLogEntryObject(env);
56         if (ANI_OK != env->Object_SetPropertyByName_Ref(logEntryObj, "name", name_string)) {
57             HILOG_ERROR(LOG_CORE, "Set LogEntry name Fail: %{public}s", CLASS_NAME_LOGENTRY);
58             return false;
59         }
60         if (ANI_OK != env->Object_SetPropertyByName_Double(logEntryObj, "mtime", value.mtime)) {
61             HILOG_ERROR(LOG_CORE, "Set LogEntry mtime Fail: %{public}s", CLASS_NAME_LOGENTRY);
62             return false;
63         }
64         if (ANI_OK != env->Object_SetPropertyByName_Double(logEntryObj, "size", value.size)) {
65             HILOG_ERROR(LOG_CORE, "Set LogEntry size Fail: %{public}s", CLASS_NAME_LOGENTRY);
66             return false;
67         }
68         if (ANI_OK != env->Array_Set_Ref(logEntryArray, index, static_cast<ani_ref>(logEntryObj))) {
69             HILOG_ERROR(LOG_CORE, "Set logEntryObj to array Fail: %{public}s", CLASS_NAME_LOGENTRY);
70             return false;
71         }
72         index++;
73     }
74     return true;
75 }
76 
CreateLogEntryObject(ani_env * env)77 ani_object LogLibraryAniUtil::CreateLogEntryObject(ani_env *env)
78 {
79     ani_class cls {};
80     ani_object logEntryObj {};
81     if (ANI_OK != env->FindClass(CLASS_NAME_LOGENTRY, &cls)) {
82         HILOG_ERROR(LOG_CORE, "FindClass %{public}s Failed", CLASS_NAME_LOGENTRY);
83         return logEntryObj;
84     }
85 
86     ani_method logEntryConstructor {};
87     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &logEntryConstructor)) {
88         HILOG_ERROR(LOG_CORE, "get %{public}s ctor Failed", CLASS_NAME_LOGENTRY);
89         return logEntryObj;
90     }
91 
92     if (ANI_OK != env->Object_New(cls, logEntryConstructor, &logEntryObj)) {
93         HILOG_ERROR(LOG_CORE, "Create Object Failed: %{public}s", CLASS_NAME_LOGENTRY);
94         return logEntryObj;
95     }
96     return logEntryObj;
97 }
98 
ListResult(ani_env * env,const std::vector<HiviewFileInfo> & fileInfos)99 ani_ref LogLibraryAniUtil::ListResult(ani_env *env, const std::vector<HiviewFileInfo>& fileInfos)
100 {
101     ani_class cls {};
102     ani_array_ref logEntryArray {};
103     if (ANI_OK != env->FindClass(CLASS_NAME_LOGENTRY, &cls)) {
104         HILOG_ERROR(LOG_CORE, "FindClass %{public}s Failed", CLASS_NAME_LOGENTRY);
105         return logEntryArray;
106     }
107 
108     ani_ref undefinedRef = LogLibraryAniUtil::GetAniUndefined(env);
109     if (ANI_OK != env->Array_New_Ref(cls, fileInfos.size(), undefinedRef, &logEntryArray)) {
110         HILOG_ERROR(LOG_CORE, "Array_New_Ref Failed");
111         return logEntryArray;
112     }
113 
114     if (fileInfos.empty()) {
115         return logEntryArray;
116     }
117 
118     if (!CreateLogEntryArray(env, fileInfos, logEntryArray)) {
119         HILOG_ERROR(LOG_CORE, "CreateLogEntryArray Failed");
120         return logEntryArray;
121     }
122     return logEntryArray;
123 }
124 
IsSystemAppCall()125 bool LogLibraryAniUtil::IsSystemAppCall()
126 {
127     uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
128     return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
129 }
130 
ThrowAniError(ani_env * env,int32_t code,const std::string & message)131 void LogLibraryAniUtil::ThrowAniError(ani_env *env, int32_t code, const std::string &message)
132 {
133     ani_class cls {};
134     if (ANI_OK != env->FindClass(CLASS_NAME_BUSINESSERROR, &cls)) {
135         HILOG_ERROR(LOG_CORE, "find class %{public}s failed", CLASS_NAME_BUSINESSERROR);
136         return;
137     }
138     ani_method ctor {};
139     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
140         HILOG_ERROR(LOG_CORE, "find method BusinessError constructor failed");
141         return;
142     }
143     ani_object error {};
144     if (ANI_OK != env->Object_New(cls, ctor, &error)) {
145         HILOG_ERROR(LOG_CORE, "new object %{public}s failed", CLASS_NAME_BUSINESSERROR);
146         return;
147     }
148     if (ANI_OK != env->Object_SetPropertyByName_Double(error, "code", static_cast<ani_double>(code))) {
149         HILOG_ERROR(LOG_CORE, "set property BusinessError.code failed");
150         return;
151     }
152     ani_string messageRef {};
153     if (ANI_OK != env->String_NewUTF8(message.c_str(), message.size(), &messageRef)) {
154         HILOG_ERROR(LOG_CORE, "new message string failed");
155         return;
156     }
157     if (ANI_OK != env->Object_SetPropertyByName_Ref(error, "message", static_cast<ani_ref>(messageRef))) {
158         HILOG_ERROR(LOG_CORE, "set property BusinessError.message failed");
159         return;
160     }
161     if (ANI_OK != env->ThrowError(static_cast<ani_error>(error))) {
162         HILOG_ERROR(LOG_CORE, "throwError ani_error object failed");
163     }
164 }
165 
GetErrorDetailByRet(const int32_t retCode)166 std::pair<int32_t, std::string> LogLibraryAniUtil::GetErrorDetailByRet(const int32_t retCode)
167 {
168     HIVIEW_LOGI("origin result code is %{public}d.", retCode);
169     const std::map<int32_t, std::pair<int32_t, std::string>> errMap = {
170         {SUCCESS, {SUCCESS, "Success."}},
171         {HiviewNapiErrCode::ERR_PERMISSION_CHECK, {HiviewNapiErrCode::ERR_PERMISSION_CHECK,
172             "Permission denied. The app does not have the necessary permissions."}},
173         {HiviewNapiErrCode::ERR_NON_SYS_APP_PERMISSION, {HiviewNapiErrCode::ERR_NON_SYS_APP_PERMISSION,
174             "Permission denied, non-system app called system api."}},
175         {HiviewNapiErrCode::ERR_PARAM_CHECK,
176             {HiviewNapiErrCode::ERR_PARAM_CHECK, "Parameter error. The content of dest is invalid."}},
177         {HiviewNapiErrCode::ERR_INNER_INVALID_LOGTYPE,
178             {HiviewNapiErrCode::ERR_PARAM_CHECK, "Parameter error. The value of logType is invalid."}},
179         {HiviewNapiErrCode::ERR_INNER_READ_ONLY,
180             {HiviewNapiErrCode::ERR_PARAM_CHECK, "Parameter error. The specified logType is read-only."}},
181         {HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST,
182             {HiviewNapiErrCode::ERR_SOURCE_FILE_NOT_EXIST, "Source file does not exists."}}
183     };
184     return errMap.find(retCode) == errMap.end() ?
185         std::make_pair(HiviewNapiErrCode::ERR_DEFAULT, "Environment is abnormal.") : errMap.at(retCode);
186 }
187 
CopyOrMoveFile(ani_env * env,ani_string logType,ani_string logName,ani_string dest,bool isMove)188 ani_object LogLibraryAniUtil::CopyOrMoveFile(ani_env *env,
189     ani_string logType, ani_string logName, ani_string dest, bool isMove)
190 {
191     isMove ? HIVIEW_LOGI("call move") : HIVIEW_LOGI("call copy");
192     std::string logTypeTemp = LogLibraryAniUtil::ParseStringValue(env, logType);
193     std::string logNameTemp = LogLibraryAniUtil::ParseStringValue(env, logName);
194     std::string destTemp = LogLibraryAniUtil::ParseStringValue(env, dest);
195     HIVIEW_LOGI("type:%{public}s, name:%{public}s, dir: %{public}s",
196         logTypeTemp.c_str(), StringUtil::HideSnInfo(logNameTemp).c_str(), destTemp.c_str());
197 
198     if (!LogLibraryAniUtil::CheckDirPath(destTemp)) {
199         HIVIEW_LOGE("dest param is invalid: %{public}s", destTemp.c_str());
200         return LogLibraryAniUtil::CopyOrMoveResult(env,
201             LogLibraryAniUtil::GetErrorDetailByRet(HiviewNapiErrCode::ERR_PARAM_CHECK));
202     }
203 
204     if (isMove) {
205         int32_t result = HiviewServiceAgent::GetInstance().Move(logTypeTemp, logNameTemp, destTemp);
206         return LogLibraryAniUtil::CopyOrMoveResult(env, LogLibraryAniUtil::GetErrorDetailByRet(result));
207     } else {
208         int32_t result = HiviewServiceAgent::GetInstance().Copy(logTypeTemp, logNameTemp, destTemp);
209         return LogLibraryAniUtil::CopyOrMoveResult(env, LogLibraryAniUtil::GetErrorDetailByRet(result));
210     }
211 }
212 
CheckDirPath(const std::string & path)213 bool LogLibraryAniUtil::CheckDirPath(const std::string& path)
214 {
215     return path.empty() || path.find("..") == std::string::npos;
216 }
217 
CopyOrMoveResult(ani_env * env,std::pair<int32_t,std::string> result)218 ani_object LogLibraryAniUtil::CopyOrMoveResult(ani_env *env, std::pair<int32_t, std::string> result)
219 {
220     ani_object results_obj {};
221     ani_class cls {};
222     if (ANI_OK != env->FindClass(CLASS_NAME_RESULTS, &cls)) {
223         HILOG_ERROR(LOG_CORE, "failed to find class %{public}s", CLASS_NAME_RESULTS);
224         return results_obj;
225     }
226 
227     ani_method ctor {};
228     if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) {
229         HILOG_ERROR(LOG_CORE, "get method %{public}s <ctor> failed", CLASS_NAME_RESULTS);
230         return results_obj;
231     }
232 
233     if (ANI_OK != env->Object_New(cls, ctor, &results_obj)) {
234         HILOG_ERROR(LOG_CORE, "create object %{public}s failed", CLASS_NAME_RESULTS);
235         return results_obj;
236     }
237 
238     ani_method codeSetter {};
239     if (ANI_OK != env->Class_FindMethod(cls, "<set>code", nullptr, &codeSetter)) {
240         HILOG_ERROR(LOG_CORE, "get method codeSetter %{public}s failed", CLASS_NAME_RESULTS);
241         return results_obj;
242     }
243 
244     if (ANI_OK != env->Object_CallMethod_Void(results_obj, codeSetter, static_cast<ani_double>(result.first))) {
245         HILOG_ERROR(LOG_CORE, "call method codeSetter %{public}s failed", CLASS_NAME_RESULTS);
246         return results_obj;
247     }
248 
249     ani_method messageSetter {};
250     if (ANI_OK != env->Class_FindMethod(cls, "<set>message", nullptr, &messageSetter)) {
251         HILOG_ERROR(LOG_CORE, "find method messageSetter %{public}s failed", CLASS_NAME_RESULTS);
252         return results_obj;
253     }
254 
255     std::string message = result.second;
256     ani_string message_string {};
257     env->String_NewUTF8(message.c_str(), message.size(), &message_string);
258 
259     if (ANI_OK != env->Object_CallMethod_Void(results_obj, messageSetter, message_string)) {
260         HILOG_ERROR(LOG_CORE, "call method messageSetter Fail %{public}s", CLASS_NAME_RESULTS);
261         return results_obj;
262     }
263 
264     return results_obj;
265 }
266 
GetAniUndefined(ani_env * env)267 ani_ref LogLibraryAniUtil::GetAniUndefined(ani_env *env)
268 {
269     ani_ref result {};
270     if (ANI_OK != env->GetUndefined(&result)) {
271         HILOG_ERROR(LOG_CORE, "GetUndefined Fail");
272         return result;
273     }
274     return result;
275 }
276