• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 # Copyright (C) 2024 HiHope Open Source Organization .
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14  */
15 
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <securec.h>
22 
23 #include "lwip/sockets.h"
24 #include "hks_client.h"
25 #include "hi_fs.h"
26 
27 #define RANDOM_DEV_FD  (LWIP_SOCKET_OFFSET + LWIP_CONFIG_NUM_SOCKETS)
28 #define RANDOM_DEV_PATH  "/dev/random"
29 
30 #define IS_SOCKET_FD(fd) ((fd) >= LWIP_SOCKET_OFFSET && (fd) < (LWIP_SOCKET_OFFSET + LWIP_CONFIG_NUM_SOCKETS))
31 
32 #define HI_FS_MAX_OPEN_FILES (32+1)
33 #define HI_FS_FD_OFFSET RANDOM_DEV_FD
34 
35 #define IS_HI_FS_FD(fd) ((fd) >= HI_FS_FD_OFFSET && (fd) < (HI_FS_FD_OFFSET + HI_FS_MAX_OPEN_FILES))
36 #define HI_FS_FD(fd) ((fd) - HI_FS_FD_OFFSET)
37 
38 #define FREE_AND_SET_NULL(ptr) do { \
39     free(ptr);                      \
40     ptr = NULL;                     \
41 } while (0)
42 
43 /**
44  * @brief Get canonical form of a given path based on cwd(Current working directory).
45  *
46  * @param cwd Indicates the current working directory.
47  * @param path Indicates the path to be canonicalization.
48  * @param buf Indicates the pointer to the buffer where the result will be return.
49  * @param bufSize Indicates the size of the buffer.
50  * @return Returns the length of the canonical path.
51  *
52  * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/').
53  *            if the buffer is not big enough the result will be truncated, but the return value will always be the
54  *            length of the canonical path.
55  */
GetCanonicalPath(const char * cwd,const char * path,char * buf,size_t bufSize)56 static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize)
57 {
58     if (!path) {
59         path = "";
60     }
61 
62     if (!cwd || path[0] == '/') {
63         cwd = "";
64     }
65 
66     size_t tmpLen = strlen(cwd) + strlen(path) + 4; // three '/' and one '\0'
67     if (tmpLen <= 0) {
68         return 0;
69     }
70     char *tmpBuf = (char *)malloc(tmpLen);
71     if (tmpBuf == NULL) {
72         return 0;
73     }
74 
75     if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
76         free(tmpBuf);
77         return 0;
78     }
79 
80     char *p;
81     /* replace /./ to / */
82     while ((p = strstr(tmpBuf, "/./")) != NULL) {
83         if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 2, tmpLen - (p - tmpBuf) - 2)) {
84             free(tmpBuf);
85             return 0;
86         }
87     }
88 
89     /* replace // to / */
90     while ((p = strstr(tmpBuf, "//")) != NULL) {
91         if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
92             free(tmpBuf);
93             return 0;
94         }
95     }
96 
97     /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */
98     while ((p = strstr(tmpBuf, "/../")) != NULL) {
99         char *start = p;
100         while (start > tmpBuf && *--start != '/') {
101         }
102         if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + 3, tmpLen - (p - tmpBuf) - 3)) {
103             free(tmpBuf);
104             return 0;
105         }
106     }
107 
108     size_t totalLen = strlen(tmpBuf);
109 
110     /* strip the last / */
111     if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') {
112         tmpBuf[--totalLen] = 0;
113     }
114 
115     if (!buf || bufSize == 0) {
116         free(tmpBuf);
117         return totalLen;
118     }
119 
120     if (EOK != memcpy_s(buf, bufSize, tmpBuf, (totalLen + 1 > bufSize) ? bufSize : totalLen + 1)) {
121         free(tmpBuf);
122         return 0;
123     }
124 
125     buf[bufSize - 1] = 0;
126     free(tmpBuf);
127     return totalLen;
128 }
129 
open(const char * file,int oflag,...)130 int open(const char *file, int oflag, ...)
131 {
132     int fd = -1;
133     unsigned flags = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE | O_TRUNC | O_EXCL | O_DIRECTORY;
134     if (((unsigned)oflag & ~flags) || (file == NULL)) {
135         errno = EINVAL;
136         return -1;
137     }
138     size_t pathLen = strlen(file) + 1;
139     if (pathLen <= 0) {
140         errno = EINVAL;
141         return -1;
142     }
143     char *canonicalPath = (char *)malloc(pathLen);
144     if (!canonicalPath) {
145         errno = ENOMEM;
146         return -1;
147     }
148     if (GetCanonicalPath(NULL, file, canonicalPath, pathLen) == 0) {
149         FREE_AND_SET_NULL(canonicalPath);
150         errno = ENOMEM;
151         return -1;
152     }
153     if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
154         FREE_AND_SET_NULL(canonicalPath);
155         if ((O_ACCMODE & (unsigned)oflag) != O_RDONLY) {
156             errno = EPERM;
157             return -1;
158         }
159         if ((unsigned)oflag & O_DIRECTORY) {
160             errno = ENOTDIR;
161             return -1;
162         }
163         return RANDOM_DEV_FD;
164     }
165     if (strcmp(canonicalPath, "/") == 0 || strcmp(canonicalPath, "/dev") == 0) {
166         FREE_AND_SET_NULL(canonicalPath);
167         if ((unsigned)oflag & O_DIRECTORY) {
168             errno = EPERM;
169             return -1;
170         }
171         errno = EISDIR;
172         return -1;
173     }
174     FREE_AND_SET_NULL(canonicalPath);
175     fd = hi_open(file, (uint32_t)oflag);
176     if (fd < 0) {
177 	return -1;
178     }
179     return fd + HI_FS_FD_OFFSET;
180 }
181 
close(int fd)182 int close(int fd)
183 {
184     if (fd == RANDOM_DEV_FD) {
185         return 0;
186     }
187     if (IS_SOCKET_FD(fd)) {
188         return closesocket(fd);
189     }
190     if (IS_HI_FS_FD(fd)) {
191         return hi_close(HI_FS_FD(fd));
192     }
193     errno = EBADF;
194     return -1;
195 }
196 
read(int fd,void * buf,size_t nbytes)197 ssize_t read(int fd, void *buf, size_t nbytes)
198 {
199     if (fd == RANDOM_DEV_FD) {
200         if (nbytes == 0) {
201             return 0;
202         }
203         if (buf == NULL) {
204             errno = EINVAL;
205             return -1;
206         }
207         if (nbytes > 1024) {
208             nbytes = 1024; /* hks_generate_random: random_size must <= 1024 */
209         }
210         struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbytes};
211         if (hks_generate_random(&key) != 0) {
212             errno = EIO;
213             return -1;
214         }
215         return (ssize_t)nbytes;
216     }
217     if (IS_SOCKET_FD(fd)) {
218         return recv(fd, buf, nbytes, 0);
219     }
220     if (IS_HI_FS_FD(fd)) {
221         return hi_read(HI_FS_FD(fd), buf, nbytes);
222     }
223     errno = EBADF;
224     return -1;
225 }
226 
write(int fd,const void * buf,size_t nbytes)227 ssize_t write(int fd, const void *buf, size_t nbytes)
228 {
229     if (fd == RANDOM_DEV_FD) {
230         errno = EBADF; /* "/dev/random" is readonly */
231         return -1;
232     }
233     if (IS_SOCKET_FD(fd)) {
234         return send(fd, buf, nbytes, 0);
235     }
236     if (IS_HI_FS_FD(fd)) {
237         return hi_write(HI_FS_FD(fd), (const char*)buf, nbytes);
238     }
239     errno = EBADF;
240     return -1;
241 }
242 
lseek(int fd,off_t offset,int whence)243 off_t lseek(int fd, off_t offset, int whence)
244 {
245     if (fd == RANDOM_DEV_FD) {
246         errno = ENOTSUP;
247         return (off_t)-1;
248     }
249     if (IS_SOCKET_FD(fd)) {
250         errno = ESPIPE;
251         return (off_t)-1;
252     }
253     if (IS_HI_FS_FD(fd)) {
254         return hi_lseek(HI_FS_FD(fd), offset, whence);
255     }
256     errno = EBADF;
257     return (off_t)-1;
258 }
259 
unlink(const char * path)260 int unlink(const char *path)
261 {
262     return hi_unlink(path);
263 }
264 
fsync(int fd)265 int fsync(int fd)
266 {
267     (void)fd;
268     return 0;
269 }
270