11bd4fe43Sopenharmony_ci/*
21bd4fe43Sopenharmony_ci * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
31bd4fe43Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
41bd4fe43Sopenharmony_ci *
51bd4fe43Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
61bd4fe43Sopenharmony_ci * are permitted provided that the following conditions are met:
71bd4fe43Sopenharmony_ci *
81bd4fe43Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
91bd4fe43Sopenharmony_ci *    conditions and the following disclaimer.
101bd4fe43Sopenharmony_ci *
111bd4fe43Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
121bd4fe43Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
131bd4fe43Sopenharmony_ci *    provided with the distribution.
141bd4fe43Sopenharmony_ci *
151bd4fe43Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
161bd4fe43Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
171bd4fe43Sopenharmony_ci *    permission.
181bd4fe43Sopenharmony_ci *
191bd4fe43Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
201bd4fe43Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
211bd4fe43Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
221bd4fe43Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
231bd4fe43Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
241bd4fe43Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
251bd4fe43Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
261bd4fe43Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
271bd4fe43Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
281bd4fe43Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
291bd4fe43Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
301bd4fe43Sopenharmony_ci */
311bd4fe43Sopenharmony_ci
321bd4fe43Sopenharmony_ci#include <errno.h>
331bd4fe43Sopenharmony_ci#include <fcntl.h>
341bd4fe43Sopenharmony_ci#include <unistd.h>
351bd4fe43Sopenharmony_ci#include <string.h>
361bd4fe43Sopenharmony_ci#include <stdlib.h>
371bd4fe43Sopenharmony_ci#include <securec.h>
381bd4fe43Sopenharmony_ci
391bd4fe43Sopenharmony_ci#include "lwip/sockets.h"
401bd4fe43Sopenharmony_ci#include "hks_client.h"
411bd4fe43Sopenharmony_ci#include "hi_fs.h"
421bd4fe43Sopenharmony_ci
431bd4fe43Sopenharmony_ci#define RANDOM_DEV_FD  (LWIP_SOCKET_OFFSET + LWIP_CONFIG_NUM_SOCKETS)
441bd4fe43Sopenharmony_ci#define RANDOM_DEV_PATH  "/dev/random"
451bd4fe43Sopenharmony_ci
461bd4fe43Sopenharmony_ci#define IS_SOCKET_FD(fd) ((fd) >= LWIP_SOCKET_OFFSET && (fd) < (LWIP_SOCKET_OFFSET + LWIP_CONFIG_NUM_SOCKETS))
471bd4fe43Sopenharmony_ci
481bd4fe43Sopenharmony_ci#define HI_FS_MAX_OPEN_FILES (32+1)
491bd4fe43Sopenharmony_ci#define HI_FS_FD_OFFSET RANDOM_DEV_FD
501bd4fe43Sopenharmony_ci
511bd4fe43Sopenharmony_ci#define IS_HI_FS_FD(fd) ((fd) >= HI_FS_FD_OFFSET && (fd) < (HI_FS_FD_OFFSET + HI_FS_MAX_OPEN_FILES))
521bd4fe43Sopenharmony_ci#define HI_FS_FD(fd) ((fd) - HI_FS_FD_OFFSET)
531bd4fe43Sopenharmony_ci
541bd4fe43Sopenharmony_ci#define FREE_AND_SET_NULL(ptr) do { \
551bd4fe43Sopenharmony_ci    free(ptr);                      \
561bd4fe43Sopenharmony_ci    ptr = NULL;                     \
571bd4fe43Sopenharmony_ci} while (0)
581bd4fe43Sopenharmony_ci
591bd4fe43Sopenharmony_ci/**
601bd4fe43Sopenharmony_ci * @brief Get canonical form of a given path based on cwd(Current working directory).
611bd4fe43Sopenharmony_ci *
621bd4fe43Sopenharmony_ci * @param cwd Indicates the current working directory.
631bd4fe43Sopenharmony_ci * @param path Indicates the path to be canonicalization.
641bd4fe43Sopenharmony_ci * @param buf Indicates the pointer to the buffer where the result will be return.
651bd4fe43Sopenharmony_ci * @param bufSize Indicates the size of the buffer.
661bd4fe43Sopenharmony_ci * @return Returns the length of the canonical path.
671bd4fe43Sopenharmony_ci *
681bd4fe43Sopenharmony_ci * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/').
691bd4fe43Sopenharmony_ci *            if the buffer is not big enough the result will be truncated, but the return value will always be the
701bd4fe43Sopenharmony_ci *            length of the canonical path.
711bd4fe43Sopenharmony_ci */
721bd4fe43Sopenharmony_cistatic size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize)
731bd4fe43Sopenharmony_ci{
741bd4fe43Sopenharmony_ci    if (!path) {
751bd4fe43Sopenharmony_ci        path = "";
761bd4fe43Sopenharmony_ci    }
771bd4fe43Sopenharmony_ci
781bd4fe43Sopenharmony_ci    if (!cwd || path[0] == '/') {
791bd4fe43Sopenharmony_ci        cwd = "";
801bd4fe43Sopenharmony_ci    }
811bd4fe43Sopenharmony_ci
821bd4fe43Sopenharmony_ci    size_t tmpLen = strlen(cwd) + strlen(path) + 4; // three '/' and one '\0'
831bd4fe43Sopenharmony_ci    if (tmpLen <= 0) {
841bd4fe43Sopenharmony_ci        return 0;
851bd4fe43Sopenharmony_ci    }
861bd4fe43Sopenharmony_ci    char *tmpBuf = (char *)malloc(tmpLen);
871bd4fe43Sopenharmony_ci    if (tmpBuf == NULL) {
881bd4fe43Sopenharmony_ci        return 0;
891bd4fe43Sopenharmony_ci    }
901bd4fe43Sopenharmony_ci
911bd4fe43Sopenharmony_ci    if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
921bd4fe43Sopenharmony_ci        free(tmpBuf);
931bd4fe43Sopenharmony_ci        return 0;
941bd4fe43Sopenharmony_ci    }
951bd4fe43Sopenharmony_ci
961bd4fe43Sopenharmony_ci    char *p;
971bd4fe43Sopenharmony_ci    /* replace /./ to / */
981bd4fe43Sopenharmony_ci    while ((p = strstr(tmpBuf, "/./")) != NULL) {
991bd4fe43Sopenharmony_ci        if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 2, tmpLen - (p - tmpBuf) - 2)) {
1001bd4fe43Sopenharmony_ci            free(tmpBuf);
1011bd4fe43Sopenharmony_ci            return 0;
1021bd4fe43Sopenharmony_ci        }
1031bd4fe43Sopenharmony_ci    }
1041bd4fe43Sopenharmony_ci
1051bd4fe43Sopenharmony_ci    /* replace // to / */
1061bd4fe43Sopenharmony_ci    while ((p = strstr(tmpBuf, "//")) != NULL) {
1071bd4fe43Sopenharmony_ci        if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
1081bd4fe43Sopenharmony_ci            free(tmpBuf);
1091bd4fe43Sopenharmony_ci            return 0;
1101bd4fe43Sopenharmony_ci        }
1111bd4fe43Sopenharmony_ci    }
1121bd4fe43Sopenharmony_ci
1131bd4fe43Sopenharmony_ci    /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */
1141bd4fe43Sopenharmony_ci    while ((p = strstr(tmpBuf, "/../")) != NULL) {
1151bd4fe43Sopenharmony_ci        char *start = p;
1161bd4fe43Sopenharmony_ci        while (start > tmpBuf && *--start != '/') {
1171bd4fe43Sopenharmony_ci        }
1181bd4fe43Sopenharmony_ci        if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + 3, tmpLen - (p - tmpBuf) - 3)) {
1191bd4fe43Sopenharmony_ci            free(tmpBuf);
1201bd4fe43Sopenharmony_ci            return 0;
1211bd4fe43Sopenharmony_ci        }
1221bd4fe43Sopenharmony_ci    }
1231bd4fe43Sopenharmony_ci
1241bd4fe43Sopenharmony_ci    size_t totalLen = strlen(tmpBuf);
1251bd4fe43Sopenharmony_ci
1261bd4fe43Sopenharmony_ci    /* strip the last / */
1271bd4fe43Sopenharmony_ci    if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') {
1281bd4fe43Sopenharmony_ci        tmpBuf[--totalLen] = 0;
1291bd4fe43Sopenharmony_ci    }
1301bd4fe43Sopenharmony_ci
1311bd4fe43Sopenharmony_ci    if (!buf || bufSize == 0) {
1321bd4fe43Sopenharmony_ci        free(tmpBuf);
1331bd4fe43Sopenharmony_ci        return totalLen;
1341bd4fe43Sopenharmony_ci    }
1351bd4fe43Sopenharmony_ci
1361bd4fe43Sopenharmony_ci    if (EOK != memcpy_s(buf, bufSize, tmpBuf, (totalLen + 1 > bufSize) ? bufSize : totalLen + 1)) {
1371bd4fe43Sopenharmony_ci        free(tmpBuf);
1381bd4fe43Sopenharmony_ci        return 0;
1391bd4fe43Sopenharmony_ci    }
1401bd4fe43Sopenharmony_ci
1411bd4fe43Sopenharmony_ci    buf[bufSize - 1] = 0;
1421bd4fe43Sopenharmony_ci    free(tmpBuf);
1431bd4fe43Sopenharmony_ci    return totalLen;
1441bd4fe43Sopenharmony_ci}
1451bd4fe43Sopenharmony_ci
1461bd4fe43Sopenharmony_ciint open(const char *file, int oflag, ...)
1471bd4fe43Sopenharmony_ci{
1481bd4fe43Sopenharmony_ci    int fd = -1;
1491bd4fe43Sopenharmony_ci    unsigned flags = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY;
1501bd4fe43Sopenharmony_ci    if (((unsigned)oflag & ~flags) || (file == NULL)) {
1511bd4fe43Sopenharmony_ci        errno = EINVAL;
1521bd4fe43Sopenharmony_ci        return -1;
1531bd4fe43Sopenharmony_ci    }
1541bd4fe43Sopenharmony_ci    size_t pathLen = strlen(file) + 1;
1551bd4fe43Sopenharmony_ci    if (pathLen <= 0) {
1561bd4fe43Sopenharmony_ci        errno = EINVAL;
1571bd4fe43Sopenharmony_ci        return -1;
1581bd4fe43Sopenharmony_ci    }
1591bd4fe43Sopenharmony_ci    char *canonicalPath = (char *)malloc(pathLen);
1601bd4fe43Sopenharmony_ci    if (!canonicalPath) {
1611bd4fe43Sopenharmony_ci        errno = ENOMEM;
1621bd4fe43Sopenharmony_ci        return -1;
1631bd4fe43Sopenharmony_ci    }
1641bd4fe43Sopenharmony_ci    if (GetCanonicalPath(NULL, file, canonicalPath, pathLen) == 0) {
1651bd4fe43Sopenharmony_ci        FREE_AND_SET_NULL(canonicalPath);
1661bd4fe43Sopenharmony_ci        errno = ENOMEM;
1671bd4fe43Sopenharmony_ci        return -1;
1681bd4fe43Sopenharmony_ci    }
1691bd4fe43Sopenharmony_ci    if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
1701bd4fe43Sopenharmony_ci        FREE_AND_SET_NULL(canonicalPath);
1711bd4fe43Sopenharmony_ci        if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) {
1721bd4fe43Sopenharmony_ci            errno = EPERM;
1731bd4fe43Sopenharmony_ci            return -1;
1741bd4fe43Sopenharmony_ci        }
1751bd4fe43Sopenharmony_ci        if ((unsigned)oflag & O_DIRECTORY) {
1761bd4fe43Sopenharmony_ci            errno = ENOTDIR;
1771bd4fe43Sopenharmony_ci            return -1;
1781bd4fe43Sopenharmony_ci        }
1791bd4fe43Sopenharmony_ci        return RANDOM_DEV_FD;
1801bd4fe43Sopenharmony_ci    }
1811bd4fe43Sopenharmony_ci    if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) {
1821bd4fe43Sopenharmony_ci        FREE_AND_SET_NULL(canonicalPath);
1831bd4fe43Sopenharmony_ci        if ((unsigned)oflag & O_DIRECTORY) {
1841bd4fe43Sopenharmony_ci            errno = EPERM;
1851bd4fe43Sopenharmony_ci            return -1;
1861bd4fe43Sopenharmony_ci        }
1871bd4fe43Sopenharmony_ci        errno = EISDIR;
1881bd4fe43Sopenharmony_ci        return -1;
1891bd4fe43Sopenharmony_ci    }
1901bd4fe43Sopenharmony_ci    FREE_AND_SET_NULL(canonicalPath);
1911bd4fe43Sopenharmony_ci    fd = hi_open(file, (uint32_t)oflag);
1921bd4fe43Sopenharmony_ci    if (fd < 0) {
1931bd4fe43Sopenharmony_ci	return -1;
1941bd4fe43Sopenharmony_ci    }
1951bd4fe43Sopenharmony_ci    return fd + HI_FS_FD_OFFSET;
1961bd4fe43Sopenharmony_ci}
1971bd4fe43Sopenharmony_ci
1981bd4fe43Sopenharmony_ciint close(int fd)
1991bd4fe43Sopenharmony_ci{
2001bd4fe43Sopenharmony_ci    if (fd == RANDOM_DEV_FD) {
2011bd4fe43Sopenharmony_ci        return 0;
2021bd4fe43Sopenharmony_ci    }
2031bd4fe43Sopenharmony_ci    if (IS_SOCKET_FD(fd)) {
2041bd4fe43Sopenharmony_ci        return closesocket(fd);
2051bd4fe43Sopenharmony_ci    }
2061bd4fe43Sopenharmony_ci    if (IS_HI_FS_FD(fd)) {
2071bd4fe43Sopenharmony_ci        return hi_close(HI_FS_FD(fd));
2081bd4fe43Sopenharmony_ci    }
2091bd4fe43Sopenharmony_ci    errno = EBADF;
2101bd4fe43Sopenharmony_ci    return -1;
2111bd4fe43Sopenharmony_ci}
2121bd4fe43Sopenharmony_ci
2131bd4fe43Sopenharmony_cissize_t read(int fd, void *buf, size_t nbytes)
2141bd4fe43Sopenharmony_ci{
2151bd4fe43Sopenharmony_ci    if (fd == RANDOM_DEV_FD) {
2161bd4fe43Sopenharmony_ci        if (nbytes == 0) {
2171bd4fe43Sopenharmony_ci            return 0;
2181bd4fe43Sopenharmony_ci        }
2191bd4fe43Sopenharmony_ci        if (buf == NULL) {
2201bd4fe43Sopenharmony_ci            errno = EINVAL;
2211bd4fe43Sopenharmony_ci            return -1;
2221bd4fe43Sopenharmony_ci        }
2231bd4fe43Sopenharmony_ci        if (nbytes > 1024) {
2241bd4fe43Sopenharmony_ci            nbytes = 1024; /* hks_generate_random: random_size must <= 1024 */
2251bd4fe43Sopenharmony_ci        }
2261bd4fe43Sopenharmony_ci        struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbytes};
2271bd4fe43Sopenharmony_ci        if (hks_generate_random(&key) != 0) {
2281bd4fe43Sopenharmony_ci            errno = EIO;
2291bd4fe43Sopenharmony_ci            return -1;
2301bd4fe43Sopenharmony_ci        }
2311bd4fe43Sopenharmony_ci        return (ssize_t)nbytes;
2321bd4fe43Sopenharmony_ci    }
2331bd4fe43Sopenharmony_ci    if (IS_SOCKET_FD(fd)) {
2341bd4fe43Sopenharmony_ci        return recv(fd, buf, nbytes, 0);
2351bd4fe43Sopenharmony_ci    }
2361bd4fe43Sopenharmony_ci    if (IS_HI_FS_FD(fd)) {
2371bd4fe43Sopenharmony_ci        return hi_read(HI_FS_FD(fd), buf, nbytes);
2381bd4fe43Sopenharmony_ci    }
2391bd4fe43Sopenharmony_ci    errno = EBADF;
2401bd4fe43Sopenharmony_ci    return -1;
2411bd4fe43Sopenharmony_ci}
2421bd4fe43Sopenharmony_ci
2431bd4fe43Sopenharmony_cissize_t write(int fd, const void *buf, size_t nbytes)
2441bd4fe43Sopenharmony_ci{
2451bd4fe43Sopenharmony_ci    if (fd == RANDOM_DEV_FD) {
2461bd4fe43Sopenharmony_ci        errno = EBADF; /* "/dev/random" is readonly */
2471bd4fe43Sopenharmony_ci        return -1;
2481bd4fe43Sopenharmony_ci    }
2491bd4fe43Sopenharmony_ci    if (IS_SOCKET_FD(fd)) {
2501bd4fe43Sopenharmony_ci        return send(fd, buf, nbytes, 0);
2511bd4fe43Sopenharmony_ci    }
2521bd4fe43Sopenharmony_ci    if (IS_HI_FS_FD(fd)) {
2531bd4fe43Sopenharmony_ci        return hi_write(HI_FS_FD(fd), (const char*)buf, nbytes);
2541bd4fe43Sopenharmony_ci    }
2551bd4fe43Sopenharmony_ci    errno = EBADF;
2561bd4fe43Sopenharmony_ci    return -1;
2571bd4fe43Sopenharmony_ci}
2581bd4fe43Sopenharmony_ci
2591bd4fe43Sopenharmony_cioff_t lseek(int fd, off_t offset, int whence)
2601bd4fe43Sopenharmony_ci{
2611bd4fe43Sopenharmony_ci    if (fd == RANDOM_DEV_FD) {
2621bd4fe43Sopenharmony_ci        errno = ENOTSUP;
2631bd4fe43Sopenharmony_ci        return (off_t)-1;
2641bd4fe43Sopenharmony_ci    }
2651bd4fe43Sopenharmony_ci    if (IS_SOCKET_FD(fd)) {
2661bd4fe43Sopenharmony_ci        errno = ESPIPE;
2671bd4fe43Sopenharmony_ci        return (off_t)-1;
2681bd4fe43Sopenharmony_ci    }
2691bd4fe43Sopenharmony_ci    if (IS_HI_FS_FD(fd)) {
2701bd4fe43Sopenharmony_ci        return hi_lseek(HI_FS_FD(fd), offset, whence);
2711bd4fe43Sopenharmony_ci    }
2721bd4fe43Sopenharmony_ci    errno = EBADF;
2731bd4fe43Sopenharmony_ci    return (off_t)-1;
2741bd4fe43Sopenharmony_ci}
2751bd4fe43Sopenharmony_ci
2761bd4fe43Sopenharmony_ciint unlink(const char *path)
2771bd4fe43Sopenharmony_ci{
2781bd4fe43Sopenharmony_ci    return hi_unlink(path);
2791bd4fe43Sopenharmony_ci}
2801bd4fe43Sopenharmony_ci
2811bd4fe43Sopenharmony_ciint fsync(int fd)
2821bd4fe43Sopenharmony_ci{
2831bd4fe43Sopenharmony_ci    (void)fd;
2841bd4fe43Sopenharmony_ci    return 0;
2851bd4fe43Sopenharmony_ci}
286