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 
16 #include "utils/set_flag_utils.h"
17 #include "utils/file_utils.h"
18 
19 #include <fcntl.h>
20 #include <filesystem>
21 #include <regex>
22 #include <sys/ioctl.h>
23 #include <sys/stat.h>
24 #include <unistd.h>
25 
26 #include "storage_service_log.h"
27 
28 namespace OHOS {
29 namespace StorageService {
30 const int START_USER_ID = 100;
31 const int MAX_USER_ID = 10736;
32 #define HMFS_MONITOR_FL 0x00000002
33 #define HMFS_IOCTL_HW_GET_FLAGS _IOR(0XF5, 70, unsigned int)
34 #define HMFS_IOCTL_HW_SET_FLAGS _IOR(0XF5, 71, unsigned int)
35 const std::string PATH_EL0 = "/data/service/el0/storage_daemon/sd";
36 const std::string PATH_EL1 = "/data/service/el1/public/storage_daemon/sd";
37 
ParseDirAllPath()38 void SetFlagUtils::ParseDirAllPath()
39 {
40     ParseDirPath(PATH_EL0);
41     ParseDirPath(PATH_EL1);
42 }
43 
ParseDirPath(const std::string & path)44 void SetFlagUtils::ParseDirPath(const std::string &path)
45 {
46     std::error_code errCode;
47     if (!std::filesystem::exists(path, errCode)) {
48         LOGE("Invalid file path.");
49         return;
50     }
51     if (!StorageDaemon::IsDir(path)) {
52         LOGE("Input path is not a directory.");
53         return;
54     }
55     if (SetDirDelFlags(path) == false) {
56         LOGE("path not exist.");
57         return;
58     }
59     std::regex pathRegex("/temp");
60     if (std::regex_match(path, pathRegex)) {
61         LOGE("Invalid file path.");
62         return;
63     }
64 
65     std::regex idRegex("/storage_daemon/sd/(\\d+)/");
66     std::smatch match;
67     if (std::regex_search(path, match, idRegex)) {
68         int userId = std::atoi(match[1].str().c_str());
69         if (userId < START_USER_ID || userId > MAX_USER_ID) {
70             LOGE("Invalid file path, userid:%{public}d", userId);
71             return;
72         }
73     }
74 
75     std::filesystem::directory_iterator pathList(path);
76     for (const auto& resPath : pathList) {
77         if (StorageDaemon::IsDir(resPath.path())) {
78             ParseDirPath(resPath.path().c_str());
79         } else if (StorageDaemon::IsFile(resPath.path())) {
80             SetFileDelFlags(resPath.path().c_str());
81         } else {
82             LOGE("Invalid file path.");
83         }
84     }
85 }
86 
SetFileDelFlags(const std::string & filepath)87 bool SetFlagUtils::SetFileDelFlags(const std::string &filepath)
88 {
89     LOGI("SetFlagUtils SetFileDelFlags for filepath=%{public}s start.", filepath.c_str());
90     char absPath[PATH_MAX] = {0};
91     if (realpath(filepath.c_str(), absPath) == nullptr) {
92         LOGE("SetFlagUtils Failed to get file realpath");
93         return false;
94     }
95     int32_t fd = open(absPath, O_RDWR);
96     if (fd < 0) {
97         LOGE("SetFlagUtils Failed to open file, errno: %{public}d", errno);
98         return false;
99     }
100     unsigned int flags = 0;
101     int32_t ret = ioctl(fd, HMFS_IOCTL_HW_GET_FLAGS, &flags);
102     if (ret < 0) {
103         LOGE("SetFlagUtils Failed to get file flags, errno: %{public}d", errno);
104         close(fd);
105         return false;
106     }
107     if (flags & HMFS_MONITOR_FL) {
108         LOGE("SetFlagUtils Delete control flag ia already set");
109         close(fd);
110         return true;
111     }
112     flags |= HMFS_MONITOR_FL;
113     ret  = ioctl(fd, HMFS_IOCTL_HW_SET_FLAGS, &flags);
114     if (ret < 0) {
115         LOGE("SetFlagUtils Failed to set file flags, errno: %{public}d", errno);
116     }
117     close(fd);
118     return true;
119 }
120 
SetDirDelFlags(const std::string & dirpath)121 bool SetFlagUtils::SetDirDelFlags(const std::string &dirpath)
122 {
123     LOGI("SetFlagUtils SetDirDelFlags for dirpath=%{public}s start.", dirpath.c_str());
124     char absPath[PATH_MAX] = {0};
125     if (realpath(dirpath.c_str(), absPath) == nullptr) {
126         LOGE("SetFlagUtils Failed to get realpath");
127         return false;
128     }
129     int32_t fd = open(absPath, O_DIRECTORY);
130     if (fd < 0) {
131         LOGE("SetFlagUtils Failed to open dir, errno: %{public}d", errno);
132         return false;
133     }
134     unsigned int flags = 0;
135     int32_t ret = ioctl(fd, HMFS_IOCTL_HW_GET_FLAGS, &flags);
136     if (ret < 0) {
137         LOGE("SetFlagUtils Failed to get flags, errno: %{public}d", errno);
138         close(fd);
139         return false;
140     }
141     if (flags & HMFS_MONITOR_FL) {
142         LOGE("SetFlagUtils Delete control flag ia already set");
143         close(fd);
144         return true;
145     }
146     flags |= HMFS_MONITOR_FL;
147     ret  = ioctl(fd, HMFS_IOCTL_HW_SET_FLAGS, &flags);
148     if (ret < 0) {
149         LOGE("SetFlagUtils Failed to set flags, errno: %{public}d", errno);
150     }
151     close(fd);
152     return true;
153 }
154 }
155 }