1fb726d48Sopenharmony_ci/* 2fb726d48Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. 3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb726d48Sopenharmony_ci * You may obtain a copy of the License at 6fb726d48Sopenharmony_ci * 7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb726d48Sopenharmony_ci * 9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 13fb726d48Sopenharmony_ci * limitations under the License. 14fb726d48Sopenharmony_ci */ 15fb726d48Sopenharmony_ci 16fb726d48Sopenharmony_ci#include "file.h" 17fb726d48Sopenharmony_ci#include <cerrno> 18fb726d48Sopenharmony_ci#include <fcntl.h> 19fb726d48Sopenharmony_ci#include <fstream> 20fb726d48Sopenharmony_ci#include <iostream> 21fb726d48Sopenharmony_ci#include <sys/stat.h> 22fb726d48Sopenharmony_ci#include <unistd.h> 23fb726d48Sopenharmony_ci 24fb726d48Sopenharmony_ci#include "log.h" 25fb726d48Sopenharmony_ci#if defined(_WIN32) 26fb726d48Sopenharmony_ci#include <direct.h> 27fb726d48Sopenharmony_ci#include <io.h> 28fb726d48Sopenharmony_ci#include <windows.h> 29fb726d48Sopenharmony_ci#endif 30fb726d48Sopenharmony_ci#if defined(is_linux) || defined(_WIN32) 31fb726d48Sopenharmony_ci#include <filesystem> 32fb726d48Sopenharmony_ci#endif 33fb726d48Sopenharmony_ci#include "zlib.h" 34fb726d48Sopenharmony_ci#include "contrib/minizip/zip.h" 35fb726d48Sopenharmony_ci#include "contrib/minizip/unzip.h" 36fb726d48Sopenharmony_ci 37fb726d48Sopenharmony_cinamespace SysTuning { 38fb726d48Sopenharmony_cinamespace base { 39fb726d48Sopenharmony_cistatic TraceParserStatus g_status = TRACE_PARSER_ABNORMAL; 40fb726d48Sopenharmony_ci 41fb726d48Sopenharmony_civoid SetAnalysisResult(TraceParserStatus stat) 42fb726d48Sopenharmony_ci{ 43fb726d48Sopenharmony_ci g_status = stat; 44fb726d48Sopenharmony_ci} 45fb726d48Sopenharmony_ciTraceParserStatus GetAnalysisResult() 46fb726d48Sopenharmony_ci{ 47fb726d48Sopenharmony_ci return g_status; 48fb726d48Sopenharmony_ci} 49fb726d48Sopenharmony_ci 50fb726d48Sopenharmony_cissize_t Read(int32_t fd, uint8_t *dst, size_t dstSize) 51fb726d48Sopenharmony_ci{ 52fb726d48Sopenharmony_ci#if defined(_WIN32) 53fb726d48Sopenharmony_ci return _read(fd, dst, static_cast<unsigned>(dstSize)); 54fb726d48Sopenharmony_ci#else 55fb726d48Sopenharmony_ci ssize_t ret = -1; 56fb726d48Sopenharmony_ci do { 57fb726d48Sopenharmony_ci ret = read(fd, dst, dstSize); 58fb726d48Sopenharmony_ci } while (ret == -1 && errno == EINTR); 59fb726d48Sopenharmony_ci return ret; 60fb726d48Sopenharmony_ci#endif 61fb726d48Sopenharmony_ci} 62fb726d48Sopenharmony_ciint32_t OpenFile(const std::string &path, int32_t flags, uint32_t mode) 63fb726d48Sopenharmony_ci{ 64fb726d48Sopenharmony_ci TS_ASSERT((flags & O_CREAT) == 0 || mode != K_FILE_MODE_INVALID); 65fb726d48Sopenharmony_ci#if defined(_WIN32) 66fb726d48Sopenharmony_ci int32_t fd(_open(path.c_str(), flags | O_BINARY, mode)); 67fb726d48Sopenharmony_ci#else 68fb726d48Sopenharmony_ci int32_t fd(open(path.c_str(), flags | O_CLOEXEC, mode)); 69fb726d48Sopenharmony_ci#endif 70fb726d48Sopenharmony_ci return fd; 71fb726d48Sopenharmony_ci} 72fb726d48Sopenharmony_ci 73fb726d48Sopenharmony_cistd::string GetExecutionDirectoryPath() 74fb726d48Sopenharmony_ci{ 75fb726d48Sopenharmony_ci char currPath[1024] = {0}; 76fb726d48Sopenharmony_ci#if defined(_WIN32) 77fb726d48Sopenharmony_ci ::GetModuleFileNameA(NULL, currPath, MAX_PATH); 78fb726d48Sopenharmony_ci (strrchr(currPath, '\\'))[1] = 0; 79fb726d48Sopenharmony_ci#else 80fb726d48Sopenharmony_ci (void)readlink("/proc/self/exe", currPath, sizeof(currPath) - 1); 81fb726d48Sopenharmony_ci#endif 82fb726d48Sopenharmony_ci std::string str(currPath); 83fb726d48Sopenharmony_ci return str.substr(0, str.find_last_of('/')); 84fb726d48Sopenharmony_ci} 85fb726d48Sopenharmony_ci#if defined(is_linux) || defined(_WIN32) 86fb726d48Sopenharmony_cistd::vector<std::string> GetFilesNameFromDir(const std::string &path, bool onlyFileName) 87fb726d48Sopenharmony_ci{ 88fb726d48Sopenharmony_ci std::vector<std::string> soFiles; 89fb726d48Sopenharmony_ci 90fb726d48Sopenharmony_ci std::filesystem::path dirPath(path); 91fb726d48Sopenharmony_ci // 检查文件是否存在 92fb726d48Sopenharmony_ci if (!std::filesystem::exists(dirPath)) { 93fb726d48Sopenharmony_ci TS_LOGI("!std::filesystem::exists(dirPath), dirPath: %s\n", path.data()); 94fb726d48Sopenharmony_ci return soFiles; 95fb726d48Sopenharmony_ci } 96fb726d48Sopenharmony_ci // 遍历目录 97fb726d48Sopenharmony_ci for (const auto &entry : std::filesystem::recursive_directory_iterator(dirPath)) { 98fb726d48Sopenharmony_ci if (entry.is_directory()) { 99fb726d48Sopenharmony_ci continue; 100fb726d48Sopenharmony_ci } 101fb726d48Sopenharmony_ci soFiles.emplace_back(onlyFileName ? entry.path().filename().string() : entry.path().string()); 102fb726d48Sopenharmony_ci } 103fb726d48Sopenharmony_ci return soFiles; 104fb726d48Sopenharmony_ci} 105fb726d48Sopenharmony_ci#endif 106fb726d48Sopenharmony_ci 107fb726d48Sopenharmony_cibool UnZipFile(const std::string &zipFile, std::string &traceFile) 108fb726d48Sopenharmony_ci{ 109fb726d48Sopenharmony_ci std::filesystem::path stdZipFile(zipFile); 110fb726d48Sopenharmony_ci // 检查文件是否存在 111fb726d48Sopenharmony_ci if (!std::filesystem::exists(stdZipFile)) { 112fb726d48Sopenharmony_ci TS_LOGI("!std::filesystem::exists(dirPath), dirPath: %s\n", zipFile.data()); 113fb726d48Sopenharmony_ci return false; 114fb726d48Sopenharmony_ci } 115fb726d48Sopenharmony_ci std::ifstream zipIfstream(stdZipFile); 116fb726d48Sopenharmony_ci char buf[2]; 117fb726d48Sopenharmony_ci zipIfstream.read(buf, 2); 118fb726d48Sopenharmony_ci if (buf[0] != 'P' || buf[1] != 'K') { 119fb726d48Sopenharmony_ci // 不是zip文件, 返回true走正常解析流程 120fb726d48Sopenharmony_ci return true; 121fb726d48Sopenharmony_ci } else { 122fb726d48Sopenharmony_ci auto unzipDirPath = stdZipFile.parent_path().append("tmp").string(); 123fb726d48Sopenharmony_ci LocalUnzip(zipFile, unzipDirPath); 124fb726d48Sopenharmony_ci auto files = GetFilesNameFromDir(unzipDirPath, false); 125fb726d48Sopenharmony_ci if (files.size() == 1) { 126fb726d48Sopenharmony_ci traceFile = files[0]; 127fb726d48Sopenharmony_ci return true; 128fb726d48Sopenharmony_ci } 129fb726d48Sopenharmony_ci return false; 130fb726d48Sopenharmony_ci } 131fb726d48Sopenharmony_ci} 132fb726d48Sopenharmony_ci 133fb726d48Sopenharmony_cibool LocalUnzip(const std::string &zipFile, const std::string &dstDir) 134fb726d48Sopenharmony_ci{ 135fb726d48Sopenharmony_ci int err = 0; 136fb726d48Sopenharmony_ci void *buf; 137fb726d48Sopenharmony_ci uInt size_buf; 138fb726d48Sopenharmony_ci // 创建 dstDir 139fb726d48Sopenharmony_ci if (std::filesystem::exists(dstDir)) { 140fb726d48Sopenharmony_ci std::filesystem::remove_all(dstDir); 141fb726d48Sopenharmony_ci std::filesystem::create_directories(dstDir); 142fb726d48Sopenharmony_ci } 143fb726d48Sopenharmony_ci 144fb726d48Sopenharmony_ci // 打开zip文件 145fb726d48Sopenharmony_ci unzFile uf = unzOpen(zipFile.c_str()); 146fb726d48Sopenharmony_ci if (uf == NULL) { 147fb726d48Sopenharmony_ci std::cout << "unzOpen error." << std::endl; 148fb726d48Sopenharmony_ci return false; 149fb726d48Sopenharmony_ci } 150fb726d48Sopenharmony_ci 151fb726d48Sopenharmony_ci // 获取zip文件信息 152fb726d48Sopenharmony_ci unz_global_info gi; 153fb726d48Sopenharmony_ci err = unzGetGlobalInfo(uf, &gi); 154fb726d48Sopenharmony_ci if (err != UNZ_OK) { 155fb726d48Sopenharmony_ci std::cout << "unzGetGlobalInfo error." << std::endl; 156fb726d48Sopenharmony_ci return false; 157fb726d48Sopenharmony_ci } 158fb726d48Sopenharmony_ci 159fb726d48Sopenharmony_ci size_buf = 512000000; 160fb726d48Sopenharmony_ci buf = (void *)malloc(size_buf); 161fb726d48Sopenharmony_ci 162fb726d48Sopenharmony_ci // 遍历zip 163fb726d48Sopenharmony_ci for (int i = 0; i < gi.number_entry; i++) { 164fb726d48Sopenharmony_ci char filename_inzip[256]; 165fb726d48Sopenharmony_ci unz_file_info file_info; 166fb726d48Sopenharmony_ci uLong ratio = 0; 167fb726d48Sopenharmony_ci const char *string_method = ""; 168fb726d48Sopenharmony_ci char charCrypt = ' '; 169fb726d48Sopenharmony_ci err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); 170fb726d48Sopenharmony_ci if (err != UNZ_OK) { 171fb726d48Sopenharmony_ci std::cout << "error " << err << " with zipfile in unzGetCurrentFileInfo." << std::endl; 172fb726d48Sopenharmony_ci break; 173fb726d48Sopenharmony_ci } 174fb726d48Sopenharmony_ci std::string isdir; 175fb726d48Sopenharmony_ci std::string filename = filename_inzip; 176fb726d48Sopenharmony_ci if (filename.back() == '/' || filename.back() == '\\') { 177fb726d48Sopenharmony_ci //* 是目录,则创建目录 178fb726d48Sopenharmony_ci isdir = " is directory"; 179fb726d48Sopenharmony_ci std::string dir = dstDir + "/" + filename; 180fb726d48Sopenharmony_ci if (!std::filesystem::exists(dir)) { 181fb726d48Sopenharmony_ci std::filesystem::create_directories(dir); 182fb726d48Sopenharmony_ci } 183fb726d48Sopenharmony_ci } else { 184fb726d48Sopenharmony_ci //* 是文件,打开 -> 读取 -> 写入解压文件 -> 关闭 185fb726d48Sopenharmony_ci isdir = " is file"; 186fb726d48Sopenharmony_ci 187fb726d48Sopenharmony_ci err = unzOpenCurrentFile(uf); 188fb726d48Sopenharmony_ci if (err != UNZ_OK) { 189fb726d48Sopenharmony_ci std::cout << "error " << err << " with zipfile in unzOpenCurrentFile." << std::endl; 190fb726d48Sopenharmony_ci } else { 191fb726d48Sopenharmony_ci std::string writefile = dstDir + "/" + filename; 192fb726d48Sopenharmony_ci std::filesystem::path fpath(writefile); 193fb726d48Sopenharmony_ci std::string par = fpath.parent_path().string(); 194fb726d48Sopenharmony_ci if (!fpath.parent_path().empty() && !std::filesystem::exists(fpath.parent_path())) { 195fb726d48Sopenharmony_ci std::filesystem::create_directories(fpath.parent_path()); 196fb726d48Sopenharmony_ci } 197fb726d48Sopenharmony_ci err = unzReadCurrentFile(uf, buf, size_buf); 198fb726d48Sopenharmony_ci if (err < 0) { 199fb726d48Sopenharmony_ci std::cout << "error " << err << " with zipfile in unzReadCurrentFile." << std::endl; 200fb726d48Sopenharmony_ci break; 201fb726d48Sopenharmony_ci } 202fb726d48Sopenharmony_ci if (err > 0) { 203fb726d48Sopenharmony_ci FILE *fout = fopen(writefile.c_str(), "wb"); 204fb726d48Sopenharmony_ci if (fwrite(buf, (unsigned)err, 1, fout) != 1) { 205fb726d48Sopenharmony_ci std::cout << "error in writing extracted filee." << std::endl; 206fb726d48Sopenharmony_ci err = UNZ_ERRNO; 207fb726d48Sopenharmony_ci break; 208fb726d48Sopenharmony_ci } 209fb726d48Sopenharmony_ci fclose(fout); 210fb726d48Sopenharmony_ci } 211fb726d48Sopenharmony_ci unzCloseCurrentFile(uf); 212fb726d48Sopenharmony_ci } 213fb726d48Sopenharmony_ci } 214fb726d48Sopenharmony_ci 215fb726d48Sopenharmony_ci if ((i + 1) < gi.number_entry) { 216fb726d48Sopenharmony_ci err = unzGoToNextFile(uf); 217fb726d48Sopenharmony_ci if (err != UNZ_OK) { 218fb726d48Sopenharmony_ci std::cout << "error " << err << " with zipfile in unzGoToNextFile." << std::endl; 219fb726d48Sopenharmony_ci break; 220fb726d48Sopenharmony_ci } 221fb726d48Sopenharmony_ci } 222fb726d48Sopenharmony_ci } 223fb726d48Sopenharmony_ci 224fb726d48Sopenharmony_ci unzClose(uf); 225fb726d48Sopenharmony_ci 226fb726d48Sopenharmony_ci return true; 227fb726d48Sopenharmony_ci} 228fb726d48Sopenharmony_ci} // namespace base 229fb726d48Sopenharmony_ci} // namespace SysTuning 230