154568cb3Sopenharmony_ci/*
254568cb3Sopenharmony_ci * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
354568cb3Sopenharmony_ci *
454568cb3Sopenharmony_ci * UniProton is licensed under Mulan PSL v2.
554568cb3Sopenharmony_ci * You can use this software according to the terms and conditions of the Mulan PSL v2.
654568cb3Sopenharmony_ci * You may obtain a copy of Mulan PSL v2 at:
754568cb3Sopenharmony_ci *          http://license.coscl.org.cn/MulanPSL2
854568cb3Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
954568cb3Sopenharmony_ci * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
1054568cb3Sopenharmony_ci * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
1154568cb3Sopenharmony_ci * See the Mulan PSL v2 for more details.
1254568cb3Sopenharmony_ci * Create: 2022-09-21
1354568cb3Sopenharmony_ci * Description: 文件系统vfs层
1454568cb3Sopenharmony_ci */
1554568cb3Sopenharmony_ci
1654568cb3Sopenharmony_ci#include "stdlib.h"
1754568cb3Sopenharmony_ci#include "string.h"
1854568cb3Sopenharmony_ci#include "securec.h"
1954568cb3Sopenharmony_ci#include "vfs_mount.h"
2054568cb3Sopenharmony_ci#include "vfs_files.h"
2154568cb3Sopenharmony_ci#include "vfs_maps.h"
2254568cb3Sopenharmony_ci#include "vfs_config.h"
2354568cb3Sopenharmony_ci#include "vfs_operations.h"
2454568cb3Sopenharmony_ci#include "prt_fs.h"
2554568cb3Sopenharmony_ci
2654568cb3Sopenharmony_cistatic struct TagMountPoint *g_mountPoints;
2754568cb3Sopenharmony_ci
2854568cb3Sopenharmony_cistatic void OsMpDeleteFromList(struct TagMountPoint *mp)
2954568cb3Sopenharmony_ci{
3054568cb3Sopenharmony_ci    struct TagMountPoint *prev = NULL;
3154568cb3Sopenharmony_ci
3254568cb3Sopenharmony_ci    if (g_mountPoints == mp) {
3354568cb3Sopenharmony_ci        g_mountPoints = mp->mNext;
3454568cb3Sopenharmony_ci        return;
3554568cb3Sopenharmony_ci    }
3654568cb3Sopenharmony_ci
3754568cb3Sopenharmony_ci    for (prev = g_mountPoints; prev != NULL; prev = prev->mNext) {
3854568cb3Sopenharmony_ci        if (prev->mNext != mp) {
3954568cb3Sopenharmony_ci            continue;
4054568cb3Sopenharmony_ci        }
4154568cb3Sopenharmony_ci
4254568cb3Sopenharmony_ci        prev->mNext = mp->mNext;
4354568cb3Sopenharmony_ci        break;
4454568cb3Sopenharmony_ci    }
4554568cb3Sopenharmony_ci}
4654568cb3Sopenharmony_ci
4754568cb3Sopenharmony_cistatic S32 OsVfsFindMpByPath(const char *mPath, const char *iPath)
4854568cb3Sopenharmony_ci{
4954568cb3Sopenharmony_ci    const char *t = NULL;
5054568cb3Sopenharmony_ci    S32 matches = 0;
5154568cb3Sopenharmony_ci    do {
5254568cb3Sopenharmony_ci        while ((*mPath == '/') && (*(mPath + 1) != '/')) {
5354568cb3Sopenharmony_ci            mPath++;
5454568cb3Sopenharmony_ci        }
5554568cb3Sopenharmony_ci        while ((*iPath == '/') && (*(iPath + 1) != '/')) {
5654568cb3Sopenharmony_ci            iPath++;
5754568cb3Sopenharmony_ci        }
5854568cb3Sopenharmony_ci
5954568cb3Sopenharmony_ci        t = strchr(mPath, '/');
6054568cb3Sopenharmony_ci        if (t == NULL) {
6154568cb3Sopenharmony_ci            t = strchr(mPath, '\0');
6254568cb3Sopenharmony_ci        }
6354568cb3Sopenharmony_ci        if ((t == mPath) || (t == NULL)) {
6454568cb3Sopenharmony_ci            break;
6554568cb3Sopenharmony_ci        }
6654568cb3Sopenharmony_ci        if (strncmp(mPath, iPath, (size_t)(t - mPath)) != 0) {
6754568cb3Sopenharmony_ci            return 0;
6854568cb3Sopenharmony_ci        }
6954568cb3Sopenharmony_ci
7054568cb3Sopenharmony_ci        iPath += (t - mPath);
7154568cb3Sopenharmony_ci        if ((*iPath != '\0') && (*iPath != '/')) {
7254568cb3Sopenharmony_ci            return 0;
7354568cb3Sopenharmony_ci        }
7454568cb3Sopenharmony_ci
7554568cb3Sopenharmony_ci        matches += (t - mPath);
7654568cb3Sopenharmony_ci        mPath += (t - mPath);
7754568cb3Sopenharmony_ci    } while (*mPath != '\0');
7854568cb3Sopenharmony_ci
7954568cb3Sopenharmony_ci    return matches;
8054568cb3Sopenharmony_ci}
8154568cb3Sopenharmony_ci
8254568cb3Sopenharmony_cistruct TagMountPoint *OsVfsFindMp(const char *path, const char **pathInMp)
8354568cb3Sopenharmony_ci{
8454568cb3Sopenharmony_ci    struct TagMountPoint *mp = g_mountPoints;
8554568cb3Sopenharmony_ci    struct TagMountPoint *bestMp = NULL;
8654568cb3Sopenharmony_ci    const char *iPath = NULL;
8754568cb3Sopenharmony_ci    S32 bestMatches = 0;
8854568cb3Sopenharmony_ci    S32 matches;
8954568cb3Sopenharmony_ci
9054568cb3Sopenharmony_ci    if (path == NULL) {
9154568cb3Sopenharmony_ci        return NULL;
9254568cb3Sopenharmony_ci    }
9354568cb3Sopenharmony_ci
9454568cb3Sopenharmony_ci    if (pathInMp != NULL) {
9554568cb3Sopenharmony_ci        *pathInMp = NULL;
9654568cb3Sopenharmony_ci    }
9754568cb3Sopenharmony_ci
9854568cb3Sopenharmony_ci    while ((mp != NULL) && (mp->mPath != NULL)) {
9954568cb3Sopenharmony_ci        matches = OsVfsFindMpByPath(mp->mPath, path);
10054568cb3Sopenharmony_ci        if (matches > bestMatches) {
10154568cb3Sopenharmony_ci            bestMatches = matches;
10254568cb3Sopenharmony_ci            bestMp = mp;
10354568cb3Sopenharmony_ci
10454568cb3Sopenharmony_ci            iPath = path + matches;
10554568cb3Sopenharmony_ci            while ((*iPath == '/') && (*(iPath + 1) != '/')) {
10654568cb3Sopenharmony_ci                iPath++;
10754568cb3Sopenharmony_ci            }
10854568cb3Sopenharmony_ci
10954568cb3Sopenharmony_ci            if (pathInMp != NULL) {
11054568cb3Sopenharmony_ci                *pathInMp = path;
11154568cb3Sopenharmony_ci            }
11254568cb3Sopenharmony_ci        }
11354568cb3Sopenharmony_ci        mp = mp->mNext;
11454568cb3Sopenharmony_ci    }
11554568cb3Sopenharmony_ci    return bestMp;
11654568cb3Sopenharmony_ci}
11754568cb3Sopenharmony_ci
11854568cb3Sopenharmony_ciS32 OsVfsFindMountPoint(const char *fsType)
11954568cb3Sopenharmony_ci{
12054568cb3Sopenharmony_ci    struct TagMountPoint *iter = NULL;
12154568cb3Sopenharmony_ci    for (iter = g_mountPoints; iter != NULL; iter = iter->mNext) {
12254568cb3Sopenharmony_ci        if ((iter->mFs != NULL) && (iter->mFs->fsType != NULL) &&
12354568cb3Sopenharmony_ci            strcmp(iter->mFs->fsType, fsType) == 0) {
12454568cb3Sopenharmony_ci            return FS_OK;
12554568cb3Sopenharmony_ci        }
12654568cb3Sopenharmony_ci    }
12754568cb3Sopenharmony_ci    return FS_NOK;
12854568cb3Sopenharmony_ci}
12954568cb3Sopenharmony_ci
13054568cb3Sopenharmony_cistatic void OsVfsFreeMp(struct TagMountPoint *mp)
13154568cb3Sopenharmony_ci{
13254568cb3Sopenharmony_ci    if (mp == NULL) {
13354568cb3Sopenharmony_ci        return;
13454568cb3Sopenharmony_ci    }
13554568cb3Sopenharmony_ci    if (mp->mPath != NULL) {
13654568cb3Sopenharmony_ci        free((void *)mp->mPath);
13754568cb3Sopenharmony_ci    }
13854568cb3Sopenharmony_ci    if (mp->mDev != NULL) {
13954568cb3Sopenharmony_ci        free((void *)mp->mDev);
14054568cb3Sopenharmony_ci    }
14154568cb3Sopenharmony_ci    free(mp);
14254568cb3Sopenharmony_ci}
14354568cb3Sopenharmony_ci
14454568cb3Sopenharmony_ciS32 OsVfsMount(const char *source, const char *target,
14554568cb3Sopenharmony_ci                           const char *filesystemtype, uintptr_t mountflags,
14654568cb3Sopenharmony_ci                           const void *data)
14754568cb3Sopenharmony_ci{
14854568cb3Sopenharmony_ci    S32 ret;
14954568cb3Sopenharmony_ci    struct TagMountPoint *mp = NULL;
15054568cb3Sopenharmony_ci    struct TagFsMap *mFs = NULL;
15154568cb3Sopenharmony_ci    const char *pathInMp = NULL;
15254568cb3Sopenharmony_ci
15354568cb3Sopenharmony_ci    if ((target == NULL) || (target[0] != '/')) {
15454568cb3Sopenharmony_ci        return FS_NOK;
15554568cb3Sopenharmony_ci    }
15654568cb3Sopenharmony_ci    (void)OsVfsLock();
15754568cb3Sopenharmony_ci    /* 确认是否已经被挂载 */
15854568cb3Sopenharmony_ci    mp = OsVfsFindMp(target, &pathInMp);
15954568cb3Sopenharmony_ci    if (mp != NULL && pathInMp != NULL) {
16054568cb3Sopenharmony_ci        OsVfsUnlock();
16154568cb3Sopenharmony_ci        return FS_NOK;
16254568cb3Sopenharmony_ci    }
16354568cb3Sopenharmony_ci
16454568cb3Sopenharmony_ci    mFs = OsVfsGetFsMap(filesystemtype);
16554568cb3Sopenharmony_ci    if ((mFs == NULL) || (mFs->fsMops == NULL) || (mFs->fsMops->mount == NULL)) {
16654568cb3Sopenharmony_ci        OsVfsUnlock();
16754568cb3Sopenharmony_ci        return FS_NOK;
16854568cb3Sopenharmony_ci    }
16954568cb3Sopenharmony_ci
17054568cb3Sopenharmony_ci    mp = (struct TagMountPoint *)malloc(sizeof(struct TagMountPoint));
17154568cb3Sopenharmony_ci    if (mp == NULL) {
17254568cb3Sopenharmony_ci        OsVfsUnlock();
17354568cb3Sopenharmony_ci        return FS_NOK;
17454568cb3Sopenharmony_ci    }
17554568cb3Sopenharmony_ci    if (memset_s(mp, sizeof(struct TagMountPoint), 0, sizeof(struct TagMountPoint)) != EOK) {
17654568cb3Sopenharmony_ci        free(mp);
17754568cb3Sopenharmony_ci        OsVfsUnlock();
17854568cb3Sopenharmony_ci        return FS_NOK;
17954568cb3Sopenharmony_ci    }
18054568cb3Sopenharmony_ci
18154568cb3Sopenharmony_ci    mp->mFs = mFs;
18254568cb3Sopenharmony_ci    mp->mDev = NULL;
18354568cb3Sopenharmony_ci    if (source != NULL) {
18454568cb3Sopenharmony_ci        mp->mDev = strdup(source);
18554568cb3Sopenharmony_ci        if (mp->mDev == NULL) {
18654568cb3Sopenharmony_ci            OsVfsFreeMp(mp);
18754568cb3Sopenharmony_ci            OsVfsUnlock();
18854568cb3Sopenharmony_ci            return FS_NOK;
18954568cb3Sopenharmony_ci        }
19054568cb3Sopenharmony_ci    }
19154568cb3Sopenharmony_ci    mp->mPath = strdup(target);
19254568cb3Sopenharmony_ci    if (mp->mPath == NULL) {
19354568cb3Sopenharmony_ci        OsVfsFreeMp(mp);
19454568cb3Sopenharmony_ci        OsVfsUnlock();
19554568cb3Sopenharmony_ci        return FS_NOK;
19654568cb3Sopenharmony_ci    }
19754568cb3Sopenharmony_ci
19854568cb3Sopenharmony_ci    ret = mp->mFs->fsMops->mount(mp, mountflags, data);
19954568cb3Sopenharmony_ci    if (ret != 0) {
20054568cb3Sopenharmony_ci        OsVfsFreeMp(mp);
20154568cb3Sopenharmony_ci        OsVfsUnlock();
20254568cb3Sopenharmony_ci        return FS_NOK;
20354568cb3Sopenharmony_ci    }
20454568cb3Sopenharmony_ci    mp->mRefs = 0;
20554568cb3Sopenharmony_ci    mp->mWriteEnable = (mountflags & MS_RDONLY) ? FALSE : TRUE;
20654568cb3Sopenharmony_ci    mp->mFs->fsRefs++;
20754568cb3Sopenharmony_ci    mp->mNext = g_mountPoints;
20854568cb3Sopenharmony_ci    g_mountPoints = mp;
20954568cb3Sopenharmony_ci    OsVfsUnlock();
21054568cb3Sopenharmony_ci    return FS_OK;
21154568cb3Sopenharmony_ci}
21254568cb3Sopenharmony_ci
21354568cb3Sopenharmony_ciS32 OsVfsUmount(const char *target)
21454568cb3Sopenharmony_ci{
21554568cb3Sopenharmony_ci    struct TagMountPoint *mp = NULL;
21654568cb3Sopenharmony_ci    const char *pathInMp = NULL;
21754568cb3Sopenharmony_ci    S32 ret = FS_NOK;
21854568cb3Sopenharmony_ci
21954568cb3Sopenharmony_ci    if (target == NULL) {
22054568cb3Sopenharmony_ci        return ret;
22154568cb3Sopenharmony_ci    }
22254568cb3Sopenharmony_ci
22354568cb3Sopenharmony_ci    (void)OsVfsLock();
22454568cb3Sopenharmony_ci    mp = OsVfsFindMp(target, &pathInMp);
22554568cb3Sopenharmony_ci    if ((mp == NULL) || (mp->mRefs != 0) ||
22654568cb3Sopenharmony_ci        (mp->mFs == NULL) || (mp->mFs->fsMops == NULL) ||
22754568cb3Sopenharmony_ci        (mp->mFs->fsMops->umount == NULL)) {
22854568cb3Sopenharmony_ci        OsVfsUnlock();
22954568cb3Sopenharmony_ci        return ret;
23054568cb3Sopenharmony_ci    }
23154568cb3Sopenharmony_ci
23254568cb3Sopenharmony_ci    ret = mp->mFs->fsMops->umount(mp);
23354568cb3Sopenharmony_ci    if (ret != 0) {
23454568cb3Sopenharmony_ci        OsVfsUnlock();
23554568cb3Sopenharmony_ci        return ret;
23654568cb3Sopenharmony_ci    }
23754568cb3Sopenharmony_ci
23854568cb3Sopenharmony_ci    OsMpDeleteFromList(mp);
23954568cb3Sopenharmony_ci    mp->mFs->fsRefs--;
24054568cb3Sopenharmony_ci    free((void *)mp->mPath);
24154568cb3Sopenharmony_ci    free((void *)mp->mDev);
24254568cb3Sopenharmony_ci    free(mp);
24354568cb3Sopenharmony_ci
24454568cb3Sopenharmony_ci    OsVfsUnlock();
24554568cb3Sopenharmony_ci    return FS_OK;
24654568cb3Sopenharmony_ci}
24754568cb3Sopenharmony_ci
24854568cb3Sopenharmony_cistatic void OsCloseFdsInMp(struct TagMountPoint *mp)
24954568cb3Sopenharmony_ci{
25054568cb3Sopenharmony_ci    for (S32 fd = 0; fd < NR_OPEN_DEFAULT; fd++) {
25154568cb3Sopenharmony_ci        struct TagFile *f = OsFdToFile(fd);
25254568cb3Sopenharmony_ci        if (f == NULL) {
25354568cb3Sopenharmony_ci            continue;
25454568cb3Sopenharmony_ci        }
25554568cb3Sopenharmony_ci        if ((f->fMp == mp) &&
25654568cb3Sopenharmony_ci            (f->fFops != NULL) &&
25754568cb3Sopenharmony_ci            (f->fFops->close != NULL)) {
25854568cb3Sopenharmony_ci            (void)f->fFops->close(f);
25954568cb3Sopenharmony_ci        }
26054568cb3Sopenharmony_ci    }
26154568cb3Sopenharmony_ci}
26254568cb3Sopenharmony_ciS32 OsVfsUmount2(const char *target, S32 flag)
26354568cb3Sopenharmony_ci{
26454568cb3Sopenharmony_ci    struct TagMountPoint *mp = NULL;
26554568cb3Sopenharmony_ci    const char *pathInMp = NULL;
26654568cb3Sopenharmony_ci    S32 ret = FS_NOK;
26754568cb3Sopenharmony_ci
26854568cb3Sopenharmony_ci    if (target == NULL) {
26954568cb3Sopenharmony_ci        return ret;
27054568cb3Sopenharmony_ci    }
27154568cb3Sopenharmony_ci
27254568cb3Sopenharmony_ci    (void)OsVfsLock();
27354568cb3Sopenharmony_ci    mp = OsVfsFindMp(target, &pathInMp);
27454568cb3Sopenharmony_ci    if ((mp == NULL) || (mp->mRefs != 0) ||
27554568cb3Sopenharmony_ci        (mp->mFs == NULL) || (mp->mFs->fsMops == NULL) ||
27654568cb3Sopenharmony_ci        (mp->mFs->fsMops->umount2 == NULL)) {
27754568cb3Sopenharmony_ci        OsVfsUnlock();
27854568cb3Sopenharmony_ci        return ret;
27954568cb3Sopenharmony_ci    }
28054568cb3Sopenharmony_ci
28154568cb3Sopenharmony_ci    /* 关闭当前挂载节点下的所有文件 */
28254568cb3Sopenharmony_ci    if ((U32)flag & MNT_FORCE) {
28354568cb3Sopenharmony_ci        OsCloseFdsInMp(mp);
28454568cb3Sopenharmony_ci    }
28554568cb3Sopenharmony_ci
28654568cb3Sopenharmony_ci    ret = mp->mFs->fsMops->umount2(mp, flag);
28754568cb3Sopenharmony_ci    if (ret != 0) {
28854568cb3Sopenharmony_ci        OsVfsUnlock();
28954568cb3Sopenharmony_ci        return FS_NOK;
29054568cb3Sopenharmony_ci    }
29154568cb3Sopenharmony_ci
29254568cb3Sopenharmony_ci    OsMpDeleteFromList(mp);
29354568cb3Sopenharmony_ci    mp->mFs->fsRefs--;
29454568cb3Sopenharmony_ci    free((void *)mp->mPath);
29554568cb3Sopenharmony_ci    free((void *)mp->mDev);
29654568cb3Sopenharmony_ci    free(mp);
29754568cb3Sopenharmony_ci
29854568cb3Sopenharmony_ci    OsVfsUnlock();
29954568cb3Sopenharmony_ci    return FS_OK;
30054568cb3Sopenharmony_ci}
30154568cb3Sopenharmony_ci
302