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 "lfs_adapter.h"
34 #include "los_config.h"
35 #include "vfs_files.h"
36 #include "vfs_operations.h"
37 #include "vfs_partition.h"
38 #include "vfs_maps.h"
39 #include "vfs_mount.h"
40 #include "securec.h"
41 #include "los_fs.h"
42 
43 static struct PartitionCfg g_partitionCfg;
44 static struct DeviceDesc *g_lfsDevice = NULL;
45 
LfsGetStartAddr(int partition)46 static uint32_t LfsGetStartAddr(int partition)
47 {
48     if (g_lfsDevice == NULL) {
49         struct DeviceDesc *device = NULL;
50         for (device = getDeviceList(); device != NULL; device = device->dNext) {
51             if (strcmp(device->dFsType, "littlefs") == 0) {
52                 g_lfsDevice = device;
53                 break;
54             }
55         }
56     }
57 
58     if ((g_lfsDevice == NULL) || (partition >= g_lfsDevice->dPartNum)) {
59         return INVALID_DEVICE_ADDR;
60     }
61 
62     return (uint32_t)g_lfsDevice->dAddrArray[partition];
63 }
64 
littlefs_block_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *dst, lfs_size_t size)65 WEAK int littlefs_block_read(const struct lfs_config *c, lfs_block_t block,
66                              lfs_off_t off, void *dst, lfs_size_t size)
67 {
68     UINT32 addr = c->block_size * block + off;
69     UINT32 startaddr = LfsGetStartAddr((int)c->context);
70     if (startaddr == INVALID_DEVICE_ADDR) {
71         return -1;
72     }
73     addr += startaddr;
74 
75     return (g_partitionCfg.readFunc)((int)c->context, &addr, dst, size);
76 }
77 
littlefs_block_write(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *dst, lfs_size_t size)78 WEAK int littlefs_block_write(const struct lfs_config *c, lfs_block_t block,
79                               lfs_off_t off, const void *dst, lfs_size_t size)
80 {
81     UINT32 addr = c->block_size * block + off;
82     UINT32 startaddr = LfsGetStartAddr((int)c->context);
83     if (startaddr == INVALID_DEVICE_ADDR) {
84         return -1;
85     }
86 
87     addr += startaddr;
88 
89     return (g_partitionCfg.writeFunc)((int)c->context, &addr, dst, size);
90 }
91 
littlefs_block_erase(const struct lfs_config *c, lfs_block_t block)92 WEAK int littlefs_block_erase(const struct lfs_config *c, lfs_block_t block)
93 {
94     UINT32 addr = c->block_size * block;
95     UINT32 startaddr = LfsGetStartAddr((int)c->context);
96     if (startaddr == INVALID_DEVICE_ADDR) {
97         return -1;
98     }
99 
100     addr += startaddr;
101 
102     return (g_partitionCfg.eraseFunc)((int)c->context, addr, c->block_size);
103 }
104 
littlefs_block_sync(const struct lfs_config *c)105 WEAK int littlefs_block_sync(const struct lfs_config *c)
106 {
107     (void)c;
108     return 0;
109 }
110 
ConvertFlagToLfsOpenFlag(int oflags)111 static int ConvertFlagToLfsOpenFlag (int oflags)
112 {
113     int lfsOpenFlag = 0;
114 
115     if (oflags & O_CREAT) {
116         lfsOpenFlag |= LFS_O_CREAT;
117     }
118 
119     if (oflags & O_EXCL) {
120         lfsOpenFlag |= LFS_O_EXCL;
121     }
122 
123     if (oflags & O_TRUNC) {
124         lfsOpenFlag |= LFS_O_TRUNC;
125     }
126 
127     if (oflags & O_APPEND) {
128         lfsOpenFlag |= LFS_O_APPEND;
129     }
130 
131     if (oflags & O_RDWR) {
132         lfsOpenFlag |= LFS_O_RDWR;
133     }
134 
135     if (oflags & O_WRONLY) {
136         lfsOpenFlag |= LFS_O_WRONLY;
137     }
138 
139     if (oflags == O_RDONLY) {
140         lfsOpenFlag |= LFS_O_RDONLY;
141     }
142 
143     return lfsOpenFlag;
144 }
145 
LittlefsErrno(int result)146 static int LittlefsErrno(int result)
147 {
148     return (result < 0) ? -result : result;
149 }
150 
LfsConfigAdapter(struct PartitionCfg *pCfg, struct lfs_config *lfsCfg)151 void LfsConfigAdapter(struct PartitionCfg *pCfg, struct lfs_config *lfsCfg)
152 {
153     lfsCfg->context = (void *)pCfg->partNo;
154 
155     lfsCfg->read_size = pCfg->readSize;
156     lfsCfg->prog_size = pCfg->writeSize;
157     lfsCfg->cache_size = pCfg->cacheSize;
158     lfsCfg->block_cycles = pCfg->blockCycles;
159     lfsCfg->lookahead_size = pCfg->lookaheadSize;
160     lfsCfg->block_size = pCfg->blockSize;
161     lfsCfg->block_count = pCfg->blockCount;
162 
163     lfsCfg->read = littlefs_block_read;
164     lfsCfg->prog = littlefs_block_write;
165     lfsCfg->erase = littlefs_block_erase;
166     lfsCfg->sync = littlefs_block_sync;
167 
168     g_partitionCfg.readFunc = pCfg->readFunc;
169     g_partitionCfg.writeFunc = pCfg->writeFunc;
170     g_partitionCfg.eraseFunc = pCfg->eraseFunc;
171 }
172 
LfsMount(struct MountPoint *mp, unsigned long mountflags, const void *data)173 int LfsMount(struct MountPoint *mp, unsigned long mountflags, const void *data)
174 {
175     int ret;
176     lfs_t *mountHdl = NULL;
177     struct lfs_config *cfg = NULL;
178 
179     if ((mp == NULL) || (mp->mPath == NULL) || (data == NULL)) {
180         errno = EFAULT;
181         ret = (int)LOS_NOK;
182         goto errout;
183     }
184 
185     if (mountflags & MS_REMOUNT) {
186         errno = ENOSYS;
187         ret = (int)LOS_NOK;
188         goto errout;
189     }
190 
191     mountHdl = (lfs_t *)LOSCFG_FS_MALLOC_HOOK(sizeof(lfs_t) + sizeof(struct lfs_config));
192     if (mountHdl == NULL) {
193         errno = ENODEV;
194         ret = (int)LOS_NOK;
195         goto errout;
196     }
197     (void)memset_s(mountHdl, sizeof(lfs_t) + sizeof(struct lfs_config), 0, sizeof(lfs_t) + sizeof(struct lfs_config));
198     mp->mData = (void *)mountHdl;
199     cfg = (void *)((UINTPTR)mountHdl + sizeof(lfs_t));
200 
201     LfsConfigAdapter((struct PartitionCfg *)data, cfg);
202 
203     ret = lfs_mount((lfs_t *)mp->mData, cfg);
204     if (ret != 0) {
205         ret = lfs_format((lfs_t *)mp->mData, cfg);
206         if (ret == 0) {
207             ret = lfs_mount((lfs_t *)mp->mData, cfg);
208         }
209     }
210     if (ret != 0) {
211         LOSCFG_FS_FREE_HOOK(mountHdl);
212         errno = LittlefsErrno(ret);
213         ret = (int)LOS_NOK;
214     }
215 
216 errout:
217     return ret;
218 }
219 
LfsUmount(struct MountPoint *mp)220 int LfsUmount(struct MountPoint *mp)
221 {
222     int ret;
223 
224     if (mp == NULL) {
225         errno = EFAULT;
226         return (int)LOS_NOK;
227     }
228 
229     if (mp->mData == NULL) {
230         errno = ENOENT;
231         return (int)LOS_NOK;
232     }
233 
234     ret = lfs_unmount((lfs_t *)mp->mData);
235     if (ret != 0) {
236         errno = LittlefsErrno(ret);
237         ret = (int)LOS_NOK;
238     }
239 
240     LOSCFG_FS_FREE_HOOK(mp->mData);
241     mp->mData = NULL;
242     return ret;
243 }
244 
LfsUnlink(struct MountPoint *mp, const char *fileName)245 int LfsUnlink(struct MountPoint *mp, const char *fileName)
246 {
247     int ret;
248 
249     if ((mp == NULL) || (fileName == NULL)) {
250         errno = EFAULT;
251         return (int)LOS_NOK;
252     }
253 
254     if (mp->mData == NULL) {
255         errno = ENOENT;
256         return (int)LOS_NOK;
257     }
258 
259     ret = lfs_remove((lfs_t *)mp->mData, fileName);
260     if (ret != 0) {
261         errno = LittlefsErrno(ret);
262         ret = (int)LOS_NOK;
263     }
264 
265     return ret;
266 }
267 
LfsMkdir(struct MountPoint *mp, const char *dirName)268 int LfsMkdir(struct MountPoint *mp, const char *dirName)
269 {
270     int ret;
271 
272     if ((dirName == NULL) || (mp == NULL)) {
273         errno = EFAULT;
274         return (int)LOS_NOK;
275     }
276 
277     if (mp->mData == NULL) {
278         errno = ENOENT;
279         return (int)LOS_NOK;
280     }
281 
282     lfs_t *lfs = (lfs_t *)mp->mData;
283 
284     ret = lfs_mkdir(lfs, dirName);
285     if (ret != 0) {
286         errno = LittlefsErrno(ret);
287         ret = (int)LOS_NOK;
288     }
289 
290     return ret;
291 }
292 
LfsRmdir(struct MountPoint *mp, const char *dirName)293 int LfsRmdir(struct MountPoint *mp, const char *dirName)
294 {
295     int ret;
296     lfs_t *lfs = NULL;
297 
298     if (mp == NULL) {
299         errno = EFAULT;
300         return (int)LOS_NOK;
301     }
302 
303     if (mp->mData == NULL) {
304         errno = ENOENT;
305         return (int)LOS_NOK;
306     }
307 
308     lfs = (lfs_t *)mp->mData;
309 
310     if (dirName == NULL) {
311         errno = EFAULT;
312         return (int)LOS_NOK;
313     }
314 
315     ret = lfs_remove(lfs, dirName);
316     if (ret != 0) {
317         errno = LittlefsErrno(ret);
318         ret = (int)LOS_NOK;
319     }
320 
321     return ret;
322 }
323 
LfsOpendir(struct Dir *dir, const char *dirName)324 int LfsOpendir(struct Dir *dir, const char *dirName)
325 {
326     int ret;
327 
328     if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) {
329         errno = EFAULT;
330         return (int)LOS_NOK;
331     }
332 
333     lfs_t *lfs = (lfs_t *)dir->dMp->mData;
334     lfs_dir_t *dirInfo = (lfs_dir_t *)LOSCFG_FS_MALLOC_HOOK(sizeof(lfs_dir_t));
335     if (dirInfo == NULL) {
336         errno = ENOMEM;
337         return (int)LOS_NOK;
338     }
339 
340     (void)memset_s(dirInfo, sizeof(lfs_dir_t), 0, sizeof(lfs_dir_t));
341     ret = lfs_dir_open(lfs, dirInfo, dirName);
342     if (ret != 0) {
343         LOSCFG_FS_FREE_HOOK(dirInfo);
344         errno = LittlefsErrno(ret);
345         goto errout;
346     }
347 
348     dir->dData = dirInfo;
349     dir->dOffset = 0;
350 
351     return LOS_OK;
352 
353 errout:
354     return (int)LOS_NOK;
355 }
356 
LfsReaddir(struct Dir *dir, struct dirent *dent)357 int LfsReaddir(struct Dir *dir, struct dirent *dent)
358 {
359     int ret;
360     struct lfs_info lfsInfo;
361 
362     if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL) ||
363         (dent == NULL)) {
364         errno = EFAULT;
365         return (int)LOS_NOK;
366     }
367 
368     if (dir->dData == NULL) {
369         errno = EBADF;
370         return (int)LOS_NOK;
371     }
372 
373     lfs_t *lfs = (lfs_t *)dir->dMp->mData;
374     lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData;
375 
376     ret = lfs_dir_read(lfs, dirInfo, &lfsInfo);
377     if (ret == TRUE) {
378         (void)strncpy_s(dent->d_name, sizeof(dent->d_name), lfsInfo.name, strlen(lfsInfo.name) + 1);
379         if (lfsInfo.type == LFS_TYPE_DIR) {
380             dent->d_type = DT_DIR;
381         } else if (lfsInfo.type == LFS_TYPE_REG) {
382             dent->d_type = DT_REG;
383         }
384 
385         dent->d_reclen = lfsInfo.size;
386 
387         return LOS_OK;
388     }
389 
390     if (ret != 0) {
391         errno = LittlefsErrno(ret);
392     }
393 
394     return (int)LOS_NOK;
395 }
396 
LfsClosedir(struct Dir *dir)397 int LfsClosedir(struct Dir *dir)
398 {
399     int ret;
400 
401     if ((dir == NULL) || (dir->dMp == NULL) || (dir->dMp->mData == NULL)) {
402         errno = EFAULT;
403         return (int)LOS_NOK;
404     }
405 
406     if (dir->dData == NULL) {
407         errno = EBADF;
408         return (int)LOS_NOK;
409     }
410 
411     lfs_t *lfs = (lfs_t *)dir->dMp->mData;
412     lfs_dir_t *dirInfo = (lfs_dir_t *)dir->dData;
413 
414     ret = lfs_dir_close(lfs, dirInfo);
415     if (ret != 0) {
416         errno = LittlefsErrno(ret);
417         ret = (int)LOS_NOK;
418     }
419 
420     LOSCFG_FS_FREE_HOOK(dirInfo);
421     dir->dData = NULL;
422 
423     return ret;
424 }
425 
LfsOpen(struct File *file, const char *pathName, int openFlag)426 int LfsOpen(struct File *file, const char *pathName, int openFlag)
427 {
428     int ret;
429     lfs_file_t *lfsHandle = NULL;
430 
431     if ((pathName == NULL) || (file == NULL) || (file->fMp == NULL) ||
432         (file->fMp->mData == NULL)) {
433         errno = EFAULT;
434         return (int)LOS_NOK;
435     }
436 
437     lfsHandle = (lfs_file_t *)LOSCFG_FS_MALLOC_HOOK(sizeof(lfs_file_t));
438     if (lfsHandle == NULL) {
439         errno = ENOMEM;
440         return (int)LOS_NOK;
441     }
442 
443     int lfsOpenFlag = ConvertFlagToLfsOpenFlag(openFlag);
444     ret = lfs_file_open((lfs_t *)file->fMp->mData, lfsHandle, pathName, lfsOpenFlag);
445     if (ret != 0) {
446         LOSCFG_FS_FREE_HOOK(lfsHandle);
447         errno = LittlefsErrno(ret);
448         goto errout;
449     }
450 
451     file->fData = (void *)lfsHandle;
452     return ret;
453 
454 errout:
455     return INVALID_FD;
456 }
457 
LfsRead(struct File *file, char *buf, size_t len)458 int LfsRead(struct File *file, char *buf, size_t len)
459 {
460     int ret;
461     struct MountPoint *mp = NULL;
462     lfs_file_t *lfsHandle = NULL;
463 
464     if (buf == NULL) {
465         errno = EFAULT;
466         return (int)LOS_NOK;
467     }
468 
469     if ((file == NULL) || (file->fData == NULL)) {
470         errno = EBADF;
471         return (int)LOS_NOK;
472     }
473 
474     lfsHandle = (lfs_file_t *)file->fData;
475     mp = file->fMp;
476     if ((mp == NULL) || (mp->mData == NULL)) {
477         errno = EFAULT;
478         return (int)LOS_NOK;
479     }
480 
481     ret = lfs_file_read((lfs_t *)mp->mData, lfsHandle, buf, len);
482     if (ret < 0) {
483         errno = LittlefsErrno(ret);
484         ret = (int)LOS_NOK;
485     }
486     return ret;
487 }
488 
LfsWrite(struct File *file, const char *buf, size_t len)489 int LfsWrite(struct File *file, const char *buf, size_t len)
490 {
491     int ret;
492     struct MountPoint *mp = NULL;
493     lfs_file_t *lfsHandle = NULL;
494 
495     if (buf == NULL) {
496         errno = EFAULT;
497         return (int)LOS_NOK;
498     }
499 
500     if ((file == NULL) || (file->fData == NULL)) {
501         errno = EBADF;
502         return (int)LOS_NOK;
503     }
504 
505     lfsHandle = (lfs_file_t *)file->fData;
506     mp = file->fMp;
507     if ((mp == NULL) || (mp->mData == NULL)) {
508         errno = EFAULT;
509         return (int)LOS_NOK;
510     }
511 
512     ret = lfs_file_write((lfs_t *)mp->mData, lfsHandle, buf, len);
513     if (ret < 0) {
514         errno = LittlefsErrno(ret);
515         ret = (int)LOS_NOK;
516     }
517     return ret;
518 }
519 
LfsSeek(struct File *file, off_t offset, int whence)520 off_t LfsSeek(struct File *file, off_t offset, int whence)
521 {
522     off_t ret;
523     struct MountPoint *mp = NULL;
524     lfs_file_t *lfsHandle = NULL;
525 
526     if ((file == NULL) || (file->fData == NULL)) {
527         errno = EBADF;
528         return (off_t)LOS_NOK;
529     }
530 
531     lfsHandle = (lfs_file_t *)file->fData;
532     mp = file->fMp;
533     if ((mp == NULL) || (mp->mData == NULL)) {
534         errno = EFAULT;
535         return (off_t)LOS_NOK;
536     }
537 
538     ret = (off_t)lfs_file_seek((lfs_t *)mp->mData, lfsHandle, offset, whence);
539     if (ret < 0) {
540         errno = LittlefsErrno(ret);
541         ret = (off_t)LOS_NOK;
542     }
543 
544     return ret;
545 }
546 
LfsClose(struct File *file)547 int LfsClose(struct File *file)
548 {
549     int ret;
550     struct MountPoint *mp = NULL;
551     lfs_file_t *lfsHandle = NULL;
552 
553     if ((file == NULL) || (file->fData == NULL)) {
554         errno = EBADF;
555         return (int)LOS_NOK;
556     }
557 
558     lfsHandle = (lfs_file_t *)file->fData;
559     mp = file->fMp;
560     if ((mp == NULL) || (mp->mData == NULL)) {
561         errno = EFAULT;
562         return (int)LOS_NOK;
563     }
564 
565     ret = lfs_file_close((lfs_t *)mp->mData, lfsHandle);
566     if (ret != 0) {
567         errno = LittlefsErrno(ret);
568         ret = (int)LOS_NOK;
569     }
570 
571     LOSCFG_FS_FREE_HOOK(file->fData);
572     file->fData = NULL;
573     return ret;
574 }
575 
LfsRename(struct MountPoint *mp, const char *oldName, const char *newName)576 int LfsRename(struct MountPoint *mp, const char *oldName, const char *newName)
577 {
578     int ret;
579 
580     if ((mp == NULL) || (oldName == NULL) || (newName == NULL)) {
581         errno = EFAULT;
582         return (int)LOS_NOK;
583     }
584 
585     if (mp->mData == NULL) {
586         errno = ENOENT;
587         return (int)LOS_NOK;
588     }
589 
590     ret = lfs_rename((lfs_t *)mp->mData, oldName, newName);
591     if (ret != 0) {
592         errno = LittlefsErrno(ret);
593         ret = (int)LOS_NOK;
594     }
595 
596     return ret;
597 }
598 
LfsStat(struct MountPoint *mp, const char *path, struct stat *buf)599 int LfsStat(struct MountPoint *mp, const char *path, struct stat *buf)
600 {
601     int ret;
602     struct lfs_info info;
603 
604     if ((mp == NULL) || (path == NULL) || (buf == NULL)) {
605         errno = EFAULT;
606         return (int)LOS_NOK;
607     }
608 
609     if (mp->mData == NULL) {
610         errno = ENOENT;
611         return (int)LOS_NOK;
612     }
613 
614     ret = lfs_stat((lfs_t *)mp->mData, path, &info);
615     if (ret == 0) {
616         buf->st_size = info.size;
617         if (info.type == LFS_TYPE_REG) {
618             buf->st_mode = S_IFREG;
619         } else {
620             buf->st_mode = S_IFDIR;
621         }
622     } else {
623         errno = LittlefsErrno(ret);
624         ret = (int)LOS_NOK;
625     }
626 
627     return ret;
628 }
629 
LfsSync(struct File *file)630 int LfsSync(struct File *file)
631 {
632     int ret;
633     struct MountPoint *mp = NULL;
634 
635     if ((file == NULL) || (file->fData == NULL)) {
636         errno = EBADF;
637         return (int)LOS_NOK;
638     }
639 
640     if ((file->fMp == NULL) || (file->fMp->mData == NULL)) {
641         errno = EFAULT;
642         return (int)LOS_NOK;
643     }
644 
645     mp = file->fMp;
646     ret = lfs_file_sync((lfs_t *)mp->mData, (lfs_file_t *)file->fData);
647     if (ret != 0) {
648         errno = LittlefsErrno(ret);
649         ret = (int)LOS_NOK;
650     }
651     return ret;
652 }
653 
LfsFormat(const char *partName, void *privData)654 int LfsFormat(const char *partName, void *privData)
655 {
656     int ret;
657     lfs_t lfs = {0};
658     struct lfs_config cfg = {0};
659 
660     (void)partName;
661 
662     LfsConfigAdapter((struct PartitionCfg *)privData, &cfg);
663 
664     ret = lfs_format(&lfs, &cfg);
665     if (ret != 0) {
666         errno = LittlefsErrno(ret);
667         ret = (int)LOS_NOK;
668     }
669     return ret;
670 }
671 
672 static struct MountOps g_lfsMnt = {
673     .mount = LfsMount,
674     .umount = LfsUmount,
675     .umount2 = NULL,
676     .statfs = NULL,
677 };
678 
679 static struct FileOps g_lfsFops = {
680     .open = LfsOpen,
681     .close = LfsClose,
682     .read = LfsRead,
683     .write = LfsWrite,
684     .lseek = LfsSeek,
685     .stat = LfsStat,
686     .truncate = NULL,
687     .unlink = LfsUnlink,
688     .rename = LfsRename,
689     .ioctl = NULL, /* not support */
690     .sync = LfsSync,
691     .rmdir = LfsRmdir,
692     .opendir = LfsOpendir,
693     .readdir = LfsReaddir,
694     .closedir = LfsClosedir,
695     .mkdir = LfsMkdir,
696 };
697 
698 static struct FsManagement g_lfsMgt = {
699     .fdisk = NULL,
700     .format = LfsFormat,
701 };
702 
LfsInit(void)703 void LfsInit(void)
704 {
705     (void)OsFsRegister("littlefs", &g_lfsMnt, &g_lfsFops, &g_lfsMgt);
706 }
707