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