1 /*
2  * Copyright (c) 2021 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 "package_file.h"
17 
18 #include <fstream>
19 
20 #include "db_errno.h"
21 #include "value_hash_calc.h"
22 #include "parcel.h"
23 #include "platform_specific.h"
24 
25 namespace DistributedDB {
26 using std::string;
27 using std::vector;
28 using std::list;
29 using std::ifstream;
30 using std::ofstream;
31 using std::ios;
32 using std::ios_base;
33 
34 namespace {
35     constexpr uint32_t MAX_FILE_NAME_LEN = 256;
36     constexpr uint32_t CHECKSUM_LEN = SHA256_DIGEST_LENGTH;
37     constexpr uint32_t CHECKSUM_BLOCK_SIZE = 64;
38     constexpr uint32_t DEVICE_ID_LEN = SHA256_DIGEST_LENGTH;
39     constexpr uint32_t MAGIC_LEN = 16;
40     constexpr uint32_t CURRENT_VERSION = 0;
41     constexpr uint64_t BUFFER_LEN = 4096;
42     const string MAGIC = "HW package file";
43     const string FILE_SEPARATOR = "/";
44     const string INVALID_FILE_WORDS = "..";
45 
46     const uint32_t FILE_HEADER_LEN = MAGIC_LEN + CHECKSUM_LEN + DEVICE_ID_LEN + Parcel::GetUInt32Len() * 3;
47     const uint32_t FILE_CONTEXT_LEN = MAX_FILE_NAME_LEN + Parcel::GetUInt32Len() * 2 + Parcel::GetUInt64Len() * 2;
48 }
49 
50 struct FileContext {
51     char fileName[MAX_FILE_NAME_LEN] = {0};
52     uint32_t fileType = 0;
53     uint32_t parentID = 0;
54     uint64_t fileLen = 0;
55     uint64_t offset = 0;
56 };
57 
Clear(ofstream & target,const string & targetFile)58 static void Clear(ofstream &target, const string &targetFile)
59 {
60     if (target.is_open()) {
61         target.close();
62     }
63     if (OS::RemoveFile(targetFile) != E_OK) {
64         LOGE("Remove file failed.");
65     }
66 }
67 
GetChecksum(const string & file,vector<char> & result)68 static int GetChecksum(const string &file, vector<char> &result)
69 {
70     ifstream fileHandle(file, ios::in | ios::binary);
71     if (!fileHandle.good()) {
72         LOGE("[GetChecksum]Error fileHandle!");
73         return -E_INVALID_PATH;
74     }
75     ValueHashCalc calc;
76     int errCode = calc.Initialize();
77     if (errCode != E_OK) {
78         LOGE("[GetChecksum]Calc Initialize fail!");
79         return errCode;
80     }
81     fileHandle.seekg(static_cast<int64_t>(MAGIC_LEN + Parcel::GetUInt32Len() + CHECKSUM_LEN), ios_base::beg);
82     vector<uint8_t> buffer(CHECKSUM_BLOCK_SIZE, 0);
83     bool readEnd = false;
84     while (!readEnd) {
85         fileHandle.read(reinterpret_cast<char *>(buffer.data()), buffer.size());
86         if (fileHandle.eof()) {
87             readEnd = true;
88         } else if (!fileHandle.good()) {
89             LOGE("[GetChecksum]fileHandle error!");
90             return -E_INVALID_PATH;
91         }
92         errCode = calc.Update(buffer);
93         if (errCode != E_OK) {
94             LOGE("[GetChecksum]Calc Update fail!");
95             return errCode;
96         }
97         buffer.assign(CHECKSUM_BLOCK_SIZE, 0);
98     }
99     vector<uint8_t> resultBuf;
100     errCode = calc.GetResult(resultBuf);
101     if (errCode != E_OK) {
102         LOGE("[GetChecksum]Calc GetResult fail!");
103         return errCode;
104     }
105     result.assign(resultBuf.begin(), resultBuf.end());
106     return E_OK;
107 }
108 
GetFileContexts(const string & sourcePath,list<FileContext> & fileContexts)109 static int GetFileContexts(const string &sourcePath, list<FileContext> &fileContexts)
110 {
111     list<OS::FileAttr> files;
112     int errCode = OS::GetFileAttrFromPath(sourcePath, files, false);
113     if (errCode != E_OK) {
114         LOGE("[GetFileContexts] get file attr from path fail, errCode = [%d]", errCode);
115         return errCode;
116     }
117     FileContext fileContext;
118     int countLimit = 0;
119     for (auto file = files.begin(); file != files.end(); file++, countLimit++) {
120         if (countLimit > 20) { // Limit number of files 20 for security
121             LOGE("Too deep access for get file context!");
122             return -E_INVALID_PATH;
123         }
124 
125         if (file->fileType != OS::FILE && file->fileType != OS::PATH) {
126             continue;
127         }
128 
129         errCode = memset_s(fileContext.fileName, MAX_FILE_NAME_LEN, 0, MAX_FILE_NAME_LEN);
130         if (errCode != EOK) {
131             return -E_SECUREC_ERROR;
132         }
133 
134         if (file->fileName.size() >= MAX_FILE_NAME_LEN) {
135             LOGE("file name is too long!");
136             return -E_INVALID_FILE;
137         }
138 
139         errCode = memcpy_s(fileContext.fileName, MAX_FILE_NAME_LEN, file->fileName.c_str(), file->fileName.size());
140         if (errCode != EOK) {
141             return -E_SECUREC_ERROR;
142         }
143 
144         fileContext.fileLen = file->fileLen;
145         fileContext.fileType = file->fileType;
146         fileContexts.push_back(fileContext);
147     }
148     LOGD("Get file contexts, fileContexts size is [%zu]", fileContexts.size());
149     return E_OK;
150 }
151 
FileContentCopy(ifstream & sourceFile,ofstream & targetFile,uint64_t fileLen)152 static int FileContentCopy(ifstream &sourceFile, ofstream &targetFile, uint64_t fileLen)
153 {
154     uint64_t leftLen = fileLen;
155     vector<char> buffer(BUFFER_LEN, 0);
156     while (leftLen > 0) {
157         uint64_t readLen = (leftLen > BUFFER_LEN) ? BUFFER_LEN : leftLen;
158         sourceFile.read(buffer.data(), readLen);
159         if (!sourceFile.good()) {
160             LOGE("[FileContentCopy] SourceFile error! sys[%d]", errno);
161             return -E_INVALID_PATH;
162         }
163         targetFile.write(buffer.data(), readLen);
164         if (!targetFile.good()) {
165             LOGE("[FileContentCopy] TargetFile error! sys[%d]", errno);
166             return -E_INVALID_PATH;
167         }
168         leftLen -= readLen;
169     }
170     return E_OK;
171 }
172 
PackFileHeader(ofstream & targetFile,const FileInfo & fileInfo,uint32_t fileNum)173 static int PackFileHeader(ofstream &targetFile, const FileInfo &fileInfo, uint32_t fileNum)
174 {
175     if (fileInfo.deviceID.size() != DEVICE_ID_LEN) {
176         return -E_INVALID_ARGS;
177     }
178     vector<uint8_t> buffer(FILE_HEADER_LEN, 0);
179     vector<char> checksum(CHECKSUM_LEN, 0);
180     Parcel parcel(buffer.data(), FILE_HEADER_LEN);
181 
182     int errCode = parcel.WriteBlob(MAGIC.c_str(), MAGIC_LEN);
183     if (errCode != E_OK) {
184         return errCode;
185     }
186     // before current version package version is always 0
187     errCode = parcel.WriteUInt32(CURRENT_VERSION);
188     if (errCode != E_OK) {
189         return errCode;
190     }
191     errCode = parcel.WriteBlob(checksum.data(), CHECKSUM_LEN);
192     if (errCode != E_OK) {
193         return errCode;
194     }
195     errCode = parcel.WriteBlob(fileInfo.deviceID.c_str(), DEVICE_ID_LEN);
196     if (errCode != E_OK) {
197         return errCode;
198     }
199     errCode = parcel.WriteUInt32(fileInfo.dbType);
200     if (errCode != E_OK) {
201         return errCode;
202     }
203     errCode = parcel.WriteUInt32(fileNum);
204     if (errCode != E_OK) {
205         return errCode;
206     }
207     targetFile.write(reinterpret_cast<char *>(buffer.data()), buffer.size());
208     if (!targetFile.good()) {
209         return -E_INVALID_PATH;
210     }
211     return E_OK;
212 }
213 
CheckMagicHeader(Parcel & fileHeaderParcel)214 static int CheckMagicHeader(Parcel &fileHeaderParcel)
215 {
216     vector<char> buffer(MAGIC_LEN, 0);
217     (void)fileHeaderParcel.ReadBlob(buffer.data(), MAGIC_LEN);
218     if (fileHeaderParcel.IsError()) {
219         LOGE("[CheckMagicHeader]fileHeaderParcel error!");
220         return -E_PARSE_FAIL;
221     }
222     if (memcmp(MAGIC.c_str(), buffer.data(), MAGIC_LEN) != 0) {
223         return -E_INVALID_FILE;
224     }
225     return E_OK;
226 }
227 
UnpackFileHeader(ifstream & sourceFile,const string & sourceFileName,FileInfo & fileInfo,uint32_t & fileNum)228 static int UnpackFileHeader(ifstream &sourceFile, const string &sourceFileName, FileInfo &fileInfo, uint32_t &fileNum)
229 {
230     vector<uint8_t> fileHeader(FILE_HEADER_LEN, 0);
231     sourceFile.read(reinterpret_cast<char *>(fileHeader.data()), FILE_HEADER_LEN);
232     if (!sourceFile.good()) {
233         LOGE("UnpackFileHeader sourceFile error!");
234         return -E_INVALID_FILE;
235     }
236     Parcel parcel(fileHeader.data(), FILE_HEADER_LEN);
237     int errCode = CheckMagicHeader(parcel);
238     if (errCode != E_OK) {
239         return errCode;
240     }
241     uint32_t version;
242     vector<char> buffer(CHECKSUM_LEN, 0);
243     (void)parcel.ReadUInt32(version);
244     (void)parcel.ReadBlob(buffer.data(), CHECKSUM_LEN);
245     if (parcel.IsError()) {
246         LOGE("UnpackFileHeader parcel version error!");
247         return -E_PARSE_FAIL;
248     }
249     vector<char> checksum(CHECKSUM_LEN, 0);
250     errCode = GetChecksum(sourceFileName, checksum);
251     if (errCode != E_OK) {
252         LOGE("Get checksum failed.");
253         return errCode;
254     }
255     if (buffer != checksum) {
256         LOGE("Checksum check failed.");
257         return -E_INVALID_FILE;
258     }
259     buffer.resize(DEVICE_ID_LEN);
260     (void)parcel.ReadBlob(buffer.data(), DEVICE_ID_LEN);
261     if (parcel.IsError()) {
262         return -E_PARSE_FAIL;
263     }
264     fileInfo.deviceID.resize(DEVICE_ID_LEN);
265     fileInfo.deviceID.assign(buffer.begin(), buffer.end());
266     (void)parcel.ReadUInt32(fileInfo.dbType);
267     (void)parcel.ReadUInt32(fileNum);
268     if (parcel.IsError()) {
269         LOGE("UnpackFileHeader parcel dbType error!");
270         return -E_PARSE_FAIL;
271     }
272     return E_OK;
273 }
274 
PackFileContext(ofstream & targetFile,const FileContext & fileContext)275 static int PackFileContext(ofstream &targetFile, const FileContext &fileContext)
276 {
277     vector<uint8_t> buffer(FILE_CONTEXT_LEN, 0);
278     Parcel parcel(buffer.data(), FILE_CONTEXT_LEN);
279     int errCode = parcel.WriteBlob(fileContext.fileName, MAX_FILE_NAME_LEN);
280     if (errCode != E_OK) {
281         LOGE("PackFileContext fileContext fileName error!");
282         return errCode;
283     }
284     errCode = parcel.WriteUInt32(fileContext.fileType);
285     if (errCode != E_OK) {
286         return errCode;
287     }
288     errCode = parcel.WriteUInt32(0);
289     if (errCode != E_OK) {
290         return errCode;
291     }
292     errCode = parcel.WriteUInt64(fileContext.fileLen);
293     if (errCode != E_OK) {
294         return errCode;
295     }
296     errCode = parcel.WriteUInt64(fileContext.offset);
297     if (errCode != E_OK) {
298         return errCode;
299     }
300     targetFile.write(reinterpret_cast<char *>(buffer.data()), buffer.size());
301     if (!targetFile.good()) {
302         return -E_INVALID_PATH;
303     }
304     return E_OK;
305 }
306 
UnpackFileContext(ifstream & sourceFile,FileContext & fileContext)307 static int UnpackFileContext(ifstream &sourceFile, FileContext &fileContext)
308 {
309     vector<uint8_t> buffer(FILE_CONTEXT_LEN, 0);
310     sourceFile.read(reinterpret_cast<char *>(buffer.data()), buffer.size());
311     if (!sourceFile.good()) {
312         return -E_INVALID_PATH;
313     }
314     Parcel parcel(buffer.data(), FILE_CONTEXT_LEN);
315     (void)parcel.ReadBlob(fileContext.fileName, MAX_FILE_NAME_LEN);
316     (void)parcel.ReadUInt32(fileContext.fileType);
317     (void)parcel.ReadUInt32(fileContext.parentID);
318     (void)parcel.ReadUInt64(fileContext.fileLen);
319     (void)parcel.ReadUInt64(fileContext.offset);
320     if (parcel.IsError()) {
321         return -E_PARSE_FAIL;
322     }
323     return E_OK;
324 }
325 
PackFileContent(ofstream & targetFile,const string & sourcePath,const FileContext & fileContext)326 static int PackFileContent(ofstream &targetFile, const string &sourcePath, const FileContext &fileContext)
327 {
328     if (fileContext.fileType != OS::FILE) {
329         return E_OK;
330     }
331     string fileName = sourcePath + fileContext.fileName;
332     ifstream file(fileName, ios::in | ios::binary);
333     if (!file.good()) {
334         LOGE("[PackFileContent] File error! sys[%d]", errno);
335         return -E_INVALID_PATH;
336     }
337     file.seekg(0, ios_base::end);
338     if (!file.good()) {
339         LOGE("[PackFileContent]file error after seekg! sys[%d]", errno);
340         return -E_INVALID_PATH;
341     }
342     if (file.tellg() < 0) {
343         LOGE("[PackFileContent]file error after tellg! sys[%d]", errno);
344         return -E_INVALID_PATH;
345     }
346     uint64_t fileLen = static_cast<uint64_t>(file.tellg());
347     file.seekg(0, ios_base::beg);
348     if (!file.good()) {
349         LOGE("[PackFileContent]file error after seekg fileLen! sys[%d]", errno);
350         return -E_INVALID_PATH;
351     }
352 
353     return FileContentCopy(file, targetFile, fileLen);
354 }
355 
UnpackFileContent(ifstream & sourceFile,const string & targetPath,const FileContext & fileContext)356 static int UnpackFileContent(ifstream &sourceFile, const string &targetPath, const FileContext &fileContext)
357 {
358     if (fileContext.fileType != OS::FILE) {
359         return E_OK;
360     }
361 
362     string fileName = fileContext.fileName;
363     fileName = targetPath + FILE_SEPARATOR + fileName;
364 
365     // check if fileName contains the words ".."
366     std::string::size_type pos = fileName.find(INVALID_FILE_WORDS);
367     if (pos != std::string::npos) {
368         LOGE("[UnpackFileContent]fileName contains the words double dot!!!");
369         return -E_INVALID_PATH;
370     }
371 
372     ofstream file(fileName, ios::out | ios::binary);
373     if (!file.good()) {
374         file.close();
375         LOGE("[UnpackFileContent]Get checksum failed.");
376         return -E_INVALID_PATH;
377     }
378     int errCode = FileContentCopy(sourceFile, file, fileContext.fileLen);
379     file.close();
380     return errCode;
381 }
382 
WriteChecksum(const string & targetFile)383 static int WriteChecksum(const string &targetFile)
384 {
385     vector<char> checksum(CHECKSUM_LEN, 0);
386     int errCode = GetChecksum(targetFile, checksum);
387     if (errCode != E_OK) {
388         LOGE("Get checksum failed.");
389         return errCode;
390     }
391     ofstream targetHandle(targetFile, ios::in | ios::out | ios::binary);
392     if (!targetHandle.good()) {
393         Clear(targetHandle, targetFile);
394         LOGE("[WriteChecksum]targetHandle error, sys err [%d]", errno);
395         return -E_INVALID_PATH;
396     }
397     targetHandle.seekp(static_cast<int64_t>(MAGIC_LEN + Parcel::GetUInt32Len()), ios_base::beg);
398     if (!targetHandle.good()) {
399         Clear(targetHandle, targetFile);
400         LOGE("[WriteChecksum]targetHandle error after seekp, sys err [%d]", errno);
401         return -E_INVALID_PATH;
402     }
403     targetHandle.write(checksum.data(), checksum.size());
404     if (!targetHandle.good()) {
405         Clear(targetHandle, targetFile);
406         LOGE("[WriteChecksum]targetHandle error after write, sys err [%d]", errno);
407         return -E_INVALID_PATH;
408     }
409     targetHandle.close();
410     return E_OK;
411 }
412 
CopyFilePermissions(const string & sourceFile,const string & targetFile)413 static int CopyFilePermissions(const string &sourceFile, const string &targetFile)
414 {
415     uint32_t permissions;
416     int errCode = OS::GetFilePermissions(sourceFile, permissions);
417     if (errCode != E_OK) {
418         LOGE("Get file permissions failed.");
419         return errCode;
420     }
421     errCode = OS::SetFilePermissions(targetFile, permissions);
422     if (errCode != E_OK) {
423         LOGE("Set file permissions failed.");
424     }
425     return errCode;
426 }
427 
PackageFiles(const string & sourcePath,const string & targetFile,const FileInfo & fileInfo)428 int PackageFile::PackageFiles(const string &sourcePath, const string &targetFile,
429     const FileInfo &fileInfo)
430 {
431     int errCode = ExePackage(sourcePath, targetFile, fileInfo);
432     if (errno == EKEYREVOKED) {
433         errCode = -E_EKEYREVOKED;
434         LOGE("[PackageFile][PackageFiles] Forbid access files errCode [%d].", errCode);
435     }
436     return errCode;
437 }
438 
GetPackageVersion(const std::string & sourceFile,uint32_t & version)439 int PackageFile::GetPackageVersion(const std::string &sourceFile, uint32_t &version)
440 {
441     int errCode = E_OK;
442     vector<uint8_t> fileHeader(FILE_HEADER_LEN, 0);
443     Parcel parcel(fileHeader.data(), FILE_HEADER_LEN);
444 
445     ifstream sourceHandle(sourceFile, ios::in | ios::binary);
446     if (!sourceHandle.good()) { // LCOV_EXCL_BR_LINE
447         LOGE("sourceHandle error, sys err [%d]", errno);
448         errCode = -E_INVALID_PATH;
449         goto END;
450     }
451 
452     sourceHandle.read(reinterpret_cast<char *>(fileHeader.data()), FILE_HEADER_LEN);
453     if (!sourceHandle.good()) { // LCOV_EXCL_BR_LINE
454         LOGE("GetPackageVersion read sourceFile handle error!");
455         errCode = -E_INVALID_PATH;
456         goto END;
457     }
458 
459     errCode = CheckMagicHeader(parcel);
460     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
461         errCode = -E_INVALID_PATH;
462         goto END;
463     }
464 
465     (void)parcel.ReadUInt32(version);
466 END:
467     if (errno == EKEYREVOKED) { // LCOV_EXCL_BR_LINE
468         errCode = -E_EKEYREVOKED;
469         LOGE("[PackageFile][PackageFiles] Forbid access files by secLabel, errCode [%d].", errCode);
470     }
471     return errCode;
472 }
473 
ExePackage(const string & sourcePath,const string & targetFile,const FileInfo & fileInfo)474 int PackageFile::ExePackage(const string &sourcePath, const string &targetFile, const FileInfo &fileInfo)
475 {
476     list<FileContext> fileContexts;
477     int errCode = GetFileContexts(sourcePath, fileContexts);
478     if (errCode != E_OK) {
479         return errCode;
480     }
481     if (fileContexts.empty()) {
482         return -E_EMPTY_PATH;
483     }
484     bool targetExists = OS::CheckPathExistence(targetFile);
485     ofstream targetHandle(targetFile, ios::out | ios::binary);
486     if (!targetHandle.good()) {
487         Clear(targetHandle, targetFile);
488         LOGE("[PackageFiles]targetHandle error, sys err [%d], [%zu]", errno, fileContexts.size());
489         return -E_INVALID_PATH;
490     }
491 
492     std::string fileName = string(fileContexts.front().fileName);
493     errCode = CopyFilePermissionsIfNeed(targetExists, sourcePath, fileName, targetFile, targetHandle);
494     if (errCode != E_OK) {
495         return errCode;
496     }
497 
498     errCode = PackFileHeader(targetHandle, fileInfo, static_cast<uint32_t>(fileContexts.size()));
499     if (errCode != E_OK) {
500         Clear(targetHandle, targetFile);
501         LOGE("[PackageFiles]Pack file header err[%d]!!!", errCode);
502         return errCode;
503     }
504     // FILE_HEADER_LEN is 92, FILE_CONTEXT_LEN is 280, fileContexts.size() < UINT_MAX, the offset will never overflow.
505     uint64_t offset = FILE_HEADER_LEN + FILE_CONTEXT_LEN * static_cast<uint64_t>(fileContexts.size());
506     for (auto &file : fileContexts) {
507         file.offset = offset;
508         errCode = PackFileContext(targetHandle, file);
509         if (errCode != E_OK) {
510             Clear(targetHandle, targetFile);
511             LOGE("[PackageFiles]Pack file context err[%d]!!!", errCode);
512             return errCode;
513         }
514         offset += file.fileLen;
515     }
516     for (const auto &file : fileContexts) {
517         // If file type is path no need pack content in PackFileContent
518         errCode = PackFileContent(targetHandle, sourcePath, file);
519         if (errCode != E_OK) {
520             Clear(targetHandle, targetFile);
521             return errCode;
522         }
523     }
524     targetHandle.close();
525     return WriteChecksum(targetFile);
526 }
527 
UnpackFile(const string & sourceFile,const string & targetPath,FileInfo & fileInfo)528 int PackageFile::UnpackFile(const string &sourceFile, const string &targetPath, FileInfo &fileInfo)
529 {
530     ifstream sourceHandle(sourceFile, ios::in | ios::binary);
531     if (!sourceHandle.good()) {
532         LOGE("sourceHandle error, sys err [%d]", errno);
533         return -E_INVALID_PATH;
534     }
535     uint32_t fileNum;
536     int errCode = UnpackFileHeader(sourceHandle, sourceFile, fileInfo, fileNum);
537     if (errCode != E_OK) {
538         return errCode;
539     }
540     FileContext fileContext;
541     list<FileContext> fileContexts;
542     sourceHandle.seekg(static_cast<int64_t>(FILE_HEADER_LEN), ios_base::beg);
543     if (!sourceHandle.good()) {
544         return -E_INVALID_PATH;
545     }
546     for (uint32_t fileCount = 0; fileCount < fileNum; fileCount++) {
547         errCode = UnpackFileContext(sourceHandle, fileContext);
548         if (errCode != E_OK) {
549             return errCode;
550         }
551         fileContexts.push_back(fileContext);
552     }
553 
554     for (const auto &file : fileContexts) {
555         if (file.fileType == OS::PATH) {
556             std::string dirPath = targetPath + "/" + std::string(file.fileName);
557             if (!OS::CheckPathExistence(dirPath) && OS::MakeDBDirectory(dirPath) != E_OK) {
558                 return -E_SYSTEM_API_FAIL;
559             }
560             continue;
561         }
562         errCode = UnpackFileContent(sourceHandle, targetPath, file);
563         if (errCode != E_OK) {
564             return errCode;
565         }
566     }
567     return E_OK;
568 }
569 
CopyFilePermissionsIfNeed(bool targetExists,const std::string & sourcePath,const std::string & fileName,const std::string & targetFile,std::ofstream & targetHandle)570 int PackageFile::CopyFilePermissionsIfNeed(bool targetExists, const std::string &sourcePath,
571     const std::string &fileName, const std::string &targetFile, std::ofstream &targetHandle)
572 {
573     if (targetExists) {
574         return E_OK;
575     }
576     int errCode = CopyFilePermissions(sourcePath + FILE_SEPARATOR + fileName, targetFile);
577     if (errCode != E_OK) {
578         LOGE("Copy file fail when execute pack files! errCode = [%d]", errCode);
579         Clear(targetHandle, targetFile);
580     }
581     return errCode;
582 }
583 }
584