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 75int 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 93UINT32 g_fsMutex; 94static UINT32 g_dirNum = 0; 95 96int 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 109void 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 */ 131static 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 207static 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 229static 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 302static 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 333static struct File *VfsAttachFileReady(int fd) 334{ 335 return VfsAttachFile(fd, FILE_STATUS_READY); 336} 337 338static struct File *VfsAttachFileWithStatus(int fd, int status) 339{ 340 return VfsAttachFile(fd, (UINT32)status); 341} 342 343static void VfsDetachFile(const struct File *file) 344{ 345 (void)file; 346 LOS_FsUnlock(); 347} 348 349static 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 380static 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 413static 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 442static 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 465static 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 488static int MapToPosixRet(int ret) 489{ 490 return ((ret) < 0 ? -1 : (ret)); 491} 492 493/* POSIX interface */ 494int 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) 559FUNC_ALIAS(open, _open, (const char *path, int flags, ...), int); 560#endif 561 562int 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) 587FUNC_ALIAS(close, _close, (int fd), int); 588#endif 589 590ssize_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) 632FUNC_ALIAS(read, _read, (int fd, void *buff, size_t bytes), ssize_t); 633#endif 634 635ssize_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) 664FUNC_ALIAS(write, _write, (int fd, const void *buff, size_t bytes), ssize_t); 665#endif 666 667off_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) 687FUNC_ALIAS(lseek, _lseek, (int fd, off_t off, int whence), off_t); 688#endif 689 690int 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) 727FUNC_ALIAS(stat, _stat, (const char *path, struct stat *stat), int); 728#endif 729 730int 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 767int 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) 796FUNC_ALIAS(unlink, _unlink, (const char *path), int); 797#endif 798 799int 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 857int 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 883DIR *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 944struct 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 973int 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 1011int 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 1044int 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 1074int lstat(const char *path, struct stat *buffer) 1075{ 1076 return stat(path, buffer); 1077} 1078 1079int 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) 1092FUNC_ALIAS(fstat, _fstat, (int fd, struct stat *buf), int); 1093#endif 1094 1095int 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 1125int 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 1146ssize_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 1203ssize_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 1257int 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 1267int 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 1300int 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 1334ssize_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 1381ssize_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