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"
26 using namespace testmock;
27 namespace fs = std::filesystem;
28
SimulateFileLock(const std::string & filePath)29 bool 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
ReleaseFileLock(const std::string & filePath)56 bool 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
AddFileToZip(zipFile zip,const std::string & filePath,const std::string & entryName)82 bool 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
AddFolderToZip(zipFile zip,const std::string & folderPath,const std::string & entryName)124 bool 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
CompressFiles(const std::vector<std::string> & files,const std::string & zipFilename)149 bool 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
181 namespace {
182 // 将内容写入 module.json 文件
WriteToFile(const std::string & filePath,const std::string & content)183 void 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
CreateFiles(const std::string hspAbcContent)194 void 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
CreateHspFile(const std::string hspFileName,const std::string hspAbcContent)214 std::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