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