17c804472Sopenharmony_ci/* 27c804472Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 47c804472Sopenharmony_ci * you may not use this file except in compliance with the License. 57c804472Sopenharmony_ci * You may obtain a copy of the License at 67c804472Sopenharmony_ci * 77c804472Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 87c804472Sopenharmony_ci * 97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 127c804472Sopenharmony_ci * See the License for the specific language governing permissions and 137c804472Sopenharmony_ci * limitations under the License. 147c804472Sopenharmony_ci */ 157c804472Sopenharmony_ci 167c804472Sopenharmony_ci#include "MockFile.h" 177c804472Sopenharmony_ci#include <filesystem> 187c804472Sopenharmony_ci#include <cstdio> 197c804472Sopenharmony_ci#include <iostream> 207c804472Sopenharmony_ci#include <fstream> 217c804472Sopenharmony_ci#include <fcntl.h> 227c804472Sopenharmony_ci#include <unistd.h> 237c804472Sopenharmony_ci#include <sys/file.h> 247c804472Sopenharmony_ci#include "zlib.h" 257c804472Sopenharmony_ci#include "contrib/minizip/zip.h" 267c804472Sopenharmony_ciusing namespace testmock; 277c804472Sopenharmony_cinamespace fs = std::filesystem; 287c804472Sopenharmony_ci 297c804472Sopenharmony_cibool MockFile::SimulateFileLock(const std::string& filePath) 307c804472Sopenharmony_ci{ 317c804472Sopenharmony_ci int fd = open(filePath.c_str(), O_RDWR | O_CREAT); 327c804472Sopenharmony_ci if (fd == -1) { 337c804472Sopenharmony_ci // Handle error 347c804472Sopenharmony_ci return false; 357c804472Sopenharmony_ci } 367c804472Sopenharmony_ci 377c804472Sopenharmony_ci // Attempt to acquire an exclusive lock 387c804472Sopenharmony_ci struct flock fl; 397c804472Sopenharmony_ci fl.l_type = F_WRLCK; // Exclusive write lock 407c804472Sopenharmony_ci fl.l_whence = SEEK_SET; // Starting from beginning of file 417c804472Sopenharmony_ci fl.l_start = 0; // Starting from offset 0 427c804472Sopenharmony_ci fl.l_len = 0; // Lock whole file 437c804472Sopenharmony_ci fl.l_pid = getpid(); // PID of process holding the lock 447c804472Sopenharmony_ci 457c804472Sopenharmony_ci if (fcntl(fd, F_SETLK, &fl) == -1) { 467c804472Sopenharmony_ci // Lock failed (file is already locked) 477c804472Sopenharmony_ci close(fd); 487c804472Sopenharmony_ci return true; // Simulate that file is locked 497c804472Sopenharmony_ci } 507c804472Sopenharmony_ci 517c804472Sopenharmony_ci // Lock acquired, simulate that file is not locked 527c804472Sopenharmony_ci close(fd); 537c804472Sopenharmony_ci return false; 547c804472Sopenharmony_ci} 557c804472Sopenharmony_ci 567c804472Sopenharmony_cibool MockFile::ReleaseFileLock(const std::string& filePath) 577c804472Sopenharmony_ci{ 587c804472Sopenharmony_ci int fd = open(filePath.c_str(), O_RDWR | O_CREAT); 597c804472Sopenharmony_ci if (fd == -1) { 607c804472Sopenharmony_ci // Handle error 617c804472Sopenharmony_ci return false; 627c804472Sopenharmony_ci } 637c804472Sopenharmony_ci 647c804472Sopenharmony_ci struct flock fl; 657c804472Sopenharmony_ci fl.l_type = F_UNLCK; // Unlock the file 667c804472Sopenharmony_ci fl.l_whence = SEEK_SET; // Starting from beginning of file 677c804472Sopenharmony_ci fl.l_start = 0; // Starting from offset 0 687c804472Sopenharmony_ci fl.l_len = 0; // Unlock whole file 697c804472Sopenharmony_ci 707c804472Sopenharmony_ci if (fcntl(fd, F_SETLK, &fl) == -1) { 717c804472Sopenharmony_ci // Failed to unlock 727c804472Sopenharmony_ci close(fd); 737c804472Sopenharmony_ci return false; 747c804472Sopenharmony_ci } 757c804472Sopenharmony_ci 767c804472Sopenharmony_ci // Successfully unlocked 777c804472Sopenharmony_ci close(fd); 787c804472Sopenharmony_ci return true; 797c804472Sopenharmony_ci} 807c804472Sopenharmony_ci 817c804472Sopenharmony_ci// Function to add a file to zip 827c804472Sopenharmony_cibool MockFile::AddFileToZip(zipFile zip, const std::string& filePath, const std::string& entryName) 837c804472Sopenharmony_ci{ 847c804472Sopenharmony_ci if (zipOpenNewFileInZip(zip, entryName.c_str(), NULL, NULL, 0, NULL, 0, NULL, Z_DEFLATED, 857c804472Sopenharmony_ci Z_DEFAULT_COMPRESSION) != ZIP_OK) { 867c804472Sopenharmony_ci std::cerr << "Failed to create entry in zip file for " << filePath << std::endl; 877c804472Sopenharmony_ci return false; 887c804472Sopenharmony_ci } 897c804472Sopenharmony_ci 907c804472Sopenharmony_ci FILE* file = fopen(filePath.c_str(), "rb"); 917c804472Sopenharmony_ci if (!file) { 927c804472Sopenharmony_ci std::cerr << "Failed to open file " << filePath << std::endl; 937c804472Sopenharmony_ci zipCloseFileInZip(zip); 947c804472Sopenharmony_ci return false; 957c804472Sopenharmony_ci } 967c804472Sopenharmony_ci 977c804472Sopenharmony_ci const int bufferSize = 1024; 987c804472Sopenharmony_ci void* buffer = malloc(bufferSize); 997c804472Sopenharmony_ci int size; 1007c804472Sopenharmony_ci while ((size = fread(buffer, 1, bufferSize, file)) > 0) { 1017c804472Sopenharmony_ci if (zipWriteInFileInZip(zip, buffer, size) < 0) { 1027c804472Sopenharmony_ci std::cerr << "Failed to write to zip for " << filePath << std::endl; 1037c804472Sopenharmony_ci free(buffer); 1047c804472Sopenharmony_ci if (fclose(file) == EOF) { 1057c804472Sopenharmony_ci std::cerr << "Failed to close file" << std::endl; 1067c804472Sopenharmony_ci return false; 1077c804472Sopenharmony_ci } 1087c804472Sopenharmony_ci zipCloseFileInZip(zip); 1097c804472Sopenharmony_ci return false; 1107c804472Sopenharmony_ci } 1117c804472Sopenharmony_ci } 1127c804472Sopenharmony_ci 1137c804472Sopenharmony_ci free(buffer); 1147c804472Sopenharmony_ci if (fclose(file) == EOF) { 1157c804472Sopenharmony_ci std::cerr << "Failed to close file" << std::endl; 1167c804472Sopenharmony_ci return false; 1177c804472Sopenharmony_ci } 1187c804472Sopenharmony_ci zipCloseFileInZip(zip); 1197c804472Sopenharmony_ci 1207c804472Sopenharmony_ci return true; 1217c804472Sopenharmony_ci} 1227c804472Sopenharmony_ci 1237c804472Sopenharmony_ci// Function to add a folder and its contents recursively to zip 1247c804472Sopenharmony_cibool MockFile::AddFolderToZip(zipFile zip, const std::string& folderPath, const std::string& entryName) 1257c804472Sopenharmony_ci{ 1267c804472Sopenharmony_ci for (const auto& entry : fs::recursive_directory_iterator(folderPath)) { 1277c804472Sopenharmony_ci std::string relativePath = entry.path().string().substr(folderPath.length() + 1); // Relative path 1287c804472Sopenharmony_ci 1297c804472Sopenharmony_ci if (fs::is_directory(entry)) { 1307c804472Sopenharmony_ci // Create directory entry 1317c804472Sopenharmony_ci if (zipOpenNewFileInZip(zip, (entryName + "/" + relativePath + "/").c_str(), NULL, NULL, 0, 1327c804472Sopenharmony_ci NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) != ZIP_OK) { 1337c804472Sopenharmony_ci std::cerr << "Failed to create entry in zip file for " << entry.path() << std::endl; 1347c804472Sopenharmony_ci return false; 1357c804472Sopenharmony_ci } 1367c804472Sopenharmony_ci zipCloseFileInZip(zip); 1377c804472Sopenharmony_ci } else { 1387c804472Sopenharmony_ci // Add file 1397c804472Sopenharmony_ci if (!AddFileToZip(zip, entry.path().string(), entryName + "/" + relativePath)) { 1407c804472Sopenharmony_ci return false; 1417c804472Sopenharmony_ci } 1427c804472Sopenharmony_ci } 1437c804472Sopenharmony_ci } 1447c804472Sopenharmony_ci 1457c804472Sopenharmony_ci return true; 1467c804472Sopenharmony_ci} 1477c804472Sopenharmony_ci 1487c804472Sopenharmony_ci// Main compression function 1497c804472Sopenharmony_cibool MockFile::CompressFiles(const std::vector<std::string>& files, const std::string& zipFilename) 1507c804472Sopenharmony_ci{ 1517c804472Sopenharmony_ci zipFile zip = zipOpen(zipFilename.c_str(), APPEND_STATUS_CREATE); 1527c804472Sopenharmony_ci if (!zip) { 1537c804472Sopenharmony_ci std::cerr << "Could not create zip file " << zipFilename << std::endl; 1547c804472Sopenharmony_ci return false; 1557c804472Sopenharmony_ci } 1567c804472Sopenharmony_ci 1577c804472Sopenharmony_ci for (const auto& file : files) { 1587c804472Sopenharmony_ci if (fs::is_directory(file)) { 1597c804472Sopenharmony_ci // Add directory and its contents 1607c804472Sopenharmony_ci if (!AddFolderToZip(zip, file, fs::path(file).filename())) { 1617c804472Sopenharmony_ci zipClose(zip, NULL); 1627c804472Sopenharmony_ci return false; 1637c804472Sopenharmony_ci } 1647c804472Sopenharmony_ci } else { 1657c804472Sopenharmony_ci // Add individual file 1667c804472Sopenharmony_ci if (!AddFileToZip(zip, file, fs::path(file).filename())) { 1677c804472Sopenharmony_ci zipClose(zip, NULL); 1687c804472Sopenharmony_ci return false; 1697c804472Sopenharmony_ci } 1707c804472Sopenharmony_ci } 1717c804472Sopenharmony_ci } 1727c804472Sopenharmony_ci 1737c804472Sopenharmony_ci if (zipClose(zip, NULL) != ZIP_OK) { 1747c804472Sopenharmony_ci std::cerr << "Failed to close zip file " << zipFilename << std::endl; 1757c804472Sopenharmony_ci return false; 1767c804472Sopenharmony_ci } 1777c804472Sopenharmony_ci 1787c804472Sopenharmony_ci return true; 1797c804472Sopenharmony_ci} 1807c804472Sopenharmony_ci 1817c804472Sopenharmony_cinamespace { 1827c804472Sopenharmony_ci// 将内容写入 module.json 文件 1837c804472Sopenharmony_civoid WriteToFile(const std::string& filePath, const std::string& content) 1847c804472Sopenharmony_ci{ 1857c804472Sopenharmony_ci std::ofstream file(filePath); 1867c804472Sopenharmony_ci if (!file) { 1877c804472Sopenharmony_ci std::cerr << "Error creating file: " << filePath << std::endl; 1887c804472Sopenharmony_ci return; 1897c804472Sopenharmony_ci } 1907c804472Sopenharmony_ci file << content; 1917c804472Sopenharmony_ci file.close(); 1927c804472Sopenharmony_ci} 1937c804472Sopenharmony_ci 1947c804472Sopenharmony_civoid CreateFiles(const std::string hspAbcContent) 1957c804472Sopenharmony_ci{ 1967c804472Sopenharmony_ci std::filesystem::path dir("ets"); 1977c804472Sopenharmony_ci 1987c804472Sopenharmony_ci // 检查文件夹是否存在 1997c804472Sopenharmony_ci if (std::filesystem::exists(dir)) { 2007c804472Sopenharmony_ci std::cout << "Folder already exists." << std::endl; 2017c804472Sopenharmony_ci } else { 2027c804472Sopenharmony_ci // 创建文件夹 2037c804472Sopenharmony_ci std::filesystem::create_directory(dir); 2047c804472Sopenharmony_ci std::cout << "Folder created successfully." << std::endl; 2057c804472Sopenharmony_ci } 2067c804472Sopenharmony_ci // 生成hsp文件 2077c804472Sopenharmony_ci // 在ets下写入文件modules.abc 2087c804472Sopenharmony_ci WriteToFile("ets/modules.abc", hspAbcContent); 2097c804472Sopenharmony_ci // 在当前目录下写入文件module.json 2107c804472Sopenharmony_ci WriteToFile("module.json", hspAbcContent); 2117c804472Sopenharmony_ci} 2127c804472Sopenharmony_ci} 2137c804472Sopenharmony_ci 2147c804472Sopenharmony_cistd::string MockFile::CreateHspFile(const std::string hspFileName, const std::string hspAbcContent) 2157c804472Sopenharmony_ci{ 2167c804472Sopenharmony_ci CreateFiles(hspAbcContent); 2177c804472Sopenharmony_ci std::vector<std::string> filesToCompress = { "ets", "module.json" }; 2187c804472Sopenharmony_ci std::string zipFilename = hspFileName + ".zip"; 2197c804472Sopenharmony_ci std::string newFileName = hspFileName + ".hsp"; 2207c804472Sopenharmony_ci if (CompressFiles(filesToCompress, zipFilename)) { 2217c804472Sopenharmony_ci std::cout << "Compression successful. File created: " << zipFilename << std::endl; 2227c804472Sopenharmony_ci if (std::rename(zipFilename.c_str(), newFileName.c_str()) != 0) { 2237c804472Sopenharmony_ci std::cout << newFileName << " 创建hsp文件失败" << std::endl; 2247c804472Sopenharmony_ci return ""; 2257c804472Sopenharmony_ci } 2267c804472Sopenharmony_ci } else { 2277c804472Sopenharmony_ci std::cerr << "Compression failed." << std::endl; 2287c804472Sopenharmony_ci return ""; 2297c804472Sopenharmony_ci } 2307c804472Sopenharmony_ci return newFileName; 2317c804472Sopenharmony_ci} 232