• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "copy/file_size_utils.h"
17 
18 #include <sys/stat.h>
19 #include <filesystem>
20 
21 #include "dfs_error.h"
22 #include "file_uri.h"
23 #include "utils_log.h"
24 
25 #undef LOG_DOMAIN
26 #undef LOG_TAG
27 #define LOG_DOMAIN 0xD001600
28 #define LOG_TAG "distributedfile_daemon"
29 
30 namespace OHOS {
31 namespace Storage {
32 namespace DistributedFile {
33 using namespace AppFileService;
34 using namespace AppFileService::ModuleFileUri;
35 using namespace FileManagement;
36 static constexpr int DISMATCH = 0;
37 static constexpr int MATCH = 1;
38 
GetSize(const std::string & uri,bool isSrcUri,uint64_t & size)39 int32_t FileSizeUtils::GetSize(const std::string &uri, bool isSrcUri, uint64_t &size)
40 {
41     auto path = GetPathFromUri(uri, isSrcUri);
42     if (path.empty()) {
43         return ERR_BAD_VALUE;
44     }
45 
46     bool isDirectory;
47     auto ret = IsDirectory(uri, isSrcUri, isDirectory);
48     if (ret != E_OK) {
49         return ret;
50     }
51     if (isDirectory) {
52         return GetDirSize(path, size);
53     } else {
54         return GetFileSize(path, size);
55     }
56 }
57 
IsDirectory(const std::string & uri,bool isSrcUri,bool & isDirectory)58 int32_t FileSizeUtils::IsDirectory(const std::string &uri, bool isSrcUri, bool &isDirectory)
59 {
60     auto path = GetPathFromUri(uri, isSrcUri);
61     if (path.empty()) {
62         return ERR_BAD_VALUE;
63     }
64 
65     bool isDir = false;
66     auto ret = IsDirectory(path, isDir);
67     if (ret != E_OK) {
68         return ret;
69     }
70 
71     bool isFile = false;
72     ret = IsFile(path, isFile);
73     if (ret != E_OK) {
74         return ret;
75     }
76 
77     if (isDir == isFile) {
78         return ERR_BAD_VALUE;
79     }
80     isDirectory = isDir;
81     return E_OK;
82 }
83 
FilterFunc(const struct dirent * filename)84 int FileSizeUtils::FilterFunc(const struct dirent *filename)
85 {
86     if (std::string_view(filename->d_name) == "." || std::string_view(filename->d_name) == "..") {
87         return DISMATCH;
88     }
89     return MATCH;
90 }
91 
Deleter(struct NameList * arg)92 void FileSizeUtils::Deleter(struct NameList *arg)
93 {
94     for (int i = 0; i < arg->direntNum; i++) {
95         free((arg->namelist)[i]);
96         (arg->namelist)[i] = nullptr;
97     }
98     free(arg->namelist);
99     arg->namelist = nullptr;
100     delete arg;
101     arg = nullptr;
102 }
103 
GetDirNameList(const std::string & path)104 std::unique_ptr<struct NameList, decltype(FileSizeUtils::Deleter) *> FileSizeUtils::GetDirNameList(
105     const std::string &path)
106 {
107     std::unique_ptr<struct NameList, decltype(Deleter) *> pNameList = { new (std::nothrow) struct NameList, Deleter };
108     if (pNameList == nullptr) {
109         LOGE("Failed to request heap memory.");
110         return pNameList;
111     }
112     int num = scandir(path.c_str(), &(pNameList->namelist), FilterFunc, alphasort);
113     pNameList->direntNum = num;
114     return pNameList;
115 }
116 
GetFileSize(const std::string & path,uint64_t & size)117 int32_t FileSizeUtils::GetFileSize(const std::string &path, uint64_t &size)
118 {
119     struct stat buf {};
120     int ret = stat(path.c_str(), &buf);
121     if (ret == -1) {
122         LOGI("Stat failed.");
123         size = 0;
124         return errno;
125     }
126     size = static_cast<uint64_t>(buf.st_size);
127     return E_OK;
128 }
129 
GetDirSize(const std::string & path,uint64_t & size)130 int32_t FileSizeUtils::GetDirSize(const std::string &path, uint64_t &size)
131 {
132     auto pNameList = GetDirNameList(path);
133     if (pNameList == nullptr) {
134         return ENOMEM;
135     }
136     size = 0;
137     for (int i = 0; i < pNameList->direntNum; i++) {
138         std::string dest = path + '/' + std::string((pNameList->namelist[i])->d_name);
139         if ((pNameList->namelist[i])->d_type == DT_LNK) {
140             continue;
141         }
142         if ((pNameList->namelist[i])->d_type == DT_DIR) {
143             uint64_t subSize = 0;
144             auto err = GetDirSize(dest, subSize);
145             if (err != E_OK) {
146                 LOGE("GetDirSize failed, path is %{public}s", dest.c_str());
147                 return err;
148             }
149             size += subSize;
150         } else {
151             struct stat st {};
152             if (stat(dest.c_str(), &st) == -1) {
153                 return errno;
154             }
155             size += static_cast<uint64_t>(st.st_size);
156         }
157     }
158     return E_OK;
159 }
160 
IsFile(const std::string & path,bool & result)161 int32_t FileSizeUtils::IsFile(const std::string &path, bool &result)
162 {
163     struct stat buf {};
164     int ret = stat(path.c_str(), &buf);
165     if (ret == -1) {
166         return errno;
167     }
168     result = (buf.st_mode & S_IFMT) == S_IFREG;
169     return E_OK;
170 }
171 
IsDirectory(const std::string & path,bool & result)172 int32_t FileSizeUtils::IsDirectory(const std::string &path, bool &result)
173 {
174     struct stat buf {};
175     int ret = stat(path.c_str(), &buf);
176     if (ret == -1) {
177         return errno;
178     }
179     result = (buf.st_mode & S_IFMT) == S_IFDIR;
180     return E_OK;
181 }
182 
GetPathFromUri(const std::string & uri,bool isSrcUri)183 std::string FileSizeUtils::GetPathFromUri(const std::string &uri, bool isSrcUri)
184 {
185     std::string path;
186     FileUri fileUri(uri);
187     if (isSrcUri) {
188         path = GetRealPath(fileUri.GetRealPath());
189     } else {
190         path = GetRealPath(fileUri.GetPath());
191     }
192     return path;
193 }
194 
GetRealPath(const std::string & path)195 std::string FileSizeUtils::GetRealPath(const std::string &path)
196 {
197     std::filesystem::path tempPath(path);
198     std::filesystem::path realPath{};
199     for (const auto& component : tempPath) {
200         if (component == ".") {
201             continue;
202         } else if (component == "..") {
203             realPath = realPath.parent_path();
204         } else {
205             realPath /= component;
206         }
207     }
208     return realPath.string();
209 }
210 } // namespace DistributedFile
211 } // namespace Storage
212 } // namespace OHOS
213