1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci#include "script_instructionhelper.h" 16fb299fa2Sopenharmony_ci#include <dlfcn.h> 17fb299fa2Sopenharmony_ci#include <set> 18fb299fa2Sopenharmony_ci#include "dump.h" 19fb299fa2Sopenharmony_ci#include "scope_guard.h" 20fb299fa2Sopenharmony_ci#include "script_basicinstruction.h" 21fb299fa2Sopenharmony_ci#include "script_loadscript.h" 22fb299fa2Sopenharmony_ci#include "script_manager_impl.h" 23fb299fa2Sopenharmony_ci#include "script_registercmd.h" 24fb299fa2Sopenharmony_ci#include "script_updateprocesser.h" 25fb299fa2Sopenharmony_ci#include "script_utils.h" 26fb299fa2Sopenharmony_ci 27fb299fa2Sopenharmony_ciusing namespace BasicInstruction; 28fb299fa2Sopenharmony_ciusing namespace Updater; 29fb299fa2Sopenharmony_ci 30fb299fa2Sopenharmony_cinamespace Uscript { 31fb299fa2Sopenharmony_cistatic std::set<std::string> g_reservedInstructions = { 32fb299fa2Sopenharmony_ci "LoadScript", "RegisterCmd", "abort", "assert", "concat", 33fb299fa2Sopenharmony_ci "is_substring", "stdout", "sleep", "set_progress", "ui_print", 34fb299fa2Sopenharmony_ci "show_progress", "set_proportion" 35fb299fa2Sopenharmony_ci }; 36fb299fa2Sopenharmony_ci 37fb299fa2Sopenharmony_cistatic ScriptInstructionHelper* g_instructionHelper = nullptr; 38fb299fa2Sopenharmony_ci 39fb299fa2Sopenharmony_ciScriptInstructionHelper* ScriptInstructionHelper::GetBasicInstructionHelper(ScriptManagerImpl *impl) 40fb299fa2Sopenharmony_ci{ 41fb299fa2Sopenharmony_ci if (g_instructionHelper == nullptr) { 42fb299fa2Sopenharmony_ci if (impl == nullptr) { 43fb299fa2Sopenharmony_ci return nullptr; 44fb299fa2Sopenharmony_ci } 45fb299fa2Sopenharmony_ci g_instructionHelper = new ScriptInstructionHelper(impl); 46fb299fa2Sopenharmony_ci } 47fb299fa2Sopenharmony_ci return g_instructionHelper; 48fb299fa2Sopenharmony_ci} 49fb299fa2Sopenharmony_ci 50fb299fa2Sopenharmony_civoid ScriptInstructionHelper::ReleaseBasicInstructionHelper() 51fb299fa2Sopenharmony_ci{ 52fb299fa2Sopenharmony_ci if (g_instructionHelper != nullptr) { 53fb299fa2Sopenharmony_ci delete g_instructionHelper; 54fb299fa2Sopenharmony_ci } 55fb299fa2Sopenharmony_ci g_instructionHelper = nullptr; 56fb299fa2Sopenharmony_ci} 57fb299fa2Sopenharmony_ci 58fb299fa2Sopenharmony_ciScriptInstructionHelper::~ScriptInstructionHelper() 59fb299fa2Sopenharmony_ci{ 60fb299fa2Sopenharmony_ci if (instrLib_ != nullptr) { 61fb299fa2Sopenharmony_ci dlclose(instrLib_); 62fb299fa2Sopenharmony_ci } 63fb299fa2Sopenharmony_ci instrLib_ = nullptr; 64fb299fa2Sopenharmony_ci} 65fb299fa2Sopenharmony_ci 66fb299fa2Sopenharmony_ciint32_t ScriptInstructionHelper::RegisterInstructions() const 67fb299fa2Sopenharmony_ci{ 68fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("RegisterCmder", new ScriptRegisterCmd()); 69fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("LoadScript", new ScriptLoadScript()); 70fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("Stdout", new UScriptInstructionStdout()); 71fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("Abort", new UScriptInstructionAbort()); 72fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("Assert", new UScriptInstructionAssert()); 73fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("Sleep", new UScriptInstructionSleep()); 74fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("Concat", new UScriptInstructionConcat()); 75fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("IsSubString", new UScriptInstructionIsSubString()); 76fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("set_progress", new UScriptInstructionSetProcess()); 77fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("show_progress", new UScriptInstructionShowProcess()); 78fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("ui_print", new UScriptInstructionUiPrint()); 79fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("DeleteFile", new UScriptInstructionDeleteFile()); 80fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("DeleteDir", new UScriptInstructionDeleteDir()); 81fb299fa2Sopenharmony_ci scriptManager_->AddInstruction("set_proportion", new UScriptInstructionSetProportion()); 82fb299fa2Sopenharmony_ci return USCRIPT_SUCCESS; 83fb299fa2Sopenharmony_ci} 84fb299fa2Sopenharmony_ci 85fb299fa2Sopenharmony_cibool ScriptInstructionHelper::IsReservedInstruction(const std::string &scriptName) const 86fb299fa2Sopenharmony_ci{ 87fb299fa2Sopenharmony_ci if (g_reservedInstructions.find(scriptName) != g_reservedInstructions.end()) { 88fb299fa2Sopenharmony_ci return true; 89fb299fa2Sopenharmony_ci } 90fb299fa2Sopenharmony_ci return false; 91fb299fa2Sopenharmony_ci} 92fb299fa2Sopenharmony_ci 93fb299fa2Sopenharmony_ciint32_t ScriptInstructionHelper::AddScript(const std::string &scriptName, int32_t priority) const 94fb299fa2Sopenharmony_ci{ 95fb299fa2Sopenharmony_ci return scriptManager_->AddScript(scriptName, priority); 96fb299fa2Sopenharmony_ci} 97fb299fa2Sopenharmony_ci 98fb299fa2Sopenharmony_ciint32_t ScriptInstructionHelper::AddInstruction(const std::string &instrName, const UScriptInstructionPtr instr) 99fb299fa2Sopenharmony_ci{ 100fb299fa2Sopenharmony_ci if (IsReservedInstruction(instrName)) { 101fb299fa2Sopenharmony_ci USCRIPT_LOGE(" %s reserved", instrName.c_str()); 102fb299fa2Sopenharmony_ci return USCRIPT_ERROR_REVERED; 103fb299fa2Sopenharmony_ci } 104fb299fa2Sopenharmony_ci return scriptManager_->AddInstruction(instrName, instr); 105fb299fa2Sopenharmony_ci} 106fb299fa2Sopenharmony_ci 107fb299fa2Sopenharmony_ciint32_t ScriptInstructionHelper::RegisterAddInstruction(const Uscript::UScriptInstructionFactoryPtr factory, 108fb299fa2Sopenharmony_ci const std::string &instrName) 109fb299fa2Sopenharmony_ci{ 110fb299fa2Sopenharmony_ci UPDATER_INIT_RECORD; 111fb299fa2Sopenharmony_ci // Create instruction and register it 112fb299fa2Sopenharmony_ci UScriptInstructionPtr instr = nullptr; 113fb299fa2Sopenharmony_ci int32_t ret = factory->CreateInstructionInstance(instr, instrName); 114fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS || instr == nullptr) { 115fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to create instruction for %s", instrName.c_str()); 116fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 117fb299fa2Sopenharmony_ci return ret == USCRIPT_SUCCESS ? USCRIPT_ERROR_CREATE_OBJ : USCRIPT_NOTEXIST_INSTRUCTION; 118fb299fa2Sopenharmony_ci } 119fb299fa2Sopenharmony_ci 120fb299fa2Sopenharmony_ci ret = AddInstruction(instrName, instr); 121fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS) { 122fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to add instruction for %s", instrName.c_str()); 123fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(ret); 124fb299fa2Sopenharmony_ci // ret is USCRIPT_ERROR_REVERED, instr register failed, can be deleted 125fb299fa2Sopenharmony_ci delete instr; 126fb299fa2Sopenharmony_ci instr = nullptr; 127fb299fa2Sopenharmony_ci } 128fb299fa2Sopenharmony_ci // ScriptManagerImpl::AddInstruction has saved instr, don't delete it here!!! 129fb299fa2Sopenharmony_ci return ret; 130fb299fa2Sopenharmony_ci} 131fb299fa2Sopenharmony_ci 132fb299fa2Sopenharmony_ciint32_t ScriptInstructionHelper::RegisterUserInstruction(const std::string& libName, 133fb299fa2Sopenharmony_ci const std::string &instrName) 134fb299fa2Sopenharmony_ci{ 135fb299fa2Sopenharmony_ci // first get realpath of libName, then compare with realLibName 136fb299fa2Sopenharmony_ci UPDATER_INIT_RECORD; 137fb299fa2Sopenharmony_ci char *realPath = realpath(libName.c_str(), nullptr); 138fb299fa2Sopenharmony_ci if (realPath == nullptr) { 139fb299fa2Sopenharmony_ci USCRIPT_LOGE("realPath is NULL %s", libName.c_str()); 140fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 141fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 142fb299fa2Sopenharmony_ci } 143fb299fa2Sopenharmony_ci std::string realLibName = realPath; 144fb299fa2Sopenharmony_ci free(realPath); 145fb299fa2Sopenharmony_ci if (!userInstrLibName_.empty() && userInstrLibName_.compare(realLibName) != 0) { 146fb299fa2Sopenharmony_ci USCRIPT_LOGE("Lib name must be equal %s ", realLibName.c_str()); 147fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 148fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 149fb299fa2Sopenharmony_ci } 150fb299fa2Sopenharmony_ci 151fb299fa2Sopenharmony_ci userInstrLibName_.assign(realLibName); 152fb299fa2Sopenharmony_ci Uscript::UScriptInstructionFactoryPtr factory = nullptr; 153fb299fa2Sopenharmony_ci if (instrLib_ == nullptr) { 154fb299fa2Sopenharmony_ci instrLib_ = dlopen(realLibName.c_str(), RTLD_LAZY | RTLD_LOCAL); 155fb299fa2Sopenharmony_ci } 156fb299fa2Sopenharmony_ci if (instrLib_ == nullptr) { 157fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to dlopen %s , dlerror: %s", libName.c_str(), dlerror()); 158fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 159fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 160fb299fa2Sopenharmony_ci } 161fb299fa2Sopenharmony_ci auto pGetInstructionFactory = 162fb299fa2Sopenharmony_ci (Uscript::UScriptInstructionFactoryPtr(*)())dlsym(instrLib_, "GetInstructionFactory"); 163fb299fa2Sopenharmony_ci auto pReleaseInstructionFactory = 164fb299fa2Sopenharmony_ci (void(*)(Uscript::UScriptInstructionFactoryPtr))dlsym(instrLib_, "ReleaseInstructionFactory"); 165fb299fa2Sopenharmony_ci if (pReleaseInstructionFactory == nullptr || pGetInstructionFactory == nullptr) { 166fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to get sym %s", libName.c_str()); 167fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 168fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 169fb299fa2Sopenharmony_ci } 170fb299fa2Sopenharmony_ci factory = pGetInstructionFactory(); 171fb299fa2Sopenharmony_ci if (factory == nullptr) { 172fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to create instruction factory for %s", instrName.c_str()); 173fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 174fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 175fb299fa2Sopenharmony_ci } 176fb299fa2Sopenharmony_ci ON_SCOPE_EXIT(freeFactory) { 177fb299fa2Sopenharmony_ci pReleaseInstructionFactory(factory); 178fb299fa2Sopenharmony_ci }; 179fb299fa2Sopenharmony_ci 180fb299fa2Sopenharmony_ci return RegisterAddInstruction(factory, instrName); 181fb299fa2Sopenharmony_ci} 182fb299fa2Sopenharmony_ci 183fb299fa2Sopenharmony_ciint32_t ScriptInstructionHelper::RegisterUserInstruction(const std::string &instrName, 184fb299fa2Sopenharmony_ci Uscript::UScriptInstructionFactory *factory) 185fb299fa2Sopenharmony_ci{ 186fb299fa2Sopenharmony_ci if (factory == nullptr) { 187fb299fa2Sopenharmony_ci USCRIPT_LOGE("%s factory is null", instrName.c_str()); 188fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 189fb299fa2Sopenharmony_ci } 190fb299fa2Sopenharmony_ci 191fb299fa2Sopenharmony_ci // Create instruction and register it 192fb299fa2Sopenharmony_ci UScriptInstructionPtr instr = nullptr; 193fb299fa2Sopenharmony_ci int32_t ret = factory->CreateInstructionInstance(instr, instrName); 194fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS || instr == nullptr) { 195fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to create instruction for %s", instrName.c_str()); 196fb299fa2Sopenharmony_ci // when instr == nullptr && ret == USCRIPT_SUCCESS, shouldn't return USCRIPT_SUCCESS 197fb299fa2Sopenharmony_ci return ret == USCRIPT_SUCCESS ? USCRIPT_ERROR_CREATE_OBJ : USCRIPT_NOTEXIST_INSTRUCTION; 198fb299fa2Sopenharmony_ci } 199fb299fa2Sopenharmony_ci 200fb299fa2Sopenharmony_ci ret = AddInstruction(instrName, instr); 201fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS) { 202fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to add instruction for %s", instrName.c_str()); 203fb299fa2Sopenharmony_ci delete instr; 204fb299fa2Sopenharmony_ci instr = nullptr; 205fb299fa2Sopenharmony_ci return ret; 206fb299fa2Sopenharmony_ci } 207fb299fa2Sopenharmony_ci 208fb299fa2Sopenharmony_ci USCRIPT_LOGD("RegisterUserInstruction %s successfull", instrName.c_str()); 209fb299fa2Sopenharmony_ci return ret; 210fb299fa2Sopenharmony_ci} 211fb299fa2Sopenharmony_ci} // namespace Uscript 212