1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2022 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #define _GNU_SOURCE 1
33 #include "ff.h"
34 #include "fatfs.h"
35 #include "errno.h"
36 #include "stdbool.h"
37 #include "limits.h"
38 #include "pthread.h"
39 #include "time.h"
40 #include "securec.h"
41 #include "los_compiler.h"
42 #include "los_debug.h"
43 #include "los_sched.h"
44 #include "vfs_files.h"
45 #include "vfs_operations.h"
46 #include "vfs_partition.h"
47 #include "vfs_maps.h"
48 #include "vfs_mount.h"
49 #include "los_fs.h"
50
51 /* the max name length of different parts should not bigger than 32 */
52 #define FS_DRIVE_NAME_MAX_LEN 32
53
54 #ifndef FAT_MAX_OPEN_DIRS
55 #define FAT_MAX_OPEN_DIRS 8
56 #endif /* FAT_MAX_OPEN_DIRS */
57
58 #ifndef FS_LOCK_TIMEOUT_SEC
59 #define FS_LOCK_TIMEOUT_SEC 15
60 #endif /* FS_LOCK_TIMEOUT_SEC */
61
62 static UINT8 g_workBuffer[FF_MAX_SS];
63 static char *g_volPath[FF_VOLUMES] = {FF_VOLUME_STRS};
64
65 PARTITION VolToPart[] = {
66 { 0, 0, 1, 0, 0 },
67 { 0, 0, 2, 0, 0 },
68 { 0, 0, 3, 0, 0 },
69 { 0, 0, 4, 0, 0 }
70 };
71
FsChangeDrive(const char * path)72 static int FsChangeDrive(const char *path)
73 {
74 INT32 res;
75 errno_t retErr;
76 UINT16 pathLen = strlen((char const *)path);
77 /* the max name length of different parts is 16 */
78 CHAR tmpPath[FS_DRIVE_NAME_MAX_LEN] = { "/" };
79
80 /* make sure the path begin with "/", the path like /xxx/yyy/... */
81 if (pathLen >= (FS_DRIVE_NAME_MAX_LEN - 1)) {
82 /* 2: except first flag "/" and last end flag */
83 pathLen = FS_DRIVE_NAME_MAX_LEN - 2;
84 }
85
86 retErr = strncpy_s(tmpPath + 1, (FS_DRIVE_NAME_MAX_LEN - 1), (char const *)path, pathLen);
87 if (retErr != EOK) {
88 return (int)LOS_NOK;
89 }
90
91 res = f_chdrive(tmpPath);
92 if (res != FR_OK) {
93 return (int)LOS_NOK;
94 }
95
96 return (int)LOS_OK;
97 }
98
Remount(struct MountPoint * mp,unsigned long mountflags)99 static int Remount(struct MountPoint *mp, unsigned long mountflags)
100 {
101 FATFS *fatfs = (FATFS *)mp->mData;
102
103 /* remount is not allowed when the device is not mounted. */
104 if (fatfs->fs_type == 0) {
105 errno = EINVAL;
106 return (int)LOS_NOK;
107 }
108 mp->mWriteEnable = (mountflags & MS_RDONLY) ? FALSE : TRUE;
109
110 return (int)LOS_OK;
111 }
112
FatFsGetMode(int oflags)113 static unsigned int FatFsGetMode(int oflags)
114 {
115 UINT32 fmode = FA_READ;
116
117 if ((UINT32)oflags & O_WRONLY) {
118 fmode |= FA_WRITE;
119 }
120
121 if (((UINT32)oflags & O_ACCMODE) & O_RDWR) {
122 fmode |= FA_WRITE;
123 }
124 /* Creates a new file if the file is not existing, otherwise, just open it. */
125 if ((UINT32)oflags & O_CREAT) {
126 fmode |= FA_OPEN_ALWAYS;
127 /* Creates a new file. If the file already exists, the function shall fail. */
128 if ((UINT32)oflags & O_EXCL) {
129 fmode |= FA_CREATE_NEW;
130 }
131 }
132 /* Creates a new file. If the file already exists, its length shall be truncated to 0. */
133 if ((UINT32)oflags & O_TRUNC) {
134 fmode |= FA_CREATE_ALWAYS;
135 }
136
137 return fmode;
138 }
139
FatfsErrno(int result)140 static int FatfsErrno(int result)
141 {
142 INT32 status = 0;
143
144 if (result < 0) {
145 return result;
146 }
147
148 /* FatFs errno to Libc errno */
149 switch (result) {
150 case FR_OK:
151 break;
152
153 case FR_NO_FILE:
154 case FR_NO_PATH:
155 case FR_NO_FILESYSTEM:
156 status = ENOENT;
157 break;
158
159 case FR_INVALID_NAME:
160 status = EINVAL;
161 break;
162
163 case FR_EXIST:
164 case FR_INVALID_OBJECT:
165 status = EEXIST;
166 break;
167
168 case FR_DISK_ERR:
169 case FR_NOT_READY:
170 case FR_INT_ERR:
171 status = EIO;
172 break;
173
174 case FR_WRITE_PROTECTED:
175 status = EROFS;
176 break;
177 case FR_MKFS_ABORTED:
178 case FR_INVALID_PARAMETER:
179 status = EINVAL;
180 break;
181
182 case FR_NO_SPACE_LEFT:
183 status = ENOSPC;
184 break;
185 case FR_NO_DIRENTRY:
186 status = ENFILE;
187 break;
188 case FR_NO_EMPTY_DIR:
189 status = ENOTEMPTY;
190 break;
191 case FR_IS_DIR:
192 status = EISDIR;
193 break;
194 case FR_NO_DIR:
195 status = ENOTDIR;
196 break;
197 case FR_NO_EPERM:
198 case FR_DENIED:
199 status = EPERM;
200 break;
201 case FR_LOCKED:
202 status = EBUSY;
203 break;
204 default:
205 status = result;
206 break;
207 }
208
209 return status;
210 }
211
GetLdPath(const char * source)212 char * GetLdPath(const char *source)
213 {
214 #define LDPATH_PAD 2 // 2 means: strlen("/") + len of '\0'
215 int ret;
216 int partId = GetPartIdByPartName(source);
217 if ((partId < 0) || (partId >= MAX_PARTITION_NUM)) {
218 return NULL;
219 }
220
221 char *volPath = g_volPath[partId];
222 char *ldPath = (char *)LOSCFG_FS_MALLOC_HOOK(strlen(volPath) + LDPATH_PAD);
223 if (ldPath == NULL) {
224 return NULL;
225 }
226
227 (void)memset_s(ldPath, strlen(volPath) + LDPATH_PAD, 0, strlen(volPath) + LDPATH_PAD);
228
229 /* Convert volPath to ldpath, for example, convert "inner" to "/inner" */
230 *ldPath = '/';
231 ret = strcpy_s(ldPath + 1, strlen(volPath)+1, volPath);
232 if (ret != EOK) {
233 LOSCFG_FS_FREE_HOOK(ldPath);
234 return NULL;
235 }
236
237 return ldPath;
238 }
239
PutLdPath(const char * ldPath)240 void PutLdPath(const char *ldPath)
241 {
242 if (ldPath != NULL) {
243 LOSCFG_FS_FREE_HOOK((void *)ldPath);
244 }
245 }
246
FatfsMount(struct MountPoint * mp,unsigned long mountflags,const void * data)247 int FatfsMount(struct MountPoint *mp, unsigned long mountflags,
248 const void *data)
249 {
250 FRESULT res;
251 FATFS *fs = NULL;
252
253 if (mountflags & MS_REMOUNT) {
254 return Remount(mp, mountflags);
255 }
256
257 char *ldPath = GetLdPath(mp->mDev);
258 if (ldPath == NULL) {
259 errno = EFAULT;
260 return (int)LOS_NOK;
261 }
262
263 fs = (FATFS *)LOSCFG_FS_MALLOC_HOOK(sizeof(FATFS));
264 if (fs == NULL) {
265 errno = ENOMEM;
266 PutLdPath(ldPath);
267 return (int)LOS_NOK;
268 }
269 (void)memset_s(fs, sizeof(FATFS), 0, sizeof(FATFS));
270
271 res = f_mount(fs, ldPath, 1);
272 if (res != FR_OK) {
273 LOSCFG_FS_FREE_HOOK(fs);
274 PutLdPath(ldPath);
275 errno = FatfsErrno(res);
276 return (int)LOS_NOK;
277 }
278 mp->mData = (void *)fs;
279
280 PutLdPath(ldPath);
281 return (int)LOS_OK;
282 }
283
FatfsUmount(struct MountPoint * mp)284 int FatfsUmount(struct MountPoint *mp)
285 {
286 int volId;
287 FRESULT res;
288 char *ldPath = NULL;
289 FATFS *fatfs = (FATFS *)mp->mData;
290
291 /* The volume is not mounted */
292 if (fatfs->fs_type == 0) {
293 errno = EINVAL;
294 return (int)LOS_NOK;
295 }
296
297 volId = GetPartIdByPartName(mp->mDev);
298 /* umount is not allowed when a file or directory is opened. */
299 if (f_checkopenlock(volId) != FR_OK) {
300 errno = EBUSY;
301 return (int)LOS_NOK;
302 }
303
304 ldPath = GetLdPath(mp->mDev);
305 if (ldPath == NULL) {
306 errno = EFAULT;
307 return (int)LOS_NOK;
308 }
309
310 res = f_mount((FATFS *)NULL, ldPath, 0);
311 if (res != FR_OK) {
312 errno = FatfsErrno(res);
313 PutLdPath(ldPath);
314 return (int)LOS_NOK;
315 }
316
317 if (fatfs->win != NULL) {
318 ff_memfree(fatfs->win);
319 }
320
321 LOSCFG_FS_FREE_HOOK(mp->mData);
322 mp->mData = NULL;
323
324 PutLdPath(ldPath);
325 return (int)LOS_OK;
326 }
327
FatfsUmount2(struct MountPoint * mp,int flag)328 int FatfsUmount2(struct MountPoint *mp, int flag)
329 {
330 UINT32 flags;
331 FRESULT res;
332 char *ldPath = NULL;
333 FATFS *fatfs = (FATFS *)mp->mData;
334
335 flags = MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW;
336 if ((UINT32)flag & ~flags) {
337 errno = EINVAL;
338 return (int)LOS_NOK;
339 }
340
341 /* The volume is not mounted */
342 if (fatfs->fs_type == 0) {
343 errno = EINVAL;
344 return (int)LOS_NOK;
345 }
346
347 ldPath = GetLdPath(mp->mDev);
348 if (ldPath == NULL) {
349 errno = EFAULT;
350 return (int)LOS_NOK;
351 }
352
353 res = f_mount((FATFS *)NULL, ldPath, 0);
354 if (res != FR_OK) {
355 PutLdPath(ldPath);
356 errno = FatfsErrno(res);
357 return (int)LOS_NOK;
358 }
359
360 if (fatfs->win != NULL) {
361 ff_memfree(fatfs->win);
362 }
363
364 LOSCFG_FS_FREE_HOOK(mp->mData);
365 mp->mData = NULL;
366
367 PutLdPath(ldPath);
368 return (int)LOS_OK;
369 }
370
FatfsOpen(struct File * file,const char * path,int oflag)371 int FatfsOpen(struct File *file, const char *path, int oflag)
372 {
373 FRESULT res;
374 UINT32 fmode;
375 FIL *fp = NULL;
376 int ret;
377
378 if (path == NULL) {
379 errno = EFAULT;
380 return (int)LOS_NOK;
381 }
382
383 fmode = FatFsGetMode(oflag);
384
385 fp = (FIL *)LOSCFG_FS_MALLOC_HOOK(sizeof(FIL));
386 if (fp == NULL) {
387 errno = ENOMEM;
388 return (int)LOS_NOK;
389 }
390
391 ret = FsChangeDrive(path);
392 if (ret != (int)LOS_OK) {
393 PRINT_ERR("FAT open ChangeDrive err 0x%x!\r\n", ret);
394 errno = ENOENT;
395 LOSCFG_FS_FREE_HOOK(fp);
396 return (int)LOS_NOK;
397 }
398
399 res = f_open(fp, path, fmode);
400 if (res != FR_OK) {
401 PRINT_ERR("FAT open err 0x%x!\r\n", res);
402 LOSCFG_FS_FREE_HOOK(fp);
403 errno = FatfsErrno(res);
404 return (int)LOS_NOK;
405 }
406
407 file->fData = (void *)fp;
408
409 return (int)LOS_OK;
410 }
411
FatfsClose(struct File * file)412 int FatfsClose(struct File *file)
413 {
414 FRESULT res;
415 FIL *fp = (FIL *)file->fData;
416
417 if ((fp == NULL) || (fp->obj.fs == NULL)) {
418 errno = ENOENT;
419 return (int)LOS_NOK;
420 }
421
422 res = f_close(fp);
423 if (res != FR_OK) {
424 PRINT_ERR("FAT close err 0x%x!\r\n", res);
425 errno = FatfsErrno(res);
426 return (int)LOS_NOK;
427 }
428
429 #if !FF_FS_TINY
430 if (fp->buf != NULL) {
431 (void)ff_memfree(fp->buf);
432 }
433 #endif
434 LOSCFG_FS_FREE_HOOK(file->fData);
435 file->fData = NULL;
436
437 return (int)LOS_OK;
438 }
439
FatfsRead(struct File * file,char * buf,size_t nbyte)440 ssize_t FatfsRead(struct File *file, char *buf, size_t nbyte)
441 {
442 FRESULT res;
443 UINT32 lenRead;
444 FIL *fp = (FIL *)file->fData;
445
446 if (buf == NULL) {
447 errno = EFAULT;
448 return (ssize_t)LOS_NOK;
449 }
450
451 if (fp == NULL) {
452 errno = ENOENT;
453 return (ssize_t)LOS_NOK;
454 }
455
456 res = f_read(fp, buf, nbyte, &lenRead);
457 if (res != FR_OK) {
458 errno = FatfsErrno(res);
459 return (ssize_t)LOS_NOK;
460 }
461
462 return (ssize_t)lenRead;
463 }
464
FatfsWrite(struct File * file,const char * buf,size_t nbyte)465 ssize_t FatfsWrite(struct File *file, const char *buf, size_t nbyte)
466 {
467 FRESULT res;
468 UINT32 lenWrite;
469 static BOOL overFlow = FALSE;
470 FIL *fp = (FIL *)file->fData;
471
472 if (buf == NULL) {
473 errno = EFAULT;
474 return (ssize_t)LOS_NOK;
475 }
476
477 if ((fp == NULL) || (fp->obj.fs == NULL)) {
478 errno = ENOENT;
479 return (ssize_t)LOS_NOK;
480 }
481
482 res = f_write(fp, buf, nbyte, &lenWrite);
483 if ((res == FR_OK) && (lenWrite == 0) && (nbyte != 0) && (overFlow == FALSE)) {
484 overFlow = TRUE;
485 PRINT_ERR("FAT write err!\r\n");
486 }
487
488 if ((res != FR_OK) || (nbyte != lenWrite)) {
489 errno = FatfsErrno(res);
490 return (ssize_t)LOS_NOK;
491 }
492
493 return (ssize_t)lenWrite;
494 }
495
FatfsLseek(struct File * file,off_t offset,int whence)496 off_t FatfsLseek(struct File *file, off_t offset, int whence)
497 {
498 FRESULT res;
499 off_t pos;
500 FIL *fp = (FIL *)file->fData;
501
502 if ((fp == NULL) || (fp->obj.fs == NULL)) {
503 errno = ENOENT;
504 return (off_t)LOS_NOK;
505 }
506
507 if (whence == SEEK_SET) {
508 pos = 0;
509 } else if (whence == SEEK_CUR) {
510 pos = f_tell(fp);
511 } else if (whence == SEEK_END) {
512 pos = f_size(fp);
513 } else {
514 errno = EINVAL;
515 return (off_t)LOS_NOK;
516 }
517
518 res = f_lseek(fp, offset + pos);
519 if (res != FR_OK) {
520 errno = FatfsErrno(res);
521 return (off_t)LOS_NOK;
522 }
523
524 pos = f_tell(fp);
525 return pos;
526 }
527
528 /* Remove the specified FILE */
FatfsUnlink(struct MountPoint * mp,const char * path)529 int FatfsUnlink(struct MountPoint *mp, const char *path)
530 {
531 FRESULT res;
532 int ret;
533
534 if (path == NULL) {
535 errno = EFAULT;
536 return (int)LOS_NOK;
537 }
538
539 if (!mp->mWriteEnable) {
540 errno = EACCES;
541 return (int)LOS_NOK;
542 }
543
544 ret = FsChangeDrive(path);
545 if (ret != (int)LOS_OK) {
546 PRINT_ERR("FAT unlink ChangeDrive err 0x%x!\r\n", ret);
547 errno = ENOENT;
548 return (int)LOS_NOK;
549 }
550
551 res = f_unlink(path);
552 if (res != FR_OK) {
553 PRINT_ERR("FAT unlink err 0x%x!\r\n", res);
554 errno = FatfsErrno(res);
555 return (int)LOS_NOK;
556 }
557
558 return (int)LOS_OK;
559 }
560
FatfsStat(struct MountPoint * mp,const char * path,struct stat * buf)561 int FatfsStat(struct MountPoint *mp, const char *path, struct stat *buf)
562 {
563 FRESULT res;
564 FILINFO fileInfo = {0};
565 int ret;
566
567 if ((path == NULL) || (buf == NULL)) {
568 errno = EFAULT;
569 return (int)LOS_NOK;
570 }
571
572 ret = FsChangeDrive(path);
573 if (ret != (int)LOS_OK) {
574 PRINT_ERR("FAT stat ChangeDrive err 0x%x!\r\n", ret);
575 errno = ENOENT;
576 return (int)LOS_NOK;
577 }
578
579 res = f_stat(path, &fileInfo);
580 if (res != FR_OK) {
581 PRINT_ERR("FAT stat err 0x%x!\r\n", res);
582 errno = FatfsErrno(res);
583 return (int)LOS_NOK;
584 }
585
586 buf->st_size = fileInfo.fsize;
587 buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
588 S_IWUSR | S_IWGRP | S_IWOTH |
589 S_IXUSR | S_IXGRP | S_IXOTH;
590
591 if (fileInfo.fattrib & AM_RDO) {
592 buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
593 }
594
595 if (fileInfo.fattrib & AM_DIR) {
596 buf->st_mode &= ~S_IFREG;
597 buf->st_mode |= S_IFDIR;
598 }
599
600 return (int)LOS_OK;
601 }
602
603 /* Synchronize all changes to Flash */
FatfsSync(struct File * file)604 int FatfsSync(struct File *file)
605 {
606 FRESULT res;
607 FIL *fp = (FIL *)file->fData;
608
609 if ((fp == NULL) || (fp->obj.fs == NULL)) {
610 errno = ENOENT;
611 return (int)LOS_NOK;
612 }
613
614 res = f_sync(fp);
615 if (res != FR_OK) {
616 errno = FatfsErrno(res);
617 return (int)LOS_NOK;
618 }
619
620 return (int)LOS_OK;
621 }
622
FatfsMkdir(struct MountPoint * mp,const char * path)623 int FatfsMkdir(struct MountPoint *mp, const char *path)
624 {
625 FRESULT res;
626 int ret;
627
628 if (path == NULL) {
629 errno = EFAULT;
630 return (int)LOS_NOK;
631 }
632
633 if (!mp->mWriteEnable) {
634 errno = EACCES;
635 return (int)LOS_NOK;
636 }
637
638 ret = FsChangeDrive(path);
639 if (ret != (int)LOS_OK) {
640 PRINT_ERR("FAT mkdir ChangeDrive err 0x%x!\r\n", ret);
641 errno = ENOENT;
642 return (int)LOS_NOK;
643 }
644
645 res = f_mkdir(path);
646 if (res != FR_OK) {
647 PRINT_ERR("FAT mkdir err 0x%x!\r\n", res);
648 errno = FatfsErrno(res);
649 return (int)LOS_NOK;
650 }
651
652 return (int)LOS_OK;
653 }
654
FatfsOpendir(struct Dir * dir,const char * dirName)655 int FatfsOpendir(struct Dir *dir, const char *dirName)
656 {
657 FRESULT res;
658 DIR *dp = NULL;
659 int ret;
660
661 if (dirName == NULL) {
662 errno = EFAULT;
663 return (int)LOS_NOK;
664 }
665
666 ret = FsChangeDrive(dirName);
667 if (ret != (int)LOS_OK) {
668 PRINT_ERR("FAT opendir ChangeDrive err 0x%x!\r\n", ret);
669 errno = ENOENT;
670 return (int)LOS_NOK;
671 }
672
673 dp = (DIR *)LOSCFG_FS_MALLOC_HOOK(sizeof(DIR));
674 if (dp == NULL) {
675 errno = ENOENT;
676 return (int)LOS_NOK;
677 }
678
679 res = f_opendir(dp, dirName);
680 if (res != FR_OK) {
681 PRINT_ERR("FAT opendir err 0x%x!\r\n", res);
682 LOSCFG_FS_FREE_HOOK(dp);
683 errno = FatfsErrno(res);
684 return (int)LOS_NOK;
685 }
686
687 dir->dData = dp;
688 dir->dOffset = 0;
689
690 return (int)LOS_OK;
691 }
692
FatfsReaddir(struct Dir * dir,struct dirent * dent)693 int FatfsReaddir(struct Dir *dir, struct dirent *dent)
694 {
695 FRESULT res;
696 FILINFO fileInfo = {0};
697 DIR *dp = NULL;
698
699 if ((dir == NULL) || (dir->dData == NULL)) {
700 errno = EBADF;
701 return (int)LOS_NOK;
702 }
703
704 dp = (DIR *)dir->dData;
705 res = f_readdir(dp, &fileInfo);
706 /* if res not ok or fname is NULL , return NULL */
707 if ((res != FR_OK) || (fileInfo.fname[0] == 0x0)) {
708 PRINT_ERR("FAT readdir err 0x%x!\r\n", res);
709 errno = FatfsErrno(res);
710 return (int)LOS_NOK;
711 }
712
713 (void)memcpy_s(dent->d_name, sizeof(dent->d_name),
714 fileInfo.fname, sizeof(dent->d_name));
715 if (fileInfo.fattrib & AM_DIR) {
716 dent->d_type = DT_DIR;
717 } else {
718 dent->d_type = DT_REG;
719 }
720
721 return (int)LOS_OK;
722 }
723
FatfsClosedir(struct Dir * dir)724 int FatfsClosedir(struct Dir *dir)
725 {
726 FRESULT res;
727 DIR *dp = NULL;
728
729 if ((dir == NULL) || (dir->dData == NULL)) {
730 errno = EBADF;
731 return (int)LOS_NOK;
732 }
733
734 dp = dir->dData;
735 res = f_closedir(dp);
736 if (res != FR_OK) {
737 PRINT_ERR("FAT closedir err 0x%x!\r\n", res);
738 errno = FatfsErrno(res);
739 return (int)LOS_NOK;
740 }
741
742 LOSCFG_FS_FREE_HOOK(dir->dData);
743 dir->dData = NULL;
744
745 return (int)LOS_OK;
746 }
747
FatfsRmdir(struct MountPoint * mp,const char * path)748 int FatfsRmdir(struct MountPoint *mp, const char *path)
749 {
750 FRESULT res;
751 int ret;
752
753 if ((path == NULL) || (mp == NULL)) {
754 errno = EFAULT;
755 return (int)LOS_NOK;
756 }
757
758 if (!mp->mWriteEnable) {
759 errno = EACCES;
760 return (int)LOS_NOK;
761 }
762
763 ret = FsChangeDrive(path);
764 if (ret != (int)LOS_OK) {
765 PRINT_ERR("FAT rmdir ChangeDrive err 0x%x!\r\n", ret);
766 errno = ENOENT;
767 return (int)LOS_NOK;
768 }
769
770 res = f_rmdir(path);
771 if (res != FR_OK) {
772 PRINT_ERR("FAT rmdir err 0x%x!\r\n", res);
773 errno = FatfsErrno(res);
774 return (int)LOS_NOK;
775 }
776
777 return (int)LOS_OK;
778 }
779
FatfsRename(struct MountPoint * mp,const char * oldName,const char * newName)780 int FatfsRename(struct MountPoint *mp, const char *oldName, const char *newName)
781 {
782 FRESULT res;
783 int ret;
784
785 if ((oldName == NULL) || (newName == NULL)) {
786 errno = EFAULT;
787 return (int)LOS_NOK;
788 }
789
790 if (!mp->mWriteEnable) {
791 errno = EACCES;
792 return (int)LOS_NOK;
793 }
794
795 ret = FsChangeDrive(oldName);
796 if (ret != (int)LOS_OK) {
797 PRINT_ERR("FAT f_getfree ChangeDrive err 0x%x!\r\n", ret);
798 errno = ENOENT;
799 return (int)LOS_NOK;
800 }
801
802 res = f_rename(oldName, newName);
803 if (res != FR_OK) {
804 PRINT_ERR("FAT frename err 0x%x!\r\n", res);
805 errno = FatfsErrno(res);
806 return (int)LOS_NOK;
807 }
808
809 return (int)LOS_OK;
810 }
811
FatfsStatfs(const char * path,struct statfs * buf)812 int FatfsStatfs(const char *path, struct statfs *buf)
813 {
814 FATFS *fs = NULL;
815 UINT32 freeClust;
816 FRESULT res;
817 int ret;
818
819 if ((path == NULL) || (buf == NULL)) {
820 errno = EFAULT;
821 return (int)LOS_NOK;
822 }
823
824 ret = FsChangeDrive(path);
825 if (ret != FR_OK) {
826 PRINT_ERR("FAT f_getfree ChangeDrive err %d.", ret);
827 errno = FatfsErrno(FR_INVALID_PARAMETER);
828 return (int)LOS_NOK;
829 }
830
831 res = f_getfree(path, &freeClust, &fs);
832 if (res != FR_OK) {
833 PRINT_ERR("FAT f_getfree err 0x%x.", res);
834 errno = FatfsErrno(res);
835 return (int)LOS_NOK;
836 }
837 buf->f_bfree = freeClust;
838 buf->f_bavail = freeClust;
839 /* Cluster #0 and #1 is for VBR, reserve sectors and fat */
840 buf->f_blocks = fs->n_fatent - 2;
841 #if FF_MAX_SS != FF_MIN_SS
842 buf->f_bsize = fs->ssize * fs->csize;
843 #else
844 buf->f_bsize = FF_MIN_SS * fs->csize;
845 #endif
846
847 return (int)LOS_OK;
848 }
849
DoTruncate(struct File * file,off_t length,UINT32 count)850 static int DoTruncate(struct File *file, off_t length, UINT32 count)
851 {
852 FRESULT res = FR_OK;
853 DWORD csz;
854 FIL *fp = (FIL *)file->fData;
855
856 csz = (DWORD)(fp->obj.fs)->csize * SS(fp->obj.fs); /* Cluster size */
857 if (length > csz * count) {
858 #if FF_USE_EXPAND
859 res = f_expand(fp, 0, (FSIZE_t)(length), FALLOC_FL_KEEP_SIZE);
860 #else
861 errno = ENOSYS;
862 return (int)LOS_NOK;
863 #endif
864 } else if (length < csz * count) {
865 res = f_truncate(fp, (FSIZE_t)length);
866 }
867
868 if (res != FR_OK) {
869 errno = FatfsErrno(res);
870 return (int)LOS_NOK;
871 }
872
873 fp->obj.objsize = length; /* Set file size to length */
874 fp->flag |= 0x40; /* Set modified flag */
875
876 return (int)LOS_OK;
877 }
878
FatfsTruncate(struct File * file,off_t length)879 int FatfsTruncate(struct File *file, off_t length)
880 {
881 FRESULT res;
882 UINT count;
883 DWORD fclust;
884 FIL *fp = (FIL *)file->fData;
885
886 if ((length < 0) || (length > UINT_MAX)) {
887 errno = EINVAL;
888 return (int)LOS_NOK;
889 }
890
891 if ((fp == NULL) || (fp->obj.fs == NULL)) {
892 errno = ENOENT;
893 return (int)LOS_NOK;
894 }
895
896 res = f_getclustinfo(fp, &fclust, &count);
897 if (res != FR_OK) {
898 errno = FatfsErrno(res);
899 return (int)LOS_NOK;
900 }
901
902 return DoTruncate(file, length, count);
903 }
904
FatfsFdisk(const char * dev,int * partTbl,int arrayNum)905 int FatfsFdisk(const char *dev, int *partTbl, int arrayNum)
906 {
907 int pdrv;
908 FRESULT res;
909
910 if ((dev == NULL) || (partTbl == NULL)) {
911 errno = EFAULT;
912 return (int)LOS_NOK;
913 }
914
915 pdrv = GetDevIdByDevName(dev);
916 if (pdrv < 0) {
917 errno = EFAULT;
918 return (int)LOS_NOK;
919 }
920
921 res = f_fdisk(pdrv, (DWORD const *)partTbl, g_workBuffer);
922 if (res != FR_OK) {
923 errno = FatfsErrno(res);
924 return (int)LOS_NOK;
925 }
926
927 return (int)LOS_OK;
928 }
929
FatfsFormat(const char * partName,void * privData)930 int FatfsFormat(const char *partName, void *privData)
931 {
932 FRESULT res;
933 MKFS_PARM opt = {0};
934 int option = *(int *)privData;
935 char *dev = NULL; /* logical driver */
936
937 if (partName == NULL) {
938 errno = EFAULT;
939 return (int)LOS_NOK;
940 }
941
942 dev = GetLdPath(partName);
943 if (dev == NULL) {
944 errno = EFAULT;
945 return (int)LOS_NOK;
946 }
947
948 opt.fmt = option;
949 opt.n_sect = 0; /* use default allocation unit size depends on the volume
950 size. */
951 res = f_mkfs(dev, &opt, g_workBuffer, FF_MAX_SS);
952 if (res != FR_OK) {
953 errno = FatfsErrno(res);
954 PutLdPath(dev);
955 return (int)LOS_NOK;
956 }
957
958 return (int)LOS_OK;
959 }
960
961 static struct MountOps g_fatfsMnt = {
962 .mount = FatfsMount,
963 .umount = FatfsUmount,
964 .umount2 = FatfsUmount2,
965 .statfs = FatfsStatfs,
966 };
967
968 static struct FileOps g_fatfsFops = {
969 .open = FatfsOpen,
970 .close = FatfsClose,
971 .read = FatfsRead,
972 .write = FatfsWrite,
973 .lseek = FatfsLseek,
974 .stat = FatfsStat,
975 .truncate = FatfsTruncate,
976 .unlink = FatfsUnlink,
977 .rename = FatfsRename,
978 .ioctl = NULL, /* not support */
979 .sync = FatfsSync,
980 .opendir = FatfsOpendir,
981 .readdir = FatfsReaddir,
982 .closedir = FatfsClosedir,
983 .mkdir = FatfsMkdir,
984 .rmdir = FatfsRmdir,
985 };
986
987 static struct FsManagement g_fatfsMgt = {
988 .fdisk = FatfsFdisk,
989 .format = FatfsFormat,
990 };
991
FatFsInit(void)992 void FatFsInit(void)
993 {
994 (void)OsFsRegister("vfat", &g_fatfsMnt, &g_fatfsFops, &g_fatfsMgt);
995 }
996