• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 #include <iostream>
16 #include <filesystem>
17 #include <fstream>
18 #include <climits>
19 
20 #include "string_utils.h"
21 #include "signature_tools_errno.h"
22 #include "file_utils.h"
23 
24 namespace OHOS {
25 namespace SignatureTools {
26 namespace fs = std::filesystem;
27 
28 const int FileUtils::NUM_TWO = 2;
29 const int FileUtils::NUM_THREE = 3;
30 const int FileUtils::NUM_FOUR = 4;
31 const std::string FileUtils::LIBS_PATH_PREFIX = "libs/";
IsEmpty(std::string cs)32 bool FileUtils::IsEmpty(std::string cs)
33 {
34     if (cs.length() == 0) {
35         return true;
36     }
37     return false;
38 }
39 
IsSpaceEnough(const std::string & filePath,const int64_t requiredSpace)40 bool FileUtils::IsSpaceEnough(const std::string& filePath, const int64_t requiredSpace)
41 {
42     uint64_t freeSpace = 0;
43     struct statfs diskStatfs;
44     int ret = statfs(filePath.c_str(), &diskStatfs);
45     if (ret >= 0) {
46         freeSpace = (uint64_t)diskStatfs.f_bsize * (uint64_t)diskStatfs.f_bavail;
47     } else {
48         SIGNATURE_TOOLS_LOGE("statfs fail, error code = %d", ret);
49     }
50     return freeSpace >= static_cast<uint64_t>(requiredSpace);
51 }
52 
GetSuffix(std::string filePath)53 std::string FileUtils::GetSuffix(std::string filePath)
54 {
55     if (filePath.empty()) {
56         return "";
57     }
58     size_t lastDotPosition = filePath.rfind(".");
59     bool positionFlag = (lastDotPosition == std::string::npos) || (lastDotPosition == filePath.size() - 1);
60     if (positionFlag) {
61         return "";
62     }
63     return filePath.substr(lastDotPosition + 1);
64 }
65 
ValidFileType(const std::string & filePath,const std::initializer_list<std::string> types)66 bool FileUtils::ValidFileType(const std::string& filePath, const std::initializer_list<std::string> types)
67 {
68     std::string suffix = GetSuffix(filePath);
69     bool flag = suffix.empty() || (StringUtils::ContainsCase(types, suffix) == false);
70     if (flag) {
71         PrintErrorNumberMsg("NOT_SUPPORT_ERROR", NOT_SUPPORT_ERROR, "Not support file: " + filePath);
72         return false;
73     }
74     return true;
75 }
76 
Write(const std::string & content,const std::string & output)77 int FileUtils::Write(const std::string& content, const std::string& output)
78 {
79     std::ofstream outFile(output, std::ios::binary);
80     bool flag = (outFile.rdstate() != 0);
81     if (flag) {
82         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open output file: " + output + " failed");
83         return IO_ERROR;
84     }
85     outFile.write(&content[0], content.size());
86     if (outFile.rdstate() != 0) {
87         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "Failed to write data to output stream.");
88         return IO_ERROR;
89     }
90     return RET_OK;
91 }
92 
Read(std::ifstream & input,std::string & ret)93 int FileUtils::Read(std::ifstream& input, std::string& ret)
94 {
95     ret.clear();
96     if (input.rdstate() != 0) {
97         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "invalid input stream");
98         return IO_ERROR;
99     }
100     ret.clear();
101     std::string buffer(FileUtils::FILE_BUFFER_BLOCK, 0);
102     while (input) {
103         input.read(&buffer[0], buffer.size());
104         if (input.fail() && !input.eof()) {
105             SIGNATURE_TOOLS_LOGE("error occurred while reading data");
106             return IO_ERROR;
107         }
108         ret.append(&buffer[0], input.gcount());
109     }
110     return RET_OK;
111 }
112 
ReadFile(const std::string & path,std::string & ret)113 int FileUtils::ReadFile(const std::string& path, std::string& ret)
114 {
115     std::ifstream file(path, std::ios::binary);
116     bool flag = (file.rdstate() != 0);
117     if (flag) {
118         PrintErrorNumberMsg("IO_ERROR", IO_ERROR, "open input file: " + path + " failed");
119         return IO_ERROR;
120     }
121     if (Read(file, ret) < 0) {
122         SIGNATURE_TOOLS_LOGE("read error!");
123         return IO_ERROR;
124     }
125     return RET_OK;
126 }
127 
ReadFileByOffsetAndLength(std::ifstream & file,size_t offset,size_t length,std::string & ret)128 int FileUtils::ReadFileByOffsetAndLength(std::ifstream& file, size_t offset, size_t length, std::string& ret)
129 {
130     if (length > INT_MAX) {
131         SIGNATURE_TOOLS_LOGE("Size cannot be greater than Integer max value: %zu", length);
132         return RET_FAILED;
133     }
134     if (ReadInputByOffsetAndLength(file, offset, length, ret) < 0) {
135         SIGNATURE_TOOLS_LOGE("Error readInputByOffsetAndLength");
136         return IO_ERROR;
137     }
138     return RET_OK;
139 }
140 
ReadInputByOffsetAndLength(std::ifstream & input,size_t offset,size_t length,std::string & ret)141 int FileUtils::ReadInputByOffsetAndLength(std::ifstream& input, 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 -1;
146     }
147     input.seekg(offset);
148     if (ReadInputByLength(input, length, ret) < 0) {
149         SIGNATURE_TOOLS_LOGE("Error readInputByLength");
150         return -1;
151     }
152     return RET_OK;
153 }
154 
ReadInputByLength(std::ifstream & input,size_t length,std::string & ret)155 int FileUtils::ReadInputByLength(std::ifstream& input, size_t length, std::string& ret)
156 {
157     if (length > INT_MAX) {
158         SIGNATURE_TOOLS_LOGE("Size cannot be greater than Integer max value: %zu", length);
159         return -1;
160     }
161     if (input.rdstate() != 0) {
162         SIGNATURE_TOOLS_LOGE("Error input");
163         return -1;
164     }
165     ret.clear();
166 
167     char* buffer = new (std::nothrow)char[FILE_BUFFER_BLOCK];
168     if (buffer == NULL) {
169         SIGNATURE_TOOLS_LOGE("create buffer error!");
170         return -1;
171     }
172     size_t hasReadLen = 0;
173 
174     while (hasReadLen < length && input) {
175         int readLen = static_cast<int>(std::min(length - hasReadLen, (size_t)FILE_BUFFER_BLOCK));
176         input.read(buffer, readLen);
177         bool flag = (input.gcount() != readLen);
178         if (flag) {
179             delete[] buffer;
180             SIGNATURE_TOOLS_LOGE("read %zu bytes data less than %zu", hasReadLen, length);
181             return -1;
182         }
183         ret.append(buffer, readLen);
184         hasReadLen += readLen;
185     }
186     delete[] buffer;
187     if (hasReadLen != length) {
188         SIGNATURE_TOOLS_LOGE("read %zu bytes data less than %zu", hasReadLen, length);
189         return -1;
190     }
191     return RET_OK;
192 }
193 
AppendWriteFileByOffsetToFile(std::ifstream & input,std::ofstream & out,size_t offset,size_t size)194 bool FileUtils::AppendWriteFileByOffsetToFile(std::ifstream& input, std::ofstream& out, size_t offset, size_t size)
195 {
196     if (input.rdstate() != 0) {
197         SIGNATURE_TOOLS_LOGE("input failed.");
198         return false;
199     }
200     if (out.rdstate() != 0) {
201         SIGNATURE_TOOLS_LOGE("Failed get out stream");
202         return false;
203     }
204     input.seekg(offset);
205     if (WriteInputToOutPut(input, out, size) < 0) {
206         SIGNATURE_TOOLS_LOGE("Error: writeInputToOutPut");
207         return false;
208     }
209     return true;
210 }
211 
AppendWriteFileToFile(const std::string & inputFile,const std::string & outputFile)212 bool FileUtils::AppendWriteFileToFile(const std::string& inputFile, const std::string& outputFile)
213 {
214     std::ifstream input(inputFile, std::ios::binary);
215     std::ofstream output(outputFile, std::ios::binary | std::ios::app);
216     bool flag = (0 != input.rdstate());
217     if (flag) {
218         SIGNATURE_TOOLS_LOGE("Failed to get input stream object!");
219         return false;
220     }
221     flag = (0 != output.rdstate());
222     if (flag) {
223         SIGNATURE_TOOLS_LOGE("Failed to get output stream object!");
224         return false;
225     }
226     char* buffer = new char[FILE_BUFFER_BLOCK];
227     while (!input.eof()) {
228         input.read(buffer, FILE_BUFFER_BLOCK);
229 
230         if (input.fail() && !input.eof()) {
231             SIGNATURE_TOOLS_LOGE("error occurred while reading data");
232             delete[]buffer;
233             return false;
234         }
235         std::streamsize readLen = input.gcount();
236         if (readLen > 0) {
237             output.write(buffer, readLen);
238         }
239         if (!output) {
240             SIGNATURE_TOOLS_LOGE("error occurred while writing data");
241             delete[]buffer;
242             return false;
243         }
244     }
245     delete[]buffer;
246     return true;
247 }
248 
AppendWriteByteToFile(const std::string & bytes,const std::string & outputFile)249 bool FileUtils::AppendWriteByteToFile(const std::string& bytes, const std::string& outputFile)
250 {
251     std::ofstream output(outputFile, std::ios::binary | std::ios::app);
252     bool flag = (WriteByteToOutFile(bytes, output) == false);
253     if (flag) {
254         SIGNATURE_TOOLS_LOGE("Failed to write data to output stream, outfile: %s", outputFile.c_str());
255         return false;
256     }
257     return true;
258 }
259 
WriteInputToOutPut(std::ifstream & input,std::ofstream & output,size_t length)260 int FileUtils::WriteInputToOutPut(std::ifstream& input, std::ofstream& output, size_t length)
261 {
262     int result = RET_OK;
263     char* buf = new (std::nothrow)char[FILE_BUFFER_BLOCK];
264     if (buf == NULL) {
265         SIGNATURE_TOOLS_LOGE("create buffer error!");
266         return RET_FAILED;
267     }
268 
269     while (input) {
270         int min = std::min(static_cast<int>(length), FILE_BUFFER_BLOCK);
271         input.read(buf, min);
272         if (input.fail() && !input.eof()) {
273             SIGNATURE_TOOLS_LOGE("read error!");
274             delete[] buf;
275             return IO_ERROR;
276         }
277         length -= input.gcount();
278         output.write(buf, input.gcount());
279         if (!output.good()) {
280             SIGNATURE_TOOLS_LOGE("write error!");
281             delete[] buf;
282             return IO_ERROR;
283         }
284 
285         if (length <= 0) {
286             break;
287         }
288     }
289     delete[] buf;
290     // After the file is written, datasize must be 0, so the if condition will never hold
291     if (length != 0) {
292         SIGNATURE_TOOLS_LOGE("written length error!");
293         return IO_ERROR;
294     }
295     return result;
296 }
297 
WriteInputToOutPut(const std::string & input,const std::string & output)298 bool FileUtils::WriteInputToOutPut(const std::string& input, const std::string& output)
299 {
300     std::ifstream in(input, std::ios::binary);
301     std::ofstream out(output, std::ios::binary);
302     bool flag = (in.rdstate() != 0);
303     if (flag) {
304         SIGNATURE_TOOLS_LOGE("Failed to get input stream object!");
305         return false;
306     }
307     flag = (out.rdstate() != 0);
308     if (flag) {
309         SIGNATURE_TOOLS_LOGE("Failed to get output stream object!");
310         return false;
311     }
312     char* buffer = new char[FILE_BUFFER_BLOCK];
313     while (!in.eof()) {
314         in.read(buffer, FILE_BUFFER_BLOCK);
315 
316         if (in.fail() && !in.eof()) {
317             SIGNATURE_TOOLS_LOGE("error occurred while reading data");
318             delete[]buffer;
319             return false;
320         }
321 
322         std::streamsize readLen = in.gcount();
323         if (readLen > 0) {
324             out.write(buffer, readLen);
325         }
326 
327         if (!out) {
328             SIGNATURE_TOOLS_LOGE("error occurred while writing data");
329             delete[]buffer;
330             return false;
331         }
332     }
333     delete[]buffer;
334     return true;
335 }
336 
WriteByteToOutFile(const std::string & bytes,const std::string & outFile)337 bool FileUtils::WriteByteToOutFile(const std::string& bytes, const std::string& outFile)
338 {
339     std::ofstream ops(outFile, std::ios::binary);
340     bool flag = (WriteByteToOutFile(bytes, ops) == false);
341     if (flag) {
342         SIGNATURE_TOOLS_LOGE("Failed to write data to ops, outfile: %s", outFile.c_str());
343         return false;
344     }
345     return true;
346 }
347 
WriteByteToOutFile(const std::string & bytes,std::ofstream & outFile)348 bool FileUtils::WriteByteToOutFile(const std::string& bytes, std::ofstream& outFile)
349 {
350     if (outFile.rdstate() != 0) {
351         SIGNATURE_TOOLS_LOGE("Failed to get output stream object, outfile");
352         return false;
353     }
354     outFile.write(&bytes[0], bytes.size());
355     if (outFile.rdstate() != 0) {
356         SIGNATURE_TOOLS_LOGE("Failed to write data to ops, outfile ");
357         return false;
358     }
359     outFile.flush();
360     if (outFile.rdstate() != 0) {
361         SIGNATURE_TOOLS_LOGE("Flush error");
362         return false;
363     }
364     return true;
365 }
366 
WriteByteToOutFile(const std::vector<int8_t> & bytes,std::ofstream & outFile)367 bool FileUtils::WriteByteToOutFile(const std::vector<int8_t>& bytes, std::ofstream& outFile)
368 {
369     if (outFile.rdstate() != 0) {
370         SIGNATURE_TOOLS_LOGE("Failed to get output stream object, outfile");
371         return false;
372     }
373     outFile.write((char*)&bytes[0], bytes.size());
374     if (outFile.rdstate() != 0) {
375         SIGNATURE_TOOLS_LOGE("Failed to write data to ops, outfile ");
376         return false;
377     }
378     outFile.flush();
379     if (outFile.rdstate() != 0) {
380         SIGNATURE_TOOLS_LOGE("Flush error");
381         return false;
382     }
383     return true;
384 }
385 
IsRunnableFile(const std::string & name)386 bool FileUtils::IsRunnableFile(const std::string& name)
387 {
388     if (name.empty()) {
389         return false;
390     }
391     size_t dotPos = name.rfind('.');
392     if (dotPos == std::string::npos) {
393         return false;
394     }
395     std::string suffix = name.substr(dotPos + 1);
396     if (suffix == "an" || suffix == "abc") {
397         return true;
398     }
399     std::string libDir = name.substr(0, LIBS_PATH_PREFIX.size());
400     if (LIBS_PATH_PREFIX.compare(libDir) == 0) {
401         return true;
402     }
403     return false;
404 }
405 
IsValidFile(std::string file)406 bool FileUtils::IsValidFile(std::string file)
407 {
408     std::filesystem::path filePath = file;
409     bool flag = std::filesystem::exists(filePath);
410     if (!flag) {
411         PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + file + "' file is not exists");
412         return false;
413     }
414     flag = std::filesystem::is_directory(filePath);
415     if (flag) {
416         PrintErrorNumberMsg("FILE_NOT_FOUND", FILE_NOT_FOUND, "'" + file + "' file is a directory not file");
417         return false;
418     }
419     return true;
420 }
421 
GetFileLen(const std::string & file)422 int64_t FileUtils::GetFileLen(const std::string& file)
423 {
424     std::filesystem::path filePath = file;
425     bool flag = std::filesystem::exists(filePath) && std::filesystem::is_regular_file(filePath);
426     if (flag) {
427         return std::filesystem::file_size(filePath);
428     }
429     return -1;
430 }
431 
DelDir(const std::string & file)432 void FileUtils::DelDir(const std::string& file)
433 {
434     std::filesystem::path filePath = file;
435     bool flag = std::filesystem::is_directory(filePath);
436     if (flag) {
437         for (auto& p : std::filesystem::recursive_directory_iterator(filePath)) {
438             DelDir(p.path());
439         }
440     }
441     std::filesystem::remove(file);
442     return;
443 }
444 
445 } // namespace SignatureTools
446 } // namespace OHOS