1 /*
2  * Copyright (C) 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 #include "compress.h"
16 
17 #include <fstream>
18 
19 namespace Hdc {
AddPath(std::string path)20 bool Compress::AddPath(std::string path)
21 {
22     uv_fs_t req;
23     int rc = uv_fs_lstat(nullptr, &req, path.c_str(), nullptr);
24     uv_fs_req_cleanup(&req);
25     if (rc != 0) {
26         WRITE_LOG(LOG_FATAL, "%s is not exist", path.c_str());
27         return false;
28     }
29     if (req.statbuf.st_mode & S_IFREG) {
30         return AddEntry(path);
31     }
32     if (!AddEntry(path)) {
33         WRITE_LOG(LOG_DEBUG, "AddEntry failed dir:%s", path.c_str());
34         return false;
35     }
36     rc = uv_fs_scandir(nullptr, &req, path.c_str(), 0, nullptr);
37     if (rc < 0) {
38         WRITE_LOG(LOG_DEBUG, "uv_fs_scandir failed dir:%s", path.c_str());
39         uv_fs_req_cleanup(&req);
40         return false;
41     }
42     uv_dirent_t dent;
43     while (uv_fs_scandir_next(&req, &dent) != UV_EOF) {
44         if (strncmp(dent.name, ".", 1) == 0 || strncmp(dent.name, "..", 2) == 0) {
45             continue;
46         }
47         string subpath = path + Base::GetPathSep() + dent.name;
48         if (!AddPath(subpath)) {
49             uv_fs_req_cleanup(&req);
50             return false;
51         }
52     }
53     uv_fs_req_cleanup(&req);
54     return true;
55 }
56 
AddEntry(std::string path)57 bool Compress::AddEntry(std::string path)
58 {
59     if (this->maxcount > 0 && this->entrys.size() > this->maxcount) {
60         WRITE_LOG(LOG_FATAL, "Entry.size %zu exceeded maximum %zu", entrys.size(), maxcount);
61         return false;
62     }
63     if (this->prefix.length() > 0 && path == this->prefix) {
64         WRITE_LOG(LOG_DEBUG, "Ignoring compressed root directory");
65         return true;
66     }
67     Entry entry(this->prefix, path);
68     WRITE_LOG(LOG_DEBUG, "AddEntry %s", path.c_str());
69     entrys.push_back(entry);
70     return true;
71 }
72 
SaveToFile(std::string localPath)73 bool Compress::SaveToFile(std::string localPath)
74 {
75     if (localPath.length() <= 0) {
76         localPath = "tmp.tar";
77     }
78     uv_fs_t req;
79     int rc = uv_fs_lstat(nullptr, &req, localPath.c_str(), nullptr);
80     if (rc == 0 && req.statbuf.st_mode & S_IFDIR) {
81         return false;
82     }
83 
84     std::ofstream file(localPath.c_str(), std::ios::out | std::ios::binary);
85     if (!file.is_open()) {
86         WRITE_LOG(LOG_FATAL, "SaveToFile open file %s failed", localPath.c_str());
87         return false;
88     }
89     WRITE_LOG(LOG_DEBUG, "SaveToFile entrys len : %u", entrys.size());
90     for (auto& entry : entrys) {
91         entry.WriteToTar(file);
92     }
93     file.close();
94     return true;
95 }
96 
UpdataPrefix(std::string pathPrefix)97 void Compress::UpdataPrefix(std::string pathPrefix)
98 {
99     this->prefix = pathPrefix;
100 }
101 
UpdataMaxCount(size_t maxCount)102 void Compress::UpdataMaxCount(size_t maxCount)
103 {
104     this->maxcount = maxCount;
105 }
106 }
107