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     (void)memset_s(fp, sizeof(FIL), 0, sizeof(FIL));
391 
392     ret = FsChangeDrive(path);
393     if (ret != (int)LOS_OK) {
394         PRINT_ERR("FAT open ChangeDrive err 0x%x!\r\n", ret);
395         errno = ENOENT;
396         LOSCFG_FS_FREE_HOOK(fp);
397         return (int)LOS_NOK;
398     }
399 
400     res = f_open(fp, path, fmode);
401     if (res != FR_OK) {
402         PRINT_ERR("FAT open err 0x%x!\r\n", res);
403         LOSCFG_FS_FREE_HOOK(fp);
404         errno = FatfsErrno(res);
405         return (int)LOS_NOK;
406     }
407 
408     file->fData = (void *)fp;
409 
410     return (int)LOS_OK;
411 }
412 
FatfsClose(struct File *file)413 int FatfsClose(struct File *file)
414 {
415     FRESULT res;
416     FIL *fp = (FIL *)file->fData;
417 
418     if ((fp == NULL) || (fp->obj.fs == NULL)) {
419         errno = ENOENT;
420         return (int)LOS_NOK;
421     }
422 
423     res = f_close(fp);
424     if (res != FR_OK) {
425         PRINT_ERR("FAT close err 0x%x!\r\n", res);
426         errno = FatfsErrno(res);
427         return (int)LOS_NOK;
428     }
429 
430 #if !FF_FS_TINY
431     if (fp->buf != NULL) {
432         (void)ff_memfree(fp->buf);
433     }
434 #endif
435     LOSCFG_FS_FREE_HOOK(file->fData);
436     file->fData = NULL;
437 
438     return (int)LOS_OK;
439 }
440 
FatfsRead(struct File *file, char *buf, size_t nbyte)441 ssize_t FatfsRead(struct File *file, char *buf, size_t nbyte)
442 {
443     FRESULT res;
444     UINT32 lenRead;
445     FIL *fp = (FIL *)file->fData;
446 
447     if (buf == NULL) {
448         errno = EFAULT;
449         return (ssize_t)LOS_NOK;
450     }
451 
452     if (fp == NULL) {
453         errno = ENOENT;
454         return (ssize_t)LOS_NOK;
455     }
456 
457     res = f_read(fp, buf, nbyte, &lenRead);
458     if (res != FR_OK) {
459         errno = FatfsErrno(res);
460         return (ssize_t)LOS_NOK;
461     }
462 
463     return (ssize_t)lenRead;
464 }
465 
FatfsWrite(struct File *file, const char *buf, size_t nbyte)466 ssize_t FatfsWrite(struct File *file, const char *buf, size_t nbyte)
467 {
468     FRESULT res;
469     UINT32 lenWrite;
470     static BOOL overFlow = FALSE;
471     FIL *fp = (FIL *)file->fData;
472 
473     if (buf == NULL) {
474         errno = EFAULT;
475         return (ssize_t)LOS_NOK;
476     }
477 
478     if ((fp == NULL) || (fp->obj.fs == NULL)) {
479         errno = ENOENT;
480         return (ssize_t)LOS_NOK;
481     }
482 
483     res = f_write(fp, buf, nbyte, &lenWrite);
484     if ((res == FR_OK) && (lenWrite == 0) && (nbyte != 0) && (overFlow == FALSE)) {
485         overFlow = TRUE;
486         PRINT_ERR("FAT write err!\r\n");
487     }
488 
489     if ((res != FR_OK) || (nbyte != lenWrite)) {
490         errno = FatfsErrno(res);
491         return (ssize_t)LOS_NOK;
492     }
493 
494     return (ssize_t)lenWrite;
495 }
496 
FatfsLseek(struct File *file, off_t offset, int whence)497 off_t FatfsLseek(struct File *file, off_t offset, int whence)
498 {
499     FRESULT res;
500     off_t pos;
501     FIL *fp = (FIL *)file->fData;
502 
503     if ((fp == NULL) || (fp->obj.fs == NULL)) {
504         errno = ENOENT;
505         return (off_t)LOS_NOK;
506     }
507 
508     if (whence == SEEK_SET) {
509         pos = 0;
510     } else if (whence == SEEK_CUR) {
511         pos = f_tell(fp);
512     } else if (whence == SEEK_END) {
513         pos = f_size(fp);
514     } else {
515         errno = EINVAL;
516         return (off_t)LOS_NOK;
517     }
518 
519     res = f_lseek(fp, offset + pos);
520     if (res != FR_OK) {
521         errno = FatfsErrno(res);
522         return (off_t)LOS_NOK;
523     }
524 
525     pos = f_tell(fp);
526     return pos;
527 }
528 
529 /* Remove the specified FILE */
FatfsUnlink(struct MountPoint *mp, const char *path)530 int FatfsUnlink(struct MountPoint *mp, const char *path)
531 {
532     FRESULT res;
533     int ret;
534 
535     if (path == NULL) {
536         errno = EFAULT;
537         return (int)LOS_NOK;
538     }
539 
540     if (!mp->mWriteEnable) {
541         errno = EACCES;
542         return (int)LOS_NOK;
543     }
544 
545     ret = FsChangeDrive(path);
546     if (ret != (int)LOS_OK) {
547         PRINT_ERR("FAT unlink ChangeDrive err 0x%x!\r\n", ret);
548         errno = ENOENT;
549         return (int)LOS_NOK;
550     }
551 
552     res = f_unlink(path);
553     if (res != FR_OK) {
554         PRINT_ERR("FAT unlink err 0x%x!\r\n", res);
555         errno = FatfsErrno(res);
556         return (int)LOS_NOK;
557     }
558 
559     return (int)LOS_OK;
560 }
561 
FatfsStat(struct MountPoint *mp, const char *path, struct stat *buf)562 int FatfsStat(struct MountPoint *mp, const char *path, struct stat *buf)
563 {
564     FRESULT res;
565     FILINFO fileInfo = {0};
566     int ret;
567 
568     if ((path == NULL) || (buf == NULL)) {
569         errno = EFAULT;
570         return (int)LOS_NOK;
571     }
572 
573     ret = FsChangeDrive(path);
574     if (ret != (int)LOS_OK) {
575         PRINT_ERR("FAT stat ChangeDrive err 0x%x!\r\n", ret);
576         errno = ENOENT;
577         return (int)LOS_NOK;
578     }
579 
580     res = f_stat(path, &fileInfo);
581     if (res != FR_OK) {
582         PRINT_ERR("FAT stat err 0x%x!\r\n", res);
583         errno = FatfsErrno(res);
584         return (int)LOS_NOK;
585     }
586 
587     buf->st_size = fileInfo.fsize;
588     buf->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH |
589                    S_IWUSR | S_IWGRP | S_IWOTH |
590                    S_IXUSR | S_IXGRP | S_IXOTH;
591 
592     if (fileInfo.fattrib & AM_RDO) {
593         buf->st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
594     }
595 
596     if (fileInfo.fattrib & AM_DIR) {
597         buf->st_mode &= ~S_IFREG;
598         buf->st_mode |= S_IFDIR;
599     }
600 
601     return (int)LOS_OK;
602 }
603 
604 /* Synchronize all changes to Flash */
FatfsSync(struct File *file)605 int FatfsSync(struct File *file)
606 {
607     FRESULT res;
608     FIL *fp = (FIL *)file->fData;
609 
610     if ((fp == NULL) || (fp->obj.fs == NULL)) {
611         errno = ENOENT;
612         return (int)LOS_NOK;
613     }
614 
615     res = f_sync(fp);
616     if (res != FR_OK) {
617         errno = FatfsErrno(res);
618         return (int)LOS_NOK;
619     }
620 
621     return (int)LOS_OK;
622 }
623 
FatfsMkdir(struct MountPoint *mp, const char *path)624 int FatfsMkdir(struct MountPoint *mp, const char *path)
625 {
626     FRESULT res;
627     int ret;
628 
629     if (path == NULL) {
630         errno = EFAULT;
631         return (int)LOS_NOK;
632     }
633 
634     if (!mp->mWriteEnable) {
635         errno = EACCES;
636         return (int)LOS_NOK;
637     }
638 
639     ret = FsChangeDrive(path);
640     if (ret != (int)LOS_OK) {
641         PRINT_ERR("FAT mkdir ChangeDrive err 0x%x!\r\n", ret);
642         errno = ENOENT;
643         return (int)LOS_NOK;
644     }
645 
646     res = f_mkdir(path);
647     if (res != FR_OK) {
648         PRINT_ERR("FAT mkdir err 0x%x!\r\n", res);
649         errno = FatfsErrno(res);
650         return (int)LOS_NOK;
651     }
652 
653     return (int)LOS_OK;
654 }
655 
FatfsOpendir(struct Dir *dir, const char *dirName)656 int FatfsOpendir(struct Dir *dir, const char *dirName)
657 {
658     FRESULT res;
659     DIR *dp = NULL;
660     int ret;
661 
662     if (dirName == NULL) {
663         errno = EFAULT;
664         return (int)LOS_NOK;
665     }
666 
667     ret = FsChangeDrive(dirName);
668     if (ret != (int)LOS_OK) {
669         PRINT_ERR("FAT opendir ChangeDrive err 0x%x!\r\n", ret);
670         errno = ENOENT;
671         return (int)LOS_NOK;
672     }
673 
674     dp = (DIR *)LOSCFG_FS_MALLOC_HOOK(sizeof(DIR));
675     if (dp == NULL) {
676         errno = ENOENT;
677         return (int)LOS_NOK;
678     }
679     (void)memset_s(dp, sizeof(DIR), 0, sizeof(DIR));
680 
681     res = f_opendir(dp, dirName);
682     if (res != FR_OK) {
683         PRINT_ERR("FAT opendir err 0x%x!\r\n", res);
684         LOSCFG_FS_FREE_HOOK(dp);
685         errno = FatfsErrno(res);
686         return (int)LOS_NOK;
687     }
688 
689     dir->dData = dp;
690     dir->dOffset = 0;
691 
692     return (int)LOS_OK;
693 }
694 
FatfsReaddir(struct Dir *dir, struct dirent *dent)695 int FatfsReaddir(struct Dir *dir, struct dirent *dent)
696 {
697     FRESULT res;
698     FILINFO fileInfo = {0};
699     DIR *dp = NULL;
700 
701     if ((dir == NULL) || (dir->dData == NULL)) {
702         errno = EBADF;
703         return (int)LOS_NOK;
704     }
705 
706     dp = (DIR *)dir->dData;
707     res = f_readdir(dp, &fileInfo);
708     /* if res not ok or fname is NULL , return NULL */
709     if ((res != FR_OK) || (fileInfo.fname[0] == 0x0)) {
710         PRINT_ERR("FAT readdir err 0x%x!\r\n", res);
711         errno = FatfsErrno(res);
712         return (int)LOS_NOK;
713     }
714 
715     (void)memcpy_s(dent->d_name, sizeof(dent->d_name),
716             fileInfo.fname, sizeof(dent->d_name));
717     if (fileInfo.fattrib & AM_DIR) {
718         dent->d_type = DT_DIR;
719     } else {
720         dent->d_type = DT_REG;
721     }
722 
723     return (int)LOS_OK;
724 }
725 
FatfsClosedir(struct Dir *dir)726 int FatfsClosedir(struct Dir *dir)
727 {
728     FRESULT res;
729     DIR *dp = NULL;
730 
731     if ((dir == NULL) || (dir->dData == NULL)) {
732         errno = EBADF;
733         return (int)LOS_NOK;
734     }
735 
736     dp = dir->dData;
737     res = f_closedir(dp);
738     if (res != FR_OK) {
739         PRINT_ERR("FAT closedir err 0x%x!\r\n", res);
740         errno = FatfsErrno(res);
741         return (int)LOS_NOK;
742     }
743 
744     LOSCFG_FS_FREE_HOOK(dir->dData);
745     dir->dData = NULL;
746 
747     return (int)LOS_OK;
748 }
749 
FatfsRmdir(struct MountPoint *mp, const char *path)750 int FatfsRmdir(struct MountPoint *mp, const char *path)
751 {
752     FRESULT res;
753     int ret;
754 
755     if ((path == NULL) || (mp == NULL)) {
756         errno = EFAULT;
757         return (int)LOS_NOK;
758     }
759 
760     if (!mp->mWriteEnable) {
761         errno = EACCES;
762         return (int)LOS_NOK;
763     }
764 
765     ret = FsChangeDrive(path);
766     if (ret != (int)LOS_OK) {
767         PRINT_ERR("FAT rmdir ChangeDrive err 0x%x!\r\n", ret);
768         errno = ENOENT;
769         return (int)LOS_NOK;
770     }
771 
772     res = f_rmdir(path);
773     if (res != FR_OK) {
774         PRINT_ERR("FAT rmdir err 0x%x!\r\n", res);
775         errno = FatfsErrno(res);
776         return (int)LOS_NOK;
777     }
778 
779     return (int)LOS_OK;
780 }
781 
FatfsRename(struct MountPoint *mp, const char *oldName, const char *newName)782 int FatfsRename(struct MountPoint *mp, const char *oldName, const char *newName)
783 {
784     FRESULT res;
785     int ret;
786 
787     if ((oldName == NULL) || (newName == NULL)) {
788         errno = EFAULT;
789         return (int)LOS_NOK;
790     }
791 
792     if (!mp->mWriteEnable) {
793         errno = EACCES;
794         return (int)LOS_NOK;
795     }
796 
797     ret = FsChangeDrive(oldName);
798     if (ret != (int)LOS_OK) {
799         PRINT_ERR("FAT f_getfree ChangeDrive err 0x%x!\r\n", ret);
800         errno = ENOENT;
801         return (int)LOS_NOK;
802     }
803 
804     res = f_rename(oldName, newName);
805     if (res != FR_OK) {
806         PRINT_ERR("FAT frename err 0x%x!\r\n", res);
807         errno = FatfsErrno(res);
808         return (int)LOS_NOK;
809     }
810 
811     return (int)LOS_OK;
812 }
813 
FatfsStatfs(const char *path, struct statfs *buf)814 int FatfsStatfs(const char *path, struct statfs *buf)
815 {
816     FATFS *fs = NULL;
817     UINT32 freeClust;
818     FRESULT res;
819     int ret;
820 
821     if ((path == NULL) || (buf == NULL)) {
822         errno = EFAULT;
823         return (int)LOS_NOK;
824     }
825 
826     ret = FsChangeDrive(path);
827     if (ret != FR_OK) {
828         PRINT_ERR("FAT f_getfree ChangeDrive err %d.", ret);
829         errno = FatfsErrno(FR_INVALID_PARAMETER);
830         return (int)LOS_NOK;
831     }
832 
833     res = f_getfree(path, &freeClust, &fs);
834     if (res != FR_OK) {
835         PRINT_ERR("FAT f_getfree err 0x%x.", res);
836         errno = FatfsErrno(res);
837         return (int)LOS_NOK;
838     }
839     buf->f_bfree  = freeClust;
840     buf->f_bavail = freeClust;
841     /* Cluster #0 and #1 is for VBR, reserve sectors and fat */
842     buf->f_blocks = fs->n_fatent - 2;
843 #if FF_MAX_SS != FF_MIN_SS
844     buf->f_bsize  = fs->ssize * fs->csize;
845 #else
846     buf->f_bsize  = FF_MIN_SS * fs->csize;
847 #endif
848 
849     return (int)LOS_OK;
850 }
851 
DoTruncate(struct File *file, off_t length, UINT32 count)852 static int DoTruncate(struct File *file, off_t length, UINT32 count)
853 {
854     FRESULT res = FR_OK;
855     DWORD csz;
856     FIL *fp = (FIL *)file->fData;
857 
858     csz = (DWORD)(fp->obj.fs)->csize * SS(fp->obj.fs); /* Cluster size */
859     if (length > csz * count) {
860 #if FF_USE_EXPAND
861         res = f_expand(fp, 0, (FSIZE_t)(length), FALLOC_FL_KEEP_SIZE);
862 #else
863         errno = ENOSYS;
864         return (int)LOS_NOK;
865 #endif
866     } else if (length < csz * count) {
867         res = f_truncate(fp, (FSIZE_t)length);
868     }
869 
870     if (res != FR_OK) {
871         errno = FatfsErrno(res);
872         return (int)LOS_NOK;
873     }
874 
875     fp->obj.objsize = length; /* Set file size to length */
876     fp->flag |= 0x40; /* Set modified flag */
877 
878     return (int)LOS_OK;
879 }
880 
FatfsTruncate(struct File *file, off_t length)881 int FatfsTruncate(struct File *file, off_t length)
882 {
883     FRESULT res;
884     UINT count;
885     DWORD fclust;
886     FIL *fp = (FIL *)file->fData;
887 
888     if ((length < 0) || (length > UINT_MAX)) {
889         errno = EINVAL;
890         return (int)LOS_NOK;
891     }
892 
893     if ((fp == NULL) || (fp->obj.fs == NULL)) {
894         errno = ENOENT;
895         return (int)LOS_NOK;
896     }
897 
898     res = f_getclustinfo(fp, &fclust, &count);
899     if (res != FR_OK) {
900         errno = FatfsErrno(res);
901         return (int)LOS_NOK;
902     }
903 
904     return DoTruncate(file, length, count);
905 }
906 
FatfsFdisk(const char *dev, int *partTbl, int arrayNum)907 int FatfsFdisk(const char *dev, int *partTbl, int arrayNum)
908 {
909     int pdrv;
910     FRESULT res;
911 
912     if ((dev == NULL) || (partTbl == NULL)) {
913         errno = EFAULT;
914         return (int)LOS_NOK;
915     }
916 
917     pdrv = GetDevIdByDevName(dev);
918     if (pdrv < 0) {
919         errno = EFAULT;
920         return (int)LOS_NOK;
921     }
922 
923     res = f_fdisk(pdrv, (DWORD const *)partTbl, g_workBuffer);
924     if (res != FR_OK) {
925         errno = FatfsErrno(res);
926         return (int)LOS_NOK;
927     }
928 
929     return (int)LOS_OK;
930 }
931 
FatfsFormat(const char *partName, void *privData)932 int FatfsFormat(const char *partName, void *privData)
933 {
934     FRESULT res;
935     MKFS_PARM opt = {0};
936     int option = *(int *)privData;
937     char *dev = NULL; /* logical driver */
938 
939     if (partName == NULL) {
940         errno = EFAULT;
941         return (int)LOS_NOK;
942     }
943 
944     dev = GetLdPath(partName);
945     if (dev == NULL) {
946         errno = EFAULT;
947         return (int)LOS_NOK;
948     }
949 
950     opt.fmt = option;
951     opt.n_sect = 0; /* use default allocation unit size depends on the volume
952                        size. */
953     res = f_mkfs(dev, &opt, g_workBuffer, FF_MAX_SS);
954     if (res != FR_OK) {
955         errno = FatfsErrno(res);
956         PutLdPath(dev);
957         return (int)LOS_NOK;
958     }
959 
960     return (int)LOS_OK;
961 }
962 
963 static struct MountOps g_fatfsMnt = {
964     .mount = FatfsMount,
965     .umount = FatfsUmount,
966     .umount2 = FatfsUmount2,
967     .statfs = FatfsStatfs,
968 };
969 
970 static struct FileOps g_fatfsFops = {
971     .open = FatfsOpen,
972     .close = FatfsClose,
973     .read = FatfsRead,
974     .write = FatfsWrite,
975     .lseek = FatfsLseek,
976     .stat = FatfsStat,
977     .truncate = FatfsTruncate,
978     .unlink = FatfsUnlink,
979     .rename = FatfsRename,
980     .ioctl = NULL, /* not support */
981     .sync = FatfsSync,
982     .opendir = FatfsOpendir,
983     .readdir = FatfsReaddir,
984     .closedir = FatfsClosedir,
985     .mkdir = FatfsMkdir,
986     .rmdir = FatfsRmdir,
987 };
988 
989 static struct FsManagement g_fatfsMgt = {
990     .fdisk = FatfsFdisk,
991     .format = FatfsFormat,
992 };
993 
FatFsInit(void)994 void FatFsInit(void)
995 {
996     (void)OsFsRegister("vfat", &g_fatfsMnt, &g_fatfsFops, &g_fatfsMgt);
997 }
998