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