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