• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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