1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-09-21
13 * Description: 文件系统vfs层
14 */
15
16 #include "stdlib.h"
17 #include "string.h"
18 #include "securec.h"
19 #include "vfs_mount.h"
20 #include "vfs_files.h"
21 #include "vfs_maps.h"
22 #include "vfs_config.h"
23 #include "vfs_operations.h"
24 #include "prt_fs.h"
25
26 static struct TagMountPoint *g_mountPoints;
27
OsMpDeleteFromList(struct TagMountPoint * mp)28 static void OsMpDeleteFromList(struct TagMountPoint *mp)
29 {
30 struct TagMountPoint *prev = NULL;
31
32 if (g_mountPoints == mp) {
33 g_mountPoints = mp->mNext;
34 return;
35 }
36
37 for (prev = g_mountPoints; prev != NULL; prev = prev->mNext) {
38 if (prev->mNext != mp) {
39 continue;
40 }
41
42 prev->mNext = mp->mNext;
43 break;
44 }
45 }
46
OsVfsFindMpByPath(const char * mPath,const char * iPath)47 static S32 OsVfsFindMpByPath(const char *mPath, const char *iPath)
48 {
49 const char *t = NULL;
50 S32 matches = 0;
51 do {
52 while ((*mPath == '/') && (*(mPath + 1) != '/')) {
53 mPath++;
54 }
55 while ((*iPath == '/') && (*(iPath + 1) != '/')) {
56 iPath++;
57 }
58
59 t = strchr(mPath, '/');
60 if (t == NULL) {
61 t = strchr(mPath, '\0');
62 }
63 if ((t == mPath) || (t == NULL)) {
64 break;
65 }
66 if (strncmp(mPath, iPath, (size_t)(t - mPath)) != 0) {
67 return 0;
68 }
69
70 iPath += (t - mPath);
71 if ((*iPath != '\0') && (*iPath != '/')) {
72 return 0;
73 }
74
75 matches += (t - mPath);
76 mPath += (t - mPath);
77 } while (*mPath != '\0');
78
79 return matches;
80 }
81
OsVfsFindMp(const char * path,const char ** pathInMp)82 struct TagMountPoint *OsVfsFindMp(const char *path, const char **pathInMp)
83 {
84 struct TagMountPoint *mp = g_mountPoints;
85 struct TagMountPoint *bestMp = NULL;
86 const char *iPath = NULL;
87 S32 bestMatches = 0;
88 S32 matches;
89
90 if (path == NULL) {
91 return NULL;
92 }
93
94 if (pathInMp != NULL) {
95 *pathInMp = NULL;
96 }
97
98 while ((mp != NULL) && (mp->mPath != NULL)) {
99 matches = OsVfsFindMpByPath(mp->mPath, path);
100 if (matches > bestMatches) {
101 bestMatches = matches;
102 bestMp = mp;
103
104 iPath = path + matches;
105 while ((*iPath == '/') && (*(iPath + 1) != '/')) {
106 iPath++;
107 }
108
109 if (pathInMp != NULL) {
110 *pathInMp = path;
111 }
112 }
113 mp = mp->mNext;
114 }
115 return bestMp;
116 }
117
OsVfsFindMountPoint(const char * fsType)118 S32 OsVfsFindMountPoint(const char *fsType)
119 {
120 struct TagMountPoint *iter = NULL;
121 for (iter = g_mountPoints; iter != NULL; iter = iter->mNext) {
122 if ((iter->mFs != NULL) && (iter->mFs->fsType != NULL) &&
123 strcmp(iter->mFs->fsType, fsType) == 0) {
124 return FS_OK;
125 }
126 }
127 return FS_NOK;
128 }
129
OsVfsFreeMp(struct TagMountPoint * mp)130 static void OsVfsFreeMp(struct TagMountPoint *mp)
131 {
132 if (mp == NULL) {
133 return;
134 }
135 if (mp->mPath != NULL) {
136 free((void *)mp->mPath);
137 }
138 if (mp->mDev != NULL) {
139 free((void *)mp->mDev);
140 }
141 free(mp);
142 }
143
OsVfsMount(const char * source,const char * target,const char * filesystemtype,uintptr_t mountflags,const void * data)144 S32 OsVfsMount(const char *source, const char *target,
145 const char *filesystemtype, uintptr_t mountflags,
146 const void *data)
147 {
148 S32 ret;
149 struct TagMountPoint *mp = NULL;
150 struct TagFsMap *mFs = NULL;
151 const char *pathInMp = NULL;
152
153 if ((target == NULL) || (target[0] != '/')) {
154 return FS_NOK;
155 }
156 (void)OsVfsLock();
157 /* 确认是否已经被挂载 */
158 mp = OsVfsFindMp(target, &pathInMp);
159 if (mp != NULL && pathInMp != NULL) {
160 OsVfsUnlock();
161 return FS_NOK;
162 }
163
164 mFs = OsVfsGetFsMap(filesystemtype);
165 if ((mFs == NULL) || (mFs->fsMops == NULL) || (mFs->fsMops->mount == NULL)) {
166 OsVfsUnlock();
167 return FS_NOK;
168 }
169
170 mp = (struct TagMountPoint *)malloc(sizeof(struct TagMountPoint));
171 if (mp == NULL) {
172 OsVfsUnlock();
173 return FS_NOK;
174 }
175 if (memset_s(mp, sizeof(struct TagMountPoint), 0, sizeof(struct TagMountPoint)) != EOK) {
176 free(mp);
177 OsVfsUnlock();
178 return FS_NOK;
179 }
180
181 mp->mFs = mFs;
182 mp->mDev = NULL;
183 if (source != NULL) {
184 mp->mDev = strdup(source);
185 if (mp->mDev == NULL) {
186 OsVfsFreeMp(mp);
187 OsVfsUnlock();
188 return FS_NOK;
189 }
190 }
191 mp->mPath = strdup(target);
192 if (mp->mPath == NULL) {
193 OsVfsFreeMp(mp);
194 OsVfsUnlock();
195 return FS_NOK;
196 }
197
198 ret = mp->mFs->fsMops->mount(mp, mountflags, data);
199 if (ret != 0) {
200 OsVfsFreeMp(mp);
201 OsVfsUnlock();
202 return FS_NOK;
203 }
204 mp->mRefs = 0;
205 mp->mWriteEnable = (mountflags & MS_RDONLY) ? FALSE : TRUE;
206 mp->mFs->fsRefs++;
207 mp->mNext = g_mountPoints;
208 g_mountPoints = mp;
209 OsVfsUnlock();
210 return FS_OK;
211 }
212
OsVfsUmount(const char * target)213 S32 OsVfsUmount(const char *target)
214 {
215 struct TagMountPoint *mp = NULL;
216 const char *pathInMp = NULL;
217 S32 ret = FS_NOK;
218
219 if (target == NULL) {
220 return ret;
221 }
222
223 (void)OsVfsLock();
224 mp = OsVfsFindMp(target, &pathInMp);
225 if ((mp == NULL) || (mp->mRefs != 0) ||
226 (mp->mFs == NULL) || (mp->mFs->fsMops == NULL) ||
227 (mp->mFs->fsMops->umount == NULL)) {
228 OsVfsUnlock();
229 return ret;
230 }
231
232 ret = mp->mFs->fsMops->umount(mp);
233 if (ret != 0) {
234 OsVfsUnlock();
235 return ret;
236 }
237
238 OsMpDeleteFromList(mp);
239 mp->mFs->fsRefs--;
240 free((void *)mp->mPath);
241 free((void *)mp->mDev);
242 free(mp);
243
244 OsVfsUnlock();
245 return FS_OK;
246 }
247
OsCloseFdsInMp(struct TagMountPoint * mp)248 static void OsCloseFdsInMp(struct TagMountPoint *mp)
249 {
250 for (S32 fd = 0; fd < NR_OPEN_DEFAULT; fd++) {
251 struct TagFile *f = OsFdToFile(fd);
252 if (f == NULL) {
253 continue;
254 }
255 if ((f->fMp == mp) &&
256 (f->fFops != NULL) &&
257 (f->fFops->close != NULL)) {
258 (void)f->fFops->close(f);
259 }
260 }
261 }
OsVfsUmount2(const char * target,S32 flag)262 S32 OsVfsUmount2(const char *target, S32 flag)
263 {
264 struct TagMountPoint *mp = NULL;
265 const char *pathInMp = NULL;
266 S32 ret = FS_NOK;
267
268 if (target == NULL) {
269 return ret;
270 }
271
272 (void)OsVfsLock();
273 mp = OsVfsFindMp(target, &pathInMp);
274 if ((mp == NULL) || (mp->mRefs != 0) ||
275 (mp->mFs == NULL) || (mp->mFs->fsMops == NULL) ||
276 (mp->mFs->fsMops->umount2 == NULL)) {
277 OsVfsUnlock();
278 return ret;
279 }
280
281 /* 关闭当前挂载节点下的所有文件 */
282 if ((U32)flag & MNT_FORCE) {
283 OsCloseFdsInMp(mp);
284 }
285
286 ret = mp->mFs->fsMops->umount2(mp, flag);
287 if (ret != 0) {
288 OsVfsUnlock();
289 return FS_NOK;
290 }
291
292 OsMpDeleteFromList(mp);
293 mp->mFs->fsRefs--;
294 free((void *)mp->mPath);
295 free((void *)mp->mDev);
296 free(mp);
297
298 OsVfsUnlock();
299 return FS_OK;
300 }
301
302