1427 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1427 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. All rights reserved.
 | 
						|
 *
 | 
						|
 * Redistribution and use in source and binary forms, with or without modification,
 | 
						|
 * are permitted provided that the following conditions are met:
 | 
						|
 *
 | 
						|
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 | 
						|
 *    conditions and the following disclaimer.
 | 
						|
 *
 | 
						|
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 | 
						|
 *    of conditions and the following disclaimer in the documentation and/or other materials
 | 
						|
 *    provided with the distribution.
 | 
						|
 *
 | 
						|
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 | 
						|
 *    to endorse or promote products derived from this software without specific prior written
 | 
						|
 *    permission.
 | 
						|
 *
 | 
						|
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
						|
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | 
						|
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
						|
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 | 
						|
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
						|
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
						|
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 | 
						|
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | 
						|
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
						|
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | 
						|
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
						|
 */
 | 
						|
 | 
						|
#define _GNU_SOURCE 1
 | 
						|
#include "los_fs.h"
 | 
						|
#include <stdint.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <stdarg.h>
 | 
						|
#include <stdbool.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <sys/uio.h>
 | 
						|
#include "errno.h"
 | 
						|
#include "fcntl.h"
 | 
						|
#include "los_mux.h"
 | 
						|
#include "los_debug.h"
 | 
						|
#include "los_sched.h"
 | 
						|
#include "limits.h"
 | 
						|
#include "securec.h"
 | 
						|
#include "vfs_config.h"
 | 
						|
#include "vfs_files.h"
 | 
						|
#include "vfs_maps.h"
 | 
						|
#include "vfs_mount.h"
 | 
						|
#include "vfs_operations.h"
 | 
						|
 | 
						|
#ifdef LOSCFG_NET_LWIP_SACK
 | 
						|
#include "lwipopts.h"
 | 
						|
#include "lwip/sockets.h"
 | 
						|
#define CONFIG_NSOCKET_DESCRIPTORS  LWIP_CONFIG_NUM_SOCKETS
 | 
						|
#else
 | 
						|
#define CONFIG_NSOCKET_DESCRIPTORS  0
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef LOSCFG_RANDOM_DEV
 | 
						|
#include "hks_client.h"
 | 
						|
#define RANDOM_DEV_FD  CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS
 | 
						|
#define RANDOM_DEV_PATH  "/dev/random"
 | 
						|
#endif
 | 
						|
 | 
						|
#if (LOSCFG_POSIX_PIPE_API == 1)
 | 
						|
#include "pipe_impl.h"
 | 
						|
#ifdef LOSCFG_RANDOM_DEV
 | 
						|
#define PIPE_DEV_FD (RANDOM_DEV_FD + 1)
 | 
						|
#else
 | 
						|
#define PIPE_DEV_FD (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)
 | 
						|
#endif
 | 
						|
 | 
						|
int PollQueryFd(int fd, struct PollTable *table)
 | 
						|
{
 | 
						|
    if (fd >= PIPE_DEV_FD) {
 | 
						|
        return PipePoll(fd, table);
 | 
						|
    }
 | 
						|
 | 
						|
    return -ENODEV;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#define FREE_AND_SET_NULL(ptr) do { \
 | 
						|
    LOSCFG_FS_FREE_HOOK(ptr);       \
 | 
						|
    ptr = NULL;                     \
 | 
						|
} while (0)
 | 
						|
 | 
						|
#define LOS_FCNTL   (O_NONBLOCK | O_NDELAY | O_APPEND | O_SYNC)
 | 
						|
#define IOV_MAX_CNT 4
 | 
						|
 | 
						|
UINT32 g_fsMutex;
 | 
						|
static UINT32 g_dirNum = 0;
 | 
						|
 | 
						|
int LOS_FsLock(void)
 | 
						|
{
 | 
						|
    if (!OsCheckKernelRunning()) {
 | 
						|
        return LOS_OK;
 | 
						|
    }
 | 
						|
    if (LOS_MuxPend(g_fsMutex, (UINT32)LOSCFG_FS_LOCK_TIMEOUT) != LOS_OK) {
 | 
						|
        PRINT_ERR("LOS_FsLock failed!");
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    return LOS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void LOS_FsUnlock(void)
 | 
						|
{
 | 
						|
    if (!OsCheckKernelRunning()) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    (void)LOS_MuxPost(g_fsMutex);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef LOSCFG_RANDOM_DEV
 | 
						|
/**
 | 
						|
 * @brief Get canonical form of a given path based on cwd(Current working directory).
 | 
						|
 *
 | 
						|
 * @param cwd Indicates the current working directory.
 | 
						|
 * @param path Indicates the path to be canonicalization.
 | 
						|
 * @param buf Indicates the pointer to the buffer where the result will be return.
 | 
						|
 * @param bufSize Indicates the size of the buffer.
 | 
						|
 * @return Returns the length of the canonical path.
 | 
						|
 *
 | 
						|
 * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/').
 | 
						|
 *            if the buffer is not big enough the result will be truncated, but the return value will always be the
 | 
						|
 *            length of the canonical path.
 | 
						|
 */
 | 
						|
static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize)
 | 
						|
{
 | 
						|
    size_t offset;
 | 
						|
    if (!path) {
 | 
						|
        path = "";
 | 
						|
    }
 | 
						|
 | 
						|
    if ((!cwd) || (path[0] == '/')) {
 | 
						|
        cwd = "";
 | 
						|
    }
 | 
						|
 | 
						|
    offset = strlen("///") + 1; // three '/' and one '\0'
 | 
						|
    size_t tmpLen = strlen(cwd) + strlen(path) + offset;
 | 
						|
    char *tmpBuf = (char *)LOSCFG_FS_MALLOC_HOOK(tmpLen);
 | 
						|
    if (tmpBuf == NULL) {
 | 
						|
        return LOS_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
 | 
						|
        LOSCFG_FS_FREE_HOOK(tmpBuf);
 | 
						|
        return LOS_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    char *p;
 | 
						|
    /* replace /./ to / */
 | 
						|
    offset = strlen("/./") - 1;
 | 
						|
    while ((p = strstr(tmpBuf, "/./")) != NULL) {
 | 
						|
        if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
 | 
						|
            LOSCFG_FS_FREE_HOOK(tmpBuf);
 | 
						|
            return LOS_OK;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* replace // to / */
 | 
						|
    while ((p = strstr(tmpBuf, "//")) != NULL) {
 | 
						|
        if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
 | 
						|
            LOSCFG_FS_FREE_HOOK(tmpBuf);
 | 
						|
            return LOS_OK;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */
 | 
						|
    offset = strlen("/../") - 1;
 | 
						|
    while ((p = strstr(tmpBuf, "/../")) != NULL) {
 | 
						|
        char *start = p;
 | 
						|
        while (start > tmpBuf && *(start - 1) != '/') {
 | 
						|
            --start;
 | 
						|
        }
 | 
						|
        if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
 | 
						|
            LOSCFG_FS_FREE_HOOK(tmpBuf);
 | 
						|
            return LOS_OK;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    size_t totalLen = strlen(tmpBuf);
 | 
						|
    /* strip the last / */
 | 
						|
    if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') {
 | 
						|
        tmpBuf[--totalLen] = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((!buf) || (bufSize == 0)) {
 | 
						|
        LOSCFG_FS_FREE_HOOK(tmpBuf);
 | 
						|
        return totalLen;
 | 
						|
    }
 | 
						|
 | 
						|
    if (EOK != memcpy_s(buf, bufSize, tmpBuf, (((totalLen + 1) > bufSize) ? bufSize : (totalLen + 1)))) {
 | 
						|
        LOSCFG_FS_FREE_HOOK(tmpBuf);
 | 
						|
        return LOS_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    buf[bufSize - 1] = 0;
 | 
						|
    LOSCFG_FS_FREE_HOOK(tmpBuf);
 | 
						|
    return totalLen;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
static int VfsPathCheck(const char *path, bool isFile)
 | 
						|
{
 | 
						|
    size_t len;
 | 
						|
    if ((path == NULL) || (path[0] == '\0')) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    len = strlen(path);
 | 
						|
    if (len >= PATH_MAX) {
 | 
						|
        VFS_ERRNO_SET(ENAMETOOLONG);
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isFile && path[len - 1] == '/') {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    return LOS_OK;
 | 
						|
}
 | 
						|
 | 
						|
static int VfsOpen(const char *path, int flags)
 | 
						|
{
 | 
						|
    size_t len;
 | 
						|
    struct File *file = NULL;
 | 
						|
    int fd = -1;
 | 
						|
    const char *pathInMp = NULL;
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
 | 
						|
    if (VfsPathCheck(path, TRUE) != LOS_OK) {
 | 
						|
        return fd;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return fd;
 | 
						|
    }
 | 
						|
 | 
						|
    mp = VfsMpFind(path, &pathInMp);
 | 
						|
    if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
 | 
						|
        (mp->mFs->fsFops == NULL) || (mp->mFs->fsFops->open == NULL)) {
 | 
						|
        /* path is not in any mountpoint */
 | 
						|
        VFS_ERRNO_SET(ENOENT);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return fd;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((mp->mWriteEnable == FALSE) &&
 | 
						|
        (flags & (O_CREAT | O_WRONLY | O_RDWR))) {
 | 
						|
        /* can't create file in read only mp */
 | 
						|
        VFS_ERRNO_SET(EACCES);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return fd;
 | 
						|
    }
 | 
						|
 | 
						|
    file = VfsFileGet();
 | 
						|
    if (file == NULL) {
 | 
						|
        VFS_ERRNO_SET(ENFILE);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return fd;
 | 
						|
    }
 | 
						|
 | 
						|
    len = strlen(path) + 1;
 | 
						|
    file->fullPath = LOSCFG_FS_MALLOC_HOOK(len);
 | 
						|
    if (file->fullPath == NULL) {
 | 
						|
        VFS_ERRNO_SET(ENOMEM);
 | 
						|
        VfsFilePut(file);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
    (void)strcpy_s((char *)file->fullPath, len, path);
 | 
						|
 | 
						|
    file->fFlags = (UINT32)flags;
 | 
						|
    file->fOffset = 0;
 | 
						|
    file->fData = NULL;
 | 
						|
    file->fFops = mp->mFs->fsFops;
 | 
						|
    file->fMp = mp;
 | 
						|
    file->fOwner = LOS_CurTaskIDGet();
 | 
						|
 | 
						|
    if (file->fFops->open(file, pathInMp, flags) == 0) {
 | 
						|
        mp->mRefs++;
 | 
						|
        fd = FileToFd(file);
 | 
						|
        file->fStatus = FILE_STATUS_READY; /* file now ready to use */
 | 
						|
    } else {
 | 
						|
        LOSCFG_FS_FREE_HOOK((void *)file->fullPath);
 | 
						|
        VfsFilePut(file);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return fd;
 | 
						|
}
 | 
						|
 | 
						|
/* attach to a file and then set new status */
 | 
						|
 | 
						|
static struct File *VfsAttachFile(int fd, UINT32 status)
 | 
						|
{
 | 
						|
    struct File *file = NULL;
 | 
						|
 | 
						|
    if ((fd < MIN_START_FD) || (fd >= CONFIG_NFILE_DESCRIPTORS)) {
 | 
						|
        VFS_ERRNO_SET(EBADF);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EFAULT);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    file = FdToFile(fd);
 | 
						|
    if ((file == NULL) || (file->fMp == NULL)) {
 | 
						|
        VFS_ERRNO_SET(EBADF);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (file->fStatus != FILE_STATUS_READY) {
 | 
						|
        VFS_ERRNO_SET(EBADF);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    file->fStatus = status;
 | 
						|
    return file;
 | 
						|
}
 | 
						|
 | 
						|
static struct File *VfsAttachFileReady(int fd)
 | 
						|
{
 | 
						|
    return VfsAttachFile(fd, FILE_STATUS_READY);
 | 
						|
}
 | 
						|
 | 
						|
static struct File *VfsAttachFileWithStatus(int fd, int status)
 | 
						|
{
 | 
						|
    return VfsAttachFile(fd, (UINT32)status);
 | 
						|
}
 | 
						|
 | 
						|
static void VfsDetachFile(const struct File *file)
 | 
						|
{
 | 
						|
    (void)file;
 | 
						|
    LOS_FsUnlock();
 | 
						|
}
 | 
						|
 | 
						|
static int VfsClose(int fd)
 | 
						|
{
 | 
						|
    struct File *file = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    file = VfsAttachFileWithStatus(fd, FILE_STATUS_CLOSING);
 | 
						|
    if (file == NULL) {
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((file->fFops != NULL) && (file->fFops->close != NULL)) {
 | 
						|
        ret = file->fFops->close(file);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((ret == 0) && (file->fMp != NULL)) {
 | 
						|
        file->fMp->mRefs--;
 | 
						|
    }
 | 
						|
 | 
						|
    if (file->fullPath != NULL) {
 | 
						|
        LOSCFG_FS_FREE_HOOK((void *)file->fullPath);
 | 
						|
    }
 | 
						|
 | 
						|
    VfsFilePut(file);
 | 
						|
 | 
						|
    VfsDetachFile(file);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static ssize_t VfsRead(int fd, char *buff, size_t bytes)
 | 
						|
{
 | 
						|
    struct File *file = NULL;
 | 
						|
    ssize_t ret = (ssize_t)-1;
 | 
						|
 | 
						|
    if (buff == NULL) {
 | 
						|
        VFS_ERRNO_SET(EFAULT);
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if (bytes == 0) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    file = VfsAttachFileReady(fd);
 | 
						|
    if (file == NULL) {
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((file->fFlags & O_ACCMODE) == O_WRONLY) {
 | 
						|
        VFS_ERRNO_SET(EACCES);
 | 
						|
    } else if ((file->fFops != NULL) && (file->fFops->read != NULL)) {
 | 
						|
        ret = file->fFops->read(file, buff, bytes);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    /* else ret will be -1 */
 | 
						|
    VfsDetachFile(file);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static ssize_t VfsWrite(int fd, const void *buff, size_t bytes)
 | 
						|
{
 | 
						|
    struct File *file = NULL;
 | 
						|
    ssize_t ret = (ssize_t)LOS_NOK;
 | 
						|
 | 
						|
    if ((buff == NULL) || (bytes == 0)) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    file = VfsAttachFileReady(fd);
 | 
						|
    if (file == NULL) {
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((file->fFlags & O_ACCMODE) == O_RDONLY) {
 | 
						|
        VFS_ERRNO_SET(EACCES);
 | 
						|
    } else if ((file->fFops != NULL) && (file->fFops->write != NULL)) {
 | 
						|
        ret = file->fFops->write(file, buff, bytes);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    /* else ret will be -1 */
 | 
						|
    VfsDetachFile(file);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int VfsIoctl(int fd, int func, va_list ap)
 | 
						|
{
 | 
						|
    unsigned long arg;
 | 
						|
    struct File *file = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    arg = va_arg(ap, unsigned long);
 | 
						|
    file = VfsAttachFileReady(fd);
 | 
						|
    if (file == NULL) {
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((file->fFops != NULL) && (file->fFops->ioctl != NULL)) {
 | 
						|
        ret = file->fFops->ioctl(file, func, arg);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    VfsDetachFile(file);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int VfsVfcntl(struct File *filep, int cmd, va_list ap)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    UINT32 flags;
 | 
						|
 | 
						|
    if ((filep == NULL) || (filep->fFops == NULL)) {
 | 
						|
        return -EBADF;
 | 
						|
    }
 | 
						|
 | 
						|
    if (cmd == F_GETFL) {
 | 
						|
        ret = (int)(filep->fFlags);
 | 
						|
    } else if (cmd == F_SETFL) {
 | 
						|
        flags = (UINT32)va_arg(ap, int);
 | 
						|
        flags &= LOS_FCNTL;
 | 
						|
        filep->fFlags &= ~LOS_FCNTL;
 | 
						|
        filep->fFlags |= flags;
 | 
						|
        ret = LOS_OK;
 | 
						|
    } else {
 | 
						|
        ret = -ENOSYS;
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int MapToPosixRet(int ret)
 | 
						|
{
 | 
						|
    return ((ret) < 0 ? -1 : (ret));
 | 
						|
}
 | 
						|
 | 
						|
/* POSIX interface */
 | 
						|
int open(const char *path, int flags, ...)
 | 
						|
{
 | 
						|
    if (path == NULL) {
 | 
						|
        errno = EINVAL;
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
#ifdef LOSCFG_RANDOM_DEV
 | 
						|
    unsigned flagMask = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE \
 | 
						|
                        | O_TRUNC | O_EXCL | O_DIRECTORY;
 | 
						|
    if ((unsigned)flags & ~flagMask) {
 | 
						|
        errno = EINVAL;
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    size_t pathLen = strlen(path) + 1;
 | 
						|
    if ((unsigned)pathLen > PATH_MAX) {
 | 
						|
        errno = EINVAL;
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    char *canonicalPath = (char *)LOSCFG_FS_MALLOC_HOOK(pathLen);
 | 
						|
    if (!canonicalPath) {
 | 
						|
        errno = ENOMEM;
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
    if (GetCanonicalPath(NULL, path, canonicalPath, pathLen) == 0) {
 | 
						|
        FREE_AND_SET_NULL(canonicalPath);
 | 
						|
        errno = ENOMEM;
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
 | 
						|
        FREE_AND_SET_NULL(canonicalPath);
 | 
						|
        if ((O_ACCMODE & (unsigned)flags) != O_RDONLY) {
 | 
						|
            errno = EPERM;
 | 
						|
            return (int)LOS_NOK;
 | 
						|
        }
 | 
						|
        if ((unsigned)flags & O_DIRECTORY) {
 | 
						|
            errno = ENOTDIR;
 | 
						|
            return (int)LOS_NOK;
 | 
						|
        }
 | 
						|
        return RANDOM_DEV_FD;
 | 
						|
    }
 | 
						|
    if ((strcmp(canonicalPath, "/") == 0) ||
 | 
						|
        (strcmp(canonicalPath, "/dev") == 0)) {
 | 
						|
        FREE_AND_SET_NULL(canonicalPath);
 | 
						|
        if ((unsigned)flags & O_DIRECTORY) {
 | 
						|
            errno = EPERM;
 | 
						|
            return (int)LOS_NOK;
 | 
						|
        }
 | 
						|
        errno = EISDIR;
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
    FREE_AND_SET_NULL(canonicalPath);
 | 
						|
#endif
 | 
						|
#if (LOSCFG_POSIX_PIPE_API == 1)
 | 
						|
    if (!strncmp(path, PIPE_DEV_PATH, strlen(PIPE_DEV_PATH))) {
 | 
						|
        return PipeOpen(path, flags, PIPE_DEV_FD);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    int ret = VfsOpen(path, flags);
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(open, _open, (const char *path, int flags, ...), int);
 | 
						|
#endif
 | 
						|
 | 
						|
int close(int fd)
 | 
						|
{
 | 
						|
#ifdef LOSCFG_RANDOM_DEV
 | 
						|
    if (fd == RANDOM_DEV_FD) {
 | 
						|
        return LOS_OK;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
#ifdef LOSCFG_NET_LWIP_SACK
 | 
						|
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
 | 
						|
        return closesocket(fd);
 | 
						|
    }
 | 
						|
#endif /* LOSCFG_NET_LWIP_SACK */
 | 
						|
#if (LOSCFG_POSIX_PIPE_API == 1)
 | 
						|
    if (fd >= PIPE_DEV_FD) {
 | 
						|
        return PipeClose(fd);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
    if (fd >= MIN_START_FD && fd < CONFIG_NFILE_DESCRIPTORS) {
 | 
						|
        ret = VfsClose(fd);
 | 
						|
    }
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(close, _close, (int fd), int);
 | 
						|
#endif
 | 
						|
 | 
						|
ssize_t read(int fd, void *buff, size_t bytes)
 | 
						|
{
 | 
						|
#ifdef LOSCFG_RANDOM_DEV
 | 
						|
    if (fd == RANDOM_DEV_FD) {
 | 
						|
        if (nbyte == 0) {
 | 
						|
            return FS_SUCCESS;
 | 
						|
        }
 | 
						|
        if (buf == NULL) {
 | 
						|
            errno = EINVAL;
 | 
						|
            return FS_FAILURE;
 | 
						|
        }
 | 
						|
        if (nbyte > 1024) { /* 1024, max random_size */
 | 
						|
            nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */
 | 
						|
        }
 | 
						|
        struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte};
 | 
						|
        if (hks_generate_random(&key) != 0) {
 | 
						|
            errno = EIO;
 | 
						|
            return FS_FAILURE;
 | 
						|
        }
 | 
						|
        return (ssize_t)nbyte;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
#ifdef LOSCFG_NET_LWIP_SACK
 | 
						|
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
 | 
						|
        return recv(fd, buff, bytes, 0);
 | 
						|
    }
 | 
						|
#endif /* LOSCFG_NET_LWIP_SACK */
 | 
						|
 | 
						|
#if (LOSCFG_POSIX_PIPE_API == 1)
 | 
						|
    if (fd >= PIPE_DEV_FD) {
 | 
						|
        return PipeRead(fd, buff, bytes);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    ssize_t ret = (ssize_t)LOS_NOK;
 | 
						|
    if (fd >= MIN_START_FD && fd < CONFIG_NFILE_DESCRIPTORS) {
 | 
						|
        ret = VfsRead(fd, buff, bytes);
 | 
						|
    }
 | 
						|
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(read, _read, (int fd, void *buff, size_t bytes), ssize_t);
 | 
						|
#endif
 | 
						|
 | 
						|
ssize_t write(int fd, const void *buff, size_t bytes)
 | 
						|
{
 | 
						|
#ifdef LOSCFG_RANDOM_DEV
 | 
						|
    if (fd == RANDOM_DEV_FD) {
 | 
						|
        errno = EBADF; /* "/dev/random" is readonly */
 | 
						|
        return (ssize_t)LOS_NOK;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
#ifdef LOSCFG_NET_LWIP_SACK
 | 
						|
    if (fd >= CONFIG_NFILE_DESCRIPTORS &&
 | 
						|
        fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
 | 
						|
        return send(fd, buff, bytes, 0);
 | 
						|
    }
 | 
						|
#endif /* LOSCFG_NET_LWIP_SACK */
 | 
						|
 | 
						|
#if (LOSCFG_POSIX_PIPE_API == 1)
 | 
						|
    if (fd >= PIPE_DEV_FD) {
 | 
						|
        return PipeWrite(fd, buff, bytes);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    ssize_t ret = (ssize_t)LOS_NOK;
 | 
						|
    if (fd >= MIN_START_FD && fd < CONFIG_NFILE_DESCRIPTORS) {
 | 
						|
        ret = VfsWrite(fd, buff, bytes);
 | 
						|
    }
 | 
						|
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(write, _write, (int fd, const void *buff, size_t bytes), ssize_t);
 | 
						|
#endif
 | 
						|
 | 
						|
off_t lseek(int fd, off_t off, int whence)
 | 
						|
{
 | 
						|
    struct File *file;
 | 
						|
    off_t ret = (off_t)LOS_NOK;
 | 
						|
 | 
						|
    file = VfsAttachFileReady(fd);
 | 
						|
    if (file == NULL) {
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((file->fFops == NULL) || (file->fFops->lseek == NULL)) {
 | 
						|
        ret = file->fOffset;
 | 
						|
    } else {
 | 
						|
        ret = file->fFops->lseek(file, off, whence);
 | 
						|
    }
 | 
						|
 | 
						|
    VfsDetachFile(file);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(lseek, _lseek, (int fd, off_t off, int whence), off_t);
 | 
						|
#endif
 | 
						|
 | 
						|
int stat(const char *path, struct stat *stat)
 | 
						|
{
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
    const char *pathInMp = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    if (VfsPathCheck(path, FALSE) != LOS_OK) {
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (stat == NULL) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mp = VfsMpFind(path, &pathInMp);
 | 
						|
    if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
 | 
						|
        VFS_ERRNO_SET(ENOENT);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mp->mFs->fsFops->stat != NULL) {
 | 
						|
        ret = mp->mFs->fsFops->stat(mp, pathInMp, stat);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(stat, _stat, (const char *path, struct stat *stat), int);
 | 
						|
#endif
 | 
						|
 | 
						|
int statfs(const char *path, struct statfs *buf)
 | 
						|
{
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
    const char *pathInMp = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    if (VfsPathCheck(path, FALSE) != LOS_OK) {
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (buf == NULL) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mp = VfsMpFind(path, &pathInMp);
 | 
						|
    if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
 | 
						|
        VFS_ERRNO_SET(ENOENT);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mp->mFs->fsMops->statfs != NULL) {
 | 
						|
        ret = mp->mFs->fsMops->statfs(pathInMp, buf);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
 | 
						|
int unlink(const char *path)
 | 
						|
{
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
    const char *pathInMp = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    if (VfsPathCheck(path, FALSE) != LOS_OK) {
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mp = VfsMpFind(path, &pathInMp);
 | 
						|
    if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
 | 
						|
        (mp->mFs->fsFops->unlink == NULL)) {
 | 
						|
        VFS_ERRNO_SET(ENOENT);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    ret = mp->mFs->fsFops->unlink(mp, pathInMp);
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(unlink, _unlink, (const char *path), int);
 | 
						|
#endif
 | 
						|
 | 
						|
int rename(const char *oldpath, const char *newpath)
 | 
						|
{
 | 
						|
    struct MountPoint *mpOld = NULL;
 | 
						|
    struct MountPoint *mpNew = NULL;
 | 
						|
    const char *pathInMpOld = NULL;
 | 
						|
    const char *pathInMpNew = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    if (VfsPathCheck(oldpath, FALSE) != LOS_OK) {
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
    if (VfsPathCheck(newpath, FALSE) != LOS_OK) {
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mpOld = VfsMpFind(oldpath, &pathInMpOld);
 | 
						|
 | 
						|
    if (pathInMpOld == NULL) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((mpOld == NULL) || (*pathInMpOld == '\0') ||
 | 
						|
        (mpOld->mFs->fsFops->unlink == NULL)) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mpNew = VfsMpFind(newpath, &pathInMpNew);
 | 
						|
    if ((mpNew == NULL) || (pathInMpNew == NULL) || (*pathInMpNew == '\0') || (mpNew->mFs->fsFops->unlink == NULL)) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mpOld != mpNew) {
 | 
						|
        VFS_ERRNO_SET(EXDEV);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mpOld->mFs->fsFops->rename != NULL) {
 | 
						|
        ret = mpOld->mFs->fsFops->rename(mpOld, pathInMpOld, pathInMpNew);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
 | 
						|
int fsync(int fd)
 | 
						|
{
 | 
						|
    struct File *file;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    file = VfsAttachFileReady(fd);
 | 
						|
    if (file == NULL) {
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (file->fMp->mWriteEnable == FALSE) {
 | 
						|
        VFS_ERRNO_SET(EACCES);
 | 
						|
        VfsDetachFile(file);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((file->fFops != NULL) && (file->fFops->sync != NULL)) {
 | 
						|
        ret = file->fFops->sync(file);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    VfsDetachFile(file);
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
 | 
						|
DIR *opendir(const char *path)
 | 
						|
{
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
    const char *pathInMp = NULL;
 | 
						|
    struct Dir *dir = NULL;
 | 
						|
    UINT32 ret;
 | 
						|
 | 
						|
    if (VfsPathCheck(path, FALSE) != LOS_OK) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    dir = (struct Dir *)LOSCFG_FS_MALLOC_HOOK(sizeof(struct Dir));
 | 
						|
    if (dir == NULL) {
 | 
						|
        VFS_ERRNO_SET(ENOMEM);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        LOSCFG_FS_FREE_HOOK(dir);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (g_dirNum >= LOSCFG_MAX_OPEN_DIRS) {
 | 
						|
        VFS_ERRNO_SET(ENFILE);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        LOSCFG_FS_FREE_HOOK(dir);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    mp = VfsMpFind(path, &pathInMp);
 | 
						|
    if ((mp == NULL) || (pathInMp == NULL)) {
 | 
						|
        VFS_ERRNO_SET(ENOENT);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        LOSCFG_FS_FREE_HOOK(dir);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mp->mFs->fsFops->opendir == NULL) {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        LOSCFG_FS_FREE_HOOK(dir);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    dir->dMp = mp;
 | 
						|
    dir->dOffset = 0;
 | 
						|
 | 
						|
    ret = (UINT32)mp->mFs->fsFops->opendir(dir, pathInMp);
 | 
						|
    if (ret == 0) {
 | 
						|
        mp->mRefs++;
 | 
						|
        g_dirNum++;
 | 
						|
    } else {
 | 
						|
        LOSCFG_FS_FREE_HOOK(dir);
 | 
						|
        dir = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return (DIR *)dir;
 | 
						|
}
 | 
						|
 | 
						|
struct dirent *readdir(DIR *dir)
 | 
						|
{
 | 
						|
    struct dirent *ret = NULL;
 | 
						|
    struct Dir *d = (struct Dir *)dir;
 | 
						|
 | 
						|
    if ((dir == NULL) || (d->dMp == NULL)) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((d->dMp->mFs != NULL) && (d->dMp->mFs->fsFops != NULL) &&
 | 
						|
        (d->dMp->mFs->fsFops->readdir != NULL)) {
 | 
						|
        if (d->dMp->mFs->fsFops->readdir(d, &d->dDent) == 0) {
 | 
						|
            ret = &d->dDent;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int closedir(DIR *dir)
 | 
						|
{
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
    struct Dir *d = (struct Dir *)dir;
 | 
						|
 | 
						|
    if ((d == NULL) || (d->dMp == NULL)) {
 | 
						|
        VFS_ERRNO_SET(EBADF);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mp = d->dMp;
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if ((d->dMp->mFs != NULL) && (d->dMp->mFs->fsFops != NULL) &&
 | 
						|
        (d->dMp->mFs->fsFops->closedir != NULL)) {
 | 
						|
        ret = d->dMp->mFs->fsFops->closedir(d);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    if (ret == 0) {
 | 
						|
        mp->mRefs--;
 | 
						|
        g_dirNum--;
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(EBADF);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    LOSCFG_FS_FREE_HOOK(d);
 | 
						|
    d = NULL;
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
 | 
						|
int mkdir(const char *path, mode_t mode)
 | 
						|
{
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
    const char *pathInMp = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
    (void)mode;
 | 
						|
 | 
						|
    if (VfsPathCheck(path, FALSE) != LOS_OK) {
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mp = VfsMpFind(path, &pathInMp);
 | 
						|
    if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
 | 
						|
        VFS_ERRNO_SET(ENOENT);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (mp->mFs->fsFops->mkdir != NULL) {
 | 
						|
        ret = mp->mFs->fsFops->mkdir(mp, pathInMp);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
 | 
						|
int rmdir(const char *path)
 | 
						|
{
 | 
						|
    struct MountPoint *mp = NULL;
 | 
						|
    const char *pathInMp = NULL;
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
 | 
						|
    if (path == NULL) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    mp = VfsMpFind(path, &pathInMp);
 | 
						|
    if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
 | 
						|
        (mp->mFs->fsFops->rmdir == NULL)) {
 | 
						|
        VFS_ERRNO_SET(ENOENT);
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet(ret);
 | 
						|
    }
 | 
						|
 | 
						|
    ret = mp->mFs->fsFops->rmdir(mp, pathInMp);
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
    return MapToPosixRet(ret);
 | 
						|
}
 | 
						|
 | 
						|
int lstat(const char *path, struct stat *buffer)
 | 
						|
{
 | 
						|
    return stat(path, buffer);
 | 
						|
}
 | 
						|
 | 
						|
int fstat(int fd, struct stat *buf)
 | 
						|
{
 | 
						|
    struct File *filep;
 | 
						|
    int ret;
 | 
						|
    filep = VfsAttachFileReady(fd);
 | 
						|
    if ((filep == NULL) || (filep->fMp == NULL) || filep->fullPath == NULL) {
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
    ret = stat(filep->fullPath, buf);
 | 
						|
    VfsDetachFile(filep);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
#if (LOSCFG_LIBC_NEWLIB == 1)
 | 
						|
FUNC_ALIAS(fstat, _fstat, (int fd, struct stat *buf), int);
 | 
						|
#endif
 | 
						|
 | 
						|
int fcntl(int fd, int cmd, ...)
 | 
						|
{
 | 
						|
    struct File *filep = NULL;
 | 
						|
    int ret;
 | 
						|
    va_list ap;
 | 
						|
 | 
						|
    va_start(ap, cmd);
 | 
						|
    if (fd < CONFIG_NFILE_DESCRIPTORS) {
 | 
						|
        filep = VfsAttachFileReady(fd);
 | 
						|
        ret = VfsVfcntl(filep, cmd, ap);
 | 
						|
        VfsDetachFile(filep);
 | 
						|
    } else {
 | 
						|
#ifndef LOSCFG_NET_LWIP_SACK
 | 
						|
        ret = -EBADF;
 | 
						|
#else
 | 
						|
        int arg = va_arg(ap, int);
 | 
						|
        ret = lwip_fcntl(fd, (long)cmd, arg);
 | 
						|
        va_end(ap);
 | 
						|
        return ret;
 | 
						|
#endif /* LOSCFG_NET_LWIP_SACK */
 | 
						|
    }
 | 
						|
 | 
						|
    if (ret < 0) {
 | 
						|
        VFS_ERRNO_SET(-ret);
 | 
						|
        ret = (int)LOS_NOK;
 | 
						|
    }
 | 
						|
    va_end(ap);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int ioctl(int fd, int req, ...)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    va_list ap;
 | 
						|
 | 
						|
    va_start(ap, req);
 | 
						|
    if (fd < CONFIG_NFILE_DESCRIPTORS) {
 | 
						|
        ret = VfsIoctl(fd, req, ap);
 | 
						|
    } else {
 | 
						|
#ifndef LOSCFG_NET_LWIP_SACK
 | 
						|
        ret = -EBADF;
 | 
						|
#else
 | 
						|
        UINTPTR arg = va_arg(ap, UINTPTR);
 | 
						|
        ret = lwip_ioctl(fd, (long)req, (void *)arg);
 | 
						|
#endif /* LOSCFG_NET_LWIP_SACK */
 | 
						|
    }
 | 
						|
 | 
						|
    va_end(ap);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
ssize_t readv(int fd, const struct iovec *iovBuf, int iovcnt)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    errno_t ret;
 | 
						|
    char *buf = NULL;
 | 
						|
    char *curBuf = NULL;
 | 
						|
    char *readBuf = NULL;
 | 
						|
    size_t bufLen = 0;
 | 
						|
    size_t bytesToRead;
 | 
						|
    ssize_t totalBytesRead;
 | 
						|
    size_t totalLen;
 | 
						|
    const struct iovec *iov = (const struct iovec *)iovBuf;
 | 
						|
 | 
						|
    if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) {
 | 
						|
        return (ssize_t)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; i < iovcnt; ++i) {
 | 
						|
        if ((SSIZE_MAX - bufLen) < iov[i].iov_len) {
 | 
						|
            return (ssize_t)LOS_NOK;
 | 
						|
        }
 | 
						|
        bufLen += iov[i].iov_len;
 | 
						|
    }
 | 
						|
    if (bufLen == 0) {
 | 
						|
        return (ssize_t)LOS_NOK;
 | 
						|
    }
 | 
						|
    totalLen = bufLen * sizeof(char);
 | 
						|
    buf = (char *)LOSCFG_FS_MALLOC_HOOK(totalLen);
 | 
						|
    if (buf == NULL) {
 | 
						|
        return (ssize_t)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    totalBytesRead = read(fd, buf, bufLen);
 | 
						|
    if ((size_t)totalBytesRead < totalLen) {
 | 
						|
        totalLen = (size_t)totalBytesRead;
 | 
						|
    }
 | 
						|
    curBuf = buf;
 | 
						|
    for (i = 0; i < iovcnt; ++i) {
 | 
						|
        readBuf = (char *)iov[i].iov_base;
 | 
						|
        bytesToRead = iov[i].iov_len;
 | 
						|
 | 
						|
        size_t lenToRead = totalLen < bytesToRead ? totalLen : bytesToRead;
 | 
						|
        ret = memcpy_s(readBuf, bytesToRead, curBuf, lenToRead);
 | 
						|
        if (ret != EOK) {
 | 
						|
            LOSCFG_FS_FREE_HOOK(buf);
 | 
						|
            return (ssize_t)LOS_NOK;
 | 
						|
        }
 | 
						|
        if (totalLen < (size_t)bytesToRead) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        curBuf += bytesToRead;
 | 
						|
        totalLen -= bytesToRead;
 | 
						|
    }
 | 
						|
    LOSCFG_FS_FREE_HOOK(buf);
 | 
						|
    return totalBytesRead;
 | 
						|
}
 | 
						|
 | 
						|
ssize_t writev(int fd, const struct iovec *iovBuf, int iovcnt)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    errno_t ret;
 | 
						|
    char *buf = NULL;
 | 
						|
    char *curBuf = NULL;
 | 
						|
    char *writeBuf = NULL;
 | 
						|
    size_t bufLen = 0;
 | 
						|
    size_t bytesToWrite;
 | 
						|
    ssize_t totalBytesWritten;
 | 
						|
    size_t totalLen;
 | 
						|
    const struct iovec *iov = iovBuf;
 | 
						|
 | 
						|
    if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) {
 | 
						|
        return (ssize_t)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; i < iovcnt; ++i) {
 | 
						|
        if ((SSIZE_MAX - bufLen) < iov[i].iov_len) {
 | 
						|
            VFS_ERRNO_SET(EINVAL);
 | 
						|
            return (ssize_t)LOS_NOK;
 | 
						|
        }
 | 
						|
        bufLen += iov[i].iov_len;
 | 
						|
    }
 | 
						|
    if (bufLen == 0) {
 | 
						|
        return (ssize_t)LOS_NOK;
 | 
						|
    }
 | 
						|
    totalLen = bufLen * sizeof(char);
 | 
						|
    buf = (char *)LOSCFG_FS_MALLOC_HOOK(totalLen);
 | 
						|
    if (buf == NULL) {
 | 
						|
        return (ssize_t)LOS_NOK;
 | 
						|
    }
 | 
						|
    curBuf = buf;
 | 
						|
    for (i = 0; i < iovcnt; ++i) {
 | 
						|
        writeBuf = (char *)iov[i].iov_base;
 | 
						|
        bytesToWrite = iov[i].iov_len;
 | 
						|
        if (((ssize_t)totalLen <= 0) || ((ssize_t)bytesToWrite <= 0)) {
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        ret = memcpy_s(curBuf, totalLen, writeBuf, bytesToWrite);
 | 
						|
        if (ret != EOK) {
 | 
						|
            LOSCFG_FS_FREE_HOOK(buf);
 | 
						|
            return (ssize_t)LOS_NOK;
 | 
						|
        }
 | 
						|
        curBuf += bytesToWrite;
 | 
						|
        totalLen -= bytesToWrite;
 | 
						|
    }
 | 
						|
 | 
						|
    totalBytesWritten = write(fd, buf, bufLen);
 | 
						|
    LOSCFG_FS_FREE_HOOK(buf);
 | 
						|
 | 
						|
    return totalBytesWritten;
 | 
						|
}
 | 
						|
 | 
						|
int remove(const char *filename)
 | 
						|
{
 | 
						|
    int ret = unlink(filename);
 | 
						|
    if (ret == -EISDIR) {
 | 
						|
        ret = rmdir(filename);
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int access(const char *path, int amode)
 | 
						|
{
 | 
						|
    int result;
 | 
						|
    mode_t mode;
 | 
						|
    struct stat buf;
 | 
						|
 | 
						|
    result = stat(path, &buf);
 | 
						|
    if (result != 0) {
 | 
						|
        return (int)LOS_NOK;
 | 
						|
    }
 | 
						|
 | 
						|
    mode = buf.st_mode;
 | 
						|
    if ((unsigned int)amode & R_OK) {
 | 
						|
        if ((mode & (S_IROTH | S_IRGRP | S_IRUSR)) == 0) {
 | 
						|
            VFS_ERRNO_SET(EACCES);
 | 
						|
            return (int)LOS_NOK;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ((unsigned int)amode & W_OK) {
 | 
						|
        if ((mode & (S_IWOTH | S_IWGRP | S_IWUSR)) == 0) {
 | 
						|
            VFS_ERRNO_SET(EACCES);
 | 
						|
            return (int)LOS_NOK;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    if ((unsigned int)amode & X_OK) {
 | 
						|
        if ((mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) {
 | 
						|
            VFS_ERRNO_SET(EACCES);
 | 
						|
            return (int)LOS_NOK;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int ftruncate(int fd, off_t length)
 | 
						|
{
 | 
						|
    int ret = (int)LOS_NOK;
 | 
						|
    struct File *file = NULL;
 | 
						|
 | 
						|
    if (length <= 0) {
 | 
						|
        VFS_ERRNO_SET(EINVAL);
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    file = VfsAttachFileReady(fd);
 | 
						|
    if (file == NULL) {
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if (file->fMp->mWriteEnable == FALSE) {
 | 
						|
        VFS_ERRNO_SET(EACCES);
 | 
						|
        VfsDetachFile(file);
 | 
						|
        return ret;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((file->fFlags & O_ACCMODE) == O_RDONLY) {
 | 
						|
        VFS_ERRNO_SET(EACCES);
 | 
						|
    } else if ((file->fFops != NULL) && (file->fFops->truncate != NULL)) {
 | 
						|
        ret = file->fFops->truncate(file, length);
 | 
						|
    } else {
 | 
						|
        VFS_ERRNO_SET(ENOTSUP);
 | 
						|
    }
 | 
						|
 | 
						|
    /* else ret will be -1 */
 | 
						|
    VfsDetachFile(file);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
ssize_t pread(int fd, void *buff, size_t bytes, off_t off)
 | 
						|
{
 | 
						|
    ssize_t ret = (ssize_t)LOS_NOK;
 | 
						|
    off_t savepos, pos;
 | 
						|
 | 
						|
    if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS) {
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (buff == NULL) {
 | 
						|
        VFS_ERRNO_SET(EFAULT);
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (bytes == 0) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    savepos = lseek(fd, 0, SEEK_CUR);
 | 
						|
    if (savepos == (off_t)-1) {
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    pos = lseek(fd, off, SEEK_SET);
 | 
						|
    if (pos == (off_t)-1) {
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    ret = read(fd, buff, bytes);
 | 
						|
    pos = lseek(fd, savepos, SEEK_SET);
 | 
						|
    if ((pos == (off_t)-1) && (ret >= 0)) {
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet((int)LOS_NOK);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
 | 
						|
    return MapToPosixRet((int)ret);
 | 
						|
}
 | 
						|
 | 
						|
ssize_t pwrite(int fd, const void *buff, size_t bytes, off_t off)
 | 
						|
{
 | 
						|
    ssize_t ret = (ssize_t)LOS_NOK;
 | 
						|
    off_t savepos, pos;
 | 
						|
 | 
						|
    if ((fd < 0) || (fd >= CONFIG_NFILE_DESCRIPTORS)) {
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (buff == NULL) {
 | 
						|
        VFS_ERRNO_SET(EFAULT);
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    if (bytes == 0) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LOS_FsLock() != LOS_OK) {
 | 
						|
        VFS_ERRNO_SET(EAGAIN);
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    savepos = lseek(fd, 0, SEEK_CUR);
 | 
						|
    if (savepos == (off_t)-1) {
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    pos = lseek(fd, off, SEEK_SET);
 | 
						|
    if (pos == (off_t)-1) {
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet((int)ret);
 | 
						|
    }
 | 
						|
 | 
						|
    ret = write(fd, buff, bytes);
 | 
						|
    pos = lseek(fd, savepos, SEEK_SET);
 | 
						|
    if ((pos == (off_t)-1) && (ret >= 0)) {
 | 
						|
        LOS_FsUnlock();
 | 
						|
        return MapToPosixRet((int)LOS_NOK);
 | 
						|
    }
 | 
						|
 | 
						|
    LOS_FsUnlock();
 | 
						|
 | 
						|
    return MapToPosixRet((int)ret);
 | 
						|
}
 |