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