1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-09-21
13 * Description: 文件系统vfs层
14 */
15
16 #define _GNU_SOURCE 1
17 #include <stdint.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <unistd.h>
22 #include <sys/uio.h>
23 #include <pthread.h>
24 #include "errno.h"
25 #include "fcntl.h"
26 #include "limits.h"
27 #include "securec.h"
28 #include "prt_fs.h"
29 #include "vfs_config.h"
30 #include "vfs_files.h"
31 #include "vfs_maps.h"
32 #include "vfs_mount.h"
33 #include "vfs_operations.h"
34 #include "prt_task.h"
35
36 #define FREE_AND_SET_NULL(ptr) do { \
37 free(ptr); \
38 ptr = NULL; \
39 } while (0)
40
41 static pthread_mutex_t g_vfsMutex = PTHREAD_MUTEX_INITIALIZER;
42
OsVfsLock(void)43 S32 OsVfsLock(void)
44 {
45 S32 ret = pthread_mutex_lock(&g_vfsMutex);
46 if (ret != 0) {
47 return FS_NOK;
48 }
49 return FS_OK;
50 }
51
OsVfsUnlock(void)52 void OsVfsUnlock(void)
53 {
54 (void)pthread_mutex_unlock(&g_vfsMutex);
55 return;
56 }
57
OsVfsOpen(const char * path,S32 flags,va_list ap)58 S32 OsVfsOpen(const char *path, S32 flags, va_list ap)
59 {
60 (void)ap;
61 struct TagFile *file = NULL;
62 S32 fd = -1;
63 const char *pathInMp = NULL;
64 struct TagMountPoint *mp = NULL;
65 TskHandle taskId = 0;
66
67 if ((path == NULL) || (path[strlen(path) - 1] == '/')) {
68 VFS_ERRNO_SET(EINVAL);
69 return fd;
70 }
71
72 if (OsVfsLock() != FS_OK) {
73 VFS_ERRNO_SET(EAGAIN);
74 return fd;
75 }
76
77 mp = OsVfsFindMp(path, &pathInMp);
78 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
79 (mp->mFs->fsFops == NULL) || (mp->mFs->fsFops->open == NULL)) {
80 VFS_ERRNO_SET(ENOENT);
81 OsVfsUnlock();
82 return fd;
83 }
84
85 if ((mp->mWriteEnable == FALSE) &&
86 (flags & (O_CREAT | O_WRONLY | O_RDWR))) {
87 VFS_ERRNO_SET(EACCES);
88 OsVfsUnlock();
89 return fd;
90 }
91
92 file = OsVfsGetFile();
93 if (file == NULL) {
94 VFS_ERRNO_SET(ENFILE);
95 OsVfsUnlock();
96 return fd;
97 }
98
99 file->fullPath = strdup(path);
100 if (file->fullPath == NULL) {
101 VFS_ERRNO_SET(ENOMEM);
102 OsVfsPutFile(file);
103 OsVfsUnlock();
104 return FS_NOK;
105 }
106
107 (void)PRT_TaskSelf(&taskId);
108 file->fFlags = (U32)flags;
109 file->fOffset = 0;
110 file->fData = NULL;
111 file->fFops = mp->mFs->fsFops;
112 file->fMp = mp;
113 file->fOwner = taskId;
114
115 if (file->fFops->open(file, pathInMp, flags) == 0) {
116 mp->mRefs++;
117 fd = OsFileToFd(file);
118 file->fStatus = FILE_STATUS_READY;
119 } else {
120 OsVfsPutFile(file);
121 }
122
123 OsVfsUnlock();
124 return fd;
125 }
126
OsVfsAttachFile(S32 fd,U32 status)127 static struct TagFile *OsVfsAttachFile(S32 fd, U32 status)
128 {
129 struct TagFile *file = NULL;
130
131 if ((fd < 0) || (fd >= CONFIG_NFILE_DESCRIPTORS)) {
132 VFS_ERRNO_SET(EBADF);
133 return NULL;
134 }
135
136 if (OsVfsLock() != FS_OK) {
137 VFS_ERRNO_SET(EFAULT);
138 return NULL;
139 }
140
141 file = OsFdToFile(fd);
142 if ((file == NULL) || (file->fMp == NULL)) {
143 VFS_ERRNO_SET(EBADF);
144 OsVfsUnlock();
145 return NULL;
146 }
147
148 if (file->fStatus != FILE_STATUS_READY) {
149 VFS_ERRNO_SET(EBADF);
150 OsVfsUnlock();
151 return NULL;
152 }
153
154 file->fStatus = status;
155 return file;
156 }
157
OsVfsAttachFileReady(S32 fd)158 static struct TagFile *OsVfsAttachFileReady(S32 fd)
159 {
160 return OsVfsAttachFile(fd, FILE_STATUS_READY);
161 }
162
OsVfsAttachFileWithStatus(S32 fd,S32 status)163 static struct TagFile *OsVfsAttachFileWithStatus(S32 fd, S32 status)
164 {
165 return OsVfsAttachFile(fd, (U32)status);
166 }
167
OsVfsDetachFile(const struct TagFile * file)168 static void OsVfsDetachFile(const struct TagFile *file)
169 {
170 (void)file;
171 OsVfsUnlock();
172 }
173
OsVfsClose(S32 fd)174 S32 OsVfsClose(S32 fd)
175 {
176 S32 ret = FS_NOK;
177 struct TagFile *file = OsVfsAttachFileWithStatus(fd, FILE_STATUS_CLOSING);
178 if (file == NULL) {
179 return ret;
180 }
181
182 if ((file->fFops != NULL) && (file->fFops->close != NULL)) {
183 ret = file->fFops->close(file);
184 } else {
185 VFS_ERRNO_SET(ENOTSUP);
186 }
187
188 if ((ret == 0) && (file->fMp != NULL)) {
189 file->fMp->mRefs--;
190 }
191
192 if (file->fullPath != NULL) {
193 free((void *)file->fullPath);
194 }
195
196 OsVfsDetachFile(file);
197 OsVfsPutFile(file);
198 return ret;
199 }
200
OsVfsRead(S32 fd,char * buff,size_t bytes)201 ssize_t OsVfsRead(S32 fd, char *buff, size_t bytes)
202 {
203 struct TagFile *file = NULL;
204 ssize_t ret = (ssize_t)-1;
205
206 if (buff == NULL) {
207 VFS_ERRNO_SET(EFAULT);
208 return ret;
209 }
210
211 if (bytes == 0) {
212 return 0;
213 }
214
215 file = OsVfsAttachFileReady(fd);
216 if (file == NULL) {
217 return ret;
218 }
219
220 if ((file->fFlags & O_ACCMODE) == O_WRONLY) {
221 VFS_ERRNO_SET(EACCES);
222 } else if ((file->fFops != NULL) && (file->fFops->read != NULL)) {
223 ret = file->fFops->read(file, buff, bytes);
224 } else {
225 VFS_ERRNO_SET(ENOTSUP);
226 }
227
228 OsVfsDetachFile(file);
229 return ret;
230 }
231
OsVfsWrite(S32 fd,const void * buff,size_t bytes)232 ssize_t OsVfsWrite(S32 fd, const void *buff, size_t bytes)
233 {
234 struct TagFile *file = NULL;
235 ssize_t ret = (ssize_t)FS_NOK;
236
237 if ((buff == NULL) || (bytes == 0)) {
238 VFS_ERRNO_SET(EINVAL);
239 return ret;
240 }
241
242 file = OsVfsAttachFileReady(fd);
243 if (file == NULL) {
244 return ret;
245 }
246
247 if ((file->fFlags & O_ACCMODE) == O_RDONLY) {
248 VFS_ERRNO_SET(EACCES);
249 } else if ((file->fFops != NULL) && (file->fFops->write != NULL)) {
250 ret = file->fFops->write(file, buff, bytes);
251 } else {
252 VFS_ERRNO_SET(ENOTSUP);
253 }
254
255 OsVfsDetachFile(file);
256 return ret;
257 }
258
OsVfsLseek(S32 fd,off_t off,S32 whence)259 off_t OsVfsLseek(S32 fd, off_t off, S32 whence)
260 {
261 off_t ret = (off_t)FS_NOK;
262 struct TagFile *file = OsVfsAttachFileReady(fd);
263 if (file == NULL) {
264 return ret;
265 }
266
267 if ((file->fFops == NULL) || (file->fFops->lseek == NULL)) {
268 ret = file->fOffset;
269 } else {
270 ret = file->fFops->lseek(file, off, whence);
271 }
272
273 OsVfsDetachFile(file);
274 return ret;
275 }
276
OsVfsStat(const char * path,struct stat * stat)277 S32 OsVfsStat(const char *path, struct stat *stat)
278 {
279 struct TagMountPoint *mp = NULL;
280 const char *pathInMp = NULL;
281 S32 ret = FS_NOK;
282
283 if ((path == NULL) || (stat == NULL)) {
284 VFS_ERRNO_SET(EINVAL);
285 return ret;
286 }
287
288 if (OsVfsLock() != FS_OK) {
289 VFS_ERRNO_SET(EAGAIN);
290 return ret;
291 }
292
293 mp = OsVfsFindMp(path, &pathInMp);
294 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
295 VFS_ERRNO_SET(ENOENT);
296 OsVfsUnlock();
297 return ret;
298 }
299
300 if (mp->mFs->fsFops->stat != NULL) {
301 ret = mp->mFs->fsFops->stat(mp, pathInMp, stat);
302 } else {
303 VFS_ERRNO_SET(ENOTSUP);
304 }
305
306 OsVfsUnlock();
307 return ret;
308 }
309
OsVfsFstat(S32 fd,struct stat * buf)310 S32 OsVfsFstat(S32 fd, struct stat *buf)
311 {
312 S32 ret;
313 struct TagFile *filep = OsVfsAttachFileReady(fd);
314 if ((filep == NULL) || (filep->fMp == NULL) || filep->fullPath == NULL) {
315 return FS_NOK;
316 }
317 ret = stat(filep->fullPath, buf);
318 OsVfsDetachFile(filep);
319 return ret;
320 }
321
OsVfsStatfs(const char * path,struct statfs * buf)322 S32 OsVfsStatfs(const char *path, struct statfs *buf)
323 {
324 struct TagMountPoint *mp = NULL;
325 const char *pathInMp = NULL;
326 S32 ret = FS_NOK;
327
328 if ((path == NULL) || (buf == NULL)) {
329 VFS_ERRNO_SET(EINVAL);
330 return ret;
331 }
332
333 if (OsVfsLock() != FS_OK) {
334 VFS_ERRNO_SET(EAGAIN);
335 return ret;
336 }
337
338 mp = OsVfsFindMp(path, &pathInMp);
339 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
340 VFS_ERRNO_SET(ENOENT);
341 OsVfsUnlock();
342 return ret;
343 }
344
345 if (mp->mFs->fsFops->stat != NULL) {
346 ret = mp->mFs->fsMops->statfs(pathInMp, buf);
347 } else {
348 VFS_ERRNO_SET(ENOTSUP);
349 }
350
351 OsVfsUnlock();
352 return ret;
353 }
354
OsVfsUnlink(const char * path)355 S32 OsVfsUnlink(const char *path)
356 {
357 struct TagMountPoint *mp = NULL;
358 const char *pathInMp = NULL;
359 S32 ret = FS_NOK;
360
361 if (path == NULL) {
362 VFS_ERRNO_SET(EINVAL);
363 return ret;
364 }
365
366 if (OsVfsLock() != FS_OK) {
367 VFS_ERRNO_SET(EAGAIN);
368 return ret;
369 }
370
371 mp = OsVfsFindMp(path, &pathInMp);
372 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0') ||
373 (mp->mFs->fsFops->unlink == NULL)) {
374 VFS_ERRNO_SET(ENOENT);
375 OsVfsUnlock();
376 return ret;
377 }
378
379 ret = mp->mFs->fsFops->unlink(mp, pathInMp);
380
381 OsVfsUnlock();
382 return ret;
383 }
384
OsVfsRename(const char * oldName,const char * newName)385 S32 OsVfsRename(const char *oldName, const char *newName)
386 {
387 struct TagMountPoint *mpOld = NULL;
388 struct TagMountPoint *mpNew = NULL;
389 const char *pathInMpOld = NULL;
390 const char *pathInMpNew = NULL;
391 S32 ret = FS_NOK;
392
393 if ((oldName == NULL) || (newName == NULL)) {
394 VFS_ERRNO_SET(EINVAL);
395 return ret;
396 }
397
398 if (OsVfsLock() != FS_OK) {
399 VFS_ERRNO_SET(EAGAIN);
400 return ret;
401 }
402
403 mpOld = OsVfsFindMp(oldName, &pathInMpOld);
404
405 if (pathInMpOld == NULL) {
406 VFS_ERRNO_SET(EINVAL);
407 OsVfsUnlock();
408 return ret;
409 }
410
411 if ((mpOld == NULL) || (*pathInMpOld == '\0') ||
412 (mpOld->mFs->fsFops->unlink == NULL)) {
413 VFS_ERRNO_SET(EINVAL);
414 OsVfsUnlock();
415 return ret;
416 }
417
418 mpNew = OsVfsFindMp(newName, &pathInMpNew);
419 if ((mpNew == NULL) || (pathInMpNew == NULL) || (*pathInMpNew == '\0') || (mpNew->mFs->fsFops->unlink == NULL)) {
420 VFS_ERRNO_SET(EINVAL);
421 OsVfsUnlock();
422 return ret;
423 }
424
425 if (mpOld != mpNew) {
426 VFS_ERRNO_SET(EXDEV);
427 OsVfsUnlock();
428 return ret;
429 }
430
431 if (mpOld->mFs->fsFops->rename != NULL) {
432 ret = mpOld->mFs->fsFops->rename(mpOld, pathInMpOld, pathInMpNew);
433 } else {
434 VFS_ERRNO_SET(ENOTSUP);
435 }
436
437 OsVfsUnlock();
438 return ret;
439 }
440
OsVfsIoctl(S32 fd,S32 func,unsigned long arg)441 S32 OsVfsIoctl(S32 fd, S32 func, unsigned long arg)
442 {
443 S32 ret = FS_NOK;
444 struct TagFile *file = OsVfsAttachFileReady(fd);
445 if (file == NULL) {
446 return ret;
447 }
448
449 if ((file->fFops != NULL) && (file->fFops->ioctl != NULL)) {
450 ret = file->fFops->ioctl(file, func, arg);
451 } else {
452 VFS_ERRNO_SET(ENOTSUP);
453 }
454
455 OsVfsDetachFile(file);
456 return ret;
457 }
458
OsVfsSync(S32 fd)459 S32 OsVfsSync(S32 fd)
460 {
461 S32 ret = FS_NOK;
462 struct TagFile *file = OsVfsAttachFileReady(fd);
463 if (file == NULL) {
464 return ret;
465 }
466
467 if (file->fMp->mWriteEnable == FALSE) {
468 VFS_ERRNO_SET(EACCES);
469 OsVfsDetachFile(file);
470 return ret;
471 }
472
473 if ((file->fFops != NULL) && (file->fFops->sync != NULL)) {
474 ret = file->fFops->sync(file);
475 } else {
476 VFS_ERRNO_SET(ENOTSUP);
477 }
478
479 OsVfsDetachFile(file);
480 return ret;
481 }
482
OsVfsOpendir(const char * path)483 DIR *OsVfsOpendir(const char *path)
484 {
485 struct TagMountPoint *mp = NULL;
486 const char *pathInMp = NULL;
487 struct TagDir *dir = NULL;
488 U32 ret;
489
490 if (path == NULL) {
491 VFS_ERRNO_SET(EINVAL);
492 return NULL;
493 }
494
495 dir = (struct TagDir *)malloc(sizeof(struct TagDir));
496 if (dir == NULL) {
497 VFS_ERRNO_SET(ENOMEM);
498 return NULL;
499 }
500
501 if (OsVfsLock() != FS_OK) {
502 VFS_ERRNO_SET(EAGAIN);
503 free(dir);
504 return NULL;
505 }
506
507 mp = OsVfsFindMp(path, &pathInMp);
508 if ((mp == NULL) || (pathInMp == NULL)) {
509 VFS_ERRNO_SET(ENOENT);
510 OsVfsUnlock();
511 free(dir);
512 return NULL;
513 }
514
515 if (mp->mFs->fsFops->opendir == NULL) {
516 VFS_ERRNO_SET(ENOTSUP);
517 OsVfsUnlock();
518 free(dir);
519 return NULL;
520 }
521
522 dir->dMp = mp;
523 dir->dOffset = 0;
524
525 ret = (U32)mp->mFs->fsFops->opendir(dir, pathInMp);
526 if (ret == 0) {
527 mp->mRefs++;
528 } else {
529 free(dir);
530 dir = NULL;
531 }
532
533 OsVfsUnlock();
534 return (DIR *)dir;
535 }
536
OsVfsReaddir(DIR * d)537 struct dirent *OsVfsReaddir(DIR *d)
538 {
539 struct dirent *ret = NULL;
540 struct TagDir *dir = (struct TagDir *)d;
541
542 if ((dir == NULL) || (dir->dMp == NULL)) {
543 VFS_ERRNO_SET(EINVAL);
544 return NULL;
545 }
546
547 if (OsVfsLock() != FS_OK) {
548 VFS_ERRNO_SET(EAGAIN);
549 return NULL;
550 }
551
552 if ((dir->dMp->mFs != NULL) && (dir->dMp->mFs->fsFops != NULL) &&
553 (dir->dMp->mFs->fsFops->readdir != NULL)) {
554 if (dir->dMp->mFs->fsFops->readdir(dir, &dir->dDent) == 0) {
555 ret = &dir->dDent;
556 }
557 } else {
558 VFS_ERRNO_SET(ENOTSUP);
559 }
560
561 OsVfsUnlock();
562 return ret;
563 }
564
OsVfsClosedir(DIR * d)565 S32 OsVfsClosedir(DIR *d)
566 {
567 struct TagMountPoint *mp = NULL;
568 S32 ret = FS_NOK;
569 struct TagDir *dir = (struct TagDir *)d;
570
571 if ((dir == NULL) || (dir->dMp == NULL)) {
572 VFS_ERRNO_SET(EBADF);
573 return ret;
574 }
575
576 mp = dir->dMp;
577
578 if (OsVfsLock() != FS_OK) {
579 VFS_ERRNO_SET(EAGAIN);
580 return ret;
581 }
582
583 if ((dir->dMp->mFs != NULL) && (dir->dMp->mFs->fsFops != NULL) &&
584 (dir->dMp->mFs->fsFops->closedir != NULL)) {
585 ret = dir->dMp->mFs->fsFops->closedir(dir);
586 } else {
587 VFS_ERRNO_SET(ENOTSUP);
588 }
589
590 if (ret == 0) {
591 mp->mRefs--;
592 } else {
593 VFS_ERRNO_SET(EBADF);
594 }
595
596 OsVfsUnlock();
597 free(dir);
598 dir = NULL;
599 return ret;
600 }
601
OsVfsMkdir(const char * path,S32 mode)602 S32 OsVfsMkdir(const char *path, S32 mode)
603 {
604 struct TagMountPoint *mp = NULL;
605 const char *pathInMp = NULL;
606 S32 ret = FS_NOK;
607 (void)mode;
608
609 if (path == NULL) {
610 VFS_ERRNO_SET(EINVAL);
611 return ret;
612 }
613
614 if (OsVfsLock() != FS_OK) {
615 VFS_ERRNO_SET(EAGAIN);
616 return ret;
617 }
618
619 mp = OsVfsFindMp(path, &pathInMp);
620 if ((mp == NULL) || (pathInMp == NULL) || (*pathInMp == '\0')) {
621 VFS_ERRNO_SET(ENOENT);
622 OsVfsUnlock();
623 return ret;
624 }
625
626 if (mp->mFs->fsFops->mkdir != NULL) {
627 ret = mp->mFs->fsFops->mkdir(mp, pathInMp);
628 } else {
629 VFS_ERRNO_SET(ENOTSUP);
630 ret = FS_NOK;
631 }
632
633 OsVfsUnlock();
634 return ret;
635 }
636
OsVfsFcntl(S32 fd,S32 cmd,va_list ap)637 S32 OsVfsFcntl(S32 fd, S32 cmd, va_list ap)
638 {
639 S32 ret = FS_NOK;
640 U32 flags;
641 struct TagFile *filep = OsVfsAttachFileReady(fd);
642 if (filep == NULL) {
643 return ret;
644 }
645
646 if (filep->fFops == NULL) {
647 VFS_ERRNO_SET(EBADF);
648 OsVfsDetachFile(filep);
649 return ret;
650 }
651
652 if (cmd == F_GETFL) {
653 ret = (S32)(filep->fFlags);
654 } else if (cmd == F_SETFL) {
655 flags = (U32)va_arg(ap, S32);
656 flags &= PRT_FCNTL;
657 filep->fFlags &= ~PRT_FCNTL;
658 filep->fFlags |= flags;
659 ret = FS_OK;
660 } else {
661 VFS_ERRNO_SET(ENOSYS);
662 }
663 OsVfsDetachFile(filep);
664 va_end(ap);
665 return ret;
666 }
667
OsVfsPread(S32 fd,void * buff,size_t bytes,off_t off)668 ssize_t OsVfsPread(S32 fd, void *buff, size_t bytes, off_t off)
669 {
670 off_t savepos, pos;
671 ssize_t ret;
672
673 if (buff == NULL) {
674 VFS_ERRNO_SET(EFAULT);
675 return (ssize_t)FS_NOK;
676 }
677
678 if (bytes == 0) {
679 return 0;
680 }
681
682 if (OsVfsLock() != FS_OK) {
683 VFS_ERRNO_SET(EAGAIN);
684 return (ssize_t)FS_NOK;
685 }
686
687 savepos = lseek(fd, 0, SEEK_CUR);
688 if (savepos == (off_t)-1) {
689 OsVfsUnlock();
690 return (ssize_t)FS_NOK;
691 }
692
693 pos = lseek(fd, off, SEEK_SET);
694 if (pos == (off_t)-1) {
695 OsVfsUnlock();
696 return (ssize_t)FS_NOK;
697 }
698
699 ret = read(fd, buff, bytes);
700 pos = lseek(fd, savepos, SEEK_SET);
701 if ((pos == (off_t)-1) && (ret >= 0)) {
702 OsVfsUnlock();
703 return (ssize_t)FS_NOK;
704 }
705
706 OsVfsUnlock();
707 return ret;
708 }
709
OsVfsPwrite(S32 fd,const void * buff,size_t bytes,off_t off)710 ssize_t OsVfsPwrite(S32 fd, const void *buff, size_t bytes, off_t off)
711 {
712 ssize_t ret;
713 off_t savepos, pos;
714
715 if (buff == NULL) {
716 VFS_ERRNO_SET(EFAULT);
717 return (ssize_t)FS_NOK;
718 }
719
720 if (bytes == 0) {
721 return 0;
722 }
723
724 if (OsVfsLock() != FS_OK) {
725 VFS_ERRNO_SET(EAGAIN);
726 return (ssize_t)FS_NOK;
727 }
728
729 savepos = lseek(fd, 0, SEEK_CUR);
730 if (savepos == (off_t)-1) {
731 OsVfsUnlock();
732 return (ssize_t)FS_NOK;
733 }
734
735 pos = lseek(fd, off, SEEK_SET);
736 if (pos == (off_t)-1) {
737 OsVfsUnlock();
738 return (ssize_t)FS_NOK;
739 }
740
741 ret = write(fd, buff, bytes);
742 pos = lseek(fd, savepos, SEEK_SET);
743 if ((pos == (off_t)-1) && (ret >= 0)) {
744 OsVfsUnlock();
745 return (ssize_t)FS_NOK;
746 }
747
748 OsVfsUnlock();
749 return ret;
750 }
751
OsVfsFtruncate(S32 fd,off_t length)752 S32 OsVfsFtruncate(S32 fd, off_t length)
753 {
754 S32 ret = FS_NOK;
755 struct TagFile *file = NULL;
756
757 if (length <= 0) {
758 VFS_ERRNO_SET(EINVAL);
759 return ret;
760 }
761
762 file = OsVfsAttachFileReady(fd);
763 if (file == NULL) {
764 return ret;
765 }
766
767 if (file->fMp->mWriteEnable == FALSE) {
768 VFS_ERRNO_SET(EACCES);
769 OsVfsDetachFile(file);
770 return ret;
771 }
772
773 if ((file->fFlags & O_ACCMODE) == O_RDONLY) {
774 VFS_ERRNO_SET(EACCES);
775 } else if ((file->fFops != NULL) && (file->fFops->truncate != NULL)) {
776 ret = file->fFops->truncate(file, length);
777 } else {
778 VFS_ERRNO_SET(ENOTSUP);
779 }
780
781 OsVfsDetachFile(file);
782 return ret;
783 }
784
OsVfsReadv(S32 fd,const struct iovec * iovBuf,S32 iovcnt)785 ssize_t OsVfsReadv(S32 fd, const struct iovec *iovBuf, S32 iovcnt)
786 {
787 S32 i;
788 errno_t ret;
789 char *buf = NULL;
790 char *curBuf = NULL;
791 char *readBuf = NULL;
792 size_t bufLen = 0;
793 size_t bytesToRead;
794 ssize_t totalBytesRead;
795 size_t totalLen;
796 const struct iovec *iov = (const struct iovec *)iovBuf;
797
798 if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) {
799 return (ssize_t)FS_NOK;
800 }
801
802 for (i = 0; i < iovcnt; ++i) {
803 if ((SSIZE_MAX - bufLen) < iov[i].iov_len) {
804 return (ssize_t)FS_NOK;
805 }
806 bufLen += iov[i].iov_len;
807 }
808 if (bufLen == 0) {
809 return (ssize_t)FS_NOK;
810 }
811 totalLen = bufLen * sizeof(char);
812 buf = (char *)malloc(totalLen);
813 if (buf == NULL) {
814 return (ssize_t)FS_NOK;
815 }
816
817 totalBytesRead = read(fd, buf, bufLen);
818 if ((size_t)totalBytesRead < totalLen) {
819 totalLen = (size_t)totalBytesRead;
820 }
821 curBuf = buf;
822 for (i = 0; i < iovcnt; ++i) {
823 readBuf = (char *)iov[i].iov_base;
824 bytesToRead = iov[i].iov_len;
825
826 size_t lenToRead = totalLen < bytesToRead ? totalLen : bytesToRead;
827 ret = memcpy_s(readBuf, bytesToRead, curBuf, lenToRead);
828 if (ret != EOK) {
829 free(buf);
830 return (ssize_t)FS_NOK;
831 }
832 if (totalLen < (size_t)bytesToRead) {
833 break;
834 }
835 curBuf += bytesToRead;
836 totalLen -= bytesToRead;
837 }
838 free(buf);
839 return totalBytesRead;
840 }
841
OsVfsWritev(S32 fd,const struct iovec * iovBuf,S32 iovcnt)842 ssize_t OsVfsWritev(S32 fd, const struct iovec *iovBuf, S32 iovcnt)
843 {
844 S32 i;
845 errno_t ret;
846 char *buf = NULL;
847 char *curBuf = NULL;
848 char *writeBuf = NULL;
849 size_t bufLen = 0;
850 size_t bytesToWrite;
851 ssize_t totalBytesWritten;
852 size_t totalLen;
853 const struct iovec *iov = iovBuf;
854
855 if ((iov == NULL) || (iovcnt <= 0) || (iovcnt > IOV_MAX_CNT)) {
856 return (ssize_t)FS_NOK;
857 }
858
859 for (i = 0; i < iovcnt; ++i) {
860 if ((SSIZE_MAX - bufLen) < iov[i].iov_len) {
861 VFS_ERRNO_SET(EINVAL);
862 return (ssize_t)FS_NOK;
863 }
864 bufLen += iov[i].iov_len;
865 }
866 if (bufLen == 0) {
867 return (ssize_t)FS_NOK;
868 }
869 totalLen = bufLen * sizeof(char);
870 buf = (char *)malloc(totalLen);
871 if (buf == NULL) {
872 return (ssize_t)FS_NOK;
873 }
874 curBuf = buf;
875 for (i = 0; i < iovcnt; ++i) {
876 writeBuf = (char *)iov[i].iov_base;
877 bytesToWrite = iov[i].iov_len;
878 if (((ssize_t)totalLen <= 0) || ((ssize_t)bytesToWrite <= 0)) {
879 continue;
880 }
881 ret = memcpy_s(curBuf, totalLen, writeBuf, bytesToWrite);
882 if (ret != EOK) {
883 free(buf);
884 return (ssize_t)FS_NOK;
885 }
886 curBuf += bytesToWrite;
887 totalLen -= bytesToWrite;
888 }
889
890 totalBytesWritten = write(fd, buf, bufLen);
891 free(buf);
892
893 return totalBytesWritten;
894 }
895