• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <securec.h>
38 
39 #include "lwip/sockets.h"
40 #include "hks_client.h"
41 #include "hi_fs.h"
42 
43 #define RANDOM_DEV_FD  (LWIP_SOCKET_OFFSET + LWIP_CONFIG_NUM_SOCKETS)
44 #define RANDOM_DEV_PATH  "/dev/random"
45 
46 #define IS_SOCKET_FD(fd) ((fd) >= LWIP_SOCKET_OFFSET && (fd) < (LWIP_SOCKET_OFFSET + LWIP_CONFIG_NUM_SOCKETS))
47 
48 #define HI_FS_MAX_OPEN_FILES (32+1)
49 #define HI_FS_FD_OFFSET RANDOM_DEV_FD
50 
51 #define IS_HI_FS_FD(fd) ((fd) >= HI_FS_FD_OFFSET && (fd) < (HI_FS_FD_OFFSET + HI_FS_MAX_OPEN_FILES))
52 #define HI_FS_FD(fd) ((fd) - HI_FS_FD_OFFSET)
53 
54 #define FREE_AND_SET_NULL(ptr) do { \
55     free(ptr);                      \
56     ptr = NULL;                     \
57 } while (0)
58 
59 /**
60  * @brief Get canonical form of a given path based on cwd(Current working directory).
61  *
62  * @param cwd Indicates the current working directory.
63  * @param path Indicates the path to be canonicalization.
64  * @param buf Indicates the pointer to the buffer where the result will be return.
65  * @param bufSize Indicates the size of the buffer.
66  * @return Returns the length of the canonical path.
67  *
68  * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/').
69  *            if the buffer is not big enough the result will be truncated, but the return value will always be the
70  *            length of the canonical path.
71  */
GetCanonicalPath(const char * cwd,const char * path,char * buf,size_t bufSize)72 static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize)
73 {
74     if (!path) {
75         path = "";
76     }
77 
78     if (!cwd || path[0] == '/') {
79         cwd = "";
80     }
81 
82     size_t tmpLen = strlen(cwd) + strlen(path) + 4; // three '/' and one '\0'
83     if (tmpLen <= 0) {
84         return 0;
85     }
86     char *tmpBuf = (char *)malloc(tmpLen);
87     if (tmpBuf == NULL) {
88         return 0;
89     }
90 
91     if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
92         free(tmpBuf);
93         return 0;
94     }
95 
96     char *p;
97     /* replace /./ to / */
98     while ((p = strstr(tmpBuf, "/./")) != NULL) {
99         if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 2, tmpLen - (p - tmpBuf) - 2)) {
100             free(tmpBuf);
101             return 0;
102         }
103     }
104 
105     /* replace // to / */
106     while ((p = strstr(tmpBuf, "//")) != NULL) {
107         if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
108             free(tmpBuf);
109             return 0;
110         }
111     }
112 
113     /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */
114     while ((p = strstr(tmpBuf, "/../")) != NULL) {
115         char *start = p;
116         while (start > tmpBuf && *--start != '/') {
117         }
118         if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + 3, tmpLen - (p - tmpBuf) - 3)) {
119             free(tmpBuf);
120             return 0;
121         }
122     }
123 
124     size_t totalLen = strlen(tmpBuf);
125 
126     /* strip the last / */
127     if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') {
128         tmpBuf[--totalLen] = 0;
129     }
130 
131     if (!buf || bufSize == 0) {
132         free(tmpBuf);
133         return totalLen;
134     }
135 
136     if (EOK != memcpy_s(buf, bufSize, tmpBuf, (totalLen + 1 > bufSize) ? bufSize : totalLen + 1)) {
137         free(tmpBuf);
138         return 0;
139     }
140 
141     buf[bufSize - 1] = 0;
142     free(tmpBuf);
143     return totalLen;
144 }
145 
open(const char * file,int oflag,...)146 int open(const char *file, int oflag, ...)
147 {
148     int fd = -1;
149     unsigned flags = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY;
150     if (((unsigned)oflag & ~flags) || (file == NULL)) {
151         errno = EINVAL;
152         return -1;
153     }
154     size_t pathLen = strlen(file) + 1;
155     if (pathLen <= 0) {
156         errno = EINVAL;
157         return -1;
158     }
159     char *canonicalPath = (char *)malloc(pathLen);
160     if (!canonicalPath) {
161         errno = ENOMEM;
162         return -1;
163     }
164     if (GetCanonicalPath(NULL, file, canonicalPath, pathLen) == 0) {
165         FREE_AND_SET_NULL(canonicalPath);
166         errno = ENOMEM;
167         return -1;
168     }
169     if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
170         FREE_AND_SET_NULL(canonicalPath);
171         if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) {
172             errno = EPERM;
173             return -1;
174         }
175         if ((unsigned)oflag & O_DIRECTORY) {
176             errno = ENOTDIR;
177             return -1;
178         }
179         return RANDOM_DEV_FD;
180     }
181     if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) {
182         FREE_AND_SET_NULL(canonicalPath);
183         if ((unsigned)oflag & O_DIRECTORY) {
184             errno = EPERM;
185             return -1;
186         }
187         errno = EISDIR;
188         return -1;
189     }
190     FREE_AND_SET_NULL(canonicalPath);
191     fd = hi_open(file, (uint32_t)oflag);
192     if (fd < 0) {
193 	return -1;
194     }
195     return fd + HI_FS_FD_OFFSET;
196 }
197 
close(int fd)198 int close(int fd)
199 {
200     if (fd == RANDOM_DEV_FD) {
201         return 0;
202     }
203     if (IS_SOCKET_FD(fd)) {
204         return closesocket(fd);
205     }
206     if (IS_HI_FS_FD(fd)) {
207         return hi_close(HI_FS_FD(fd));
208     }
209     errno = EBADF;
210     return -1;
211 }
212 
read(int fd,void * buf,size_t nbytes)213 ssize_t read(int fd, void *buf, size_t nbytes)
214 {
215     if (fd == RANDOM_DEV_FD) {
216         if (nbytes == 0) {
217             return 0;
218         }
219         if (buf == NULL) {
220             errno = EINVAL;
221             return -1;
222         }
223         if (nbytes > 1024) {
224             nbytes = 1024; /* hks_generate_random: random_size must <= 1024 */
225         }
226         struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbytes};
227         if (hks_generate_random(&key) != 0) {
228             errno = EIO;
229             return -1;
230         }
231         return (ssize_t)nbytes;
232     }
233     if (IS_SOCKET_FD(fd)) {
234         return recv(fd, buf, nbytes, 0);
235     }
236     if (IS_HI_FS_FD(fd)) {
237         return hi_read(HI_FS_FD(fd), buf, nbytes);
238     }
239     errno = EBADF;
240     return -1;
241 }
242 
write(int fd,const void * buf,size_t nbytes)243 ssize_t write(int fd, const void *buf, size_t nbytes)
244 {
245     if (fd == RANDOM_DEV_FD) {
246         errno = EBADF; /* "/dev/random" is readonly */
247         return -1;
248     }
249     if (IS_SOCKET_FD(fd)) {
250         return send(fd, buf, nbytes, 0);
251     }
252     if (IS_HI_FS_FD(fd)) {
253         return hi_write(HI_FS_FD(fd), (const char*)buf, nbytes);
254     }
255     errno = EBADF;
256     return -1;
257 }
258 
lseek(int fd,off_t offset,int whence)259 off_t lseek(int fd, off_t offset, int whence)
260 {
261     if (fd == RANDOM_DEV_FD) {
262         errno = ENOTSUP;
263         return (off_t)-1;
264     }
265     if (IS_SOCKET_FD(fd)) {
266         errno = ESPIPE;
267         return (off_t)-1;
268     }
269     if (IS_HI_FS_FD(fd)) {
270         return hi_lseek(HI_FS_FD(fd), offset, whence);
271     }
272     errno = EBADF;
273     return (off_t)-1;
274 }
275 
unlink(const char * path)276 int unlink(const char *path)
277 {
278     return hi_unlink(path);
279 }
280 
fsync(int fd)281 int fsync(int fd)
282 {
283     (void)fd;
284     return 0;
285 }
286