fs.c 14.4 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
 *
 * 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.
 */
C
chenjing 已提交
31
#include "fs_operations.h"
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

C
chenjing 已提交
45 46 47
struct FsMap g_fsmap[MAX_FILESYSTEM_LEN] = {0};
struct FsMap *g_fs = NULL;

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

M
mamingshuai 已提交
56 57 58 59 60
#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 已提交
61
#define RANDOM_DEV_PATH  "/dev/random"
M
mamingshuai 已提交
62
#endif
L
likailong 已提交
63

64 65 66 67 68
#define FREE_AND_SET_NULL(ptr) do { \
    free(ptr);                      \
    ptr = NULL;                     \
} while (0)

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

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

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

    if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
        free(tmpBuf);
C
chenjing 已提交
103
        return FS_SUCCESS;
104 105 106 107
    }

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

    /* replace // to / */
    while ((p = strstr(tmpBuf, "//")) != NULL) {
        if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
            free(tmpBuf);
C
chenjing 已提交
120
            return FS_SUCCESS;
121 122 123 124
        }
    }

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

    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 已提交
148
    if (EOK != memcpy_s(buf, bufSize, tmpBuf, (((totalLen + 1) > bufSize) ? bufSize : (totalLen + 1)))) {
149
        free(tmpBuf);
C
chenjing 已提交
150
        return FS_SUCCESS;
151 152 153 154 155 156
    }

    buf[bufSize - 1] = 0;
    free(tmpBuf);
    return totalLen;
}
M
mamingshuai 已提交
157 158
#endif

C
chenjing 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
static void InitMountInfo(void)
{
    extern struct MountOps g_fatfsMnt;
    extern struct FileOps g_fatfsFops;
    g_fsmap[0].fileSystemtype = strdup("fat");
    g_fsmap[0].fsMops = &g_fatfsMnt;
    g_fsmap[0].fsFops = &g_fatfsFops;
    extern struct MountOps g_lfsMnt;
    extern struct FileOps g_lfsFops;
    g_fsmap[1].fileSystemtype = strdup("littlefs");
    g_fsmap[1].fsMops = &g_lfsMnt;
    g_fsmap[1].fsFops = &g_lfsFops;
}

static struct FsMap *MountFindfs(const char *fileSystemtype)
{
    struct FsMap *m = NULL;

    for (int i = 0; i < MAX_FILESYSTEM_LEN; i++) {
        m = &(g_fsmap[i]);
        if (m->fileSystemtype && strcmp(fileSystemtype, m->fileSystemtype) == 0) {
            return m;
        }
    }

    return NULL;
}

M
mamingshuai 已提交
187 188 189 190
int mount(const char *source, const char *target,
          const char *filesystemtype, unsigned long mountflags,
          const void *data)
{
C
chenjing 已提交
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    static int initFlag = 0;

    if (initFlag == 0) {
        InitMountInfo();
        initFlag = 1;
    }

    g_fs = MountFindfs(filesystemtype);
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }

    if (g_fs->fsMops == NULL || g_fs->fsMops->Mount == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }

    return g_fs->fsMops->Mount(source, target, filesystemtype, mountflags, data);
M
mamingshuai 已提交
210 211 212 213
}

int umount(const char *target)
{
C
chenjing 已提交
214 215 216 217 218 219 220 221 222
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsMops == NULL || g_fs->fsMops->Umount == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsMops->Umount(target);
M
mamingshuai 已提交
223 224 225 226
}

int umount2(const char *target, int flag)
{
C
chenjing 已提交
227 228 229 230 231 232 233 234 235
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsMops == NULL || g_fs->fsMops->Umount2 == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsMops->Umount2(target, flag);
M
mamingshuai 已提交
236
}
237

M
mamingshuai 已提交
238
int open(const char *path, int oflag, ...)
L
likailong 已提交
239
{
M
mamingshuai 已提交
240
#ifdef LOSCFG_RANDOM_DEV
241 242 243
    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;
C
chenjing 已提交
244
        return FS_FAILURE;
245
    }
M
mamingshuai 已提交
246 247

    size_t pathLen = strlen(path) + 1;
248 249 250
    char *canonicalPath = (char *)malloc(pathLen);
    if (!canonicalPath) {
        errno = ENOMEM;
C
chenjing 已提交
251
        return FS_FAILURE;
252
    }
M
mamingshuai 已提交
253
    if (GetCanonicalPath(NULL, path, canonicalPath, pathLen) == 0) {
254 255
        FREE_AND_SET_NULL(canonicalPath);
        errno = ENOMEM;
C
chenjing 已提交
256
        return FS_FAILURE;
257
    }
M
mamingshuai 已提交
258

259 260 261 262
    if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
        FREE_AND_SET_NULL(canonicalPath);
        if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) {
            errno = EPERM;
C
chenjing 已提交
263
            return FS_FAILURE;
264 265 266
        }
        if ((unsigned)oflag & O_DIRECTORY) {
            errno = ENOTDIR;
C
chenjing 已提交
267
            return FS_FAILURE;
L
likailong 已提交
268 269 270
        }
        return RANDOM_DEV_FD;
    }
271 272 273 274
    if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) {
        FREE_AND_SET_NULL(canonicalPath);
        if ((unsigned)oflag & O_DIRECTORY) {
            errno = EPERM;
C
chenjing 已提交
275
            return FS_FAILURE;
276 277
        }
        errno = EISDIR;
C
chenjing 已提交
278
        return FS_FAILURE;
279 280
    }
    FREE_AND_SET_NULL(canonicalPath);
M
mamingshuai 已提交
281
#endif
C
chenjing 已提交
282 283 284 285 286 287 288 289 290
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Open == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Open(path, oflag);
L
likailong 已提交
291 292 293 294
}

int close(int fd)
{
M
mamingshuai 已提交
295
#ifdef LOSCFG_RANDOM_DEV
L
likailong 已提交
296
    if (fd == RANDOM_DEV_FD) {
C
chenjing 已提交
297
        return FS_SUCCESS;
L
likailong 已提交
298
    }
M
mamingshuai 已提交
299
#endif
300 301 302 303 304
#ifdef LOSCFG_NET_LWIP_SACK
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
        return closesocket(fd);
    }
#endif
C
chenjing 已提交
305 306 307 308 309 310 311 312 313
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Close == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Close(fd);
L
likailong 已提交
314 315
}

M
mamingshuai 已提交
316
ssize_t read(int fd, void *buf, size_t nbyte)
L
likailong 已提交
317
{
M
mamingshuai 已提交
318
#ifdef LOSCFG_RANDOM_DEV
L
likailong 已提交
319
    if (fd == RANDOM_DEV_FD) {
M
mamingshuai 已提交
320
        if (nbyte == 0) {
C
chenjing 已提交
321
            return FS_SUCCESS;
L
likailong 已提交
322 323 324
        }
        if (buf == NULL) {
            errno = EINVAL;
C
chenjing 已提交
325
            return FS_FAILURE;
L
likailong 已提交
326
        }
M
mamingshuai 已提交
327 328
        if (nbyte > 1024) {
            nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */
L
likailong 已提交
329
        }
M
mamingshuai 已提交
330
        struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte};
L
likailong 已提交
331 332
        if (hks_generate_random(&key) != 0) {
            errno = EIO;
C
chenjing 已提交
333
            return FS_FAILURE;
L
likailong 已提交
334
        }
M
mamingshuai 已提交
335
        return (ssize_t)nbyte;
L
likailong 已提交
336
    }
M
mamingshuai 已提交
337
#endif
338 339
#ifdef LOSCFG_NET_LWIP_SACK
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
M
mamingshuai 已提交
340
        return recv(fd, buf, nbyte, 0);
341 342
    }
#endif
C
chenjing 已提交
343 344 345 346 347 348 349 350 351
    if (g_fs->fsFops == NULL || g_fs->fsFops->Read == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Read(fd, buf, nbyte);
L
likailong 已提交
352 353
}

M
mamingshuai 已提交
354
ssize_t write(int fd, const void *buf, size_t nbyte)
L
likailong 已提交
355
{
M
mamingshuai 已提交
356
#ifdef LOSCFG_RANDOM_DEV
L
likailong 已提交
357 358
    if (fd == RANDOM_DEV_FD) {
        errno = EBADF; /* "/dev/random" is readonly */
C
chenjing 已提交
359
        return FS_FAILURE;
L
likailong 已提交
360
    }
M
mamingshuai 已提交
361
#endif
362 363
#ifdef LOSCFG_NET_LWIP_SACK
    if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
M
mamingshuai 已提交
364
        return send(fd, buf, nbyte, 0);
365 366
    }
#endif
C
chenjing 已提交
367 368 369 370 371 372 373 374 375
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Write == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Write(fd, buf, nbyte);
M
mamingshuai 已提交
376 377 378 379
}

off_t lseek(int fd, off_t offset, int whence)
{
C
chenjing 已提交
380 381 382 383 384 385 386 387 388
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Seek == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Seek(fd, offset, whence);
M
mamingshuai 已提交
389 390 391 392
}

int unlink(const char *path)
{
C
chenjing 已提交
393 394 395 396 397 398 399 400 401
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Unlink == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Unlink(path);
M
mamingshuai 已提交
402 403 404 405
}

int fstat(int fd, struct stat *buf)
{
C
chenjing 已提交
406 407 408 409 410 411 412 413 414
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Fstat == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Fstat(fd, buf);
M
mamingshuai 已提交
415 416 417 418
}

int stat(const char *path, struct stat *buf)
{
C
chenjing 已提交
419 420 421 422 423 424 425 426 427
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Stat == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Stat(path, buf);
M
mamingshuai 已提交
428 429 430 431
}

int fsync(int fd)
{
C
chenjing 已提交
432 433 434 435 436 437 438 439 440
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Fsync == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Fsync(fd);
M
mamingshuai 已提交
441 442 443 444
}

int mkdir(const char *path, mode_t mode)
{
C
chenjing 已提交
445 446 447 448 449 450 451 452 453
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Mkdir == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Mkdir(path, mode);
M
mamingshuai 已提交
454 455 456 457
}

DIR *opendir(const char *dirName)
{
C
chenjing 已提交
458 459 460 461 462 463 464 465 466
    if (g_fs == NULL) {
        errno = ENODEV;
        return NULL;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Opendir == NULL) {
        errno = ENOSYS;
        return NULL;
    }
    return g_fs->fsFops->Opendir(dirName);
M
mamingshuai 已提交
467 468 469 470
}

struct dirent *readdir(DIR *dir)
{
C
chenjing 已提交
471 472 473 474 475 476 477 478 479
    if (g_fs == NULL) {
        errno = ENODEV;
        return NULL;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Readdir == NULL) {
        errno = ENOSYS;
        return NULL;
    }
    return g_fs->fsFops->Readdir(dir);
M
mamingshuai 已提交
480 481 482 483
}

int closedir(DIR *dir)
{
C
chenjing 已提交
484 485 486 487 488 489 490 491 492
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Closedir == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Closedir(dir);
M
mamingshuai 已提交
493 494 495 496
}

int rmdir(const char *path)
{
C
chenjing 已提交
497 498 499 500 501 502 503 504 505
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Rmdir == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Rmdir(path);
M
mamingshuai 已提交
506 507 508 509
}

int rename(const char *oldName, const char *newName)
{
C
chenjing 已提交
510 511 512 513 514 515 516 517 518
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Rename == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Rename(oldName, newName);
M
mamingshuai 已提交
519 520 521 522
}

int statfs(const char *path, struct statfs *buf)
{
C
chenjing 已提交
523 524 525 526 527 528 529 530 531
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsMops == NULL || g_fs->fsMops->Statfs == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsMops->Statfs(path, buf);
M
mamingshuai 已提交
532 533 534 535
}

int ftruncate(int fd, off_t length)
{
C
chenjing 已提交
536 537 538 539 540 541 542 543 544
    if (g_fs == NULL) {
        errno = ENODEV;
        return FS_FAILURE;
    }
    if (g_fs->fsFops == NULL || g_fs->fsFops->Ftruncate == NULL) {
        errno = ENOSYS;
        return FS_FAILURE;
    }
    return g_fs->fsFops->Ftruncate(fd, length);
L
likailong 已提交
545
}