1 /*
2  * Copyright (c) 2022-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 "help_utils.h"
17 
18 #include <cerrno>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <mntent.h>
22 #include <sys/mount.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 
26 #include "ipc/istorage_daemon.h"
27 #include "user/user_manager.h"
28 #include "utils/file_utils.h"
29 
30 namespace OHOS {
31 namespace StorageDaemon {
32 namespace StorageTest {
33 const std::string hmdfsTarget = "/storage/media/%d/local";
34 static constexpr int MODE_0711 = 0711;
35 const std::vector<Dir> StorageTestUtils::gRootDirs = {
36     {"/data/app/%s/%d", MODE_0711, OID_ROOT, OID_ROOT},
37     {"/data/service/%s/%d", MODE_0711, OID_ROOT, OID_ROOT},
38     {"/data/chipset/%s/%d", MODE_0711, OID_ROOT, OID_ROOT}
39 };
40 
41 const std::vector<Dir> StorageTestUtils::gSubDirs = {
42     {"/data/app/%s/%d/base", MODE_0711, OID_ROOT, OID_ROOT},
43     {"/data/app/%s/%d/database", MODE_0711, OID_ROOT, OID_ROOT}
44 };
45 
46 const std::vector<Dir> StorageTestUtils::gHmdfsDirs = {
47     {"/data/service/el2/%d/hmdfs", MODE_0711, OID_SYSTEM, OID_SYSTEM},
48     {"/data/service/el2/%d/hmdfs/files", MODE_0711, OID_SYSTEM, OID_SYSTEM},
49     {"/data/service/el2/%d/hmdfs/data", MODE_0711, OID_SYSTEM, OID_SYSTEM},
50     {"/storage/media/%d", MODE_0711, OID_ROOT, OID_ROOT},
51     {"/storage/media/%d/local", MODE_0711, OID_ROOT, OID_ROOT}
52 };
53 
CheckMount(const std::string & dstPath)54 bool StorageTestUtils::CheckMount(const std::string& dstPath)
55 {
56     const std::string fileName = "/proc/mounts";
57     FILE *mntFile;
58     struct mntent *mntent = nullptr;
59 
60     mntFile = setmntent(fileName.c_str(), "r");
61     if (!mntFile) {
62         return false;
63     }
64 
65     while ((mntent = getmntent(mntFile)) != nullptr) {
66         if (dstPath.compare(mntent->mnt_dir) == 0) {
67             endmntent(mntFile);
68             return true;
69         }
70     }
71     endmntent(mntFile);
72     return false;
73 }
74 
CheckDir(const std::string & path)75 bool StorageTestUtils::CheckDir(const std::string &path)
76 {
77     struct stat st;
78     if (lstat(path.c_str(), &st) != 0) {
79         return false;
80     }
81     return S_ISDIR(st.st_mode) == 1;
82 }
83 
CheckUserDir(int32_t userId,uint32_t flags)84 bool StorageTestUtils::CheckUserDir(int32_t userId, uint32_t flags)
85 {
86     for (const Dir &dir : gRootDirs) {
87         std::string path(dir.path);
88         path.replace(path.find("%d"), strlen("%d"), std::to_string(userId));
89 
90         if (flags & IStorageDaemon::CRYPTO_FLAG_EL1) {
91             std::string realPath(path);
92             realPath.replace(realPath.find("%s"), strlen("%s"), "el1");
93             if (CheckDir(realPath) == false) {
94                 return false;
95             }
96         }
97         if (flags & IStorageDaemon::CRYPTO_FLAG_EL2) {
98             std::string realPath(path);
99             realPath.replace(realPath.find("%s"), strlen("%s"), "el2");
100             if (CheckDir(realPath) == false) {
101                 return false;
102             }
103         }
104     }
105 
106     for (const Dir &dir : gSubDirs) {
107         if (flags & IStorageDaemon::CRYPTO_FLAG_EL1) {
108             std::string path(dir.path);
109             path.replace(path.find("%d"), strlen("%d"), std::to_string(userId));
110             path.replace(path.find("%s"), strlen("%s"), "el1");
111             if (CheckDir(path) == false) {
112                 return false;
113             }
114         }
115 
116         if (flags & IStorageDaemon::CRYPTO_FLAG_EL2) {
117             std::string path(dir.path);
118             path.replace(path.find("%d"), strlen("%d"), std::to_string(userId));
119             path.replace(path.find("%s"), strlen("%s"), "el2");
120             if (CheckDir(path) == false) {
121                 return false;
122             }
123         }
124     }
125 
126     for (const Dir &dir : gHmdfsDirs) {
127         std::string path(dir.path);
128         path.replace(path.find("%d"), strlen("%d"), std::to_string(userId));
129         if (CheckDir(path) == false) {
130             return false;
131         }
132     }
133     return true;
134 }
135 
CreateFile(const std::string & path)136 bool StorageTestUtils::CreateFile(const std::string &path)
137 {
138     (void)RmDirRecurse(path);
139     int fd = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, MODE);
140     if (fd == -1) {
141         return false;
142     }
143     (void)close(fd);
144     return true;
145 }
146 
MkDir(const std::string & path,mode_t mode)147 bool StorageTestUtils::MkDir(const std::string &path, mode_t mode)
148 {
149     if (access(path.c_str(), 0) == 0) {
150         if (rmdir(path.c_str()) != 0) {
151             return false;
152         }
153     }
154     if (mkdir(path.c_str(), mode) != 0) {
155         return false;
156     }
157     if (access(path.c_str(), 0) != 0) {
158         return false;
159     }
160     return true;
161 }
162 
RmDirRecurse(const std::string & path)163 bool StorageTestUtils::RmDirRecurse(const std::string &path)
164 {
165     struct stat st;
166     if (lstat(path.c_str(), &st) != 0) {
167         return false;
168     }
169     if (S_ISDIR(st.st_mode) != 1) {
170         return (unlink(path.c_str()) == 0);
171     }
172 
173     DIR *dir = opendir(path.c_str());
174     if (!dir) {
175         if (errno == ENOENT) {
176             return true;
177         }
178         return false;
179     }
180 
181     for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
182         if (ent->d_type == DT_DIR) {
183             if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
184                 continue;
185             }
186 
187             if (!RmDirRecurse(path + "/" + ent->d_name)) {
188                 (void)closedir(dir);
189                 return false;
190             }
191         } else {
192             if (unlink((path + "/" + ent->d_name).c_str())) {
193                 (void)closedir(dir);
194                 return false;
195             }
196         }
197     }
198 
199     (void)closedir(dir);
200     if (rmdir(path.c_str())) {
201         return false;
202     }
203 
204     return true;
205 }
206 
RmDir(const int32_t userId)207 void StorageTestUtils::RmDir(const int32_t userId)
208 {
209     std::vector<std::string> paths = {
210         "/data/app/el1/",
211         "/data/app/el2/",
212         "/data/service/el1/",
213         "/data/service/el2/",
214         "/data/chipset/el1/",
215         "/data/chipset/el2/",
216         "/storage/media/"
217     };
218 
219     for (auto path : paths) {
220         path.append(std::to_string(userId));
221         RmDirRecurse(path);
222     }
223 }
224 
ClearTestResource()225 void StorageTestUtils::ClearTestResource()
226 {
227     const int32_t userIds[] = {
228         USER_ID1,
229         USER_ID2,
230         USER_ID3,
231         USER_ID4,
232         USER_ID5
233     };
234     for (const auto id : userIds) {
235         std::string dstPath(hmdfsTarget);
236         dstPath.replace(dstPath.find("%d"), strlen("%d"), std::to_string(id));
237         UMount(dstPath);
238         RmDir(id);
239     }
240 }
241 } // StorageTest
242 } // STORAGE_DAEMON
243 } // OHOS
244