1 /*
2 * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #define _GNU_SOURCE 1
32 #include "los_fs.h"
33 #include <stdint.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdarg.h>
37 #include <unistd.h>
38 #include <sys/uio.h>
39 #include "errno.h"
40 #include "fcntl.h"
41 #include "los_mux.h"
42 #include "los_debug.h"
43 #include "los_sched.h"
44 #include "limits.h"
45 #include "securec.h"
46 #include "vfs_config.h"
47 #include "vfs_files.h"
48 #include "vfs_maps.h"
49 #include "vfs_mount.h"
50 #include "vfs_operations.h"
51
52 #if (LOSCFG_LIBC_NEWLIB == 1)
53 #define ALIAS_OF(of) __attribute__((alias(#of)))
54 #define FUNC_ALIAS(real_func, new_alias, args_list, return_type) \
55 return_type new_alias args_list ALIAS_OF(real_func)
56 #else
57 #define FUNC_ALIAS(real_func, new_alias, args_list, return_type)
58 #endif
59
60 #ifdef LOSCFG_NET_LWIP_SACK
61 #include "lwipopts.h"
62 #include "lwip/sockets.h"
63 #define CONFIG_NSOCKET_DESCRIPTORS LWIP_CONFIG_NUM_SOCKETS
64 #else
65 #define CONFIG_NSOCKET_DESCRIPTORS 0
66 #endif
67
68 #ifdef LOSCFG_RANDOM_DEV
69 #include "hks_client.h"
70 #define RANDOM_DEV_FD CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS
71 #define RANDOM_DEV_PATH "/dev/random"
72 #endif
73
74 #if (LOSCFG_POSIX_PIPE_API == 1)
75 #include "pipe_impl.h"
76 #ifdef LOSCFG_RANDOM_DEV
77 #define PIPE_DEV_FD (RANDOM_DEV_FD + 1)
78 #else
79 #define PIPE_DEV_FD (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)
80 #endif
81
PollQueryFd(int fd,struct PollTable * table)82 int PollQueryFd(int fd, struct PollTable *table)
83 {
84 if (fd >= PIPE_DEV_FD) {
85 return PipePoll(fd, table);
86 }
87
88 return -ENODEV;
89 }
90 #endif
91
92 #define FREE_AND_SET_NULL(ptr) do { \
93 LOSCFG_FS_FREE_HOOK(ptr); \
94 ptr = NULL; \
95 } while (0)
96
97 #define LOS_FCNTL (O_NONBLOCK | O_NDELAY | O_APPEND | O_SYNC)
98 #define IOV_MAX_CNT 4
99
100 UINT32 g_fsMutex;
101 static UINT32 g_dirNum = 0;
102
LOS_FsLock(void)103 int LOS_FsLock(void)
104 {
105 if (!OsCheckKernelRunning()) {
106 return LOS_OK;
107 }
108 if (LOS_MuxPend(g_fsMutex, (UINT32)LOSCFG_FS_LOCK_TIMEOUT) != LOS_OK) {
109 PRINT_ERR("LOS_FsLock failed!");
110 return (int)LOS_NOK;
111 }
112
113 return LOS_OK;
114 }
115
LOS_FsUnlock(void)116 void LOS_FsUnlock(void)
117 {
118 if (!OsCheckKernelRunning()) {
119 return;
120 }
121 (void)LOS_MuxPost(g_fsMutex);
122 }
123
124 #ifdef LOSCFG_RANDOM_DEV
125 /**
126 * @brief Get canonical form of a given path based on cwd(Current working directory).
127 *
128 * @param cwd Indicates the current working directory.
129 * @param path Indicates the path to be canonicalization.
130 * @param buf Indicates the pointer to the buffer where the result will be return.
131 * @param bufSize Indicates the size of the buffer.
132 * @return Returns the length of the canonical path.
133 *
134 * @attention if path is an absolute path, cwd is ignored. if cwd if not specified, it is assumed to be root('/').
135 * if the buffer is not big enough the result will be truncated, but the return value will always be the
136 * length of the canonical path.
137 */
GetCanonicalPath(const char * cwd,const char * path,char * buf,size_t bufSize)138 static size_t GetCanonicalPath(const char *cwd, const char *path, char *buf, size_t bufSize)
139 {
140 size_t offset;
141 if (!path) {
142 path = "";
143 }
144
145 if ((!cwd) || (path[0] == '/')) {
146 cwd = "";
147 }
148
149 offset = strlen("///") + 1; // three '/' and one '\0'
150 size_t tmpLen = strlen(cwd) + strlen(path) + offset;
151 char *tmpBuf = (char *)LOSCFG_FS_MALLOC_HOOK(tmpLen);
152 if (tmpBuf == NULL) {
153 return LOS_OK;
154 }
155
156 if (-1 == sprintf_s(tmpBuf, tmpLen, "/%s/%s/", cwd, path)) {
157 LOSCFG_FS_FREE_HOOK(tmpBuf);
158 return LOS_OK;
159 }
160
161 char *p;
162 /* replace /./ to / */
163 offset = strlen("/./") - 1;
164 while ((p = strstr(tmpBuf, "/./")) != NULL) {
165 if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
166 LOSCFG_FS_FREE_HOOK(tmpBuf);
167 return LOS_OK;
168 }
169 }
170
171 /* replace // to / */
172 while ((p = strstr(tmpBuf, "//")) != NULL) {
173 if (EOK != memmove_s(p, tmpLen - (p - tmpBuf), p + 1, tmpLen - (p - tmpBuf) - 1)) {
174 LOSCFG_FS_FREE_HOOK(tmpBuf);
175 return LOS_OK;
176 }
177 }
178
179 /* handle /../ (e.g., replace /aa/bb/../ to /aa/) */
180 offset = strlen("/../") - 1;
181 while ((p = strstr(tmpBuf, "/../")) != NULL) {
182 char *start = p;
183 while (start > tmpBuf && *(start - 1) != '/') {
184 --start;
185 }
186 if (EOK != memmove_s(start, tmpLen - (start - tmpBuf), p + offset, tmpLen - (p - tmpBuf) - offset)) {
187 LOSCFG_FS_FREE_HOOK(tmpBuf);
188 return LOS_OK;
189 }
190 }
191
192 size_t totalLen = strlen(tmpBuf);
193 /* strip the last / */
194 if (totalLen > 1 && tmpBuf[totalLen - 1] == '/') {
195 tmpBuf[--totalLen] = 0;
196 }
197
198 if ((!buf) || (bufSize == 0)) {
199 LOSCFG_FS_FREE_HOOK(tmpBuf);
200 return totalLen;
201 }
202
203 if (EOK != memcpy_s(buf, bufSize, tmpBuf, (((totalLen + 1) > bufSize) ? bufSize : (totalLen + 1)))) {
204 LOSCFG_FS_FREE_HOOK(tmpBuf);
205 return LOS_OK;
206 }
207
208 buf[bufSize - 1] = 0;
209 LOSCFG_FS_FREE_HOOK(tmpBuf);
210 return totalLen;
211 }
212 #endif
213
VfsPathCheck(const char * path,bool isFile)214 static int VfsPathCheck(const char *path, bool isFile)
215 {
216 size_t len;
217 if ((path == NULL) || (path[0] == '\0')) {
218 VFS_ERRNO_SET(EINVAL);
219 return (int)LOS_NOK;
220 }
221
222 len = strlen(path);
223 if (len >= PATH_MAX) {
224 VFS_ERRNO_SET(ENAMETOOLONG);
225 return (int)LOS_NOK;
226 }
227
228 if (isFile && path[len - 1] == '/') {
229 VFS_ERRNO_SET(EINVAL);
230 return (int)LOS_NOK;
231 }
232
233 return LOS_OK;
234 }
235
VfsOpen(const char * path,int flags)236 static int VfsOpen(const char *path, int flags)
237 {
238 size_t len;
239 struct File *file = NULL;
240 int fd = -1;
241 const char *pathInMp = NULL;
242 struct MountPoint *mp = NULL;
243
244 if (VfsPathCheck(path, TRUE) != LOS_OK) {
245 return fd;
246 }
247
248 if (LOS_FsLock() != LOS_OK) {
249 VFS_ERRNO_SET(EAGAIN);
250 return fd;
251 }
252
253 mp = VfsMpFind(path, &pathInMp);
254 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
255 (mp->mFs->fsFops == NULL) || (mp->mFs->fsFops->open == NULL)) {
256 /* path is not in any mountpoint */
257 VFS_ERRNO_SET(ENOENT);
258 LOS_FsUnlock();
259 return fd;
260 }
261
262 if ((mp->mWriteEnable == FALSE) &&
263 (flags & (O_CREAT | O_WRONLY | O_RDWR))) {
264 /* can't create file in read only mp */
265 VFS_ERRNO_SET(EACCES);
266 LOS_FsUnlock();
267 return fd;
268 }
269
270 file = VfsFileGet();
271 if (file == NULL) {
272 VFS_ERRNO_SET(ENFILE);
273 LOS_FsUnlock();
274 return fd;
275 }
276
277 len = strlen(path) + 1;
278 file->fullPath = LOSCFG_FS_MALLOC_HOOK(len);
279 if (file->fullPath == NULL) {
280 VFS_ERRNO_SET(ENOMEM);
281 VfsFilePut(file);
282 LOS_FsUnlock();
283 return (int)LOS_NOK;
284 }
285 (void)strcpy_s((char *)file->fullPath, len, path);
286
287 file->fFlags = (UINT32)flags;
288 file->fOffset = 0;
289 file->fData = NULL;
290 file->fFops = mp->mFs->fsFops;
291 file->fMp = mp;
292 file->fOwner = LOS_CurTaskIDGet();
293
294 if (file->fFops->open(file, pathInMp, flags) == 0) {
295 mp->mRefs++;
296 fd = FileToFd(file);
297 file->fStatus = FILE_STATUS_READY; /* file now ready to use */
298 } else {
299 LOSCFG_FS_FREE_HOOK((void *)file->fullPath);
300 VfsFilePut(file);
301 }
302
303 LOS_FsUnlock();
304 return fd;
305 }
306
307 /* attach to a file and then set new status */
308
VfsAttachFile(int fd,UINT32 status)309 static struct File *VfsAttachFile(int fd, UINT32 status)
310 {
311 struct File *file = NULL;
312
313 if ((fd < MIN_START_FD) || (fd >= CONFIG_NFILE_DESCRIPTORS)) {
314 VFS_ERRNO_SET(EBADF);
315 return NULL;
316 }
317
318 if (LOS_FsLock() != LOS_OK) {
319 VFS_ERRNO_SET(EFAULT);
320 return NULL;
321 }
322
323 file = FdToFile(fd);
324 if ((file == NULL) || (file->fMp == NULL)) {
325 VFS_ERRNO_SET(EBADF);
326 LOS_FsUnlock();
327 return NULL;
328 }
329
330 if (file->fStatus != FILE_STATUS_READY) {
331 VFS_ERRNO_SET(EBADF);
332 LOS_FsUnlock();
333 return NULL;
334 }
335
336 file->fStatus = status;
337 return file;
338 }
339
VfsAttachFileReady(int fd)340 static struct File *VfsAttachFileReady(int fd)
341 {
342 return VfsAttachFile(fd, FILE_STATUS_READY);
343 }
344
VfsAttachFileWithStatus(int fd,int status)345 static struct File *VfsAttachFileWithStatus(int fd, int status)
346 {
347 return VfsAttachFile(fd, (UINT32)status);
348 }
349
VfsDetachFile(const struct File * file)350 static void VfsDetachFile(const struct File *file)
351 {
352 (void)file;
353 LOS_FsUnlock();
354 }
355
VfsClose(int fd)356 static int VfsClose(int fd)
357 {
358 struct File *file = NULL;
359 int ret = (int)LOS_NOK;
360
361 file = VfsAttachFileWithStatus(fd, FILE_STATUS_CLOSING);
362 if (file == NULL) {
363 return ret;
364 }
365
366 if ((file->fFops != NULL) && (file->fFops->close != NULL)) {
367 ret = file->fFops->close(file);
368 } else {
369 VFS_ERRNO_SET(ENOTSUP);
370 }
371
372 if ((ret == 0) && (file->fMp != NULL)) {
373 file->fMp->mRefs--;
374 }
375
376 if (file->fullPath != NULL) {
377 LOSCFG_FS_FREE_HOOK((void *)file->fullPath);
378 }
379
380 VfsFilePut(file);
381
382 VfsDetachFile(file);
383
384 return ret;
385 }
386
VfsRead(int fd,char * buff,size_t bytes)387 static ssize_t VfsRead(int fd, char *buff, size_t bytes)
388 {
389 struct File *file = NULL;
390 ssize_t ret = (ssize_t)-1;
391
392 if (buff == NULL) {
393 VFS_ERRNO_SET(EFAULT);
394 return ret;
395 }
396
397 if (bytes == 0) {
398 return 0;
399 }
400
401 file = VfsAttachFileReady(fd);
402 if (file == NULL) {
403 return ret;
404 }
405
406 if ((file->fFlags & O_ACCMODE) == O_WRONLY) {
407 VFS_ERRNO_SET(EACCES);
408 } else if ((file->fFops != NULL) && (file->fFops->read != NULL)) {
409 ret = file->fFops->read(file, buff, bytes);
410 } else {
411 VFS_ERRNO_SET(ENOTSUP);
412 }
413
414 /* else ret will be -1 */
415 VfsDetachFile(file);
416
417 return ret;
418 }
419
VfsWrite(int fd,const void * buff,size_t bytes)420 static ssize_t VfsWrite(int fd, const void *buff, size_t bytes)
421 {
422 struct File *file = NULL;
423 ssize_t ret = (ssize_t)LOS_NOK;
424
425 if ((buff == NULL) || (bytes == 0)) {
426 VFS_ERRNO_SET(EINVAL);
427 return ret;
428 }
429
430 file = VfsAttachFileReady(fd);
431 if (file == NULL) {
432 return ret;
433 }
434
435 if ((file->fFlags & O_ACCMODE) == O_RDONLY) {
436 VFS_ERRNO_SET(EACCES);
437 } else if ((file->fFops != NULL) && (file->fFops->write != NULL)) {
438 ret = file->fFops->write(file, buff, bytes);
439 } else {
440 VFS_ERRNO_SET(ENOTSUP);
441 }
442
443 /* else ret will be -1 */
444 VfsDetachFile(file);
445
446 return ret;
447 }
448
VfsIoctl(int fd,int func,va_list ap)449 static int VfsIoctl(int fd, int func, va_list ap)
450 {
451 unsigned long arg;
452 struct File *file = NULL;
453 int ret = (int)LOS_NOK;
454
455 arg = va_arg(ap, unsigned long);
456 file = VfsAttachFileReady(fd);
457 if (file == NULL) {
458 return ret;
459 }
460
461 if ((file->fFops != NULL) && (file->fFops->ioctl != NULL)) {
462 ret = file->fFops->ioctl(file, func, arg);
463 } else {
464 VFS_ERRNO_SET(ENOTSUP);
465 }
466
467 VfsDetachFile(file);
468
469 return ret;
470 }
471
VfsVfcntl(struct File * filep,int cmd,va_list ap)472 static int VfsVfcntl(struct File *filep, int cmd, va_list ap)
473 {
474 int ret;
475 UINT32 flags;
476
477 if ((filep == NULL) || (filep->fFops == NULL)) {
478 return -EBADF;
479 }
480
481 if (cmd == F_GETFL) {
482 ret = (int)(filep->fFlags);
483 } else if (cmd == F_SETFL) {
484 flags = (UINT32)va_arg(ap, int);
485 flags &= LOS_FCNTL;
486 filep->fFlags &= ~LOS_FCNTL;
487 filep->fFlags |= flags;
488 ret = LOS_OK;
489 } else {
490 ret = -ENOSYS;
491 }
492 return ret;
493 }
494
MapToPosixRet(int ret)495 static int MapToPosixRet(int ret)
496 {
497 return ((ret) < 0 ? -1 : (ret));
498 }
499
500 /* POSIX interface */
open(const char * path,int flags,...)501 int open(const char *path, int flags, ...)
502 {
503 if (path == NULL) {
504 errno = EINVAL;
505 return (int)LOS_NOK;
506 }
507 #ifdef LOSCFG_RANDOM_DEV
508 unsigned flagMask = O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_LARGEFILE \
509 | O_TRUNC | O_EXCL | O_DIRECTORY;
510 if ((unsigned)flags & ~flagMask) {
511 errno = EINVAL;
512 return (int)LOS_NOK;
513 }
514
515 size_t pathLen = strlen(path) + 1;
516 if ((unsigned)pathLen > PATH_MAX) {
517 errno = EINVAL;
518 return (int)LOS_NOK;
519 }
520
521 char *canonicalPath = (char *)LOSCFG_FS_MALLOC_HOOK(pathLen);
522 if (!canonicalPath) {
523 errno = ENOMEM;
524 return (int)LOS_NOK;
525 }
526 if (GetCanonicalPath(NULL, path, canonicalPath, pathLen) == 0) {
527 FREE_AND_SET_NULL(canonicalPath);
528 errno = ENOMEM;
529 return (int)LOS_NOK;
530 }
531
532 if (strcmp(canonicalPath, RANDOM_DEV_PATH) == 0) {
533 FREE_AND_SET_NULL(canonicalPath);
534 if ((O_ACCMODE & (unsigned)flags) != O_RDONLY) {
535 errno = EPERM;
536 return (int)LOS_NOK;
537 }
538 if ((unsigned)flags & O_DIRECTORY) {
539 errno = ENOTDIR;
540 return (int)LOS_NOK;
541 }
542 return RANDOM_DEV_FD;
543 }
544 if ((strcmp(canonicalPath, "/") == 0) ||
545 (strcmp(canonicalPath, "/dev") == 0)) {
546 FREE_AND_SET_NULL(canonicalPath);
547 if ((unsigned)flags & O_DIRECTORY) {
548 errno = EPERM;
549 return (int)LOS_NOK;
550 }
551 errno = EISDIR;
552 return (int)LOS_NOK;
553 }
554 FREE_AND_SET_NULL(canonicalPath);
555 #endif
556 #if (LOSCFG_POSIX_PIPE_API == 1)
557 if (!strncmp(path, PIPE_DEV_PATH, strlen(PIPE_DEV_PATH))) {
558 return PipeOpen(path, flags, PIPE_DEV_FD);
559 }
560 #endif
561
562 int ret = VfsOpen(path, flags);
563 return MapToPosixRet(ret);
564 }
565 FUNC_ALIAS(open, _open, (const char *path, int flags, ...), int);
566
close(int fd)567 int close(int fd)
568 {
569 #ifdef LOSCFG_RANDOM_DEV
570 if (fd == RANDOM_DEV_FD) {
571 return LOS_OK;
572 }
573 #endif
574 #ifdef LOSCFG_NET_LWIP_SACK
575 if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
576 return closesocket(fd);
577 }
578 #endif /* LOSCFG_NET_LWIP_SACK */
579 #if (LOSCFG_POSIX_PIPE_API == 1)
580 if (fd >= PIPE_DEV_FD) {
581 return PipeClose(fd);
582 }
583 #endif
584
585 int ret = (int)LOS_NOK;
586 if (fd >= MIN_START_FD && fd < CONFIG_NFILE_DESCRIPTORS) {
587 ret = VfsClose(fd);
588 }
589 return MapToPosixRet(ret);
590 }
591 FUNC_ALIAS(close, _close, (int fd), int);
592
read(int fd,void * buff,size_t bytes)593 ssize_t read(int fd, void *buff, size_t bytes)
594 {
595 #ifdef LOSCFG_RANDOM_DEV
596 if (fd == RANDOM_DEV_FD) {
597 if (nbyte == 0) {
598 return FS_SUCCESS;
599 }
600 if (buf == NULL) {
601 errno = EINVAL;
602 return FS_FAILURE;
603 }
604 if (nbyte > 1024) { /* 1024, max random_size */
605 nbyte = 1024; /* hks_generate_random: random_size must <= 1024 */
606 }
607 struct hks_blob key = {HKS_BLOB_TYPE_RAW, (uint8_t *)buf, nbyte};
608 if (hks_generate_random(&key) != 0) {
609 errno = EIO;
610 return FS_FAILURE;
611 }
612 return (ssize_t)nbyte;
613 }
614 #endif
615 #ifdef LOSCFG_NET_LWIP_SACK
616 if (fd >= CONFIG_NFILE_DESCRIPTORS && fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
617 return recv(fd, buff, bytes, 0);
618 }
619 #endif /* LOSCFG_NET_LWIP_SACK */
620
621 #if (LOSCFG_POSIX_PIPE_API == 1)
622 if (fd >= PIPE_DEV_FD) {
623 return PipeRead(fd, buff, bytes);
624 }
625 #endif
626
627 ssize_t ret = (ssize_t)LOS_NOK;
628 if (fd >= MIN_START_FD && fd < CONFIG_NFILE_DESCRIPTORS) {
629 ret = VfsRead(fd, buff, bytes);
630 }
631
632 return MapToPosixRet(ret);
633 }
634 FUNC_ALIAS(read, _read, (int fd, void *buff, size_t bytes), ssize_t);
635
write(int fd,const void * buff,size_t bytes)636 ssize_t write(int fd, const void *buff, size_t bytes)
637 {
638 #ifdef LOSCFG_RANDOM_DEV
639 if (fd == RANDOM_DEV_FD) {
640 errno = EBADF; /* "/dev/random" is readonly */
641 return (ssize_t)LOS_NOK;
642 }
643 #endif
644 #ifdef LOSCFG_NET_LWIP_SACK
645 if (fd >= CONFIG_NFILE_DESCRIPTORS &&
646 fd < (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS)) {
647 return send(fd, buff, bytes, 0);
648 }
649 #endif /* LOSCFG_NET_LWIP_SACK */
650
651 #if (LOSCFG_POSIX_PIPE_API == 1)
652 if (fd >= PIPE_DEV_FD) {
653 return PipeWrite(fd, buff, bytes);
654 }
655 #endif
656
657 ssize_t ret = (ssize_t)LOS_NOK;
658 if (fd >= MIN_START_FD && fd < CONFIG_NFILE_DESCRIPTORS) {
659 ret = VfsWrite(fd, buff, bytes);
660 }
661
662 return MapToPosixRet(ret);
663 }
664 FUNC_ALIAS(write, _write, (int fd, const void *buff, size_t bytes), ssize_t);
665
lseek(int fd,off_t off,int whence)666 off_t lseek(int fd, off_t off, int whence)
667 {
668 struct File *file;
669 off_t ret = (off_t)LOS_NOK;
670
671 file = VfsAttachFileReady(fd);
672 if (file == NULL) {
673 return ret;
674 }
675
676 if ((file->fFops == NULL) || (file->fFops->lseek == NULL)) {
677 ret = file->fOffset;
678 } else {
679 ret = file->fFops->lseek(file, off, whence);
680 }
681
682 VfsDetachFile(file);
683 return ret;
684 }
685 FUNC_ALIAS(lseek, _lseek, (int fd, off_t off, int whence), off_t);
686
stat(const char * path,struct stat * stat)687 int stat(const char *path, struct stat *stat)
688 {
689 struct MountPoint *mp = NULL;
690 const char *pathInMp = NULL;
691 int ret = (int)LOS_NOK;
692
693 if (VfsPathCheck(path, FALSE) != LOS_OK) {
694 return MapToPosixRet(ret);
695 }
696
697 if (stat == NULL) {
698 VFS_ERRNO_SET(EINVAL);
699 return MapToPosixRet(ret);
700 }
701
702 if (LOS_FsLock() != LOS_OK) {
703 VFS_ERRNO_SET(EAGAIN);
704 return MapToPosixRet(ret);
705 }
706
707 mp = VfsMpFind(path, &pathInMp);
708 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
709 VFS_ERRNO_SET(ENOENT);
710 LOS_FsUnlock();
711 return MapToPosixRet(ret);
712 }
713
714 if (mp->mFs->fsFops->stat != NULL) {
715 ret = mp->mFs->fsFops->stat(mp, pathInMp, stat);
716 } else {
717 VFS_ERRNO_SET(ENOTSUP);
718 }
719
720 LOS_FsUnlock();
721 return MapToPosixRet(ret);
722 }
723 FUNC_ALIAS(stat, _stat, (const char *path, struct stat *stat), int);
724
statfs(const char * path,struct statfs * buf)725 int statfs(const char *path, struct statfs *buf)
726 {
727 struct MountPoint *mp = NULL;
728 const char *pathInMp = NULL;
729 int ret = (int)LOS_NOK;
730
731 if (VfsPathCheck(path, FALSE) != LOS_OK) {
732 return MapToPosixRet(ret);
733 }
734
735 if (buf == NULL) {
736 VFS_ERRNO_SET(EINVAL);
737 return MapToPosixRet(ret);
738 }
739
740 if (LOS_FsLock() != LOS_OK) {
741 VFS_ERRNO_SET(EAGAIN);
742 return MapToPosixRet(ret);
743 }
744
745 mp = VfsMpFind(path, &pathInMp);
746 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
747 VFS_ERRNO_SET(ENOENT);
748 LOS_FsUnlock();
749 return MapToPosixRet(ret);
750 }
751
752 if (mp->mFs->fsMops->statfs != NULL) {
753 ret = mp->mFs->fsMops->statfs(pathInMp, buf);
754 } else {
755 VFS_ERRNO_SET(ENOTSUP);
756 }
757
758 LOS_FsUnlock();
759 return MapToPosixRet(ret);
760 }
761
unlink(const char * path)762 int unlink(const char *path)
763 {
764 struct MountPoint *mp = NULL;
765 const char *pathInMp = NULL;
766 int ret = (int)LOS_NOK;
767
768 if (VfsPathCheck(path, FALSE) != LOS_OK) {
769 return MapToPosixRet(ret);
770 }
771
772 if (LOS_FsLock() != LOS_OK) {
773 VFS_ERRNO_SET(EAGAIN);
774 return MapToPosixRet(ret);
775 }
776
777 mp = VfsMpFind(path, &pathInMp);
778 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
779 (mp->mFs->fsFops->unlink == NULL)) {
780 VFS_ERRNO_SET(ENOENT);
781 LOS_FsUnlock();
782 return MapToPosixRet(ret);
783 }
784
785 ret = mp->mFs->fsFops->unlink(mp, pathInMp);
786
787 LOS_FsUnlock();
788 return MapToPosixRet(ret);
789 }
790 FUNC_ALIAS(unlink, _unlink, (const char *path), int);
791
rename(const char * oldpath,const char * newpath)792 int rename(const char *oldpath, const char *newpath)
793 {
794 struct MountPoint *mpOld = NULL;
795 struct MountPoint *mpNew = NULL;
796 const char *pathInMpOld = NULL;
797 const char *pathInMpNew = NULL;
798 int ret = (int)LOS_NOK;
799
800 if (VfsPathCheck(oldpath, FALSE) != LOS_OK) {
801 return MapToPosixRet(ret);
802 }
803 if (VfsPathCheck(newpath, FALSE) != LOS_OK) {
804 return MapToPosixRet(ret);
805 }
806
807 if (LOS_FsLock() != LOS_OK) {
808 VFS_ERRNO_SET(EAGAIN);
809 return MapToPosixRet(ret);
810 }
811
812 mpOld = VfsMpFind(oldpath, &pathInMpOld);
813
814 if (pathInMpOld == NULL) {
815 VFS_ERRNO_SET(EINVAL);
816 LOS_FsUnlock();
817 return MapToPosixRet(ret);
818 }
819
820 if ((mpOld == NULL) || (*pathInMpOld == '\0') ||
821 (mpOld->mFs->fsFops->unlink == NULL)) {
822 VFS_ERRNO_SET(EINVAL);
823 LOS_FsUnlock();
824 return MapToPosixRet(ret);
825 }
826
827 mpNew = VfsMpFind(newpath, &pathInMpNew);
828 if ((mpNew == NULL) || (pathInMpNew == NULL) || (*pathInMpNew == '\0') || (mpNew->mFs->fsFops->unlink == NULL)) {
829 VFS_ERRNO_SET(EINVAL);
830 LOS_FsUnlock();
831 return MapToPosixRet(ret);
832 }
833
834 if (mpOld != mpNew) {
835 VFS_ERRNO_SET(EXDEV);
836 LOS_FsUnlock();
837 return MapToPosixRet(ret);
838 }
839
840 if (mpOld->mFs->fsFops->rename != NULL) {
841 ret = mpOld->mFs->fsFops->rename(mpOld, pathInMpOld, pathInMpNew);
842 } else {
843 VFS_ERRNO_SET(ENOTSUP);
844 }
845
846 LOS_FsUnlock();
847 return MapToPosixRet(ret);
848 }
849
fsync(int fd)850 int fsync(int fd)
851 {
852 struct File *file;
853 int ret = (int)LOS_NOK;
854
855 file = VfsAttachFileReady(fd);
856 if (file == NULL) {
857 return MapToPosixRet(ret);
858 }
859
860 if (file->fMp->mWriteEnable == FALSE) {
861 VFS_ERRNO_SET(EACCES);
862 VfsDetachFile(file);
863 return MapToPosixRet(ret);
864 }
865
866 if ((file->fFops != NULL) && (file->fFops->sync != NULL)) {
867 ret = file->fFops->sync(file);
868 } else {
869 VFS_ERRNO_SET(ENOTSUP);
870 }
871
872 VfsDetachFile(file);
873 return MapToPosixRet(ret);
874 }
875
opendir(const char * path)876 DIR *opendir(const char *path)
877 {
878 struct MountPoint *mp = NULL;
879 const char *pathInMp = NULL;
880 struct Dir *dir = NULL;
881 UINT32 ret;
882
883 if (VfsPathCheck(path, FALSE) != LOS_OK) {
884 return NULL;
885 }
886
887 dir = (struct Dir *)LOSCFG_FS_MALLOC_HOOK(sizeof(struct Dir));
888 if (dir == NULL) {
889 VFS_ERRNO_SET(ENOMEM);
890 return NULL;
891 }
892
893 if (LOS_FsLock() != LOS_OK) {
894 VFS_ERRNO_SET(EAGAIN);
895 LOSCFG_FS_FREE_HOOK(dir);
896 return NULL;
897 }
898
899 if (g_dirNum >= LOSCFG_MAX_OPEN_DIRS) {
900 VFS_ERRNO_SET(ENFILE);
901 LOS_FsUnlock();
902 LOSCFG_FS_FREE_HOOK(dir);
903 return NULL;
904 }
905
906 mp = VfsMpFind(path, &pathInMp);
907 if ((mp == NULL) || (pathInMp == NULL)) {
908 VFS_ERRNO_SET(ENOENT);
909 LOS_FsUnlock();
910 LOSCFG_FS_FREE_HOOK(dir);
911 return NULL;
912 }
913
914 if (mp->mFs->fsFops->opendir == NULL) {
915 VFS_ERRNO_SET(ENOTSUP);
916 LOS_FsUnlock();
917 LOSCFG_FS_FREE_HOOK(dir);
918 return NULL;
919 }
920
921 dir->dMp = mp;
922 dir->dOffset = 0;
923
924 ret = (UINT32)mp->mFs->fsFops->opendir(dir, pathInMp);
925 if (ret == 0) {
926 mp->mRefs++;
927 g_dirNum++;
928 } else {
929 LOSCFG_FS_FREE_HOOK(dir);
930 dir = NULL;
931 }
932
933 LOS_FsUnlock();
934 return (DIR *)dir;
935 }
936
readdir(DIR * dir)937 struct dirent *readdir(DIR *dir)
938 {
939 struct dirent *ret = NULL;
940 struct Dir *d = (struct Dir *)dir;
941
942 if ((dir == NULL) || (d->dMp == NULL)) {
943 VFS_ERRNO_SET(EINVAL);
944 return NULL;
945 }
946
947 if (LOS_FsLock() != LOS_OK) {
948 VFS_ERRNO_SET(EAGAIN);
949 return NULL;
950 }
951
952 if ((d->dMp->mFs != NULL) && (d->dMp->mFs->fsFops != NULL) &&
953 (d->dMp->mFs->fsFops->readdir != NULL)) {
954 if (d->dMp->mFs->fsFops->readdir(d, &d->dDent) == 0) {
955 ret = &d->dDent;
956 }
957 } else {
958 VFS_ERRNO_SET(ENOTSUP);
959 }
960
961 LOS_FsUnlock();
962
963 return ret;
964 }
965
closedir(DIR * dir)966 int closedir(DIR *dir)
967 {
968 struct MountPoint *mp = NULL;
969 int ret = (int)LOS_NOK;
970 struct Dir *d = (struct Dir *)dir;
971
972 if ((d == NULL) || (d->dMp == NULL)) {
973 VFS_ERRNO_SET(EBADF);
974 return MapToPosixRet(ret);
975 }
976
977 mp = d->dMp;
978
979 if (LOS_FsLock() != LOS_OK) {
980 VFS_ERRNO_SET(EAGAIN);
981 return MapToPosixRet(ret);
982 }
983
984 if ((d->dMp->mFs != NULL) && (d->dMp->mFs->fsFops != NULL) &&
985 (d->dMp->mFs->fsFops->closedir != NULL)) {
986 ret = d->dMp->mFs->fsFops->closedir(d);
987 } else {
988 VFS_ERRNO_SET(ENOTSUP);
989 }
990
991 if (ret == 0) {
992 mp->mRefs--;
993 g_dirNum--;
994 } else {
995 VFS_ERRNO_SET(EBADF);
996 }
997
998 LOS_FsUnlock();
999 LOSCFG_FS_FREE_HOOK(d);
1000 d = NULL;
1001 return MapToPosixRet(ret);
1002 }
1003
mkdir(const char * path,mode_t mode)1004 int mkdir(const char *path, mode_t mode)
1005 {
1006 struct MountPoint *mp = NULL;
1007 const char *pathInMp = NULL;
1008 int ret = (int)LOS_NOK;
1009 (void)mode;
1010
1011 if (VfsPathCheck(path, FALSE) != LOS_OK) {
1012 return MapToPosixRet(ret);
1013 }
1014
1015 if (LOS_FsLock() != LOS_OK) {
1016 VFS_ERRNO_SET(EAGAIN);
1017 return MapToPosixRet(ret);
1018 }
1019
1020 mp = VfsMpFind(path, &pathInMp);
1021 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
1022 VFS_ERRNO_SET(ENOENT);
1023 LOS_FsUnlock();
1024 return MapToPosixRet(ret);
1025 }
1026
1027 if (mp->mFs->fsFops->mkdir != NULL) {
1028 ret = mp->mFs->fsFops->mkdir(mp, pathInMp);
1029 } else {
1030 VFS_ERRNO_SET(ENOTSUP);
1031 }
1032
1033 LOS_FsUnlock();
1034 return MapToPosixRet(ret);
1035 }
1036
rmdir(const char * path)1037 int rmdir(const char *path)
1038 {
1039 struct MountPoint *mp = NULL;
1040 const char *pathInMp = NULL;
1041 int ret = (int)LOS_NOK;
1042
1043 if (path == NULL) {
1044 VFS_ERRNO_SET(EINVAL);
1045 return MapToPosixRet(ret);
1046 }
1047
1048 if (LOS_FsLock() != LOS_OK) {
1049 VFS_ERRNO_SET(EAGAIN);
1050 return MapToPosixRet(ret);
1051 }
1052
1053 mp = VfsMpFind(path, &pathInMp);
1054 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
1055 (mp->mFs->fsFops->rmdir == NULL)) {
1056 VFS_ERRNO_SET(ENOENT);
1057 LOS_FsUnlock();
1058 return MapToPosixRet(ret);
1059 }
1060
1061 ret = mp->mFs->fsFops->rmdir(mp, pathInMp);
1062
1063 LOS_FsUnlock();
1064 return MapToPosixRet(ret);
1065 }
1066
lstat(const char * path,struct stat * buffer)1067 int lstat(const char *path, struct stat *buffer)
1068 {
1069 return stat(path, buffer);
1070 }
1071
fstat(int fd,struct stat * buf)1072 int fstat(int fd, struct stat *buf)
1073 {
1074 struct File *filep;
1075 int ret;
1076 filep = VfsAttachFileReady(fd);
1077 if ((filep == NULL) || (filep->fMp == NULL) || filep->fullPath == NULL) {
1078 return (int)LOS_NOK;
1079 }
1080 ret = stat(filep->fullPath, buf);
1081 VfsDetachFile(filep);
1082 return ret;
1083 }
1084 FUNC_ALIAS(fstat, _fstat, (int fd, struct stat *buf), int);
1085
fcntl(int fd,int cmd,...)1086 int fcntl(int fd, int cmd, ...)
1087 {
1088 struct File *filep = NULL;
1089 int ret;
1090 va_list ap;
1091
1092 va_start(ap, cmd);
1093 if (fd < CONFIG_NFILE_DESCRIPTORS) {
1094 filep = VfsAttachFileReady(fd);
1095 ret = VfsVfcntl(filep, cmd, ap);
1096 VfsDetachFile(filep);
1097 } else {
1098 #ifndef LOSCFG_NET_LWIP_SACK
1099 ret = -EBADF;
1100 #else
1101 int arg = va_arg(ap, int);
1102 ret = lwip_fcntl(fd, (long)cmd, arg);
1103 va_end(ap);
1104 return ret;
1105 #endif /* LOSCFG_NET_LWIP_SACK */
1106 }
1107
1108 if (ret < 0) {
1109 VFS_ERRNO_SET(-ret);
1110 ret = (int)LOS_NOK;
1111 }
1112 va_end(ap);
1113 return ret;
1114 }
1115
ioctl(int fd,int req,...)1116 int ioctl(int fd, int req, ...)
1117 {
1118 int ret;
1119 va_list ap;
1120
1121 va_start(ap, req);
1122 if (fd < CONFIG_NFILE_DESCRIPTORS) {
1123 ret = VfsIoctl(fd, req, ap);
1124 } else {
1125 #ifndef LOSCFG_NET_LWIP_SACK
1126 ret = -EBADF;
1127 #else
1128 UINTPTR arg = va_arg(ap, UINTPTR);
1129 ret = lwip_ioctl(fd, (long)req, (void *)arg);
1130 #endif /* LOSCFG_NET_LWIP_SACK */
1131 }
1132
1133 va_end(ap);
1134 return ret;
1135 }
1136
readv(int fd,const struct iovec * iovBuf,int iovcnt)1137 ssize_t readv(int fd, const struct iovec *iovBuf, int iovcnt)
1138 {
1139 int i;
1140 errno_t ret;
1141 char *buf = NULL;
1142 char *curBuf = NULL;
1143 char *readBuf = NULL;
1144 size_t bufLen = 0;
1145 size_t bytesToRead;
1146 ssize_t totalBytesRead;
1147 size_t totalLen;
1148 const struct iovec *iov = (const struct iovec *)iovBuf;
1149
1150 if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) {
1151 return (ssize_t)LOS_NOK;
1152 }
1153
1154 for (i = 0; i < iovcnt; ++i) {
1155 if ((SSIZE_MAX - bufLen) < iov[i].iov_len) {
1156 return (ssize_t)LOS_NOK;
1157 }
1158 bufLen += iov[i].iov_len;
1159 }
1160 if (bufLen == 0) {
1161 return (ssize_t)LOS_NOK;
1162 }
1163 totalLen = bufLen * sizeof(char);
1164 buf = (char *)LOSCFG_FS_MALLOC_HOOK(totalLen);
1165 if (buf == NULL) {
1166 return (ssize_t)LOS_NOK;
1167 }
1168
1169 totalBytesRead = read(fd, buf, bufLen);
1170 if ((size_t)totalBytesRead < totalLen) {
1171 totalLen = (size_t)totalBytesRead;
1172 }
1173 curBuf = buf;
1174 for (i = 0; i < iovcnt; ++i) {
1175 readBuf = (char *)iov[i].iov_base;
1176 bytesToRead = iov[i].iov_len;
1177
1178 size_t lenToRead = totalLen < bytesToRead ? totalLen : bytesToRead;
1179 ret = memcpy_s(readBuf, bytesToRead, curBuf, lenToRead);
1180 if (ret != EOK) {
1181 LOSCFG_FS_FREE_HOOK(buf);
1182 return (ssize_t)LOS_NOK;
1183 }
1184 if (totalLen < (size_t)bytesToRead) {
1185 break;
1186 }
1187 curBuf += bytesToRead;
1188 totalLen -= bytesToRead;
1189 }
1190 LOSCFG_FS_FREE_HOOK(buf);
1191 return totalBytesRead;
1192 }
1193
writev(int fd,const struct iovec * iovBuf,int iovcnt)1194 ssize_t writev(int fd, const struct iovec *iovBuf, int iovcnt)
1195 {
1196 int i;
1197 errno_t ret;
1198 char *buf = NULL;
1199 char *curBuf = NULL;
1200 char *writeBuf = NULL;
1201 size_t bufLen = 0;
1202 size_t bytesToWrite;
1203 ssize_t totalBytesWritten;
1204 size_t totalLen;
1205 const struct iovec *iov = iovBuf;
1206
1207 if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) {
1208 return (ssize_t)LOS_NOK;
1209 }
1210
1211 for (i = 0; i < iovcnt; ++i) {
1212 if ((SSIZE_MAX - bufLen) < iov[i].iov_len) {
1213 VFS_ERRNO_SET(EINVAL);
1214 return (ssize_t)LOS_NOK;
1215 }
1216 bufLen += iov[i].iov_len;
1217 }
1218 if (bufLen == 0) {
1219 return (ssize_t)LOS_NOK;
1220 }
1221 totalLen = bufLen * sizeof(char);
1222 buf = (char *)LOSCFG_FS_MALLOC_HOOK(totalLen);
1223 if (buf == NULL) {
1224 return (ssize_t)LOS_NOK;
1225 }
1226 curBuf = buf;
1227 for (i = 0; i < iovcnt; ++i) {
1228 writeBuf = (char *)iov[i].iov_base;
1229 bytesToWrite = iov[i].iov_len;
1230 if (((ssize_t)totalLen <= 0) || ((ssize_t)bytesToWrite <= 0)) {
1231 continue;
1232 }
1233 ret = memcpy_s(curBuf, totalLen, writeBuf, bytesToWrite);
1234 if (ret != EOK) {
1235 LOSCFG_FS_FREE_HOOK(buf);
1236 return (ssize_t)LOS_NOK;
1237 }
1238 curBuf += bytesToWrite;
1239 totalLen -= bytesToWrite;
1240 }
1241
1242 totalBytesWritten = write(fd, buf, bufLen);
1243 LOSCFG_FS_FREE_HOOK(buf);
1244
1245 return totalBytesWritten;
1246 }
1247
remove(const char * filename)1248 int remove(const char *filename)
1249 {
1250 int ret = unlink(filename);
1251 if (ret == -EISDIR) {
1252 ret = rmdir(filename);
1253 }
1254
1255 return ret;
1256 }
1257
access(const char * path,int amode)1258 int access(const char *path, int amode)
1259 {
1260 int result;
1261 mode_t mode;
1262 struct stat buf;
1263
1264 result = stat(path, &buf);
1265 if (result != 0) {
1266 return (int)LOS_NOK;
1267 }
1268
1269 mode = buf.st_mode;
1270 if ((unsigned int)amode & R_OK) {
1271 if ((mode & (S_IROTH | S_IRGRP | S_IRUSR)) == 0) {
1272 VFS_ERRNO_SET(EACCES);
1273 return (int)LOS_NOK;
1274 }
1275 }
1276 if ((unsigned int)amode & W_OK) {
1277 if ((mode & (S_IWOTH | S_IWGRP | S_IWUSR)) == 0) {
1278 VFS_ERRNO_SET(EACCES);
1279 return (int)LOS_NOK;
1280 }
1281 }
1282 if ((unsigned int)amode & X_OK) {
1283 if ((mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) {
1284 VFS_ERRNO_SET(EACCES);
1285 return (int)LOS_NOK;
1286 }
1287 }
1288 return 0;
1289 }
1290
ftruncate(int fd,off_t length)1291 int ftruncate(int fd, off_t length)
1292 {
1293 int ret = (int)LOS_NOK;
1294 struct File *file = NULL;
1295
1296 if (length <= 0) {
1297 VFS_ERRNO_SET(EINVAL);
1298 return ret;
1299 }
1300
1301 file = VfsAttachFileReady(fd);
1302 if (file == NULL) {
1303 return ret;
1304 }
1305
1306 if (file->fMp->mWriteEnable == FALSE) {
1307 VFS_ERRNO_SET(EACCES);
1308 VfsDetachFile(file);
1309 return ret;
1310 }
1311
1312 if ((file->fFlags & O_ACCMODE) == O_RDONLY) {
1313 VFS_ERRNO_SET(EACCES);
1314 } else if ((file->fFops != NULL) && (file->fFops->truncate != NULL)) {
1315 ret = file->fFops->truncate(file, length);
1316 } else {
1317 VFS_ERRNO_SET(ENOTSUP);
1318 }
1319
1320 /* else ret will be -1 */
1321 VfsDetachFile(file);
1322 return ret;
1323 }
1324
pread(int fd,void * buff,size_t bytes,off_t off)1325 ssize_t pread(int fd, void *buff, size_t bytes, off_t off)
1326 {
1327 ssize_t ret = (ssize_t)LOS_NOK;
1328 off_t savepos, pos;
1329
1330 if (fd < 0 || fd >= CONFIG_NFILE_DESCRIPTORS) {
1331 return MapToPosixRet((int)ret);
1332 }
1333
1334 if (buff == NULL) {
1335 VFS_ERRNO_SET(EFAULT);
1336 return MapToPosixRet((int)ret);
1337 }
1338
1339 if (bytes == 0) {
1340 return 0;
1341 }
1342
1343 if (LOS_FsLock() != LOS_OK) {
1344 VFS_ERRNO_SET(EAGAIN);
1345 return MapToPosixRet((int)ret);
1346 }
1347
1348 savepos = lseek(fd, 0, SEEK_CUR);
1349 if (savepos == (off_t)-1) {
1350 LOS_FsUnlock();
1351 return MapToPosixRet((int)ret);
1352 }
1353
1354 pos = lseek(fd, off, SEEK_SET);
1355 if (pos == (off_t)-1) {
1356 LOS_FsUnlock();
1357 return MapToPosixRet((int)ret);
1358 }
1359
1360 ret = read(fd, buff, bytes);
1361 pos = lseek(fd, savepos, SEEK_SET);
1362 if ((pos == (off_t)-1) && (ret >= 0)) {
1363 LOS_FsUnlock();
1364 return MapToPosixRet((int)LOS_NOK);
1365 }
1366
1367 LOS_FsUnlock();
1368
1369 return MapToPosixRet((int)ret);
1370 }
1371
pwrite(int fd,const void * buff,size_t bytes,off_t off)1372 ssize_t pwrite(int fd, const void *buff, size_t bytes, off_t off)
1373 {
1374 ssize_t ret = (ssize_t)LOS_NOK;
1375 off_t savepos, pos;
1376
1377 if ((fd < 0) || (fd >= CONFIG_NFILE_DESCRIPTORS)) {
1378 return MapToPosixRet((int)ret);
1379 }
1380
1381 if (buff == NULL) {
1382 VFS_ERRNO_SET(EFAULT);
1383 return MapToPosixRet((int)ret);
1384 }
1385
1386 if (bytes == 0) {
1387 return 0;
1388 }
1389
1390 if (LOS_FsLock() != LOS_OK) {
1391 VFS_ERRNO_SET(EAGAIN);
1392 return MapToPosixRet((int)ret);
1393 }
1394
1395 savepos = lseek(fd, 0, SEEK_CUR);
1396 if (savepos == (off_t)-1) {
1397 LOS_FsUnlock();
1398 return MapToPosixRet((int)ret);
1399 }
1400
1401 pos = lseek(fd, off, SEEK_SET);
1402 if (pos == (off_t)-1) {
1403 LOS_FsUnlock();
1404 return MapToPosixRet((int)ret);
1405 }
1406
1407 ret = write(fd, buff, bytes);
1408 pos = lseek(fd, savepos, SEEK_SET);
1409 if ((pos == (off_t)-1) && (ret >= 0)) {
1410 LOS_FsUnlock();
1411 return MapToPosixRet((int)LOS_NOK);
1412 }
1413
1414 LOS_FsUnlock();
1415
1416 return MapToPosixRet((int)ret);
1417 }
1418