1/* 2 * Copyright (c) 2024 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 "MockFile.h" 17#include <filesystem> 18#include <cstdio> 19#include <iostream> 20#include <fstream> 21#include <fcntl.h> 22#include <unistd.h> 23#include <sys/file.h> 24#include "zlib.h" 25#include "contrib/minizip/zip.h" 26using namespace testmock; 27namespace fs = std::filesystem; 28 29bool MockFile::SimulateFileLock(const std::string& filePath) 30{ 31 int fd = open(filePath.c_str(), O_RDWR | O_CREAT); 32 if (fd == -1) { 33 // Handle error 34 return false; 35 } 36 37 // Attempt to acquire an exclusive lock 38 struct flock fl; 39 fl.l_type = F_WRLCK; // Exclusive write lock 40 fl.l_whence = SEEK_SET; // Starting from beginning of file 41 fl.l_start = 0; // Starting from offset 0 42 fl.l_len = 0; // Lock whole file 43 fl.l_pid = getpid(); // PID of process holding the lock 44 45 if (fcntl(fd, F_SETLK, &fl) == -1) { 46 // Lock failed (file is already locked) 47 close(fd); 48 return true; // Simulate that file is locked 49 } 50 51 // Lock acquired, simulate that file is not locked 52 close(fd); 53 return false; 54} 55 56bool MockFile::ReleaseFileLock(const std::string& filePath) 57{ 58 int fd = open(filePath.c_str(), O_RDWR | O_CREAT); 59 if (fd == -1) { 60 // Handle error 61 return false; 62 } 63 64 struct flock fl; 65 fl.l_type = F_UNLCK; // Unlock the file 66 fl.l_whence = SEEK_SET; // Starting from beginning of file 67 fl.l_start = 0; // Starting from offset 0 68 fl.l_len = 0; // Unlock whole file 69 70 if (fcntl(fd, F_SETLK, &fl) == -1) { 71 // Failed to unlock 72 close(fd); 73 return false; 74 } 75 76 // Successfully unlocked 77 close(fd); 78 return true; 79} 80 81// Function to add a file to zip 82bool MockFile::AddFileToZip(zipFile zip, const std::string& filePath, const std::string& entryName) 83{ 84 if (zipOpenNewFileInZip(zip, entryName.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, 85 Z_DEFAULT_COMPRESSION) != ZIP_OK) { 86 std::cerr << "Failed to create entry in zip file for " << filePath << std::endl; 87 return false; 88 } 89 90 FILE* file = fopen(filePath.c_str(), "rb"); 91 if (!file) { 92 std::cerr << "Failed to open file " << filePath << std::endl; 93 zipCloseFileInZip(zip); 94 return false; 95 } 96 97 const int bufferSize = 1024; 98 void* buffer = malloc(bufferSize); 99 int size; 100 while ((size = fread(buffer, 1, bufferSize, file)) > 0) { 101 if (zipWriteInFileInZip(zip, buffer, size) < 0) { 102 std::cerr << "Failed to write to zip for " << filePath << std::endl; 103 free(buffer); 104 if (fclose(file) == EOF) { 105 std::cerr << "Failed to close file" << std::endl; 106 return false; 107 } 108 zipCloseFileInZip(zip); 109 return false; 110 } 111 } 112 113 free(buffer); 114 if (fclose(file) == EOF) { 115 std::cerr << "Failed to close file" << std::endl; 116 return false; 117 } 118 zipCloseFileInZip(zip); 119 120 return true; 121} 122 123// Function to add a folder and its contents recursively to zip 124bool MockFile::AddFolderToZip(zipFile zip, const std::string& folderPath, const std::string& entryName) 125{ 126 for (const auto& entry : fs::recursive_directory_iterator(folderPath)) { 127 std::string relativePath = entry.path().string().substr(folderPath.length() + 1); // Relative path 128 129 if (fs::is_directory(entry)) { 130 // Create directory entry 131 if (zipOpenNewFileInZip(zip, (entryName + "/" + relativePath + "/").c_str(), NULL, NULL, 0, 132 NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) { 133 std::cerr << "Failed to create entry in zip file for " << entry.path() << std::endl; 134 return false; 135 } 136 zipCloseFileInZip(zip); 137 } else { 138 // Add file 139 if (!AddFileToZip(zip, entry.path().string(), entryName + "/" + relativePath)) { 140 return false; 141 } 142 } 143 } 144 145 return true; 146} 147 148// Main compression function 149bool MockFile::CompressFiles(const std::vector<std::string>& files, const std::string& zipFilename) 150{ 151 zipFile zip = zipOpen(zipFilename.c_str(), APPEND_STATUS_CREATE); 152 if (!zip) { 153 std::cerr << "Could not create zip file " << zipFilename << std::endl; 154 return false; 155 } 156 157 for (const auto& file : files) { 158 if (fs::is_directory(file)) { 159 // Add directory and its contents 160 if (!AddFolderToZip(zip, file, fs::path(file).filename())) { 161 zipClose(zip, NULL); 162 return false; 163 } 164 } else { 165 // Add individual file 166 if (!AddFileToZip(zip, file, fs::path(file).filename())) { 167 zipClose(zip, NULL); 168 return false; 169 } 170 } 171 } 172 173 if (zipClose(zip, NULL) != ZIP_OK) { 174 std::cerr << "Failed to close zip file " << zipFilename << std::endl; 175 return false; 176 } 177 178 return true; 179} 180 181namespace { 182// 将内容写入 module.json 文件 183void WriteToFile(const std::string& filePath, const std::string& content) 184{ 185 std::ofstream file(filePath); 186 if (!file) { 187 std::cerr << "Error creating file: " << filePath << std::endl; 188 return; 189 } 190 file << content; 191 file.close(); 192} 193 194void CreateFiles(const std::string hspAbcContent) 195{ 196 std::filesystem::path dir("ets"); 197 198 // 检查文件夹是否存在 199 if (std::filesystem::exists(dir)) { 200 std::cout << "Folder already exists." << std::endl; 201 } else { 202 // 创建文件夹 203 std::filesystem::create_directory(dir); 204 std::cout << "Folder created successfully." << std::endl; 205 } 206 // 生成hsp文件 207 // 在ets下写入文件modules.abc 208 WriteToFile("ets/modules.abc", hspAbcContent); 209 // 在当前目录下写入文件module.json 210 WriteToFile("module.json", hspAbcContent); 211} 212} 213 214std::string MockFile::CreateHspFile(const std::string hspFileName, const std::string hspAbcContent) 215{ 216 CreateFiles(hspAbcContent); 217 std::vector<std::string> filesToCompress = { "ets", "module.json" }; 218 std::string zipFilename = hspFileName + ".zip"; 219 std::string newFileName = hspFileName + ".hsp"; 220 if (CompressFiles(filesToCompress, zipFilename)) { 221 std::cout << "Compression successful. File created: " << zipFilename << std::endl; 222 if (std::rename(zipFilename.c_str(), newFileName.c_str()) != 0) { 223 std::cout << newFileName << " 创建hsp文件失败" << std::endl; 224 return ""; 225 } 226 } else { 227 std::cerr << "Compression failed." << std::endl; 228 return ""; 229 } 230 return newFileName; 231} 232