fs.c 9.2 KB
Newer Older
L
likailong 已提交
1
/*
M
mamingshuai 已提交
2 3
 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
L
likailong 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * 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.
 */

M
mamingshuai 已提交
32 33 34 35 36 37 38 39 40 41 42 43
#include "fatfs.h"
#include "dirent.h"
#include "errno.h"
#include "fcntl.h"
#include "securec.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/mount.h"
#include "sys/statfs.h"
#include "sys/stat.h"
#include "unistd.h"
L
likailong 已提交
44

45 46
#ifdef LOSCFG_NET_LWIP_SACK
#include "lwip/lwipopts.h"
Y
YOUR_NAME 已提交
47
#include "lwip/sockets.h"
48 49 50 51 52
#define CONFIG_NSOCKET_DESCRIPTORS  LWIP_CONFIG_NUM_SOCKETS
#else
#define CONFIG_NSOCKET_DESCRIPTORS  0
#endif

M
mamingshuai 已提交
53 54 55 56 57
#define CONFIG_NFILE_DESCRIPTORS    FAT_MAX_OPEN_FILES /* only for random currently */

#ifdef LOSCFG_RANDOM_DEV
#include "hks_client.h"
#define RANDOM_DEV_FD  CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS
L
likailong 已提交
58
#define RANDOM_DEV_PATH  "/dev/random"
M
mamingshuai 已提交
59
#endif
L
likailong 已提交
60

61 62 63 64 65
#define FREE_AND_SET_NULL(ptr) do { \
    free(ptr);                      \
    ptr = NULL;                     \
} while (0)

M
mamingshuai 已提交
66
#ifdef LOSCFG_RANDOM_DEV
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
/**
 * @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)
{
M
mamingshuai 已提交
82
    size_t offset;
83 84 85 86 87 88 89 90
    if (!path) {
        path = "";
    }

    if (!cwd || path[0] == '/') {
        cwd = "";
    }

M
mamingshuai 已提交
91 92
    offset = strlen("///") + 1; // three '/' and one '\0'
    size_t tmpLen = strlen(cwd) + strlen(path) + offset;
93 94 95 96 97 98 99 100 101 102 103 104
    char *tmpBuf = (char *)malloc(tmpLen);
    if (tmpBuf == NULL) {
        return 0;
    }

    if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
        free(tmpBuf);
        return 0;
    }

    char *p;
    /* replace /./ to / */
M
mamingshuai 已提交
105
    offset = strlen("/./") - 1;
106
    while ((p = strstr(tmpBuf, "/./")) != NULL) {
M
mamingshuai 已提交
107
        if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
108 109 110 111 112 113 114 115 116 117 118 119 120 121
            free(tmpBuf);
            return 0;
        }
    }

    /* replace // to / */
    while ((p = strstr(tmpBuf, "//")) != NULL) {
        if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
            free(tmpBuf);
            return 0;
        }
    }

    /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */
M
mamingshuai 已提交
122
    offset = strlen("/../") - 1;
123 124
    while ((p = strstr(tmpBuf, "/../")) != NULL) {
        char *start = p;
M
mamingshuai 已提交
125 126
        while (start > tmpBuf && *(start - 1) != '/') {
            --start;
127
        }
M
mamingshuai 已提交
128
        if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
            free(tmpBuf);
            return 0;
        }
    }

    size_t totalLen = strlen(tmpBuf);
    /* strip the last / */
    if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') {
        tmpBuf[--totalLen] = 0;
    }

    if (!buf || bufSize == 0) {
        free(tmpBuf);
        return totalLen;
    }

M
mamingshuai 已提交
145
    if (EOK != memcpy_s(buf, bufSize, tmpBuf, (((totalLen + 1) > bufSize) ? bufSize : (totalLen + 1)))) {
146 147 148 149 150 151 152 153
        free(tmpBuf);
        return 0;
    }

    buf[bufSize - 1] = 0;
    free(tmpBuf);
    return totalLen;
}
M
mamingshuai 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
#endif

int mount(const char *source, const char *target,
          const char *filesystemtype, unsigned long mountflags,
          const void *data)
{
    return fatfs_mount(source, target, filesystemtype, mountflags, data);
}

int umount(const char *target)
{
    return fatfs_umount(target);
}

int umount2(const char *target, int flag)
{
    return fatfs_umount2(target, flag);
}
172

M
mamingshuai 已提交
173
int open(const char *path, int oflag, ...)
L
likailong 已提交
174
{
M
mamingshuai 已提交
175
#ifdef LOSCFG_RANDOM_DEV
176 177 178 179 180
    unsigned flags = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY;
    if ((unsigned)oflag & ~flags) {
        errno = EINVAL;
        return -1;
    }
M
mamingshuai 已提交
181 182

    size_t pathLen = strlen(path) + 1;
183 184 185 186 187
    char *canonicalPath = (char *)malloc(pathLen);
    if (!canonicalPath) {
        errno = ENOMEM;
        return -1;
    }
M
mamingshuai 已提交
188
    if (GetCanonicalPath(NULL, path, canonicalPath, pathLen) == 0) {
189 190 191 192
        FREE_AND_SET_NULL(canonicalPath);
        errno = ENOMEM;
        return -1;
    }
M
mamingshuai 已提交
193

194 195 196 197 198 199 200 201
    if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
        FREE_AND_SET_NULL(canonicalPath);
        if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) {
            errno = EPERM;
            return -1;
        }
        if ((unsigned)oflag & O_DIRECTORY) {
            errno = ENOTDIR;
L
likailong 已提交
202 203 204 205
            return -1;
        }
        return RANDOM_DEV_FD;
    }
206 207 208 209 210 211 212 213 214 215
    if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) {
        FREE_AND_SET_NULL(canonicalPath);
        if ((unsigned)oflag & O_DIRECTORY) {
            errno = EPERM;
            return -1;
        }
        errno = EISDIR;
        return -1;
    }
    FREE_AND_SET_NULL(canonicalPath);
M
mamingshuai 已提交
216 217
#endif
    return fatfs_open(path, oflag);
L
likailong 已提交
218 219 220 221
}

int close(int fd)
{
M
mamingshuai 已提交
222
#ifdef LOSCFG_RANDOM_DEV
L
likailong 已提交
223 224 225
    if (fd == RANDOM_DEV_FD) {
        return 0;
    }
M
mamingshuai 已提交
226
#endif
227 228 229 230 231
#ifdef LOSCFG_NET_LWIP_SACK
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
        return closesocket(fd);
    }
#endif
M
mamingshuai 已提交
232
    return fatfs_close(fd);
L
likailong 已提交
233 234
}

M
mamingshuai 已提交
235
ssize_t read(int fd, void *buf, size_t nbyte)
L
likailong 已提交
236
{
M
mamingshuai 已提交
237
#ifdef LOSCFG_RANDOM_DEV
L
likailong 已提交
238
    if (fd == RANDOM_DEV_FD) {
M
mamingshuai 已提交
239
        if (nbyte == 0) {
L
likailong 已提交
240 241 242 243 244 245
            return 0;
        }
        if (buf == NULL) {
            errno = EINVAL;
            return -1;
        }
M
mamingshuai 已提交
246 247
        if (nbyte > 1024) {
            nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */
L
likailong 已提交
248
        }
M
mamingshuai 已提交
249
        struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte};
L
likailong 已提交
250 251 252 253
        if (hks_generate_random(&key) != 0) {
            errno = EIO;
            return -1;
        }
M
mamingshuai 已提交
254
        return (ssize_t)nbyte;
L
likailong 已提交
255
    }
M
mamingshuai 已提交
256
#endif
257 258
#ifdef LOSCFG_NET_LWIP_SACK
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
M
mamingshuai 已提交
259
        return recv(fd, buf, nbyte, 0);
260 261
    }
#endif
M
mamingshuai 已提交
262
    return fatfs_read(fd, buf, nbyte);
L
likailong 已提交
263 264
}

M
mamingshuai 已提交
265
ssize_t write(int fd, const void *buf, size_t nbyte)
L
likailong 已提交
266
{
M
mamingshuai 已提交
267
#ifdef LOSCFG_RANDOM_DEV
L
likailong 已提交
268 269 270 271
    if (fd == RANDOM_DEV_FD) {
        errno = EBADF; /* "/dev/random" is readonly */
        return -1;
    }
M
mamingshuai 已提交
272
#endif
273 274
#ifdef LOSCFG_NET_LWIP_SACK
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
M
mamingshuai 已提交
275
        return send(fd, buf, nbyte, 0);
276 277
    }
#endif
M
mamingshuai 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
    return fatfs_write(fd, buf, nbyte);
}

off_t lseek(int fd, off_t offset, int whence)
{
    return fatfs_lseek(fd, offset, whence);
}

int unlink(const char *path)
{
    return fatfs_unlink(path);
}

int fstat(int fd, struct stat *buf)
{
    return fatfs_fstat(fd, buf);
}

int stat(const char *path, struct stat *buf)
{
    return fatfs_stat(path, buf);
}

int fsync(int fd)
{
    return fatfs_fsync(fd);
}

int mkdir(const char *path, mode_t mode)
{
    return fatfs_mkdir(path, mode);
}

DIR *opendir(const char *dirName)
{
    return fatfs_opendir(dirName);
}

struct dirent *readdir(DIR *dir)
{
    return fatfs_readdir(dir);
}

int closedir(DIR *dir)
{
    return fatfs_closedir(dir);
}

int rmdir(const char *path)
{
    return fatfs_rmdir(path);
}

int rename(const char *oldName, const char *newName)
{
    return fatfs_rename(oldName, newName);
}

int statfs(const char *path, struct statfs *buf)
{
    return fatfs_statfs(path, buf);
}

int ftruncate(int fd, off_t length)
{
    return fatfs_ftruncate(fd, length);
L
likailong 已提交
344
}