1 /*
2  * Copyright (c) 2023-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 "tar_file.h"
17 
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <grp.h>
21 #include <pwd.h>
22 #include <stack>
23 #include <sys/types.h>
24 #include <unistd.h>
25 
26 #include "b_anony/b_anony.h"
27 #include "b_error/b_error.h"
28 #include "b_resources/b_constants.h"
29 #include "directory_ex.h"
30 #include "filemgmt_libhilog.h"
31 #include "securec.h"
32 
33 namespace OHOS::FileManagement::Backup {
34 using namespace std;
35 namespace {
36 const uint32_t OFF_T_SIZE = 4;
37 const uint32_t PERMISSION_MASK = 07777;
38 const uint64_t MAX_FILE_SIZE = 0777777777777L;
39 const uint32_t OCTSTR_LEN = sizeof(off_t) * 3 + 1;
40 const uint32_t DEFAULT_SLICE_SIZE = 100 * MB_TO_BYTE; // 分片文件大小为100M
41 const uint32_t MAX_FILE_COUNT = 6000;                 // 单个tar包最多包含6000个文件
42 const uint32_t WAIT_INDEX = 100000;
43 const uint32_t WAIT_TIME = 5;
44 const string VERSION = "1.0";
45 const string LONG_LINK_SYMBOL = "longLinkSymbol";
46 } // namespace
47 
GetInstance()48 TarFile &TarFile::GetInstance()
49 {
50     static TarFile instance;
51     return instance;
52 }
53 
Packet(const vector<string> & srcFiles,const string & tarFileName,const string & pkPath,TarMap & tarMap,std::function<void (std::string,int)> reportCb)54 bool TarFile::Packet(const vector<string> &srcFiles, const string &tarFileName, const string &pkPath, TarMap &tarMap,
55     std::function<void(std::string, int)> reportCb)
56 {
57     if (tarFileName.empty() || pkPath.empty()) {
58         HILOGE("Invalid parameter");
59         return false;
60     }
61     HILOGI("Start Packet files, tarFileName is:%{public}s", tarFileName.c_str());
62     ioBuffer_.resize(READ_BUFF_SIZE);
63     baseTarName_ = tarFileName;
64     packagePath_ = pkPath;
65     if (pkPath[pkPath.length() - 1] == '/') {
66         packagePath_ = packagePath_.substr(0, packagePath_.length() - 1);
67     }
68 
69     HILOGI("Start Create  SplitTar files");
70     CreateSplitTarFile();
71 
72     size_t index = 0;
73     for (const auto &filePath : srcFiles) {
74         int err = 0;
75         rootPath_ = filePath;
76         if (!TraversalFile(rootPath_, err)) {
77             HILOGE("ReportErr Failed to traversal file, file path is:%{public}s, err = %{public}d",
78                 GetAnonyPath(filePath).c_str(), err);
79             if (err != EACCES) {
80                 reportCb("", err);
81             }
82         }
83         index++;
84         if (index >= WAIT_INDEX) {
85             HILOGD("Sleep to wait");
86             sleep(WAIT_TIME);
87             index = 0;
88         }
89     }
90     HILOGI("Start Fill SplitTailBlocks");
91     FillSplitTailBlocks();
92 
93     tarMap = tarMap_;
94 
95     if (currentTarFile_ != nullptr) {
96         fclose(currentTarFile_);
97         currentTarFile_ = nullptr;
98     }
99     HILOGI("End Packet files, pkPath is:%{public}s", pkPath.c_str());
100     return true;
101 }
102 
ToAddFile(std::string & path,int & err)103 bool TarFile::ToAddFile(std::string &path, int &err)
104 {
105     struct stat curFileStat {};
106     auto ret = memset_s(&curFileStat, sizeof(curFileStat), 0, sizeof(curFileStat));
107     if (ret != EOK) {
108         HILOGE("Failed to call memset_s, err = %{public}d", ret);
109         return false;
110     }
111     if (lstat(path.c_str(), &curFileStat) != 0) {
112         err = errno;
113         HILOGE("Failed to lstat, err = %{public}d", errno);
114         return false;
115     }
116     if (!AddFile(path, curFileStat, err)) {
117         HILOGE("Failed to add file to tar package, file path is:%{public}s", GetAnonyPath(path).c_str());
118         return false;
119     }
120     return true;
121 }
122 
TraversalFile(string & filePath,int & err)123 bool TarFile::TraversalFile(string &filePath, int &err)
124 {
125     if (access(filePath.c_str(), F_OK) != 0) {
126         err = errno;
127         HILOGE("File path does not exists, err = %{public}d", errno);
128         return false;
129     }
130     int fd = open(filePath.c_str(), O_RDONLY);
131     if (fd < 0 && errno == ERR_NO_PERMISSION) {
132         HILOGI("noPermissionFlie, don't need to backup, path = %{public}s, err = %{public}d",
133             GetAnonyString(filePath).c_str(), errno);
134         return true;
135     } else if (fd > 0) {
136         close(fd);
137     }
138     if (!ToAddFile(filePath, err)) {
139         return false;
140     }
141     if (isReset_) {
142         return true;
143     }
144 
145     if (currentTarFileSize_ >= DEFAULT_SLICE_SIZE) {
146         HILOGI("Current tar file size is over %{public}d, start to slice",
147                static_cast<int32_t>(DEFAULT_SLICE_SIZE / MB_TO_BYTE));
148         fileCount_ = 0;
149         FillSplitTailBlocks();
150         CreateSplitTarFile();
151         return true;
152     }
153 
154     // tar包内文件数量大于6000,分片打包
155     fileCount_++;
156     if (fileCount_ == MAX_FILE_COUNT) {
157         HILOGI("The number of files in the tar package exceeds %{public}d, start to slice", MAX_FILE_COUNT);
158         fileCount_ = 0;
159         FillSplitTailBlocks();
160         CreateSplitTarFile();
161     }
162 
163     return true;
164 }
165 
CopyData(TarHeader & hdr,const string & mode,const string & uid,const string & gid,const string & size)166 static bool CopyData(TarHeader &hdr, const string &mode, const string &uid, const string &gid, const string &size)
167 {
168     auto ret = memcpy_s(hdr.mode, sizeof(hdr.mode), mode.c_str(), min(sizeof(hdr.mode) - 1, mode.length()));
169     if (ret != EOK) {
170         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
171         return false;
172     }
173     ret = memcpy_s(hdr.uid, sizeof(hdr.uid), uid.c_str(), min(sizeof(hdr.uid) - 1, uid.length()));
174     if (ret != EOK) {
175         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
176         return false;
177     }
178     ret = memcpy_s(hdr.gid, sizeof(hdr.gid), gid.c_str(), min(sizeof(hdr.gid) - 1, gid.length()));
179     if (ret != EOK) {
180         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
181         return false;
182     }
183     ret = memcpy_s(hdr.size, sizeof(hdr.size), size.c_str(), min(sizeof(hdr.size) - 1, size.length()));
184     if (ret != EOK) {
185         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
186         return false;
187     }
188     return true;
189 }
190 
I2OcsConvert(const struct stat & st,TarHeader & hdr,string & fileName)191 bool TarFile::I2OcsConvert(const struct stat &st, TarHeader &hdr, string &fileName)
192 {
193     auto ret = memset_s(&hdr, sizeof(hdr), 0, sizeof(hdr));
194     if (ret != EOK) {
195         HILOGE("Failed to call memset_s, err = %{public}d", ret);
196         return false;
197     }
198 
199     string mode = I2Ocs(sizeof(hdr.mode), st.st_mode & PERMISSION_MASK);
200     string uid = I2Ocs(sizeof(hdr.uid), st.st_uid);
201     string gid = I2Ocs(sizeof(hdr.gid), st.st_gid);
202     string size = I2Ocs(sizeof(hdr.size), 0);
203     if (!CopyData(hdr, mode, uid, gid, size)) {
204         return false;
205     }
206 
207     string mtime = I2Ocs(sizeof(hdr.mtime), st.st_mtime);
208     ret = memcpy_s(hdr.mtime, sizeof(hdr.mtime), mtime.c_str(), min(sizeof(hdr.mtime) - 1, mtime.length()));
209     if (ret != EOK) {
210         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
211         return false;
212     }
213     ret = memset_s(hdr.chksum, sizeof(hdr.chksum), BLANK_SPACE, sizeof(hdr.chksum));
214     if (ret != EOK) {
215         HILOGE("Failed to call memset_s, err = %{public}d", ret);
216         return false;
217     }
218 
219     if (S_ISREG(st.st_mode)) {
220         hdr.typeFlag = REGTYPE;
221     } else if (S_ISDIR(st.st_mode)) {
222         hdr.typeFlag = DIRTYPE;
223     } else {
224         return true;
225     }
226     off_t hdrSize = st.st_size;
227     if (sizeof(off_t) <= OFF_T_SIZE || st.st_size <= static_cast<off_t>(MAX_FILE_SIZE)) {
228         size = I2Ocs(sizeof(hdr.size), hdrSize);
229         ret = memcpy_s(hdr.size, sizeof(hdr.size), size.c_str(), min(sizeof(hdr.size) - 1, size.length()));
230         if (ret != EOK) {
231             HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
232             return false;
233         }
234     } else {
235         HILOGE("Invalid tar header size");
236         return false;
237     }
238 
239     if (S_ISDIR(st.st_mode) && fileName.back() != '/') {
240         fileName.append("/");
241     }
242 
243     return true;
244 }
245 
ReadyHeader(TarHeader & hdr,const string & fileName)246 static bool ReadyHeader(TarHeader &hdr, const string &fileName)
247 {
248     errno_t ret = EOK;
249     if (fileName.length() < TNAME_LEN) {
250         if (ret = memcpy_s(hdr.name, sizeof(hdr.name), fileName.c_str(), fileName.length()), ret != EOK) {
251             HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
252             return false;
253         }
254     } else {
255         ret = memcpy_s(hdr.name, sizeof(hdr.name), LONG_LINK_SYMBOL.c_str(),
256             min(sizeof(hdr.name) - 1, LONG_LINK_SYMBOL.length()));
257         if (ret != EOK) {
258             HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
259             return false;
260         }
261     }
262     ret = memcpy_s(hdr.magic, sizeof(hdr.magic), TMAGIC.c_str(), min(sizeof(hdr.magic) - 1, TMAGIC.length()));
263     if (ret != EOK) {
264         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
265         return false;
266     }
267     ret = memcpy_s(hdr.version, sizeof(hdr.version), VERSION.c_str(), min(sizeof(hdr.version) - 1, VERSION.length()));
268     if (ret != EOK) {
269         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
270         return false;
271     }
272     return true;
273 }
274 
AddFile(string & fileName,const struct stat & st,int & err)275 bool TarFile::AddFile(string &fileName, const struct stat &st, int &err)
276 {
277     HILOGD("tar file %{public}s", fileName.c_str());
278     currentFileName_ = fileName;
279 
280     TarHeader hdr;
281     if (!I2OcsConvert(st, hdr, fileName)) {
282         HILOGE("Failed to I2OcsConvert");
283         return false;
284     }
285     if (!ReadyHeader(hdr, fileName)) {
286         return false;
287     }
288     if (fileName.length() >= TNAME_LEN) {
289         if (!WriteLongName(fileName, GNUTYPE_LONGNAME)) {
290             return false;
291         }
292     }
293     FillOwnerName(hdr, st);
294     SetCheckSum(hdr);
295 
296     if (hdr.typeFlag != REGTYPE) {
297         if (WriteTarHeader(hdr) != BLOCK_SIZE) {
298             HILOGE("Failed to write all");
299             return false;
300         }
301         currentFileName_ = "";
302         return true;
303     }
304 
305     // write tar header of src file
306     if (WriteTarHeader(hdr) != BLOCK_SIZE) {
307         HILOGE("Failed to write all");
308         return false;
309     }
310     // write src file content to tar file
311     if (!WriteFileContent(fileName, st.st_size, err)) {
312         HILOGE("Failed to write file content");
313         return false;
314     }
315     currentFileName_ = "";
316     return true;
317 }
318 
WriteFileContent(const string & fileName,off_t size,int & err)319 bool TarFile::WriteFileContent(const string &fileName, off_t size, int &err)
320 {
321     int fd = open(fileName.c_str(), O_RDONLY | O_CLOEXEC);
322     if (fd < 0) {
323         err = errno;
324         HILOGE("Failed to open file %{public}s, err = %{public}d", GetAnonyString(fileName).data(), errno);
325         return false;
326     }
327 
328     off_t remain = size;
329     while (remain > 0) {
330         off_t read = ioBuffer_.size();
331         if (remain < read) {
332             read = remain;
333         }
334         // read buffer from src file
335         if (ReadAll(fd, ioBuffer_, read) != read) {
336             HILOGE("Failed to read all");
337             break;
338         }
339 
340         // write buffer to tar file
341         if (SplitWriteAll(ioBuffer_, read) != read) {
342             HILOGE("Failed to split write all");
343             break;
344         }
345         remain -= read;
346     }
347 
348     close(fd);
349     if (remain == 0) {
350         return CompleteBlock(size);
351     }
352     return false;
353 }
354 
SplitWriteAll(const vector<uint8_t> & ioBuffer,off_t read)355 off_t TarFile::SplitWriteAll(const vector<uint8_t> &ioBuffer, off_t read)
356 {
357     off_t len = static_cast<off_t>(ioBuffer.size());
358     if (len > read) {
359         len = read;
360     }
361     off_t count = 0;
362     while (count < len) {
363         auto writeBytes = fwrite(&ioBuffer[count], sizeof(uint8_t), len - count, currentTarFile_);
364         if (writeBytes < 1) {
365             // 再执行一遍
366             writeBytes = fwrite(&ioBuffer[count], sizeof(uint8_t), len - count, currentTarFile_);
367             if (writeBytes < 1) {
368                 HILOGE("Failed to fwrite tar file, err = %{public}d", errno);
369                 return count;
370             }
371         }
372         count += static_cast<off_t>(writeBytes);
373         currentTarFileSize_ += static_cast<off_t>(writeBytes);
374     }
375     return count;
376 }
377 
CreateSplitTarFile()378 bool TarFile::CreateSplitTarFile()
379 {
380     tarFileName_ = baseTarName_ + "." + to_string(tarFileCount_) + ".tar";
381     currentTarName_ = packagePath_ + "/" + tarFileName_;
382     if (currentTarFile_ != nullptr) {
383         fclose(currentTarFile_);
384         currentTarFile_ = nullptr;
385     }
386     // create a tar file
387     currentTarFile_ = fopen(currentTarName_.c_str(), "wb+");
388     if (currentTarFile_ == nullptr) {
389         HILOGE("Failed to open file %{public}s, err = %{public}d", currentTarName_.c_str(), errno);
390         throw BError(BError::Codes::EXT_BACKUP_PACKET_ERROR, "CreateSplitTarFile Failed to open file");
391     }
392     currentTarFileSize_ = 0;
393 
394     return true;
395 }
396 
CompleteBlock(off_t size)397 bool TarFile::CompleteBlock(off_t size)
398 {
399     if ((size % BLOCK_SIZE) > 0) {
400         int append = BLOCK_SIZE - (size % BLOCK_SIZE);
401         vector<uint8_t> buff {};
402         buff.resize(append);
403         WriteAll(buff, append);
404     }
405     return true;
406 }
407 
FillSplitTailBlocks()408 bool TarFile::FillSplitTailBlocks()
409 {
410     if (currentTarFile_ == nullptr) {
411         throw BError(BError::Codes::EXT_BACKUP_PACKET_ERROR, "FillSplitTailBlocks currentTarFile_ is null");
412     }
413 
414     // write tar file tail
415     const int END_BLOCK_SIZE = 1024;
416     vector<uint8_t> buff {};
417     buff.resize(END_BLOCK_SIZE);
418     WriteAll(buff, END_BLOCK_SIZE);
419     fflush(currentTarFile_);
420 
421     struct stat staTar {};
422     int ret = stat(currentTarName_.c_str(), &staTar);
423     if (ret != 0) {
424         HILOGE("Failed to stat file %{public}s, err = %{public}d", currentTarName_.c_str(), errno);
425         throw BError(BError::Codes::EXT_BACKUP_PACKET_ERROR, "FillSplitTailBlocks Failed to stat file");
426     }
427 
428     if (staTar.st_size == 0 && tarFileCount_ > 0 && fileCount_ == 0) {
429         fclose(currentTarFile_);
430         currentTarFile_ = nullptr;
431         remove(currentTarName_.c_str());
432         return true;
433     }
434 
435     if (isReset_) {
436         tarMap_.clear();
437     }
438 
439     tarMap_.emplace(tarFileName_, make_tuple(currentTarName_, staTar, false));
440 
441     fclose(currentTarFile_);
442     currentTarFile_ = nullptr;
443     tarFileCount_++;
444 
445     return true;
446 }
447 
SetCheckSum(TarHeader & hdr)448 void TarFile::SetCheckSum(TarHeader &hdr)
449 {
450     int sum = 0;
451     vector<uint32_t> buffer {};
452     buffer.resize(BLOCK_SIZE);
453     buffer.assign(reinterpret_cast<uint8_t *>(&hdr), reinterpret_cast<uint8_t *>(&hdr) + sizeof(hdr));
454     for (uint32_t index = 0; index < BLOCK_SIZE; index++) {
455         if (index < CHKSUM_BASE || index > CHKSUM_BASE + CHKSUM_LEN - 1) {
456             sum += (buffer[index] & 0xFF);
457         } else {
458             sum += BLANK_SPACE;
459         }
460     }
461     string chksum = I2Ocs(sizeof(hdr.chksum), sum);
462     auto ret = memcpy_s(hdr.chksum, sizeof(hdr.chksum), chksum.c_str(), min(sizeof(hdr.chksum) - 1, chksum.length()));
463     if (ret != EOK) {
464         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
465     }
466 }
467 
FillOwnerName(TarHeader & hdr,const struct stat & st)468 void TarFile::FillOwnerName(TarHeader &hdr, const struct stat &st)
469 {
470     struct passwd *pw = getpwuid(st.st_uid);
471     if (pw != nullptr) {
472         auto ret = snprintf_s(hdr.uname, sizeof(hdr.uname), sizeof(hdr.uname) - 1, "%s", pw->pw_name);
473         if (ret < 0 || ret >= static_cast<int>(sizeof(hdr.uname))) {
474             HILOGE("Fill pw_name failed, err = %{public}d", errno);
475         }
476     } else {
477         auto ret = snprintf_s(hdr.uname, sizeof(hdr.uname), sizeof(hdr.uname) - 1, "%u", st.st_uid);
478         if (ret < 0 || ret >= static_cast<int>(sizeof(hdr.uname))) {
479             HILOGE("Fill uid failed, err = %{public}d", errno);
480         }
481     }
482 
483     struct group *gr = getgrgid(st.st_gid);
484     if (gr != nullptr) {
485         auto ret = snprintf_s(hdr.gname, sizeof(hdr.gname), sizeof(hdr.gname) - 1, "%s", gr->gr_name);
486         if (ret < 0 || ret >= static_cast<int>(sizeof(hdr.gname))) {
487             HILOGE("Fill gr_name failed, err = %{public}d", errno);
488         }
489     } else {
490         auto ret = snprintf_s(hdr.gname, sizeof(hdr.gname), sizeof(hdr.gname) - 1, "%u", st.st_gid);
491         if (ret < 0 || ret >= static_cast<int>(sizeof(hdr.gname))) {
492             HILOGE("Fill gid failed, err = %{public}d", errno);
493         }
494     }
495 }
496 
ReadAll(int fd,vector<uint8_t> & ioBuffer,off_t size)497 off_t TarFile::ReadAll(int fd, vector<uint8_t> &ioBuffer, off_t size)
498 {
499     off_t count = 0;
500     off_t len = static_cast<off_t>(ioBuffer.size());
501     if (len > size) {
502         len = size;
503     }
504     while (count < len) {
505         auto readLen = read(fd, &ioBuffer[count], len - count);
506         count += static_cast<off_t>(readLen);
507         if (readLen == 0) {
508             break;
509         }
510     }
511     return count;
512 }
513 
WriteTarHeader(TarHeader & header)514 int TarFile::WriteTarHeader(TarHeader &header)
515 {
516     vector<uint8_t> buffer {};
517     buffer.resize(BLOCK_SIZE);
518     buffer.assign(reinterpret_cast<uint8_t *>(&header), reinterpret_cast<uint8_t *>(&header) + sizeof(header));
519     int ret = WriteAll(buffer, BLOCK_SIZE);
520     if (ret != BLOCK_SIZE) {
521         buffer.erase(buffer.begin(), buffer.begin() + ret);
522         ret += WriteAll(buffer, BLOCK_SIZE - ret); // 再执行一遍
523     }
524     return ret;
525 }
526 
WriteAll(const vector<uint8_t> & buf,size_t len)527 int TarFile::WriteAll(const vector<uint8_t> &buf, size_t len)
528 {
529     size_t count = 0;
530     while (count < len) {
531         auto i = fwrite(&buf[0] + count, sizeof(char), len - count, currentTarFile_);
532         if (i < 1) {
533             HILOGE("Failed to fwrite tar file, err = %{public}d", errno);
534             return count;
535         }
536         count += i;
537         currentTarFileSize_ += static_cast<off_t>(i);
538     }
539     return count;
540 }
541 
I2Ocs(int len,off_t val)542 string TarFile::I2Ocs(int len, off_t val)
543 {
544     if (len < 1) {
545         HILOGE("Invalid parameter");
546         return "";
547     }
548     char tmp[OCTSTR_LEN] = {0};
549     if (sprintf_s(tmp, sizeof(tmp), "%0*llo", len - 1, val) < 0) {
550         return "";
551     }
552     return string(tmp);
553 }
554 
WriteNormalData(TarHeader & tmp)555 static bool WriteNormalData(TarHeader& tmp)
556 {
557     const string FORMAT = "%0*d";
558 
559     strlcpy(tmp.name, LONG_LINK_SYMBOL.c_str(), sizeof(tmp.name));
560     int ret = sprintf_s(tmp.mode, sizeof(tmp.mode), FORMAT.c_str(), (int)sizeof(tmp.mode) - 1, 0);
561     if (ret < 0) {
562         return false;
563     }
564     ret = sprintf_s(tmp.uid, sizeof(tmp.uid), FORMAT.c_str(), (int)sizeof(tmp.uid) - 1, 0);
565     if (ret < 0) {
566         return false;
567     }
568     ret = sprintf_s(tmp.gid, sizeof(tmp.gid), FORMAT.c_str(), (int)sizeof(tmp.gid) - 1, 0);
569     if (ret < 0) {
570         return false;
571     }
572     ret = sprintf_s(tmp.size, sizeof(tmp.size), FORMAT.c_str(), (int)sizeof(tmp.size) - 1, 0);
573     if (ret < 0) {
574         return false;
575     }
576     ret = sprintf_s(tmp.mtime, sizeof(tmp.mtime), FORMAT.c_str(), (int)sizeof(tmp.mtime) - 1, 0);
577     if (ret < 0) {
578         return false;
579     }
580     return true;
581 }
582 
WriteLongName(string & name,char type)583 bool TarFile::WriteLongName(string &name, char type)
584 {
585     // fill tar header for long name
586     TarHeader tmp;
587     errno_t ret = memset_s(&tmp, sizeof(tmp), 0, sizeof(tmp));
588     if (ret != EOK) {
589         HILOGE("Failed to call memset_s, err = %{public}d", ret);
590         return false;
591     }
592 
593     size_t sz = name.length() + 1;
594     if (!WriteNormalData(tmp)) {
595         return false;
596     }
597     string size = I2Ocs(sizeof(tmp.size), static_cast<off_t>(sz));
598     ret = memcpy_s(tmp.size, sizeof(tmp.size), size.c_str(), min(sizeof(tmp.size) - 1, size.length()));
599     if (ret != EOK) {
600         HILOGE("Failed to call memcpy_s, err = %{public}d", ret);
601         return false;
602     }
603 
604     tmp.typeFlag = type;
605     if (ret = memset_s(tmp.chksum, sizeof(tmp.chksum), BLANK_SPACE, sizeof(tmp.chksum)), ret != EOK) {
606         HILOGE("Failed to call memset_s, err = %{public}d", ret);
607         return false;
608     }
609 
610     strlcpy(tmp.magic, TMAGIC.c_str(), sizeof(tmp.magic));
611     strlcpy(tmp.version, VERSION.c_str(), sizeof(tmp.version));
612 
613     SetCheckSum(tmp);
614 
615     // write long name head to archive
616     if (WriteTarHeader(tmp) != BLOCK_SIZE) {
617         HILOGE("Failed to write long name header");
618         return false;
619     }
620 
621     // write name to archive
622     vector<uint8_t> buffer {};
623     buffer.resize(sz);
624     buffer.assign(name.begin(), name.end());
625     if (static_cast<size_t>(WriteAll(buffer, sz)) != sz) {
626         HILOGE("Failed to write long name buffer");
627         return false;
628     }
629 
630     return CompleteBlock(static_cast<off_t>(sz));
631 }
632 
SetPacketMode(bool isReset)633 void TarFile::SetPacketMode(bool isReset)
634 {
635     isReset_ = isReset;
636 }
637 } // namespace OHOS::FileManagement::Backup