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