• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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