• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025-2025 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 #include "file_utils.h"
16 #include <chrono>
17 #include <climits>
18 #include <fcntl.h>
19 #include <fstream>
20 #include <iostream>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include "string_utils.h"
24 #include "signature_tools_errno.h"
25 
26 namespace OHOS {
27 namespace SignatureTools {
28 
29 const int FileUtils::NUM_TWO = 2;
30 const int FileUtils::NUM_THREE = 3;
31 const int FileUtils::NUM_FOUR = 4;
32 const std::string FileUtils::LIBS_PATH_PREFIX = "libs/";
33 const char ELF_MAGIC[] = { '\x7f', 'E', 'L', 'F' };
IsEmpty(std::string cs)34 bool FileUtils::IsEmpty(std::string cs)
35 {
36     if (cs.length() == 0) {
37         return true;
38     }
39     return false;
40 }
41 
GetSuffix(std::string filePath)42 std::string FileUtils::GetSuffix(std::string filePath)
43 {
44     if (filePath.empty()) {
45         return "";
46     }
47     size_t lastDotPosition = filePath.rfind(".");
48     bool positionFlag = (lastDotPosition == std::string::npos) || (lastDotPosition == filePath.size() - 1);
49     if (positionFlag) {
50         return "";
51     }
52     return filePath.substr(lastDotPosition + 1);
53 }
54 
ValidFileType(const std::string & filePath,const std::initializer_list<std::string> types)55 bool FileUtils::ValidFileType(const std::string& filePath, const std::initializer_list<std::string> types)
56 {
57     std::string suffix = GetSuffix(filePath);
58     bool flag = suffix.empty() || (StringUtils::ContainsCase(types, suffix) == false);
59     if (flag) {
60         PrintErrorNumberMsg("NOT_SUPPORT_ERROR", NOT_SUPPORT_ERROR, "Not support file: " + filePath);
61         return false;
62     }
63     return true;
64 }
65 
Write(const std::string & content,const std::string & output)66 int FileUtils::Write(const std::string& content, const std::string& output)
67 {
68     std::ofstream outFile(output, std::ios::binary);
69     bool flag = (outFile.rdstate() != 0);
70     if (flag) {
71         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open output file: " + output + " failed");
72         return IO_ERROR;
73     }
74     outFile.write(&content[0], content.size());
75     if (outFile.rdstate() != 0) {
76         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "Failed to write data to output stream.");
77         return IO_ERROR;
78     }
79     return RET_OK;
80 }
81 
Read(std::ifstream & input,std::string & ret)82 int FileUtils::Read(std::ifstream& input, std::string& ret)
83 {
84     ret.clear();
85     if (input.rdstate() != 0) {
86         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "invalid input stream");
87         return IO_ERROR;
88     }
89     ret.clear();
90     std::string buffer(FileUtils::FILE_BUFFER_BLOCK, 0);
91     while (input) {
92         input.read(&buffer[0], buffer.size());
93         if (input.fail() && !input.eof()) {
94             SIGNATURE_TOOLS_LOGE("error occurred while reading data");
95             return IO_ERROR;
96         }
97         ret.append(&buffer[0], input.gcount());
98     }
99     return RET_OK;
100 }
101 
ReadFile(const std::string & path,std::string & ret)102 int FileUtils::ReadFile(const std::string& path, std::string& ret)
103 {
104     std::ifstream file(path, std::ios::binary);
105     bool flag = (file.rdstate() != 0);
106     if (flag) {
107         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open input file: " + path + " failed");
108         return IO_ERROR;
109     }
110     if (Read(file, ret) < 0) {
111         SIGNATURE_TOOLS_LOGE("read error!");
112         return IO_ERROR;
113     }
114     return RET_OK;
115 }
116 
ReadFileToByteBuffer(const std::string & file,ByteBuffer & buffer)117 bool FileUtils::ReadFileToByteBuffer(const std::string& file, ByteBuffer& buffer)
118 {
119     std::string ret;
120     if (ReadFile(file, ret) < 0) {
121         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, file + " not exist or can not read!");
122         return false;
123     }
124     buffer.SetCapacity(static_cast<int32_t>(ret.size()));
125     buffer.PutData(ret.data(), ret.size());
126     return true;
127 }
128 
isElfFile(const std::string & filePath)129 bool FileUtils::isElfFile(const std::string& filePath)
130 {
131     char magic[sizeof(ELF_MAGIC)];
132     std::ifstream file(filePath, std::ios::binary);
133     if (!file) {
134         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open input file: " + filePath + " failed");
135         return false;
136     }
137     file.read(magic, sizeof(ELF_MAGIC));
138     return std::equal(magic, magic + sizeof(ELF_MAGIC), ELF_MAGIC);
139 }
140 
ReadFileByOffsetAndLength(std::ifstream & file,size_t offset,size_t length,std::string & ret)141 int FileUtils::ReadFileByOffsetAndLength(std::ifstream& file, size_t offset, size_t length, std::string& ret)
142 {
143     if (length > INT_MAX) {
144         SIGNATURE_TOOLS_LOGE("Size cannot be greater than Integer max value: %zu", length);
145         return RET_FAILED;
146     }
147     if (ReadInputByOffsetAndLength(file, offset, length, ret) < 0) {
148         SIGNATURE_TOOLS_LOGE("Error readInputByOffsetAndLength");
149         return IO_ERROR;
150     }
151     return RET_OK;
152 }
153 
ReadInputByOffsetAndLength(std::ifstream & input,size_t offset,size_t length,std::string & ret)154 int FileUtils::ReadInputByOffsetAndLength(std::ifstream& input, size_t offset, size_t length, std::string& ret)
155 {
156     if (length > INT_MAX) {
157         SIGNATURE_TOOLS_LOGE("Size cannot be greater than Integer max value: %zu", length);
158         return -1;
159     }
160     input.seekg(offset);
161     if (ReadInputByLength(input, length, ret) < 0) {
162         SIGNATURE_TOOLS_LOGE("Error readInputByLength");
163         return -1;
164     }
165     return RET_OK;
166 }
167 
ReadInputByLength(std::ifstream & input,size_t length,std::string & ret)168 int FileUtils::ReadInputByLength(std::ifstream& input, size_t length, std::string& ret)
169 {
170     if (length > INT_MAX) {
171         SIGNATURE_TOOLS_LOGE("Size cannot be greater than Integer max value: %zu", length);
172         return -1;
173     }
174     if (input.rdstate() != 0) {
175         SIGNATURE_TOOLS_LOGE("Error input");
176         return -1;
177     }
178     ret.clear();
179 
180     char* buffer = new (std::nothrow)char[FILE_BUFFER_BLOCK];
181     if (buffer == NULL) {
182         SIGNATURE_TOOLS_LOGE("create buffer error!");
183         return -1;
184     }
185     size_t hasReadLen = 0;
186 
187     while (hasReadLen < length && input) {
188         int readLen = static_cast<int>(std::min(length - hasReadLen, (size_t)FILE_BUFFER_BLOCK));
189         input.read(buffer, readLen);
190         bool flag = (input.gcount() != readLen);
191         if (flag) {
192             delete[] buffer;
193             SIGNATURE_TOOLS_LOGE("read %zu bytes data less than %zu", hasReadLen, length);
194             return -1;
195         }
196         ret.append(buffer, readLen);
197         hasReadLen += readLen;
198     }
199     delete[] buffer;
200     if (hasReadLen != length) {
201         SIGNATURE_TOOLS_LOGE("read %zu bytes data less than %zu", hasReadLen, length);
202         return -1;
203     }
204     return RET_OK;
205 }
206 
WriteInputToOutPut(std::ifstream & input,std::ofstream & output,size_t length)207 int FileUtils::WriteInputToOutPut(std::ifstream& input, std::ofstream& output, size_t length)
208 {
209     int result = RET_OK;
210     char* buf = new (std::nothrow)char[FILE_BUFFER_BLOCK];
211     if (buf == NULL) {
212         SIGNATURE_TOOLS_LOGE("create buffer error!");
213         return RET_FAILED;
214     }
215 
216     while (input) {
217         int min = std::min(static_cast<int>(length), FILE_BUFFER_BLOCK);
218         input.read(buf, min);
219         if (input.fail() && !input.eof()) {
220             SIGNATURE_TOOLS_LOGE("read error!");
221             delete[] buf;
222             return IO_ERROR;
223         }
224         length -= input.gcount();
225         output.write(buf, input.gcount());
226         if (!output.good()) {
227             SIGNATURE_TOOLS_LOGE("write error!");
228             delete[] buf;
229             return IO_ERROR;
230         }
231 
232         if (length <= 0) {
233             break;
234         }
235     }
236     delete[] buf;
237     // After the file is written, datasize must be 0, so the if condition will never hold
238     if (length != 0) {
239         SIGNATURE_TOOLS_LOGE("written length error!");
240         return IO_ERROR;
241     }
242     return result;
243 }
244 
WriteInputToOutPut(const std::string & input,const std::string & output)245 bool FileUtils::WriteInputToOutPut(const std::string& input, const std::string& output)
246 {
247     std::ifstream in(input, std::ios::binary);
248     std::ofstream out(output, std::ios::binary);
249     bool flag = (in.rdstate() != 0);
250     if (flag) {
251         SIGNATURE_TOOLS_LOGE("Failed to get input stream object!");
252         return false;
253     }
254     flag = (out.rdstate() != 0);
255     if (flag) {
256         SIGNATURE_TOOLS_LOGE("Failed to get output stream object!");
257         return false;
258     }
259     char* buffer = new char[FILE_BUFFER_BLOCK];
260     while (!in.eof()) {
261         in.read(buffer, FILE_BUFFER_BLOCK);
262 
263         if (in.fail() && !in.eof()) {
264             SIGNATURE_TOOLS_LOGE("error occurred while reading data");
265             delete[]buffer;
266             return false;
267         }
268 
269         std::streamsize readLen = in.gcount();
270         if (readLen > 0) {
271             out.write(buffer, readLen);
272         }
273 
274         if (!out) {
275             SIGNATURE_TOOLS_LOGE("error occurred while writing data");
276             delete[]buffer;
277             return false;
278         }
279     }
280     delete[]buffer;
281     return true;
282 }
283 
IsRunnableFile(const std::string & name)284 bool FileUtils::IsRunnableFile(const std::string& name)
285 {
286     if (name.empty()) {
287         return false;
288     }
289     size_t dotPos = name.rfind('.');
290     if (dotPos == std::string::npos) {
291         return false;
292     }
293     std::string suffix = name.substr(dotPos + 1);
294     if (suffix == "an" || suffix == "abc") {
295         return true;
296     }
297     std::string libDir = name.substr(0, LIBS_PATH_PREFIX.size());
298     if (LIBS_PATH_PREFIX.compare(libDir) == 0) {
299         return true;
300     }
301     return false;
302 }
303 
IsValidFile(std::string file)304 bool FileUtils::IsValidFile(std::string file)
305 {
306     struct stat fileStat;
307     bool flag = (stat(file.c_str(), &fileStat) == 0);
308     if (!flag) {
309         PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + file + "' file is not exists");
310         return false;
311     }
312     flag = S_ISDIR(fileStat.st_mode);
313     if (flag) {
314         PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + file + "' file is a directory not file");
315         return false;
316     }
317     SIGNATURE_TOOLS_LOGI("IsValidFile check pass %s", file.c_str());
318     return true;
319 }
320 
CopyTmpFileAndDel(const std::string & tmpFile,const std::string & output)321 bool FileUtils::CopyTmpFileAndDel(const std::string& tmpFile, const std::string& output)
322 {
323     if (tmpFile == output) {
324         return true;
325     }
326     std::ifstream src(tmpFile, std::ios::binary);
327     if (!src) {
328         PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + tmpFile + "' open failed");
329         return false;
330     }
331     std::ofstream dst(output, std::ios::binary);
332     if (!dst) {
333         PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + output + "' open failed");
334         return false;
335     }
336     SIGNATURE_TOOLS_LOGI("CopyTmpFileAndDel from %s to %s", tmpFile.c_str(), output.c_str());
337     dst << src.rdbuf();
338 
339     if (unlink(tmpFile.c_str()) != 0) {
340         SIGNATURE_TOOLS_LOGE("Error: remove tmpFile");
341         return false;
342     }
343     SIGNATURE_TOOLS_LOGI("CopyTmpFileAndDel finish");
344     return true;
345 }
346 } // namespace SignatureTools
347 } // namespace OHOS