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