xref: /kernel/liteos_m/components/fs/fatfs/fatfs.c (revision 3d8536b4)
13d8536b4Sopenharmony_ci/*
23d8536b4Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
33d8536b4Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
43d8536b4Sopenharmony_ci *
53d8536b4Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
63d8536b4Sopenharmony_ci * are permitted provided that the following conditions are met:
73d8536b4Sopenharmony_ci *
83d8536b4Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
93d8536b4Sopenharmony_ci *    conditions and the following disclaimer.
103d8536b4Sopenharmony_ci *
113d8536b4Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
123d8536b4Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
133d8536b4Sopenharmony_ci *    provided with the distribution.
143d8536b4Sopenharmony_ci *
153d8536b4Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
163d8536b4Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
173d8536b4Sopenharmony_ci *    permission.
183d8536b4Sopenharmony_ci *
193d8536b4Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
203d8536b4Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
213d8536b4Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223d8536b4Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
233d8536b4Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
243d8536b4Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
253d8536b4Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
263d8536b4Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
273d8536b4Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
283d8536b4Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
293d8536b4Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
303d8536b4Sopenharmony_ci */
313d8536b4Sopenharmony_ci
323d8536b4Sopenharmony_ci#define _GNU_SOURCE 1
333d8536b4Sopenharmony_ci#include "ff.h"
343d8536b4Sopenharmony_ci#include "fatfs.h"
353d8536b4Sopenharmony_ci#include "errno.h"
363d8536b4Sopenharmony_ci#include "stdbool.h"
373d8536b4Sopenharmony_ci#include "limits.h"
383d8536b4Sopenharmony_ci#include "pthread.h"
393d8536b4Sopenharmony_ci#include "time.h"
403d8536b4Sopenharmony_ci#include "securec.h"
413d8536b4Sopenharmony_ci#include "los_compiler.h"
423d8536b4Sopenharmony_ci#include "los_debug.h"
433d8536b4Sopenharmony_ci#include "los_sched.h"
443d8536b4Sopenharmony_ci#include "vfs_files.h"
453d8536b4Sopenharmony_ci#include "vfs_operations.h"
463d8536b4Sopenharmony_ci#include "vfs_partition.h"
473d8536b4Sopenharmony_ci#include "vfs_maps.h"
483d8536b4Sopenharmony_ci#include "vfs_mount.h"
493d8536b4Sopenharmony_ci#include "los_fs.h"
503d8536b4Sopenharmony_ci
513d8536b4Sopenharmony_ci/* the max name length of different parts should not bigger than 32 */
523d8536b4Sopenharmony_ci#define FS_DRIVE_NAME_MAX_LEN 32
533d8536b4Sopenharmony_ci
543d8536b4Sopenharmony_ci#ifndef FAT_MAX_OPEN_DIRS
553d8536b4Sopenharmony_ci#define FAT_MAX_OPEN_DIRS     8
563d8536b4Sopenharmony_ci#endif /* FAT_MAX_OPEN_DIRS */
573d8536b4Sopenharmony_ci
583d8536b4Sopenharmony_ci#ifndef FS_LOCK_TIMEOUT_SEC
593d8536b4Sopenharmony_ci#define FS_LOCK_TIMEOUT_SEC  15
603d8536b4Sopenharmony_ci#endif /* FS_LOCK_TIMEOUT_SEC */
613d8536b4Sopenharmony_ci
623d8536b4Sopenharmony_cistatic UINT8 g_workBuffer[FF_MAX_SS];
633d8536b4Sopenharmony_cistatic char *g_volPath[FF_VOLUMES] = {FF_VOLUME_STRS};
643d8536b4Sopenharmony_ci
653d8536b4Sopenharmony_ciPARTITION VolToPart[] = {
663d8536b4Sopenharmony_ci    { 0, 0, 1, 0, 0 },
673d8536b4Sopenharmony_ci    { 0, 0, 2, 0, 0 },
683d8536b4Sopenharmony_ci    { 0, 0, 3, 0, 0 },
693d8536b4Sopenharmony_ci    { 0, 0, 4, 0, 0 }
703d8536b4Sopenharmony_ci};
713d8536b4Sopenharmony_ci
723d8536b4Sopenharmony_cistatic int FsChangeDrive(const char *path)
733d8536b4Sopenharmony_ci{
743d8536b4Sopenharmony_ci    INT32 res;
753d8536b4Sopenharmony_ci    errno_t retErr;
763d8536b4Sopenharmony_ci    UINT16 pathLen = strlen((char const *)path);
773d8536b4Sopenharmony_ci    /* the max name length of different parts is 16 */
783d8536b4Sopenharmony_ci    CHAR tmpPath[FS_DRIVE_NAME_MAX_LEN] = { "/" };
793d8536b4Sopenharmony_ci
803d8536b4Sopenharmony_ci    /* make sure the path begin with "/", the path like /xxx/yyy/... */
813d8536b4Sopenharmony_ci    if (pathLen >= (FS_DRIVE_NAME_MAX_LEN - 1)) {
823d8536b4Sopenharmony_ci        /* 2: except first flag "/" and last end flag */
833d8536b4Sopenharmony_ci        pathLen = FS_DRIVE_NAME_MAX_LEN - 2;
843d8536b4Sopenharmony_ci    }
853d8536b4Sopenharmony_ci
863d8536b4Sopenharmony_ci    retErr = strncpy_s(tmpPath + 1, (FS_DRIVE_NAME_MAX_LEN - 1), (char const *)path, pathLen);
873d8536b4Sopenharmony_ci    if (retErr != EOK) {
883d8536b4Sopenharmony_ci        return (int)LOS_NOK;
893d8536b4Sopenharmony_ci    }
903d8536b4Sopenharmony_ci
913d8536b4Sopenharmony_ci    res = f_chdrive(tmpPath);
923d8536b4Sopenharmony_ci    if (res != FR_OK) {
933d8536b4Sopenharmony_ci        return (int)LOS_NOK;
943d8536b4Sopenharmony_ci    }
953d8536b4Sopenharmony_ci
963d8536b4Sopenharmony_ci    return (int)LOS_OK;
973d8536b4Sopenharmony_ci}
983d8536b4Sopenharmony_ci
993d8536b4Sopenharmony_cistatic int Remount(struct MountPoint *mp, unsigned long mountflags)
1003d8536b4Sopenharmony_ci{
1013d8536b4Sopenharmony_ci    FATFS *fatfs = (FATFS *)mp->mData;
1023d8536b4Sopenharmony_ci
1033d8536b4Sopenharmony_ci    /* remount is not allowed when the device is not mounted. */
1043d8536b4Sopenharmony_ci    if (fatfs->fs_type == 0) {
1053d8536b4Sopenharmony_ci        errno = EINVAL;
1063d8536b4Sopenharmony_ci        return (int)LOS_NOK;
1073d8536b4Sopenharmony_ci    }
1083d8536b4Sopenharmony_ci    mp->mWriteEnable = (mountflags & MS_RDONLY) ? FALSE : TRUE;
1093d8536b4Sopenharmony_ci
1103d8536b4Sopenharmony_ci    return (int)LOS_OK;
1113d8536b4Sopenharmony_ci}
1123d8536b4Sopenharmony_ci
1133d8536b4Sopenharmony_cistatic unsigned int FatFsGetMode(int oflags)
1143d8536b4Sopenharmony_ci{
1153d8536b4Sopenharmony_ci    UINT32 fmode = FA_READ;
1163d8536b4Sopenharmony_ci
1173d8536b4Sopenharmony_ci    if ((UINT32)oflags & O_WRONLY) {
1183d8536b4Sopenharmony_ci        fmode |= FA_WRITE;
1193d8536b4Sopenharmony_ci    }
1203d8536b4Sopenharmony_ci
1213d8536b4Sopenharmony_ci    if (((UINT32)oflags & O_ACCMODE) & O_RDWR) {
1223d8536b4Sopenharmony_ci        fmode |= FA_WRITE;
1233d8536b4Sopenharmony_ci    }
1243d8536b4Sopenharmony_ci    /* Creates a new file if the file is not existing, otherwise, just open it. */
1253d8536b4Sopenharmony_ci    if ((UINT32)oflags & O_CREAT) {
1263d8536b4Sopenharmony_ci        fmode |= FA_OPEN_ALWAYS;
1273d8536b4Sopenharmony_ci        /* Creates a new file. If the file already exists, the function shall fail. */
1283d8536b4Sopenharmony_ci        if ((UINT32)oflags & O_EXCL) {
1293d8536b4Sopenharmony_ci            fmode |= FA_CREATE_NEW;
1303d8536b4Sopenharmony_ci        }
1313d8536b4Sopenharmony_ci    }
1323d8536b4Sopenharmony_ci    /* Creates a new file. If the file already exists, its length shall be truncated to 0. */
1333d8536b4Sopenharmony_ci    if ((UINT32)oflags & O_TRUNC) {
1343d8536b4Sopenharmony_ci        fmode |= FA_CREATE_ALWAYS;
1353d8536b4Sopenharmony_ci    }
1363d8536b4Sopenharmony_ci
1373d8536b4Sopenharmony_ci    return fmode;
1383d8536b4Sopenharmony_ci}
1393d8536b4Sopenharmony_ci
1403d8536b4Sopenharmony_cistatic int FatfsErrno(int result)
1413d8536b4Sopenharmony_ci{
1423d8536b4Sopenharmony_ci    INT32 status = 0;
1433d8536b4Sopenharmony_ci
1443d8536b4Sopenharmony_ci    if (result < 0) {
1453d8536b4Sopenharmony_ci        return result;
1463d8536b4Sopenharmony_ci    }
1473d8536b4Sopenharmony_ci
1483d8536b4Sopenharmony_ci    /* FatFs errno to Libc errno */
1493d8536b4Sopenharmony_ci    switch (result) {
1503d8536b4Sopenharmony_ci        case FR_OK:
1513d8536b4Sopenharmony_ci            break;
1523d8536b4Sopenharmony_ci
1533d8536b4Sopenharmony_ci        case FR_NO_FILE:
1543d8536b4Sopenharmony_ci        case FR_NO_PATH:
1553d8536b4Sopenharmony_ci        case FR_NO_FILESYSTEM:
1563d8536b4Sopenharmony_ci            status = ENOENT;
1573d8536b4Sopenharmony_ci            break;
1583d8536b4Sopenharmony_ci
1593d8536b4Sopenharmony_ci        case FR_INVALID_NAME:
1603d8536b4Sopenharmony_ci            status = EINVAL;
1613d8536b4Sopenharmony_ci            break;
1623d8536b4Sopenharmony_ci
1633d8536b4Sopenharmony_ci        case FR_EXIST:
1643d8536b4Sopenharmony_ci        case FR_INVALID_OBJECT:
1653d8536b4Sopenharmony_ci            status = EEXIST;
1663d8536b4Sopenharmony_ci            break;
1673d8536b4Sopenharmony_ci
1683d8536b4Sopenharmony_ci        case FR_DISK_ERR:
1693d8536b4Sopenharmony_ci        case FR_NOT_READY:
1703d8536b4Sopenharmony_ci        case FR_INT_ERR:
1713d8536b4Sopenharmony_ci            status = EIO;
1723d8536b4Sopenharmony_ci            break;
1733d8536b4Sopenharmony_ci
1743d8536b4Sopenharmony_ci        case FR_WRITE_PROTECTED:
1753d8536b4Sopenharmony_ci            status = EROFS;
1763d8536b4Sopenharmony_ci            break;
1773d8536b4Sopenharmony_ci        case FR_MKFS_ABORTED:
1783d8536b4Sopenharmony_ci        case FR_INVALID_PARAMETER:
1793d8536b4Sopenharmony_ci            status = EINVAL;
1803d8536b4Sopenharmony_ci            break;
1813d8536b4Sopenharmony_ci
1823d8536b4Sopenharmony_ci        case FR_NO_SPACE_LEFT:
1833d8536b4Sopenharmony_ci            status = ENOSPC;
1843d8536b4Sopenharmony_ci            break;
1853d8536b4Sopenharmony_ci        case FR_NO_DIRENTRY:
1863d8536b4Sopenharmony_ci            status = ENFILE;
1873d8536b4Sopenharmony_ci            break;
1883d8536b4Sopenharmony_ci        case FR_NO_EMPTY_DIR:
1893d8536b4Sopenharmony_ci            status = ENOTEMPTY;
1903d8536b4Sopenharmony_ci            break;
1913d8536b4Sopenharmony_ci        case FR_IS_DIR:
1923d8536b4Sopenharmony_ci            status = EISDIR;
1933d8536b4Sopenharmony_ci            break;
1943d8536b4Sopenharmony_ci        case FR_NO_DIR:
1953d8536b4Sopenharmony_ci            status = ENOTDIR;
1963d8536b4Sopenharmony_ci            break;
1973d8536b4Sopenharmony_ci        case FR_NO_EPERM:
1983d8536b4Sopenharmony_ci        case FR_DENIED:
1993d8536b4Sopenharmony_ci            status = EPERM;
2003d8536b4Sopenharmony_ci            break;
2013d8536b4Sopenharmony_ci        case FR_LOCKED:
2023d8536b4Sopenharmony_ci            status = EBUSY;
2033d8536b4Sopenharmony_ci            break;
2043d8536b4Sopenharmony_ci        default:
2053d8536b4Sopenharmony_ci            status = result;
2063d8536b4Sopenharmony_ci            break;
2073d8536b4Sopenharmony_ci    }
2083d8536b4Sopenharmony_ci
2093d8536b4Sopenharmony_ci    return status;
2103d8536b4Sopenharmony_ci}
2113d8536b4Sopenharmony_ci
2123d8536b4Sopenharmony_cichar * GetLdPath(const char *source)
2133d8536b4Sopenharmony_ci{
2143d8536b4Sopenharmony_ci#define LDPATH_PAD 2  // 2 means: strlen("/") + len of '\0'
2153d8536b4Sopenharmony_ci    int ret;
2163d8536b4Sopenharmony_ci    int partId = GetPartIdByPartName(source);
2173d8536b4Sopenharmony_ci    if ((partId < 0) || (partId >= MAX_PARTITION_NUM)) {
2183d8536b4Sopenharmony_ci        return NULL;
2193d8536b4Sopenharmony_ci    }
2203d8536b4Sopenharmony_ci
2213d8536b4Sopenharmony_ci    char *volPath = g_volPath[partId];
2223d8536b4Sopenharmony_ci    char *ldPath = (char *)LOSCFG_FS_MALLOC_HOOK(strlen(volPath) + LDPATH_PAD);
2233d8536b4Sopenharmony_ci    if (ldPath == NULL) {
2243d8536b4Sopenharmony_ci        return NULL;
2253d8536b4Sopenharmony_ci    }
2263d8536b4Sopenharmony_ci
2273d8536b4Sopenharmony_ci    (void)memset_s(ldPath, strlen(volPath) + LDPATH_PAD, 0, strlen(volPath) + LDPATH_PAD);
2283d8536b4Sopenharmony_ci
2293d8536b4Sopenharmony_ci    /* Convert volPath to ldpath, for example, convert "inner" to "/inner" */
2303d8536b4Sopenharmony_ci    *ldPath = '/';
2313d8536b4Sopenharmony_ci    ret = strcpy_s(ldPath + 1, strlen(volPath)+1, volPath);
2323d8536b4Sopenharmony_ci    if (ret != EOK) {
2333d8536b4Sopenharmony_ci        LOSCFG_FS_FREE_HOOK(ldPath);
2343d8536b4Sopenharmony_ci        return NULL;
2353d8536b4Sopenharmony_ci    }
2363d8536b4Sopenharmony_ci
2373d8536b4Sopenharmony_ci    return ldPath;
2383d8536b4Sopenharmony_ci}
2393d8536b4Sopenharmony_ci
2403d8536b4Sopenharmony_civoid PutLdPath(const char *ldPath)
2413d8536b4Sopenharmony_ci{
2423d8536b4Sopenharmony_ci    if (ldPath != NULL) {
2433d8536b4Sopenharmony_ci        LOSCFG_FS_FREE_HOOK((void *)ldPath);
2443d8536b4Sopenharmony_ci    }
2453d8536b4Sopenharmony_ci}
2463d8536b4Sopenharmony_ci
2473d8536b4Sopenharmony_ciint FatfsMount(struct MountPoint *mp, unsigned long mountflags,
2483d8536b4Sopenharmony_ci               const void *data)
2493d8536b4Sopenharmony_ci{
2503d8536b4Sopenharmony_ci    FRESULT res;
2513d8536b4Sopenharmony_ci    FATFS *fs = NULL;
2523d8536b4Sopenharmony_ci
2533d8536b4Sopenharmony_ci    if (mountflags & MS_REMOUNT) {
2543d8536b4Sopenharmony_ci        return Remount(mp, mountflags);
2553d8536b4Sopenharmony_ci    }
2563d8536b4Sopenharmony_ci
2573d8536b4Sopenharmony_ci    char *ldPath = GetLdPath(mp->mDev);
2583d8536b4Sopenharmony_ci    if (ldPath == NULL) {
2593d8536b4Sopenharmony_ci        errno = EFAULT;
2603d8536b4Sopenharmony_ci        return (int)LOS_NOK;
2613d8536b4Sopenharmony_ci    }
2623d8536b4Sopenharmony_ci
2633d8536b4Sopenharmony_ci    fs = (FATFS *)LOSCFG_FS_MALLOC_HOOK(sizeof(FATFS));
2643d8536b4Sopenharmony_ci    if (fs == NULL) {
2653d8536b4Sopenharmony_ci        errno = ENOMEM;
2663d8536b4Sopenharmony_ci        PutLdPath(ldPath);
2673d8536b4Sopenharmony_ci        return (int)LOS_NOK;
2683d8536b4Sopenharmony_ci    }
2693d8536b4Sopenharmony_ci    (void)memset_s(fs, sizeof(FATFS), 0, sizeof(FATFS));
2703d8536b4Sopenharmony_ci
2713d8536b4Sopenharmony_ci    res = f_mount(fs, ldPath, 1);
2723d8536b4Sopenharmony_ci    if (res != FR_OK) {
2733d8536b4Sopenharmony_ci        LOSCFG_FS_FREE_HOOK(fs);
2743d8536b4Sopenharmony_ci        PutLdPath(ldPath);
2753d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
2763d8536b4Sopenharmony_ci        return (int)LOS_NOK;
2773d8536b4Sopenharmony_ci    }
2783d8536b4Sopenharmony_ci    mp->mData = (void *)fs;
2793d8536b4Sopenharmony_ci
2803d8536b4Sopenharmony_ci    PutLdPath(ldPath);
2813d8536b4Sopenharmony_ci    return (int)LOS_OK;
2823d8536b4Sopenharmony_ci}
2833d8536b4Sopenharmony_ci
2843d8536b4Sopenharmony_ciint FatfsUmount(struct MountPoint *mp)
2853d8536b4Sopenharmony_ci{
2863d8536b4Sopenharmony_ci    int volId;
2873d8536b4Sopenharmony_ci    FRESULT res;
2883d8536b4Sopenharmony_ci    char *ldPath = NULL;
2893d8536b4Sopenharmony_ci    FATFS *fatfs = (FATFS *)mp->mData;
2903d8536b4Sopenharmony_ci
2913d8536b4Sopenharmony_ci    /* The volume is not mounted */
2923d8536b4Sopenharmony_ci    if (fatfs->fs_type == 0) {
2933d8536b4Sopenharmony_ci        errno = EINVAL;
2943d8536b4Sopenharmony_ci        return (int)LOS_NOK;
2953d8536b4Sopenharmony_ci    }
2963d8536b4Sopenharmony_ci
2973d8536b4Sopenharmony_ci    volId = GetPartIdByPartName(mp->mDev);
2983d8536b4Sopenharmony_ci    /* umount is not allowed when a file or directory is opened. */
2993d8536b4Sopenharmony_ci    if (f_checkopenlock(volId) != FR_OK) {
3003d8536b4Sopenharmony_ci        errno = EBUSY;
3013d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3023d8536b4Sopenharmony_ci    }
3033d8536b4Sopenharmony_ci
3043d8536b4Sopenharmony_ci    ldPath = GetLdPath(mp->mDev);
3053d8536b4Sopenharmony_ci    if (ldPath == NULL) {
3063d8536b4Sopenharmony_ci        errno = EFAULT;
3073d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3083d8536b4Sopenharmony_ci    }
3093d8536b4Sopenharmony_ci
3103d8536b4Sopenharmony_ci    res = f_mount((FATFS *)NULL, ldPath, 0);
3113d8536b4Sopenharmony_ci    if (res != FR_OK) {
3123d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
3133d8536b4Sopenharmony_ci        PutLdPath(ldPath);
3143d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3153d8536b4Sopenharmony_ci    }
3163d8536b4Sopenharmony_ci
3173d8536b4Sopenharmony_ci    if (fatfs->win != NULL) {
3183d8536b4Sopenharmony_ci        ff_memfree(fatfs->win);
3193d8536b4Sopenharmony_ci    }
3203d8536b4Sopenharmony_ci
3213d8536b4Sopenharmony_ci    LOSCFG_FS_FREE_HOOK(mp->mData);
3223d8536b4Sopenharmony_ci    mp->mData = NULL;
3233d8536b4Sopenharmony_ci
3243d8536b4Sopenharmony_ci    PutLdPath(ldPath);
3253d8536b4Sopenharmony_ci    return (int)LOS_OK;
3263d8536b4Sopenharmony_ci}
3273d8536b4Sopenharmony_ci
3283d8536b4Sopenharmony_ciint FatfsUmount2(struct MountPoint *mp, int flag)
3293d8536b4Sopenharmony_ci{
3303d8536b4Sopenharmony_ci    UINT32 flags;
3313d8536b4Sopenharmony_ci    FRESULT res;
3323d8536b4Sopenharmony_ci    char *ldPath = NULL;
3333d8536b4Sopenharmony_ci    FATFS *fatfs = (FATFS *)mp->mData;
3343d8536b4Sopenharmony_ci
3353d8536b4Sopenharmony_ci    flags = MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW;
3363d8536b4Sopenharmony_ci    if ((UINT32)flag & ~flags) {
3373d8536b4Sopenharmony_ci        errno = EINVAL;
3383d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3393d8536b4Sopenharmony_ci    }
3403d8536b4Sopenharmony_ci
3413d8536b4Sopenharmony_ci    /* The volume is not mounted */
3423d8536b4Sopenharmony_ci    if (fatfs->fs_type == 0) {
3433d8536b4Sopenharmony_ci        errno = EINVAL;
3443d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3453d8536b4Sopenharmony_ci    }
3463d8536b4Sopenharmony_ci
3473d8536b4Sopenharmony_ci    ldPath = GetLdPath(mp->mDev);
3483d8536b4Sopenharmony_ci    if (ldPath == NULL) {
3493d8536b4Sopenharmony_ci        errno = EFAULT;
3503d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3513d8536b4Sopenharmony_ci    }
3523d8536b4Sopenharmony_ci
3533d8536b4Sopenharmony_ci    res = f_mount((FATFS *)NULL, ldPath, 0);
3543d8536b4Sopenharmony_ci    if (res != FR_OK) {
3553d8536b4Sopenharmony_ci        PutLdPath(ldPath);
3563d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
3573d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3583d8536b4Sopenharmony_ci    }
3593d8536b4Sopenharmony_ci
3603d8536b4Sopenharmony_ci    if (fatfs->win != NULL) {
3613d8536b4Sopenharmony_ci        ff_memfree(fatfs->win);
3623d8536b4Sopenharmony_ci    }
3633d8536b4Sopenharmony_ci
3643d8536b4Sopenharmony_ci    LOSCFG_FS_FREE_HOOK(mp->mData);
3653d8536b4Sopenharmony_ci    mp->mData = NULL;
3663d8536b4Sopenharmony_ci
3673d8536b4Sopenharmony_ci    PutLdPath(ldPath);
3683d8536b4Sopenharmony_ci    return (int)LOS_OK;
3693d8536b4Sopenharmony_ci}
3703d8536b4Sopenharmony_ci
3713d8536b4Sopenharmony_ciint FatfsOpen(struct File *file, const char *path, int oflag)
3723d8536b4Sopenharmony_ci{
3733d8536b4Sopenharmony_ci    FRESULT res;
3743d8536b4Sopenharmony_ci    UINT32 fmode;
3753d8536b4Sopenharmony_ci    FIL *fp = NULL;
3763d8536b4Sopenharmony_ci    int ret;
3773d8536b4Sopenharmony_ci
3783d8536b4Sopenharmony_ci    if (path == NULL) {
3793d8536b4Sopenharmony_ci        errno = EFAULT;
3803d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3813d8536b4Sopenharmony_ci    }
3823d8536b4Sopenharmony_ci
3833d8536b4Sopenharmony_ci    fmode = FatFsGetMode(oflag);
3843d8536b4Sopenharmony_ci
3853d8536b4Sopenharmony_ci    fp = (FIL *)LOSCFG_FS_MALLOC_HOOK(sizeof(FIL));
3863d8536b4Sopenharmony_ci    if (fp == NULL) {
3873d8536b4Sopenharmony_ci        errno = ENOMEM;
3883d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3893d8536b4Sopenharmony_ci    }
3903d8536b4Sopenharmony_ci    (void)memset_s(fp, sizeof(FIL), 0, sizeof(FIL));
3913d8536b4Sopenharmony_ci
3923d8536b4Sopenharmony_ci    ret = FsChangeDrive(path);
3933d8536b4Sopenharmony_ci    if (ret != (int)LOS_OK) {
3943d8536b4Sopenharmony_ci        PRINT_ERR("FAT open ChangeDrive err 0x%x!\r\n", ret);
3953d8536b4Sopenharmony_ci        errno = ENOENT;
3963d8536b4Sopenharmony_ci        LOSCFG_FS_FREE_HOOK(fp);
3973d8536b4Sopenharmony_ci        return (int)LOS_NOK;
3983d8536b4Sopenharmony_ci    }
3993d8536b4Sopenharmony_ci
4003d8536b4Sopenharmony_ci    res = f_open(fp, path, fmode);
4013d8536b4Sopenharmony_ci    if (res != FR_OK) {
4023d8536b4Sopenharmony_ci        PRINT_ERR("FAT open err 0x%x!\r\n", res);
4033d8536b4Sopenharmony_ci        LOSCFG_FS_FREE_HOOK(fp);
4043d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
4053d8536b4Sopenharmony_ci        return (int)LOS_NOK;
4063d8536b4Sopenharmony_ci    }
4073d8536b4Sopenharmony_ci
4083d8536b4Sopenharmony_ci    file->fData = (void *)fp;
4093d8536b4Sopenharmony_ci
4103d8536b4Sopenharmony_ci    return (int)LOS_OK;
4113d8536b4Sopenharmony_ci}
4123d8536b4Sopenharmony_ci
4133d8536b4Sopenharmony_ciint FatfsClose(struct File *file)
4143d8536b4Sopenharmony_ci{
4153d8536b4Sopenharmony_ci    FRESULT res;
4163d8536b4Sopenharmony_ci    FIL *fp = (FIL *)file->fData;
4173d8536b4Sopenharmony_ci
4183d8536b4Sopenharmony_ci    if ((fp == NULL) || (fp->obj.fs == NULL)) {
4193d8536b4Sopenharmony_ci        errno = ENOENT;
4203d8536b4Sopenharmony_ci        return (int)LOS_NOK;
4213d8536b4Sopenharmony_ci    }
4223d8536b4Sopenharmony_ci
4233d8536b4Sopenharmony_ci    res = f_close(fp);
4243d8536b4Sopenharmony_ci    if (res != FR_OK) {
4253d8536b4Sopenharmony_ci        PRINT_ERR("FAT close err 0x%x!\r\n", res);
4263d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
4273d8536b4Sopenharmony_ci        return (int)LOS_NOK;
4283d8536b4Sopenharmony_ci    }
4293d8536b4Sopenharmony_ci
4303d8536b4Sopenharmony_ci#if !FF_FS_TINY
4313d8536b4Sopenharmony_ci    if (fp->buf != NULL) {
4323d8536b4Sopenharmony_ci        (void)ff_memfree(fp->buf);
4333d8536b4Sopenharmony_ci    }
4343d8536b4Sopenharmony_ci#endif
4353d8536b4Sopenharmony_ci    LOSCFG_FS_FREE_HOOK(file->fData);
4363d8536b4Sopenharmony_ci    file->fData = NULL;
4373d8536b4Sopenharmony_ci
4383d8536b4Sopenharmony_ci    return (int)LOS_OK;
4393d8536b4Sopenharmony_ci}
4403d8536b4Sopenharmony_ci
4413d8536b4Sopenharmony_cissize_t FatfsRead(struct File *file, char *buf, size_t nbyte)
4423d8536b4Sopenharmony_ci{
4433d8536b4Sopenharmony_ci    FRESULT res;
4443d8536b4Sopenharmony_ci    UINT32 lenRead;
4453d8536b4Sopenharmony_ci    FIL *fp = (FIL *)file->fData;
4463d8536b4Sopenharmony_ci
4473d8536b4Sopenharmony_ci    if (buf == NULL) {
4483d8536b4Sopenharmony_ci        errno = EFAULT;
4493d8536b4Sopenharmony_ci        return (ssize_t)LOS_NOK;
4503d8536b4Sopenharmony_ci    }
4513d8536b4Sopenharmony_ci
4523d8536b4Sopenharmony_ci    if (fp == NULL) {
4533d8536b4Sopenharmony_ci        errno = ENOENT;
4543d8536b4Sopenharmony_ci        return (ssize_t)LOS_NOK;
4553d8536b4Sopenharmony_ci    }
4563d8536b4Sopenharmony_ci
4573d8536b4Sopenharmony_ci    res = f_read(fp, buf, nbyte, &lenRead);
4583d8536b4Sopenharmony_ci    if (res != FR_OK) {
4593d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
4603d8536b4Sopenharmony_ci        return (ssize_t)LOS_NOK;
4613d8536b4Sopenharmony_ci    }
4623d8536b4Sopenharmony_ci
4633d8536b4Sopenharmony_ci    return (ssize_t)lenRead;
4643d8536b4Sopenharmony_ci}
4653d8536b4Sopenharmony_ci
4663d8536b4Sopenharmony_cissize_t FatfsWrite(struct File *file, const char *buf, size_t nbyte)
4673d8536b4Sopenharmony_ci{
4683d8536b4Sopenharmony_ci    FRESULT res;
4693d8536b4Sopenharmony_ci    UINT32 lenWrite;
4703d8536b4Sopenharmony_ci    static BOOL overFlow = FALSE;
4713d8536b4Sopenharmony_ci    FIL *fp = (FIL *)file->fData;
4723d8536b4Sopenharmony_ci
4733d8536b4Sopenharmony_ci    if (buf == NULL) {
4743d8536b4Sopenharmony_ci        errno = EFAULT;
4753d8536b4Sopenharmony_ci        return (ssize_t)LOS_NOK;
4763d8536b4Sopenharmony_ci    }
4773d8536b4Sopenharmony_ci
4783d8536b4Sopenharmony_ci    if ((fp == NULL) || (fp->obj.fs == NULL)) {
4793d8536b4Sopenharmony_ci        errno = ENOENT;
4803d8536b4Sopenharmony_ci        return (ssize_t)LOS_NOK;
4813d8536b4Sopenharmony_ci    }
4823d8536b4Sopenharmony_ci
4833d8536b4Sopenharmony_ci    res = f_write(fp, buf, nbyte, &lenWrite);
4843d8536b4Sopenharmony_ci    if ((res == FR_OK) && (lenWrite == 0) && (nbyte != 0) && (overFlow == FALSE)) {
4853d8536b4Sopenharmony_ci        overFlow = TRUE;
4863d8536b4Sopenharmony_ci        PRINT_ERR("FAT write err!\r\n");
4873d8536b4Sopenharmony_ci    }
4883d8536b4Sopenharmony_ci
4893d8536b4Sopenharmony_ci    if ((res != FR_OK) || (nbyte != lenWrite)) {
4903d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
4913d8536b4Sopenharmony_ci        return (ssize_t)LOS_NOK;
4923d8536b4Sopenharmony_ci    }
4933d8536b4Sopenharmony_ci
4943d8536b4Sopenharmony_ci    return (ssize_t)lenWrite;
4953d8536b4Sopenharmony_ci}
4963d8536b4Sopenharmony_ci
4973d8536b4Sopenharmony_cioff_t FatfsLseek(struct File *file, off_t offset, int whence)
4983d8536b4Sopenharmony_ci{
4993d8536b4Sopenharmony_ci    FRESULT res;
5003d8536b4Sopenharmony_ci    off_t pos;
5013d8536b4Sopenharmony_ci    FIL *fp = (FIL *)file->fData;
5023d8536b4Sopenharmony_ci
5033d8536b4Sopenharmony_ci    if ((fp == NULL) || (fp->obj.fs == NULL)) {
5043d8536b4Sopenharmony_ci        errno = ENOENT;
5053d8536b4Sopenharmony_ci        return (off_t)LOS_NOK;
5063d8536b4Sopenharmony_ci    }
5073d8536b4Sopenharmony_ci
5083d8536b4Sopenharmony_ci    if (whence == SEEK_SET) {
5093d8536b4Sopenharmony_ci        pos = 0;
5103d8536b4Sopenharmony_ci    } else if (whence == SEEK_CUR) {
5113d8536b4Sopenharmony_ci        pos = f_tell(fp);
5123d8536b4Sopenharmony_ci    } else if (whence == SEEK_END) {
5133d8536b4Sopenharmony_ci        pos = f_size(fp);
5143d8536b4Sopenharmony_ci    } else {
5153d8536b4Sopenharmony_ci        errno = EINVAL;
5163d8536b4Sopenharmony_ci        return (off_t)LOS_NOK;
5173d8536b4Sopenharmony_ci    }
5183d8536b4Sopenharmony_ci
5193d8536b4Sopenharmony_ci    res = f_lseek(fp, offset + pos);
5203d8536b4Sopenharmony_ci    if (res != FR_OK) {
5213d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
5223d8536b4Sopenharmony_ci        return (off_t)LOS_NOK;
5233d8536b4Sopenharmony_ci    }
5243d8536b4Sopenharmony_ci
5253d8536b4Sopenharmony_ci    pos = f_tell(fp);
5263d8536b4Sopenharmony_ci    return pos;
5273d8536b4Sopenharmony_ci}
5283d8536b4Sopenharmony_ci
5293d8536b4Sopenharmony_ci/* Remove the specified FILE */
5303d8536b4Sopenharmony_ciint FatfsUnlink(struct MountPoint *mp, const char *path)
5313d8536b4Sopenharmony_ci{
5323d8536b4Sopenharmony_ci    FRESULT res;
5333d8536b4Sopenharmony_ci    int ret;
5343d8536b4Sopenharmony_ci
5353d8536b4Sopenharmony_ci    if (path == NULL) {
5363d8536b4Sopenharmony_ci        errno = EFAULT;
5373d8536b4Sopenharmony_ci        return (int)LOS_NOK;
5383d8536b4Sopenharmony_ci    }
5393d8536b4Sopenharmony_ci
5403d8536b4Sopenharmony_ci    if (!mp->mWriteEnable) {
5413d8536b4Sopenharmony_ci        errno = EACCES;
5423d8536b4Sopenharmony_ci        return (int)LOS_NOK;
5433d8536b4Sopenharmony_ci    }
5443d8536b4Sopenharmony_ci
5453d8536b4Sopenharmony_ci    ret = FsChangeDrive(path);
5463d8536b4Sopenharmony_ci    if (ret != (int)LOS_OK) {
5473d8536b4Sopenharmony_ci        PRINT_ERR("FAT unlink ChangeDrive err 0x%x!\r\n", ret);
5483d8536b4Sopenharmony_ci        errno = ENOENT;
5493d8536b4Sopenharmony_ci        return (int)LOS_NOK;
5503d8536b4Sopenharmony_ci    }
5513d8536b4Sopenharmony_ci
5523d8536b4Sopenharmony_ci    res = f_unlink(path);
5533d8536b4Sopenharmony_ci    if (res != FR_OK) {
5543d8536b4Sopenharmony_ci        PRINT_ERR("FAT unlink err 0x%x!\r\n", res);
5553d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
5563d8536b4Sopenharmony_ci        return (int)LOS_NOK;
5573d8536b4Sopenharmony_ci    }
5583d8536b4Sopenharmony_ci
5593d8536b4Sopenharmony_ci    return (int)LOS_OK;
5603d8536b4Sopenharmony_ci}
5613d8536b4Sopenharmony_ci
5623d8536b4Sopenharmony_ciint FatfsStat(struct MountPoint *mp, const char *path, struct stat *buf)
5633d8536b4Sopenharmony_ci{
5643d8536b4Sopenharmony_ci    FRESULT res;
5653d8536b4Sopenharmony_ci    FILINFO fileInfo = {0};
5663d8536b4Sopenharmony_ci    int ret;
5673d8536b4Sopenharmony_ci
5683d8536b4Sopenharmony_ci    if ((path == NULL) || (buf == NULL)) {
5693d8536b4Sopenharmony_ci        errno = EFAULT;
5703d8536b4Sopenharmony_ci        return (int)LOS_NOK;
5713d8536b4Sopenharmony_ci    }
5723d8536b4Sopenharmony_ci
5733d8536b4Sopenharmony_ci    ret = FsChangeDrive(path);
5743d8536b4Sopenharmony_ci    if (ret != (int)LOS_OK) {
5753d8536b4Sopenharmony_ci        PRINT_ERR("FAT stat ChangeDrive err 0x%x!\r\n", ret);
5763d8536b4Sopenharmony_ci        errno = ENOENT;
5773d8536b4Sopenharmony_ci        return (int)LOS_NOK;
5783d8536b4Sopenharmony_ci    }
5793d8536b4Sopenharmony_ci
5803d8536b4Sopenharmony_ci    res = f_stat(path, &fileInfo);
5813d8536b4Sopenharmony_ci    if (res != FR_OK) {
5823d8536b4Sopenharmony_ci        PRINT_ERR("FAT stat err 0x%x!\r\n", res);
5833d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
5843d8536b4Sopenharmony_ci        return (int)LOS_NOK;
5853d8536b4Sopenharmony_ci    }
5863d8536b4Sopenharmony_ci
5873d8536b4Sopenharmony_ci    buf->st_size = fileInfo.fsize;
5883d8536b4Sopenharmony_ci    buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
5893d8536b4Sopenharmony_ci                   S_IWUSR | S_IWGRP | S_IWOTH |
5903d8536b4Sopenharmony_ci                   S_IXUSR | S_IXGRP | S_IXOTH;
5913d8536b4Sopenharmony_ci
5923d8536b4Sopenharmony_ci    if (fileInfo.fattrib & AM_RDO) {
5933d8536b4Sopenharmony_ci        buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
5943d8536b4Sopenharmony_ci    }
5953d8536b4Sopenharmony_ci
5963d8536b4Sopenharmony_ci    if (fileInfo.fattrib & AM_DIR) {
5973d8536b4Sopenharmony_ci        buf->st_mode &= ~S_IFREG;
5983d8536b4Sopenharmony_ci        buf->st_mode |= S_IFDIR;
5993d8536b4Sopenharmony_ci    }
6003d8536b4Sopenharmony_ci
6013d8536b4Sopenharmony_ci    return (int)LOS_OK;
6023d8536b4Sopenharmony_ci}
6033d8536b4Sopenharmony_ci
6043d8536b4Sopenharmony_ci/* Synchronize all changes to Flash */
6053d8536b4Sopenharmony_ciint FatfsSync(struct File *file)
6063d8536b4Sopenharmony_ci{
6073d8536b4Sopenharmony_ci    FRESULT res;
6083d8536b4Sopenharmony_ci    FIL *fp = (FIL *)file->fData;
6093d8536b4Sopenharmony_ci
6103d8536b4Sopenharmony_ci    if ((fp == NULL) || (fp->obj.fs == NULL)) {
6113d8536b4Sopenharmony_ci        errno = ENOENT;
6123d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6133d8536b4Sopenharmony_ci    }
6143d8536b4Sopenharmony_ci
6153d8536b4Sopenharmony_ci    res = f_sync(fp);
6163d8536b4Sopenharmony_ci    if (res != FR_OK) {
6173d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
6183d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6193d8536b4Sopenharmony_ci    }
6203d8536b4Sopenharmony_ci
6213d8536b4Sopenharmony_ci    return (int)LOS_OK;
6223d8536b4Sopenharmony_ci}
6233d8536b4Sopenharmony_ci
6243d8536b4Sopenharmony_ciint FatfsMkdir(struct MountPoint *mp, const char *path)
6253d8536b4Sopenharmony_ci{
6263d8536b4Sopenharmony_ci    FRESULT res;
6273d8536b4Sopenharmony_ci    int ret;
6283d8536b4Sopenharmony_ci
6293d8536b4Sopenharmony_ci    if (path == NULL) {
6303d8536b4Sopenharmony_ci        errno = EFAULT;
6313d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6323d8536b4Sopenharmony_ci    }
6333d8536b4Sopenharmony_ci
6343d8536b4Sopenharmony_ci    if (!mp->mWriteEnable) {
6353d8536b4Sopenharmony_ci        errno = EACCES;
6363d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6373d8536b4Sopenharmony_ci    }
6383d8536b4Sopenharmony_ci
6393d8536b4Sopenharmony_ci    ret = FsChangeDrive(path);
6403d8536b4Sopenharmony_ci    if (ret != (int)LOS_OK) {
6413d8536b4Sopenharmony_ci        PRINT_ERR("FAT mkdir ChangeDrive err 0x%x!\r\n", ret);
6423d8536b4Sopenharmony_ci        errno = ENOENT;
6433d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6443d8536b4Sopenharmony_ci    }
6453d8536b4Sopenharmony_ci
6463d8536b4Sopenharmony_ci    res = f_mkdir(path);
6473d8536b4Sopenharmony_ci    if (res != FR_OK) {
6483d8536b4Sopenharmony_ci        PRINT_ERR("FAT mkdir err 0x%x!\r\n", res);
6493d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
6503d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6513d8536b4Sopenharmony_ci    }
6523d8536b4Sopenharmony_ci
6533d8536b4Sopenharmony_ci    return (int)LOS_OK;
6543d8536b4Sopenharmony_ci}
6553d8536b4Sopenharmony_ci
6563d8536b4Sopenharmony_ciint FatfsOpendir(struct Dir *dir, const char *dirName)
6573d8536b4Sopenharmony_ci{
6583d8536b4Sopenharmony_ci    FRESULT res;
6593d8536b4Sopenharmony_ci    DIR *dp = NULL;
6603d8536b4Sopenharmony_ci    int ret;
6613d8536b4Sopenharmony_ci
6623d8536b4Sopenharmony_ci    if (dirName == NULL) {
6633d8536b4Sopenharmony_ci        errno = EFAULT;
6643d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6653d8536b4Sopenharmony_ci    }
6663d8536b4Sopenharmony_ci
6673d8536b4Sopenharmony_ci    ret = FsChangeDrive(dirName);
6683d8536b4Sopenharmony_ci    if (ret != (int)LOS_OK) {
6693d8536b4Sopenharmony_ci        PRINT_ERR("FAT opendir ChangeDrive err 0x%x!\r\n", ret);
6703d8536b4Sopenharmony_ci        errno = ENOENT;
6713d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6723d8536b4Sopenharmony_ci    }
6733d8536b4Sopenharmony_ci
6743d8536b4Sopenharmony_ci    dp = (DIR *)LOSCFG_FS_MALLOC_HOOK(sizeof(DIR));
6753d8536b4Sopenharmony_ci    if (dp == NULL) {
6763d8536b4Sopenharmony_ci        errno = ENOENT;
6773d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6783d8536b4Sopenharmony_ci    }
6793d8536b4Sopenharmony_ci    (void)memset_s(dp, sizeof(DIR), 0, sizeof(DIR));
6803d8536b4Sopenharmony_ci
6813d8536b4Sopenharmony_ci    res = f_opendir(dp, dirName);
6823d8536b4Sopenharmony_ci    if (res != FR_OK) {
6833d8536b4Sopenharmony_ci        PRINT_ERR("FAT opendir err 0x%x!\r\n", res);
6843d8536b4Sopenharmony_ci        LOSCFG_FS_FREE_HOOK(dp);
6853d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
6863d8536b4Sopenharmony_ci        return (int)LOS_NOK;
6873d8536b4Sopenharmony_ci    }
6883d8536b4Sopenharmony_ci
6893d8536b4Sopenharmony_ci    dir->dData = dp;
6903d8536b4Sopenharmony_ci    dir->dOffset = 0;
6913d8536b4Sopenharmony_ci
6923d8536b4Sopenharmony_ci    return (int)LOS_OK;
6933d8536b4Sopenharmony_ci}
6943d8536b4Sopenharmony_ci
6953d8536b4Sopenharmony_ciint FatfsReaddir(struct Dir *dir, struct dirent *dent)
6963d8536b4Sopenharmony_ci{
6973d8536b4Sopenharmony_ci    FRESULT res;
6983d8536b4Sopenharmony_ci    FILINFO fileInfo = {0};
6993d8536b4Sopenharmony_ci    DIR *dp = NULL;
7003d8536b4Sopenharmony_ci
7013d8536b4Sopenharmony_ci    if ((dir == NULL) || (dir->dData == NULL)) {
7023d8536b4Sopenharmony_ci        errno = EBADF;
7033d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7043d8536b4Sopenharmony_ci    }
7053d8536b4Sopenharmony_ci
7063d8536b4Sopenharmony_ci    dp = (DIR *)dir->dData;
7073d8536b4Sopenharmony_ci    res = f_readdir(dp, &fileInfo);
7083d8536b4Sopenharmony_ci    /* if res not ok or fname is NULL , return NULL */
7093d8536b4Sopenharmony_ci    if ((res != FR_OK) || (fileInfo.fname[0] == 0x0)) {
7103d8536b4Sopenharmony_ci        PRINT_ERR("FAT readdir err 0x%x!\r\n", res);
7113d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
7123d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7133d8536b4Sopenharmony_ci    }
7143d8536b4Sopenharmony_ci
7153d8536b4Sopenharmony_ci    (void)memcpy_s(dent->d_name, sizeof(dent->d_name),
7163d8536b4Sopenharmony_ci            fileInfo.fname, sizeof(dent->d_name));
7173d8536b4Sopenharmony_ci    if (fileInfo.fattrib & AM_DIR) {
7183d8536b4Sopenharmony_ci        dent->d_type = DT_DIR;
7193d8536b4Sopenharmony_ci    } else {
7203d8536b4Sopenharmony_ci        dent->d_type = DT_REG;
7213d8536b4Sopenharmony_ci    }
7223d8536b4Sopenharmony_ci
7233d8536b4Sopenharmony_ci    return (int)LOS_OK;
7243d8536b4Sopenharmony_ci}
7253d8536b4Sopenharmony_ci
7263d8536b4Sopenharmony_ciint FatfsClosedir(struct Dir *dir)
7273d8536b4Sopenharmony_ci{
7283d8536b4Sopenharmony_ci    FRESULT res;
7293d8536b4Sopenharmony_ci    DIR *dp = NULL;
7303d8536b4Sopenharmony_ci
7313d8536b4Sopenharmony_ci    if ((dir == NULL) || (dir->dData == NULL)) {
7323d8536b4Sopenharmony_ci        errno = EBADF;
7333d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7343d8536b4Sopenharmony_ci    }
7353d8536b4Sopenharmony_ci
7363d8536b4Sopenharmony_ci    dp = dir->dData;
7373d8536b4Sopenharmony_ci    res = f_closedir(dp);
7383d8536b4Sopenharmony_ci    if (res != FR_OK) {
7393d8536b4Sopenharmony_ci        PRINT_ERR("FAT closedir err 0x%x!\r\n", res);
7403d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
7413d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7423d8536b4Sopenharmony_ci    }
7433d8536b4Sopenharmony_ci
7443d8536b4Sopenharmony_ci    LOSCFG_FS_FREE_HOOK(dir->dData);
7453d8536b4Sopenharmony_ci    dir->dData = NULL;
7463d8536b4Sopenharmony_ci
7473d8536b4Sopenharmony_ci    return (int)LOS_OK;
7483d8536b4Sopenharmony_ci}
7493d8536b4Sopenharmony_ci
7503d8536b4Sopenharmony_ciint FatfsRmdir(struct MountPoint *mp, const char *path)
7513d8536b4Sopenharmony_ci{
7523d8536b4Sopenharmony_ci    FRESULT res;
7533d8536b4Sopenharmony_ci    int ret;
7543d8536b4Sopenharmony_ci
7553d8536b4Sopenharmony_ci    if ((path == NULL) || (mp == NULL)) {
7563d8536b4Sopenharmony_ci        errno = EFAULT;
7573d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7583d8536b4Sopenharmony_ci    }
7593d8536b4Sopenharmony_ci
7603d8536b4Sopenharmony_ci    if (!mp->mWriteEnable) {
7613d8536b4Sopenharmony_ci        errno = EACCES;
7623d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7633d8536b4Sopenharmony_ci    }
7643d8536b4Sopenharmony_ci
7653d8536b4Sopenharmony_ci    ret = FsChangeDrive(path);
7663d8536b4Sopenharmony_ci    if (ret != (int)LOS_OK) {
7673d8536b4Sopenharmony_ci        PRINT_ERR("FAT rmdir ChangeDrive err 0x%x!\r\n", ret);
7683d8536b4Sopenharmony_ci        errno = ENOENT;
7693d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7703d8536b4Sopenharmony_ci    }
7713d8536b4Sopenharmony_ci
7723d8536b4Sopenharmony_ci    res = f_rmdir(path);
7733d8536b4Sopenharmony_ci    if (res != FR_OK) {
7743d8536b4Sopenharmony_ci        PRINT_ERR("FAT rmdir err 0x%x!\r\n", res);
7753d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
7763d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7773d8536b4Sopenharmony_ci    }
7783d8536b4Sopenharmony_ci
7793d8536b4Sopenharmony_ci    return (int)LOS_OK;
7803d8536b4Sopenharmony_ci}
7813d8536b4Sopenharmony_ci
7823d8536b4Sopenharmony_ciint FatfsRename(struct MountPoint *mp, const char *oldName, const char *newName)
7833d8536b4Sopenharmony_ci{
7843d8536b4Sopenharmony_ci    FRESULT res;
7853d8536b4Sopenharmony_ci    int ret;
7863d8536b4Sopenharmony_ci
7873d8536b4Sopenharmony_ci    if ((oldName == NULL) || (newName == NULL)) {
7883d8536b4Sopenharmony_ci        errno = EFAULT;
7893d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7903d8536b4Sopenharmony_ci    }
7913d8536b4Sopenharmony_ci
7923d8536b4Sopenharmony_ci    if (!mp->mWriteEnable) {
7933d8536b4Sopenharmony_ci        errno = EACCES;
7943d8536b4Sopenharmony_ci        return (int)LOS_NOK;
7953d8536b4Sopenharmony_ci    }
7963d8536b4Sopenharmony_ci
7973d8536b4Sopenharmony_ci    ret = FsChangeDrive(oldName);
7983d8536b4Sopenharmony_ci    if (ret != (int)LOS_OK) {
7993d8536b4Sopenharmony_ci        PRINT_ERR("FAT f_getfree ChangeDrive err 0x%x!\r\n", ret);
8003d8536b4Sopenharmony_ci        errno = ENOENT;
8013d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8023d8536b4Sopenharmony_ci    }
8033d8536b4Sopenharmony_ci
8043d8536b4Sopenharmony_ci    res = f_rename(oldName, newName);
8053d8536b4Sopenharmony_ci    if (res != FR_OK) {
8063d8536b4Sopenharmony_ci        PRINT_ERR("FAT frename err 0x%x!\r\n", res);
8073d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
8083d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8093d8536b4Sopenharmony_ci    }
8103d8536b4Sopenharmony_ci
8113d8536b4Sopenharmony_ci    return (int)LOS_OK;
8123d8536b4Sopenharmony_ci}
8133d8536b4Sopenharmony_ci
8143d8536b4Sopenharmony_ciint FatfsStatfs(const char *path, struct statfs *buf)
8153d8536b4Sopenharmony_ci{
8163d8536b4Sopenharmony_ci    FATFS *fs = NULL;
8173d8536b4Sopenharmony_ci    UINT32 freeClust;
8183d8536b4Sopenharmony_ci    FRESULT res;
8193d8536b4Sopenharmony_ci    int ret;
8203d8536b4Sopenharmony_ci
8213d8536b4Sopenharmony_ci    if ((path == NULL) || (buf == NULL)) {
8223d8536b4Sopenharmony_ci        errno = EFAULT;
8233d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8243d8536b4Sopenharmony_ci    }
8253d8536b4Sopenharmony_ci
8263d8536b4Sopenharmony_ci    ret = FsChangeDrive(path);
8273d8536b4Sopenharmony_ci    if (ret != FR_OK) {
8283d8536b4Sopenharmony_ci        PRINT_ERR("FAT f_getfree ChangeDrive err %d.", ret);
8293d8536b4Sopenharmony_ci        errno = FatfsErrno(FR_INVALID_PARAMETER);
8303d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8313d8536b4Sopenharmony_ci    }
8323d8536b4Sopenharmony_ci
8333d8536b4Sopenharmony_ci    res = f_getfree(path, &freeClust, &fs);
8343d8536b4Sopenharmony_ci    if (res != FR_OK) {
8353d8536b4Sopenharmony_ci        PRINT_ERR("FAT f_getfree err 0x%x.", res);
8363d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
8373d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8383d8536b4Sopenharmony_ci    }
8393d8536b4Sopenharmony_ci    buf->f_bfree  = freeClust;
8403d8536b4Sopenharmony_ci    buf->f_bavail = freeClust;
8413d8536b4Sopenharmony_ci    /* Cluster #0 and #1 is for VBR, reserve sectors and fat */
8423d8536b4Sopenharmony_ci    buf->f_blocks = fs->n_fatent - 2;
8433d8536b4Sopenharmony_ci#if FF_MAX_SS != FF_MIN_SS
8443d8536b4Sopenharmony_ci    buf->f_bsize  = fs->ssize * fs->csize;
8453d8536b4Sopenharmony_ci#else
8463d8536b4Sopenharmony_ci    buf->f_bsize  = FF_MIN_SS * fs->csize;
8473d8536b4Sopenharmony_ci#endif
8483d8536b4Sopenharmony_ci
8493d8536b4Sopenharmony_ci    return (int)LOS_OK;
8503d8536b4Sopenharmony_ci}
8513d8536b4Sopenharmony_ci
8523d8536b4Sopenharmony_cistatic int DoTruncate(struct File *file, off_t length, UINT32 count)
8533d8536b4Sopenharmony_ci{
8543d8536b4Sopenharmony_ci    FRESULT res = FR_OK;
8553d8536b4Sopenharmony_ci    DWORD csz;
8563d8536b4Sopenharmony_ci    FIL *fp = (FIL *)file->fData;
8573d8536b4Sopenharmony_ci
8583d8536b4Sopenharmony_ci    csz = (DWORD)(fp->obj.fs)->csize * SS(fp->obj.fs); /* Cluster size */
8593d8536b4Sopenharmony_ci    if (length > csz * count) {
8603d8536b4Sopenharmony_ci#if FF_USE_EXPAND
8613d8536b4Sopenharmony_ci        res = f_expand(fp, 0, (FSIZE_t)(length), FALLOC_FL_KEEP_SIZE);
8623d8536b4Sopenharmony_ci#else
8633d8536b4Sopenharmony_ci        errno = ENOSYS;
8643d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8653d8536b4Sopenharmony_ci#endif
8663d8536b4Sopenharmony_ci    } else if (length < csz * count) {
8673d8536b4Sopenharmony_ci        res = f_truncate(fp, (FSIZE_t)length);
8683d8536b4Sopenharmony_ci    }
8693d8536b4Sopenharmony_ci
8703d8536b4Sopenharmony_ci    if (res != FR_OK) {
8713d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
8723d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8733d8536b4Sopenharmony_ci    }
8743d8536b4Sopenharmony_ci
8753d8536b4Sopenharmony_ci    fp->obj.objsize = length; /* Set file size to length */
8763d8536b4Sopenharmony_ci    fp->flag |= 0x40; /* Set modified flag */
8773d8536b4Sopenharmony_ci
8783d8536b4Sopenharmony_ci    return (int)LOS_OK;
8793d8536b4Sopenharmony_ci}
8803d8536b4Sopenharmony_ci
8813d8536b4Sopenharmony_ciint FatfsTruncate(struct File *file, off_t length)
8823d8536b4Sopenharmony_ci{
8833d8536b4Sopenharmony_ci    FRESULT res;
8843d8536b4Sopenharmony_ci    UINT count;
8853d8536b4Sopenharmony_ci    DWORD fclust;
8863d8536b4Sopenharmony_ci    FIL *fp = (FIL *)file->fData;
8873d8536b4Sopenharmony_ci
8883d8536b4Sopenharmony_ci    if ((length < 0) || (length > UINT_MAX)) {
8893d8536b4Sopenharmony_ci        errno = EINVAL;
8903d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8913d8536b4Sopenharmony_ci    }
8923d8536b4Sopenharmony_ci
8933d8536b4Sopenharmony_ci    if ((fp == NULL) || (fp->obj.fs == NULL)) {
8943d8536b4Sopenharmony_ci        errno = ENOENT;
8953d8536b4Sopenharmony_ci        return (int)LOS_NOK;
8963d8536b4Sopenharmony_ci    }
8973d8536b4Sopenharmony_ci
8983d8536b4Sopenharmony_ci    res = f_getclustinfo(fp, &fclust, &count);
8993d8536b4Sopenharmony_ci    if (res != FR_OK) {
9003d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
9013d8536b4Sopenharmony_ci        return (int)LOS_NOK;
9023d8536b4Sopenharmony_ci    }
9033d8536b4Sopenharmony_ci
9043d8536b4Sopenharmony_ci    return DoTruncate(file, length, count);
9053d8536b4Sopenharmony_ci}
9063d8536b4Sopenharmony_ci
9073d8536b4Sopenharmony_ciint FatfsFdisk(const char *dev, int *partTbl, int arrayNum)
9083d8536b4Sopenharmony_ci{
9093d8536b4Sopenharmony_ci    int pdrv;
9103d8536b4Sopenharmony_ci    FRESULT res;
9113d8536b4Sopenharmony_ci
9123d8536b4Sopenharmony_ci    if ((dev == NULL) || (partTbl == NULL)) {
9133d8536b4Sopenharmony_ci        errno = EFAULT;
9143d8536b4Sopenharmony_ci        return (int)LOS_NOK;
9153d8536b4Sopenharmony_ci    }
9163d8536b4Sopenharmony_ci
9173d8536b4Sopenharmony_ci    pdrv = GetDevIdByDevName(dev);
9183d8536b4Sopenharmony_ci    if (pdrv < 0) {
9193d8536b4Sopenharmony_ci        errno = EFAULT;
9203d8536b4Sopenharmony_ci        return (int)LOS_NOK;
9213d8536b4Sopenharmony_ci    }
9223d8536b4Sopenharmony_ci
9233d8536b4Sopenharmony_ci    res = f_fdisk(pdrv, (DWORD const *)partTbl, g_workBuffer);
9243d8536b4Sopenharmony_ci    if (res != FR_OK) {
9253d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
9263d8536b4Sopenharmony_ci        return (int)LOS_NOK;
9273d8536b4Sopenharmony_ci    }
9283d8536b4Sopenharmony_ci
9293d8536b4Sopenharmony_ci    return (int)LOS_OK;
9303d8536b4Sopenharmony_ci}
9313d8536b4Sopenharmony_ci
9323d8536b4Sopenharmony_ciint FatfsFormat(const char *partName, void *privData)
9333d8536b4Sopenharmony_ci{
9343d8536b4Sopenharmony_ci    FRESULT res;
9353d8536b4Sopenharmony_ci    MKFS_PARM opt = {0};
9363d8536b4Sopenharmony_ci    int option = *(int *)privData;
9373d8536b4Sopenharmony_ci    char *dev = NULL; /* logical driver */
9383d8536b4Sopenharmony_ci
9393d8536b4Sopenharmony_ci    if (partName == NULL) {
9403d8536b4Sopenharmony_ci        errno = EFAULT;
9413d8536b4Sopenharmony_ci        return (int)LOS_NOK;
9423d8536b4Sopenharmony_ci    }
9433d8536b4Sopenharmony_ci
9443d8536b4Sopenharmony_ci    dev = GetLdPath(partName);
9453d8536b4Sopenharmony_ci    if (dev == NULL) {
9463d8536b4Sopenharmony_ci        errno = EFAULT;
9473d8536b4Sopenharmony_ci        return (int)LOS_NOK;
9483d8536b4Sopenharmony_ci    }
9493d8536b4Sopenharmony_ci
9503d8536b4Sopenharmony_ci    opt.fmt = option;
9513d8536b4Sopenharmony_ci    opt.n_sect = 0; /* use default allocation unit size depends on the volume
9523d8536b4Sopenharmony_ci                       size. */
9533d8536b4Sopenharmony_ci    res = f_mkfs(dev, &opt, g_workBuffer, FF_MAX_SS);
9543d8536b4Sopenharmony_ci    if (res != FR_OK) {
9553d8536b4Sopenharmony_ci        errno = FatfsErrno(res);
9563d8536b4Sopenharmony_ci        PutLdPath(dev);
9573d8536b4Sopenharmony_ci        return (int)LOS_NOK;
9583d8536b4Sopenharmony_ci    }
9593d8536b4Sopenharmony_ci
9603d8536b4Sopenharmony_ci    return (int)LOS_OK;
9613d8536b4Sopenharmony_ci}
9623d8536b4Sopenharmony_ci
9633d8536b4Sopenharmony_cistatic struct MountOps g_fatfsMnt = {
9643d8536b4Sopenharmony_ci    .mount = FatfsMount,
9653d8536b4Sopenharmony_ci    .umount = FatfsUmount,
9663d8536b4Sopenharmony_ci    .umount2 = FatfsUmount2,
9673d8536b4Sopenharmony_ci    .statfs = FatfsStatfs,
9683d8536b4Sopenharmony_ci};
9693d8536b4Sopenharmony_ci
9703d8536b4Sopenharmony_cistatic struct FileOps g_fatfsFops = {
9713d8536b4Sopenharmony_ci    .open = FatfsOpen,
9723d8536b4Sopenharmony_ci    .close = FatfsClose,
9733d8536b4Sopenharmony_ci    .read = FatfsRead,
9743d8536b4Sopenharmony_ci    .write = FatfsWrite,
9753d8536b4Sopenharmony_ci    .lseek = FatfsLseek,
9763d8536b4Sopenharmony_ci    .stat = FatfsStat,
9773d8536b4Sopenharmony_ci    .truncate = FatfsTruncate,
9783d8536b4Sopenharmony_ci    .unlink = FatfsUnlink,
9793d8536b4Sopenharmony_ci    .rename = FatfsRename,
9803d8536b4Sopenharmony_ci    .ioctl = NULL, /* not support */
9813d8536b4Sopenharmony_ci    .sync = FatfsSync,
9823d8536b4Sopenharmony_ci    .opendir = FatfsOpendir,
9833d8536b4Sopenharmony_ci    .readdir = FatfsReaddir,
9843d8536b4Sopenharmony_ci    .closedir = FatfsClosedir,
9853d8536b4Sopenharmony_ci    .mkdir = FatfsMkdir,
9863d8536b4Sopenharmony_ci    .rmdir = FatfsRmdir,
9873d8536b4Sopenharmony_ci};
9883d8536b4Sopenharmony_ci
9893d8536b4Sopenharmony_cistatic struct FsManagement g_fatfsMgt = {
9903d8536b4Sopenharmony_ci    .fdisk = FatfsFdisk,
9913d8536b4Sopenharmony_ci    .format = FatfsFormat,
9923d8536b4Sopenharmony_ci};
9933d8536b4Sopenharmony_ci
9943d8536b4Sopenharmony_civoid FatFsInit(void)
9953d8536b4Sopenharmony_ci{
9963d8536b4Sopenharmony_ci    (void)OsFsRegister("vfat", &g_fatfsMnt, &g_fatfsFops, &g_fatfsMgt);
9973d8536b4Sopenharmony_ci}
998