更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
fatfs.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 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#include "fatfs.h"
33#ifdef LOSCFG_FS_FAT
34#include "ff.h"
35#include "disk_pri.h"
36#include "diskio.h"
37#include "fs/file.h"
38#include "fs/fs.h"
39#include "fs/dirent_fs.h"
40#include "fs/mount.h"
41#include "vnode.h"
42#include "path_cache.h"
43#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
44#include "virpartff.h"
45#include "errcode_fat.h"
46#endif
47#include "los_tables.h"
48#include "user_copy.h"
49#include "los_vm_filemap.h"
50#include "los_hash.h"
51#include "los_vm_common.h"
52#include <time.h>
53#include <errno.h>
54#include <dirent.h>
55#include <stdlib.h>
56#include <string.h>
57#include <sys/stat.h>
58#include <sys/types.h>
59#include <fcntl.h>
60
61/**
62 * @brief
63 * @verbatim
64FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。
65其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。
66FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的字节数。
67FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,
68使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。
69
70OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,
71具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,
72支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。
73
74驱动适配
75 FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC存储设备的板子上运行FATFS,需要:
76 1、适配板端EMMC驱动,实现disk_status、disk_initialize、disk_read、disk_write、disk_ioctl接口;
77 2、新增fs_config.h文件,配置FS_MAX_SS(存储设备最大sector大小)、FF_VOLUME_STRS(分区名)等信息,
78 * @endverbatim
79 */
80
81struct VnodeOps fatfs_vops; /* forward define */
82struct file_operations_vfs fatfs_fops;
83
84#define BITMASK4 0x0F
85#define BITMASK5 0x1F
86#define BITMASK6 0x3F
87#define BITMASK7 0x7F
88#define FTIME_MIN_OFFSET 6 /*! minute offset in word */
89#define FTIME_HR_OFFSET 11 /*! hour offset in word */
90#define FTIME_MTH_OFFSET 5 /*! month offset in word */
91#define FTIME_YEAR_OFFSET 9 /*! year offset in word */
92#define FTIME_DATE_OFFSET 16 /*! date offset in dword */
93#define SEC_MULTIPLIER 2
94#define YEAR_OFFSET 80 /*! Year start from 1980 in FATFS, while start from 1900 in struct tm */
95// 结果转化 fat 转 vfs
96int fatfs_2_vfs(int result)
97{
98 int status = ENOERR;
99
100#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
101 if (result < 0 || result >= VIRERR_BASE) {
102 return result;
103 }
104#else
105 if (result < 0) {
106 return result;
107 }
108#endif
109
110 /* FatFs errno to Libc errno */
111 switch (result) {
112 case FR_OK:
113 break;
114
115 case FR_NO_FILE:
116 case FR_NO_PATH:
117 status = ENOENT;
118 break;
119
120 case FR_NO_FILESYSTEM:
121 status = ENOTSUP;
122 break;
123
124 case FR_INVALID_NAME:
125 status = EINVAL;
126 break;
127
128 case FR_EXIST:
129 case FR_INVALID_OBJECT:
130 status = EEXIST;
131 break;
132
133 case FR_DISK_ERR:
134 case FR_NOT_READY:
135 case FR_INT_ERR:
136 status = EIO;
137 break;
138
139 case FR_WRITE_PROTECTED:
140 status = EROFS;
141 break;
142 case FR_MKFS_ABORTED:
143 case FR_INVALID_PARAMETER:
144 status = EINVAL;
145 break;
146
147 case FR_NO_SPACE_LEFT:
148 status = ENOSPC;
149 break;
150 case FR_NO_DIRENTRY:
151 status = ENFILE;
152 break;
153 case FR_NO_EMPTY_DIR:
154 status = ENOTEMPTY;
155 break;
156 case FR_IS_DIR:
157 status = EISDIR;
158 break;
159 case FR_NO_DIR:
160 status = ENOTDIR;
161 break;
162 case FR_NO_EPERM:
163 case FR_DENIED:
164 status = EPERM;
165 break;
166 case FR_LOCKED:
167 case FR_TIMEOUT:
168 status = EBUSY;
169 break;
170#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
171 case FR_MODIFIED:
172 status = -VIRERR_MODIFIED;
173 break;
174 case FR_CHAIN_ERR:
175 status = -VIRERR_CHAIN_ERR;
176 break;
177 case FR_OCCUPIED:
178 status = -VIRERR_OCCUPIED;
179 break;
180 case FR_NOTCLEAR:
181 status = -VIRERR_NOTCLEAR;
182 break;
183 case FR_NOTFIT:
184 status = -VIRERR_NOTFIT;
185 break;
186 case FR_INVAILD_FATFS:
187 status = -VIRERR_INTER_ERR;
188 break;
189#endif
190 default:
191 status = -FAT_ERROR;
192 break;
193 }
194
195 return status;
196}
197
198static bool fatfs_is_last_cluster(FATFS *fs, DWORD cclust)
199{
200 switch (fs->fs_type) {
201 case FS_FAT12:
202 return (cclust == FAT12_END_OF_CLUSTER);
203 case FS_FAT16:
204 return (cclust == FAT16_END_OF_CLUSTER);
205 case FS_FAT32:
206 default:
207 return (cclust == FAT32_END_OF_CLUSTER);
208 }
209}
210
211static int fatfs_sync(unsigned long mountflags, FATFS *fs)
212{
213#ifdef LOSCFG_FS_FAT_CACHE
214 los_part *part = NULL;
215 if (!(mountflags & (MS_NOSYNC | MS_RDONLY))) {
216 part = get_part((INT)fs->pdrv);
217 if (part == NULL) {
218 return -ENODEV;
219 }
220
221 (void)OsSdSync(part->disk_id);
222 }
223#endif
224 return 0;
225}
226///哈希值比较函数,返回int
227//typedef int VfsHashCmp(struct Vnode *vnode, void *arg);
228int fatfs_hash_cmp(struct Vnode *vp, void *arg)
229{
230 DIR_FILE *dfp_target = (DIR_FILE *)arg;
231 DIR_FILE *dfp = (DIR_FILE *)vp->data;
232
233 return dfp_target->f_dir.sect != dfp->f_dir.sect ||
234 dfp_target->f_dir.dptr != dfp->f_dir.dptr ||
235 dfp_target->fno.sclst != dfp->fno.sclst;
236}
237///生成hash值的过程
238static DWORD fatfs_hash(QWORD sect, DWORD dptr, DWORD sclst)
239{
240 DWORD hash = FNV1_32A_INIT;
241 hash = LOS_HashFNV32aBuf(&sect, sizeof(QWORD), hash);
242 hash = LOS_HashFNV32aBuf(&dptr, sizeof(DWORD), hash);
243 hash = LOS_HashFNV32aBuf(&sclst, sizeof(DWORD), hash);
244
245 return hash;
246}
247
248static mode_t fatfs_get_mode(BYTE attribute, mode_t fs_mode)
249{
250 mode_t mask = 0;
251 if (attribute & AM_RDO) {
252 mask = S_IWUSR | S_IWGRP | S_IWOTH;
253 }
254 fs_mode &= ~mask;
255 if (attribute & AM_DIR) {
256 fs_mode |= S_IFDIR;
257 } else if (attribute & AM_LNK) {
258 fs_mode |= S_IFLNK;
259 } else {
260 fs_mode |= S_IFREG;
261 }
262 return fs_mode;
263}
264///类型转换
265static enum VnodeType fatfstype_2_vnodetype(BYTE type)
266{
267 switch (type) {
268 case AM_ARC:
269 return VNODE_TYPE_REG;
270 case AM_DIR:
271 return VNODE_TYPE_DIR;
272 case AM_LNK:
273 return VNODE_TYPE_LNK;
274 default:
275 return VNODE_TYPE_UNKNOWN;
276 }
277}
278
279#define DIR_SIZE 32
280static FRESULT init_cluster(DIR_FILE *pdfp, DIR *dp_new, FATFS *fs, int type, const char *target, DWORD *clust)
281{
282 FRESULT result;
283 BYTE *dir = NULL;
284 QWORD sect;
285 DWORD pclust;
286 UINT n;
287
288 /* Allocate a new cluster */
289 *clust = create_chain(&(dp_new->obj), 0);
290 if (*clust == 0) {
291 return FR_NO_SPACE_LEFT;
292 }
293 if (*clust == 1 || *clust == DISK_ERROR) {
294 return FR_DISK_ERR;
295 }
296
297 result = sync_window(fs); /* Flush FAT */
298 if (result != FR_OK) {
299 remove_chain(&(dp_new->obj), *clust, 0);
300 return result;
301 }
302
303 /* Initialize the new cluster */
304#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
305 dir = fs->win;
306#else
307 dir = PARENTFS(fs)->win;
308#endif
309
310 sect = clst2sect(fs, *clust);
311 mem_set(dir, 0, SS(fs));
312 if (type == AM_LNK && target) {
313 /* Write target to symlink */
314 (void)strcpy_s((char *)dir, SS(fs), target);
315 } else {
316 /* Write the dir cluster */
317 mem_set(dir, 0, SS(fs));
318 mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
319 dir[DIR_Name] = '.';
320 dir[DIR_Attr] = AM_DIR;
321 st_clust(fs, dir, *clust);
322 mem_cpy(dir + DIR_SIZE, dir, DIR_SIZE); /* Create ".." entry */
323 dir[DIR_SIZE + 1] = '.'; /* Add extra "." */
324 pclust = pdfp->fno.sclst;
325 if (fs->fs_type == FS_FAT32 && pclust == fs->dirbase) {
326 pclust = 0;
327 }
328 st_clust(fs, dir + DIR_SIZE, pclust);
329 }
330
331#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
332 fs->winsect = sect++;
333 fs->wflag = 1;
334#else
335 PARENTFS(fs)->winsect = sect++;
336 PARENTFS(fs)->wflag = 1;
337#endif
338 result = sync_window(fs);
339 if (result != FR_OK) {
340 remove_chain(&(dp_new->obj), *clust, 0);
341 return result;
342 }
343
344 /* Rest of directory cluster should set to be zero */
345 if (type == AM_DIR) {
346 mem_set(dir, 0, SS(fs));
347 for (n = fs->csize - 1; n > 0; n--) {
348#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
349 fs->winsect = sect++;
350 fs->wflag = 1;
351#else
352 PARENTFS(fs)->winsect = sect++;
353 PARENTFS(fs)->wflag = 1;
354#endif
355 result = sync_window(fs);
356 if (result != FR_OK) {
357 remove_chain(&(dp_new->obj), *clust, 0);
358 return result;
359 }
360 }
361 }
362
363 return FR_OK;
364}
365
366static int fatfs_create_obj(struct Vnode *parent, const char *name, int mode, struct Vnode **vpp, BYTE type, const char *target)
367{
368 struct Vnode *vp = NULL;
369 FATFS *fs = (FATFS *)parent->originMount->data;
370 DIR_FILE *dfp = (DIR_FILE *)parent->data;
371 FILINFO *finfo = &(dfp->fno);
372 DIR_FILE *dfp_new = NULL;
373 FILINFO *finfo_new = NULL;
374 DIR *dp_new = NULL;
375 QWORD time;
376 DWORD hash;
377 DWORD clust = 0;
378 FRESULT result;
379 int ret;
380
381 if ((type != AM_ARC) && (type != AM_DIR) && (type != AM_LNK)) {//文件类型
382 result = FR_INVALID_NAME;
383 goto ERROR_EXIT;
384 }
385
386 dfp_new = (DIR_FILE *)zalloc(sizeof(DIR_FILE));
387 if (dfp_new == NULL) {
388 result = FR_NOT_ENOUGH_CORE;
389 goto ERROR_EXIT;
390 }
391
392 ret = lock_fs(fs);
393 if (ret == FALSE) { /* lock failed */
394 result = FR_TIMEOUT;
395 goto ERROR_FREE;
396 }
397
398 if (finfo->fattrib & AM_ARC || finfo->fattrib & AM_LNK) {
399 result = FR_NO_DIR;
400 goto ERROR_UNLOCK;
401 }
402
403 finfo_new = &(dfp_new->fno);
404 LOS_ListInit(&finfo_new->fp_list);
405 dp_new = &(dfp_new->f_dir);
406 dp_new->obj.fs = fs;
407 dp_new->obj.sclust = finfo->sclst;
408
409 DEF_NAMBUF;
410 INIT_NAMBUF(fs);
411
412 result = create_name(dp_new, &name);
413 if (result != FR_OK) {
414 goto ERROR_UNLOCK;
415 }
416
417 result = dir_find(dp_new);
418 if (result == FR_OK) {
419 result = FR_EXIST;
420 goto ERROR_UNLOCK;
421 }
422
423 if (type == AM_DIR || type == AM_LNK) {
424 result = init_cluster(dfp, dp_new, fs, type, target, &clust);
425 if (result != FR_OK) {
426 goto ERROR_UNLOCK;
427 }
428 }
429
430 result = dir_register(dp_new);
431 if (result != FR_OK) {
432 goto ERROR_REMOVE_CHAIN;
433 }
434
435 /* Set the directory entry attribute */
436 if (time_status == SYSTEM_TIME_ENABLE) {
437 time = GET_FATTIME();
438 } else {
439 time = 0;
440 }
441 st_dword(dp_new->dir + DIR_CrtTime, time);
442 st_dword(dp_new->dir + DIR_ModTime, time);
443 st_word(dp_new->dir + DIR_LstAccDate, time >> FTIME_DATE_OFFSET);
444 dp_new->dir[DIR_Attr] = type;
445 if (((DWORD)mode & S_IWUSR) == 0) {
446 dp_new->dir[DIR_Attr] |= AM_RDO;
447 }
448 st_clust(fs, dp_new->dir, clust);
449 if (type == AM_ARC) {
450 st_dword(dp_new->dir + DIR_FileSize, 0);
451 } else if (type == AM_LNK) {
452 st_dword(dp_new->dir + DIR_FileSize, strlen(target));
453 }
454
455#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
456 PARENTFS(fs)->wflag = 1;
457#else
458 fs->wflag = 1;
459#endif
460 result = sync_fs(fs);
461 if (result != FR_OK) {
462 goto ERROR_REMOVE_CHAIN;
463 }
464 result = dir_read(dp_new, 0);
465 if (result != FR_OK) {
466 goto ERROR_REMOVE_CHAIN;
467 }
468 dp_new->blk_ofs = dir_ofs(dp_new);
469 get_fileinfo(dp_new, finfo_new);
470 if (type == AM_ARC) {
471 dp_new->obj.objsize = 0;
472 } else if (type == AM_LNK) {
473 dp_new->obj.objsize = strlen(target);
474 } else {
475 finfo_new->fsize = fs->csize * SS(fs);
476 }
477
478 ret = VnodeAlloc(&fatfs_vops, &vp);
479 if (ret != 0) {
480 result = FR_NOT_ENOUGH_CORE;
481 goto ERROR_REMOVE_CHAIN;
482 }
483
484 vp->parent = parent;
485 vp->fop = &fatfs_fops;
486 vp->data = dfp_new;
488 vp->uid = fs->fs_uid;
489 vp->gid = fs->fs_gid;
490 vp->mode = fatfs_get_mode(finfo_new->fattrib, fs->fs_mode);
492
493 hash = fatfs_hash(dp_new->sect, dp_new->dptr, finfo_new->sclst);
494 ret = VfsHashInsert(vp, hash);
495 if (ret != 0) {
496 result = FR_NOT_ENOUGH_CORE;
497 goto ERROR_REMOVE_CHAIN;
498 }
499 *vpp = vp;
500
501 unlock_fs(fs, FR_OK);
502 FREE_NAMBUF();
504
505ERROR_REMOVE_CHAIN:
506 remove_chain(&(dp_new->obj), clust, 0);
507ERROR_UNLOCK:
508 unlock_fs(fs, result);
509 FREE_NAMBUF();
510ERROR_FREE:
511 free(dfp_new);
512ERROR_EXIT:
513 return -fatfs_2_vfs(result);
514}
515/// fat文件系统对 Lookup 接口的实现
516int fatfs_lookup(struct Vnode *parent, const char *path, int len, struct Vnode **vpp)
517{
518 struct Vnode *vp = NULL;
519 FATFS *fs = (FATFS *)(parent->originMount->data);
520 DIR_FILE *dfp;
521 DIR *dp = NULL;
522 FILINFO *finfo = NULL;
523 DWORD hash;
524 FRESULT result;
525 int ret;
526
527 dfp = (DIR_FILE *)zalloc(sizeof(DIR_FILE));
528 if (dfp == NULL) {
529 ret = ENOMEM;
530 goto ERROR_EXIT;
531 }
532
533 ret = lock_fs(fs);
534 if (ret == FALSE) {
535 ret = EBUSY;
536 goto ERROR_FREE;
537 }
538 finfo = &(dfp->fno);
539 LOS_ListInit(&finfo->fp_list);
540 dp = &(dfp->f_dir);
541 dp->obj.fs = fs;
542 dp->obj.sclust = ((DIR_FILE *)(parent->data))->fno.sclst;
543
544 DEF_NAMBUF;
545 INIT_NAMBUF(fs);
546 result = create_name(dp, &path);
547 if (result != FR_OK) {
548 ret = fatfs_2_vfs(result);
549 goto ERROR_UNLOCK;
550 }
551
552 result = dir_find(dp);
553 if (result != FR_OK) {
554 ret = fatfs_2_vfs(result);
555 goto ERROR_UNLOCK;
556 }
557
558 if (dp->fn[NSFLAG] & NS_NONAME) {
559 result = FR_INVALID_NAME;
560 ret = fatfs_2_vfs(result);
561 goto ERROR_UNLOCK;
562 }
563
564 get_fileinfo(dp, finfo);
565 dp->obj.objsize = 0;
566
567 hash = fatfs_hash(dp->sect, dp->dptr, finfo->sclst);
568 ret = VfsHashGet(parent->originMount, hash, &vp, fatfs_hash_cmp, dfp);
569 if (ret != 0) {
570 ret = VnodeAlloc(&fatfs_vops, &vp);
571 if (ret != 0) {
572 ret = ENOMEM;
573 result = FR_NOT_ENOUGH_CORE;
574 goto ERROR_UNLOCK;
575 }
576 vp->parent = parent;
577 vp->fop = &fatfs_fops;
578 vp->data = dfp;
580 vp->uid = fs->fs_uid;
581 vp->gid = fs->fs_gid;
582 vp->mode = fatfs_get_mode(finfo->fattrib, fs->fs_mode);
583 if (finfo->fattrib & AM_DIR) {
584 vp->type = VNODE_TYPE_DIR;
585 finfo->fsize = fs->csize * SS(fs);
586 } else {
587 vp->type = VNODE_TYPE_REG;
588 }
589
590 ret = VfsHashInsert(vp, hash);
591 if (ret != 0) {
592 result = FR_INVALID_PARAMETER;
593 goto ERROR_UNLOCK;
594 }
595 } else {
596 vp->parent = parent;
597 free(dfp); /* hash hit dfp is no needed */
598 }
599
600 unlock_fs(fs, FR_OK);
601 FREE_NAMBUF();
602 *vpp = vp;
603 return 0;
604
605ERROR_UNLOCK:
606 unlock_fs(fs, result);
607 FREE_NAMBUF();
608ERROR_FREE:
609 free(dfp);
610ERROR_EXIT:
611 return -ret;
612}
613///创建 fat vnode 节点
614int fatfs_create(struct Vnode *parent, const char *name, int mode, struct Vnode **vpp)
615{
616 return fatfs_create_obj(parent, name, mode, vpp, AM_ARC, NULL);
617}
618
619//打开 fat 格式文件
620int fatfs_open(struct file *filep)
621{
622 struct Vnode *vp = filep->f_vnode;
623 FATFS *fs = (FATFS *)vp->originMount->data;
624 DIR_FILE *dfp = (DIR_FILE *)vp->data;
625 DIR *dp = &(dfp->f_dir);
626 FILINFO *finfo = &(dfp->fno);
627 FIL *fp;
628 int ret;
629
630 fp = (FIL *)zalloc(sizeof(FIL) + SS(fs));
631 if (fp == NULL) {
632 ret = ENOMEM;
633 goto ERROR_EXIT;
634 }
635 ret = lock_fs(fs);
636 if (ret == FALSE) {
637 ret = EBUSY;
638 goto ERROR_FREE;
639 }
640
641 fp->dir_sect = dp->sect;
642 fp->dir_ptr = dp->dir;
643 fp->obj.sclust = finfo->sclst;
644 fp->obj.objsize = finfo->fsize;
645#if FF_USE_FASTSEEK
646 fp->cltbl = 0; /* Disable fast seek mode */
647#endif
648 fp->obj.fs = fs;
649 fp->obj.id = fs->id;
650 fp->flag = FA_READ | FA_WRITE;
651 fp->err = 0;
652 fp->sect = 0;
653 fp->fptr = 0;
654 fp->buf = (BYTE *)fp + sizeof(FIL);
655 LOS_ListAdd(&finfo->fp_list, &fp->fp_entry);
656 unlock_fs(fs, FR_OK);
657
658 filep->f_priv = fp;
659 return 0;
660
661ERROR_FREE:
662 free(fp);
663ERROR_EXIT:
664 return -ret;
665}
666
667int fatfs_close(struct file *filep)
668{
669 FIL *fp = (FIL *)filep->f_priv;
670 FATFS *fs = fp->obj.fs;
671 FRESULT result;
672 int ret;
673
674 ret = lock_fs(fs);
675 if (ret == FALSE) {
676 return -EBUSY;
677 }
678#if !FF_FS_READONLY
679 result = f_sync(fp); /* Flush cached data */
680 if (result != FR_OK) {
681 goto EXIT;
682 }
683 ret = fatfs_sync(filep->f_vnode->originMount->mountFlags, fs);
684 if (ret != 0) {
685 unlock_fs(fs, FR_OK);
686 return ret;
687 }
688#endif
689 LOS_ListDelete(&fp->fp_entry);
690 free(fp);
691 filep->f_priv = NULL;
692EXIT:
693 unlock_fs(fs, result);
694 return -fatfs_2_vfs(result);
695}
696
697int fatfs_read(struct file *filep, char *buff, size_t count)
698{
699 FIL *fp = (FIL *)filep->f_priv;
700 FATFS *fs = fp->obj.fs;
701 struct Vnode *vp = filep->f_vnode;
702 FILINFO *finfo = &((DIR_FILE *)(vp->data))->fno;
703 size_t rcount;
704 FRESULT result;
705 int ret;
706
707 ret = lock_fs(fs);
708 if (ret == FALSE) {
709 return -EBUSY;
710 }
711 fp->obj.objsize = finfo->fsize;
712 fp->obj.sclust = finfo->sclst;
713 result = f_read(fp, buff, count, &rcount);
714 if (result != FR_OK) {
715 goto EXIT;
716 }
717 filep->f_pos = fp->fptr;
718EXIT:
719 unlock_fs(fs, result);
720 return rcount;
721}
722
723static FRESULT update_dir(DIR *dp, FILINFO *finfo)
724{
725 FATFS *fs = dp->obj.fs;
726 DWORD tm;
727 BYTE *dbuff = NULL;
728 FRESULT result;
729
730 result = move_window(fs, dp->sect);
731 if (result != FR_OK) {
732 return result;
733 }
734 dbuff = fs->win + dp->dptr % SS(fs);
735 dbuff[DIR_Attr] = finfo->fattrib;
736 st_clust(fs, dbuff, finfo->sclst); /* Update start cluster */
737 st_dword(dbuff + DIR_FileSize, (DWORD)finfo->fsize); /* Update file size */
738 if (time_status == SYSTEM_TIME_ENABLE) {
739 tm = GET_FATTIME();
740 } else {
741 tm = 0;
742 }
743 st_dword(dbuff + DIR_ModTime, tm); /* Update mtime */
744 st_word(dbuff + DIR_LstAccDate, tm >> FTIME_DATE_OFFSET); /* Update access date */
745#ifndef LOSCFG_FS_FAT_VIRTUAL_PARTITION
746 fs->wflag = 1;
747#else
748 PARENTFS(fs)->wflag = 1;
749#endif
750 return sync_fs(fs);
751}
752
753off64_t fatfs_lseek64(struct file *filep, off64_t offset, int whence)
754{
755 FIL *fp = (FIL *)filep->f_priv;
756 FATFS *fs = fp->obj.fs;
757 struct Vnode *vp = filep->f_vnode;
758 DIR_FILE *dfp = (DIR_FILE *)vp->data;
759 FILINFO *finfo = &(dfp->fno);
760 struct Mount *mount = vp->originMount;
761 FSIZE_t fpos;
762 FRESULT result;
763 int ret;
764
765 switch (whence) {
766 case SEEK_CUR:
767 offset = filep->f_pos + offset;
768 if (offset < 0) {
769 return -EINVAL;
770 }
771 fpos = offset;
772 break;
773 case SEEK_SET:
774 if (offset < 0) {
775 return -EINVAL;
776 }
777 fpos = offset;
778 break;
779 case SEEK_END:
780 offset = (off_t)((long long)finfo->fsize + offset);
781 if (offset < 0) {
782 return -EINVAL;
783 }
784 fpos = offset;
785 break;
786 default:
787 return -EINVAL;
788 }
789
790 if (offset >= FAT32_MAXSIZE) {
791 return -EINVAL;
792 }
793
794 ret = lock_fs(fs);
795 if (ret == FALSE) {
796 return -EBUSY;
797 }
798
799 if (fpos > finfo->fsize) {
800 if ((filep->f_oflags & O_ACCMODE) == O_RDONLY) {
801 result = FR_DENIED;
802 goto ERROR_EXIT;
803 }
804 if (mount->mountFlags & MS_RDONLY) {
805 result = FR_WRITE_PROTECTED;
806 goto ERROR_EXIT;
807 }
808 }
809 fp->obj.sclust = finfo->sclst;
810 fp->obj.objsize = finfo->fsize;
811
812 result = f_lseek(fp, fpos);
813 finfo->fsize = fp->obj.objsize;
814 finfo->sclst = fp->obj.sclust;
815 if (result != FR_OK) {
816 goto ERROR_EXIT;
817 }
818
819 result = f_sync(fp);
820 if (result != FR_OK) {
821 goto ERROR_EXIT;
822 }
823 filep->f_pos = fpos;
824
825 unlock_fs(fs, FR_OK);
826 return fpos;
827ERROR_EXIT:
828 unlock_fs(fs, result);
829 return -fatfs_2_vfs(result);
830}
831
832off_t fatfs_lseek(struct file *filep, off_t offset, int whence)
833{
834 return (off_t)fatfs_lseek64(filep, offset, whence);
835}
836
837static int update_filbuff(FILINFO *finfo, FIL *wfp, const char *data)
838{
839 LOS_DL_LIST *list = &finfo->fp_list;
840 FATFS *fs = wfp->obj.fs;
841 FIL *entry = NULL;
842 int ret = 0;
843
844 LOS_DL_LIST_FOR_EACH_ENTRY(entry, list, FIL, fp_entry) {
845 if (entry == wfp) {
846 continue;
847 }
848 if (entry->sect != 0) {
849 if (disk_read(fs->pdrv, entry->buf, entry->sect, 1) != RES_OK) {
850 ret = -1;
851 }
852 }
853 }
854
855 return ret;
856}
857
858int fatfs_write(struct file *filep, const char *buff, size_t count)
859{
860 FIL *fp = (FIL *)filep->f_priv;
861 FATFS *fs = fp->obj.fs;
862 struct Vnode *vp = filep->f_vnode;
863 FILINFO *finfo = &(((DIR_FILE *)vp->data)->fno);
864 size_t wcount;
865 FRESULT result;
866 int ret;
867
868 ret = lock_fs(fs);
869 if (ret == FALSE) {
870 return -EBUSY;
871 }
872 fp->obj.objsize = finfo->fsize;
873 fp->obj.sclust = finfo->sclst;
874 result = f_write(fp, buff, count, &wcount);
875 if (result != FR_OK) {
876 goto ERROR_EXIT;
877 }
878
879 finfo->fsize = fp->obj.objsize;
880 finfo->sclst = fp->obj.sclust;
881 result = f_sync(fp);
882 if (result != FR_OK) {
883 goto ERROR_EXIT;
884 }
885 update_filbuff(finfo, fp, buff);
886
887 filep->f_pos = fp->fptr;
888
889 unlock_fs(fs, FR_OK);
890 return wcount;
891ERROR_EXIT:
892 unlock_fs(fs, result);
893 return -fatfs_2_vfs(result);
894}
895
896int fatfs_fsync(struct file *filep)
897{
898 FIL *fp = filep->f_priv;
899 FATFS *fs = fp->obj.fs;
900 FRESULT result;
901 int ret;
902
903 ret = lock_fs(fs);
904 if (ret == FALSE) {
905 return -EBUSY;
906 }
907
908 result = f_sync(fp);
909 unlock_fs(fs, result);
910 return -fatfs_2_vfs(result);
911}
912
913int fatfs_fallocate64(struct file *filep, int mode, off64_t offset, off64_t len)
914{
915 FIL *fp = (FIL *)filep->f_priv;
916 FATFS *fs = fp->obj.fs;
917 struct Vnode *vp = filep->f_vnode;
918 FILINFO *finfo = &((DIR_FILE *)(vp->data))->fno;
919 FRESULT result;
920 int ret;
921
922 if (offset < 0 || len <= 0) {
923 return -EINVAL;
924 }
925
926 if (len >= FAT32_MAXSIZE || offset >= FAT32_MAXSIZE ||
927 len + offset >= FAT32_MAXSIZE) {
928 return -EINVAL;
929 }
930
931 if (mode != FALLOC_FL_KEEP_SIZE) {
932 return -EINVAL;
933 }
934
935 ret = lock_fs(fs);
936 if (ret == FALSE) {
937 return -EBUSY;
938 }
939 result = f_expand(fp, (FSIZE_t)offset, (FSIZE_t)len, 1);
940 if (result == FR_OK) {
941 if (finfo->sclst == 0) {
942 finfo->sclst = fp->obj.sclust;
943 }
944 result = f_sync(fp);
945 }
946 unlock_fs(fs, result);
947
948 return -fatfs_2_vfs(result);
949}
950
951static FRESULT realloc_cluster(FILINFO *finfo, FFOBJID *obj, FSIZE_t size)
952{
953 FATFS *fs = obj->fs;
954 off64_t remain;
955 DWORD cclust;
956 DWORD pclust;
957 QWORD csize;
958 FRESULT result;
959
960 if (size == 0) { /* Remove cluster chain */
961 if (finfo->sclst != 0) {
962 result = remove_chain(obj, finfo->sclst, 0);
963 if (result != FR_OK) {
964 return result;
965 }
966 finfo->sclst = 0;
967 }
968 return FR_OK;
969 }
970
971 remain = size;
972 csize = SS(fs) * fs->csize;
973 if (finfo->sclst == 0) { /* Allocate one cluster if file doesn't have any cluster */
974 cclust = create_chain(obj, 0);
975 if (cclust == 0) {
976 return FR_NO_SPACE_LEFT;
977 }
978 if (cclust == 1 || cclust == DISK_ERROR) {
979 return FR_DISK_ERR;
980 }
981 finfo->sclst = cclust;
982 }
983 cclust = finfo->sclst;
984 while (remain > csize) { /* Follow or strentch the cluster chain */
985 pclust = cclust;
986 cclust = create_chain(obj, pclust);
987 if (cclust == 0) {
988 return FR_NO_SPACE_LEFT;
989 }
990 if (cclust == 1 || cclust == DISK_ERROR) {
991 return FR_DISK_ERR;
992 }
993 remain -= csize;
994 }
995 pclust = cclust;
996 cclust = get_fat(obj, pclust);
997 if ((cclust == BAD_CLUSTER) || (cclust == DISK_ERROR)) {
998 return FR_DISK_ERR;
999 }
1000 if (!fatfs_is_last_cluster(obj->fs, cclust)) { /* Remove extra cluster if existing */
1001 result = remove_chain(obj, cclust, pclust);
1002 if (result != FR_OK) {
1003 return result;
1004 }
1005 }
1006
1007 return FR_OK;
1008}
1009
1010int fatfs_fallocate(struct file *filep, int mode, off_t offset, off_t len)
1011{
1012 return fatfs_fallocate64(filep, mode, offset, len);
1013}
1014
1015int fatfs_truncate64(struct Vnode *vp, off64_t len)
1016{
1017 FATFS *fs = (FATFS *)vp->originMount->data;
1018 DIR_FILE *dfp = (DIR_FILE *)vp->data;
1019 DIR *dp = &(dfp->f_dir);
1020 FILINFO *finfo = &(dfp->fno);
1021 FFOBJID object;
1022 FRESULT result = FR_OK;
1023 int ret;
1024
1025 if (len < 0 || len >= FAT32_MAXSIZE) {
1026 return -EINVAL;
1027 }
1028
1029 ret = lock_fs(fs);
1030 if (ret == FALSE) {
1031 result = FR_TIMEOUT;
1032 goto ERROR_OUT;
1033 }
1034 if (len == finfo->fsize) {
1035 unlock_fs(fs, FR_OK);
1036 return 0;
1037 }
1038
1039 object.fs = fs;
1040 result = realloc_cluster(finfo, &object, (FSIZE_t)len);
1041 if (result != FR_OK) {
1042 goto ERROR_UNLOCK;
1043 }
1044 finfo->fsize = (FSIZE_t)len;
1045
1046 result = update_dir(dp, finfo);
1047 if (result != FR_OK) {
1048 goto ERROR_UNLOCK;
1049 }
1050 unlock_fs(fs, FR_OK);
1051 return fatfs_sync(vp->originMount->mountFlags, fs);
1052ERROR_UNLOCK:
1053 unlock_fs(fs, result);
1054ERROR_OUT:
1055 return -fatfs_2_vfs(result);
1056}
1057
1058int fatfs_truncate(struct Vnode *vp, off_t len)
1059{
1060 return fatfs_truncate64(vp, len);
1061}
1062
1063static int fat_bind_check(struct Vnode *blk_driver, los_part **partition)
1064{
1065 los_part *part = NULL;
1066
1067 if (blk_driver == NULL || blk_driver->data == NULL) {
1068 return ENODEV;
1069 }
1070
1071 struct drv_data *dd = blk_driver->data;
1072 if (dd->ops == NULL) {
1073 return ENODEV;
1074 }
1075 const struct block_operations *bops = dd->ops;
1076 if (bops->open == NULL) {
1077 return EINVAL;
1078 }
1079 if (bops->open(blk_driver) < 0) {
1080 return EBUSY;
1081 }
1082
1083 part = los_part_find(blk_driver);
1084 if (part == NULL) {
1085 return ENODEV;
1086 }
1087 if (part->part_name != NULL) {
1088 bops->close(blk_driver);
1089 return EBUSY;
1090 }
1091
1092#ifndef FF_MULTI_PARTITION
1093 if (part->part_no_mbr > 1) {
1094 bops->close(blk_driver);
1095 return EPERM;
1096 }
1097#endif
1098
1099 *partition = part;
1100 return 0;
1101}
1102///fat将分区文件系统挂载 举例: mount /dev/mmcblk0p0 /bin1/vs/sd vfat
1103int fatfs_mount(struct Mount *mnt, struct Vnode *blk_device, const void *data)
1104{
1105 struct Vnode *vp = NULL;
1106 FATFS *fs = NULL;
1107 DIR_FILE *dfp = NULL;
1108 los_part *part = NULL;
1109 QWORD start_sector;
1110 BYTE fmt;
1111 DWORD hash;
1112 FRESULT result;
1113 int ret;
1114
1115 ret = fat_bind_check(blk_device, &part);//通过节点获取分区信息
1116 if (ret != 0) {
1117 goto ERROR_EXIT;
1118 }
1119
1120 ret = SetDiskPartName(part, "vfat");
1121 if (ret != 0) {
1122 ret = EIO;
1123 goto ERROR_EXIT;
1124 }
1125
1126 fs = (FATFS *)zalloc(sizeof(FATFS));
1127 if (fs == NULL) {
1128 ret = ENOMEM;
1129 goto ERROR_PARTNAME;
1130 }
1131
1132#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
1133 fs->vir_flag = FS_PARENT;
1134 fs->parent_fs = fs;
1135 fs->vir_amount = DISK_ERROR;
1136 fs->vir_avail = FS_VIRDISABLE;
1137#endif
1138
1139 ret = ff_cre_syncobj(0, &fs->sobj);
1140 if (ret == 0) { /* create sync object failed */
1141 ret = EINVAL;
1142 goto ERROR_WITH_FS;
1143 }
1144
1145 ret = lock_fs(fs);
1146 if (ret == FALSE) {
1147 ret = EBUSY;
1148 goto ERROR_WITH_MUX;
1149 }
1150
1151 fs->fs_type = 0;
1152 fs->pdrv = part->part_id;
1153
1154#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */
1155 if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &(fs->ssize)) != RES_OK) {
1156 ret = EIO;
1157 goto ERROR_WITH_LOCK;
1158 }
1159 if (fs->ssize > FF_MAX_SS || fs->ssize < FF_MIN_SS || (fs->ssize & (fs->ssize - 1))) {
1160 ret = EIO;
1161 goto ERROR_WITH_LOCK;
1162 }
1163#endif
1164
1165 fs->win = (BYTE *)ff_memalloc(SS(fs));
1166 if (fs->win == NULL) {
1167 ret = ENOMEM;
1168 goto ERROR_WITH_LOCK;
1169 }
1170
1171 result = find_fat_partition(fs, part, &fmt, &start_sector);
1172 if (result != FR_OK) {
1173 ret = fatfs_2_vfs(result);
1174 goto ERROR_WITH_FSWIN;
1175 }
1176
1177 result = init_fatobj(fs, fmt, start_sector);
1178 if (result != FR_OK) {
1179 ret = fatfs_2_vfs(result);
1180 goto ERROR_WITH_FSWIN;
1181 }
1182
1183 fs->fs_uid = mnt->vnodeBeCovered->uid;
1184 fs->fs_gid = mnt->vnodeBeCovered->gid;
1185 fs->fs_dmask = GetUmask();
1186 fs->fs_fmask = GetUmask();
1187 fs->fs_mode = mnt->vnodeBeCovered->mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1188
1189 dfp = (DIR_FILE *)zalloc(sizeof(DIR_FILE));
1190 if (dfp == NULL) {
1191 ret = ENOMEM;
1192 goto ERROR_WITH_FSWIN;
1193 }
1194
1195 dfp->f_dir.obj.fs = fs;
1196 dfp->f_dir.obj.sclust = 0; /* set start clust 0, root */
1197 dfp->f_dir.obj.attr = AM_DIR;
1198 dfp->f_dir.obj.objsize = 0; /* dir size is 0 */
1199 dfp->fno.fsize = 0;
1200 dfp->fno.fdate = 0;
1201 dfp->fno.ftime = 0;
1202 dfp->fno.fattrib = AM_DIR;
1203 dfp->fno.sclst = 0;
1204 dfp->fno.fsize = fs->csize * SS(fs);
1205 dfp->fno.fname[0] = '/'; /* Mark as root dir */
1206 dfp->fno.fname[1] = '\0';
1207 LOS_ListInit(&(dfp->fno.fp_list));
1208
1209 ret = VnodeAlloc(&fatfs_vops, &vp);
1210 if (ret != 0) {
1211 ret = ENOMEM;
1212 goto ERROR_WITH_FSWIN;
1213 }
1214
1215 mnt->data = fs;
1216 mnt->vnodeCovered = vp;
1217
1218 vp->parent = mnt->vnodeBeCovered;
1219 vp->fop = &fatfs_fops;
1220 vp->data = dfp;
1221 vp->originMount = mnt;
1222 vp->uid = fs->fs_uid;
1223 vp->gid = fs->fs_gid;
1224 vp->mode = mnt->vnodeBeCovered->mode;
1225 vp->type = VNODE_TYPE_DIR;
1226
1227 hash = fatfs_hash(0, 0, 0);
1228 ret = VfsHashInsert(vp, hash);
1229 if (ret != 0) {
1230 ret = -ret;
1231 goto ERROR_WITH_LOCK;
1232 }
1233 unlock_fs(fs, FR_OK);
1234
1235 return 0;
1236
1237ERROR_WITH_FSWIN:
1238 ff_memfree(fs->win);
1239ERROR_WITH_LOCK:
1240 unlock_fs(fs, FR_OK);
1241ERROR_WITH_MUX:
1242 ff_del_syncobj(&fs->sobj);
1243ERROR_WITH_FS:
1244 free(fs);
1245ERROR_PARTNAME:
1246 if (part->part_name) {
1247 free(part->part_name);
1248 part->part_name = NULL;
1249 }
1250ERROR_EXIT:
1251 return -ret;
1252}
1253
1254int fatfs_umount(struct Mount *mnt, struct Vnode **blkdriver)
1255{
1256 struct Vnode *device;
1257 FATFS *fs = (FATFS *)mnt->data;
1258 los_part *part;
1259 int ret;
1260
1261 ret = lock_fs(fs);
1262 if (ret == FALSE) {
1263 return -EBUSY;
1264 }
1265
1266 part = get_part(fs->pdrv);
1267 if (part == NULL) {
1268 unlock_fs(fs, FR_OK);
1269 return -ENODEV;
1270 }
1271 device = part->dev;
1272 if (device == NULL) {
1273 unlock_fs(fs, FR_OK);
1274 return -ENODEV;
1275 }
1276#ifdef LOSCFG_FS_FAT_CACHE
1277 ret = OsSdSync(part->disk_id);
1278 if (ret != 0) {
1279 unlock_fs(fs, FR_DISK_ERR);
1280 return -EIO;
1281 }
1282#endif
1283 if (part->part_name != NULL) {
1284 free(part->part_name);
1285 part->part_name = NULL;
1286 }
1287
1288 struct drv_data *dd = device->data;
1289 if (dd->ops == NULL) {
1290 unlock_fs(fs, FR_OK);
1291 return ENODEV;
1292 }
1293
1294 const struct block_operations *bops = dd->ops;
1295 if (bops != NULL && bops->close != NULL) {
1296 bops->close(*blkdriver);
1297 }
1298
1299 if (fs->win != NULL) {
1300 ff_memfree(fs->win);
1301 }
1302
1303 unlock_fs(fs, FR_OK);
1304
1305 ret = ff_del_syncobj(&fs->sobj);
1306 if (ret == FALSE) {
1307 return -EINVAL;
1308 }
1309 free(fs);
1310
1311 *blkdriver = device;
1312
1313 return 0;
1314}
1315
1316int fatfs_sync_adapt(struct Mount *mnt)
1317{
1318 (void)mnt;
1319 int ret = 0;
1320#ifdef LOSCFG_FS_FAT_CACHE
1321 struct Vnode *dev = NULL;
1322 los_part *part = NULL;
1323
1324 if (mnt == NULL) {
1325 return -EINVAL;
1326 }
1327
1328 dev = mnt->vnodeDev;
1329 part = los_part_find(dev);
1330 if (part == NULL) {
1331 return -EINVAL;
1332 }
1333
1334 ret = OsSdSync(part->disk_id);
1335#endif
1336 return ret;
1337}
1338
1339int fatfs_statfs(struct Mount *mnt, struct statfs *info)
1340{
1341 FATFS *fs = (FATFS *)mnt->data;
1342 DWORD nclst = 0;
1343 FRESULT result = FR_OK;
1344 int ret;
1345
1346 info->f_type = MSDOS_SUPER_MAGIC;
1347#if FF_MAX_SS != FF_MIN_SS
1348 info->f_bsize = fs->ssize * fs->csize;
1349#else
1350 info->f_bsize = FF_MIN_SS * fs->csize;
1351#endif
1352 info->f_blocks = fs->n_fatent;
1353 ret = lock_fs(fs);
1354 if (ret == FALSE) {
1355 return -EBUSY;
1356 }
1357 /* free cluster is unavailable, update it */
1358 if (fs->free_clst == DISK_ERROR) {
1359 result = fat_count_free_entries(&nclst, fs);
1360 }
1361 info->f_bfree = fs->free_clst;
1362 info->f_bavail = fs->free_clst;
1363 unlock_fs(fs, result);
1364
1365#if FF_USE_LFN
1366 /* Maximum length of filenames */
1367 info->f_namelen = FF_MAX_LFN;
1368#else
1369 /* Maximum length of filenames: 8 is the basename length, 1 is the dot, 3 is the extension length */
1370 info->f_namelen = (8 + 1 + 3);
1371#endif
1372 info->f_fsid.__val[0] = MSDOS_SUPER_MAGIC;
1373 info->f_fsid.__val[1] = 1;
1374 info->f_frsize = SS(fs) * fs->csize;
1375 info->f_files = 0;
1376 info->f_ffree = 0;
1377 info->f_flags = mnt->mountFlags;
1378
1379 return -fatfs_2_vfs(result);
1380}
1381
1382static inline int GET_SECONDS(WORD ftime)
1383{
1384 return (ftime & BITMASK5) * SEC_MULTIPLIER;
1385}
1386static inline int GET_MINUTES(WORD ftime)
1387{
1388 return (ftime >> FTIME_MIN_OFFSET) & BITMASK6;
1389}
1390static inline int GET_HOURS(WORD ftime)
1391{
1392 return (ftime >> FTIME_HR_OFFSET) & BITMASK5;
1393}
1394static inline int GET_DAY(WORD fdate)
1395{
1396 return fdate & BITMASK5;
1397}
1398static inline int GET_MONTH(WORD fdate)
1399{
1400 return (fdate >> FTIME_MTH_OFFSET) & BITMASK4;
1401}
1402static inline int GET_YEAR(WORD fdate)
1403{
1404 return (fdate >> FTIME_YEAR_OFFSET) & BITMASK7;
1405}
1406
1407static time_t fattime_transfer(WORD fdate, WORD ftime)
1408{
1409 struct tm time = { 0 };
1410 time.tm_sec = GET_SECONDS(ftime);
1411 time.tm_min = GET_MINUTES(ftime);
1412 time.tm_hour = GET_HOURS(ftime);
1413 time.tm_mday = GET_DAY(fdate);
1414 time.tm_mon = GET_MONTH(fdate);
1415 time.tm_year = GET_YEAR(fdate) + YEAR_OFFSET; /* Year start from 1980 in FATFS */
1416 time_t ret = mktime(&time);
1417 return ret;
1418}
1419
1421{
1422 struct tm st;
1423 DWORD ftime;
1424
1425 localtime_r(&time, &st);
1426
1427 ftime = (DWORD)st.tm_mday;
1428 ftime |= ((DWORD)st.tm_mon) << FTIME_MTH_OFFSET;
1429 ftime |= ((DWORD)((st.tm_year > YEAR_OFFSET) ? (st.tm_year - YEAR_OFFSET) : 0)) << FTIME_YEAR_OFFSET;
1430 ftime <<= FTIME_DATE_OFFSET;
1431
1432 ftime = (DWORD)st.tm_sec / SEC_MULTIPLIER;
1433 ftime |= ((DWORD)st.tm_min) << FTIME_MIN_OFFSET;
1434 ftime |= ((DWORD)st.tm_hour) << FTIME_HR_OFFSET;
1435
1436 return ftime;
1437}
1438
1439int fatfs_stat(struct Vnode *vp, struct stat* sp)
1440{
1441 FATFS *fs = (FATFS *)vp->originMount->data;
1442 DIR_FILE *dfp = (DIR_FILE *)vp->data;
1443 FILINFO *finfo = &(dfp->fno);
1444 time_t time;
1445 int ret;
1446
1447 ret = lock_fs(fs);
1448 if (ret == FALSE) {
1449 return EBUSY;
1450 }
1451
1452 sp->st_dev = fs->pdrv;
1453 sp->st_mode = vp->mode;
1454 sp->st_nlink = 1;
1455 sp->st_uid = fs->fs_uid;
1456 sp->st_gid = fs->fs_gid;
1457 sp->st_size = finfo->fsize;
1458 sp->st_blksize = fs->csize * SS(fs);
1459 if (finfo->fattrib & AM_ARC) {
1460 sp->st_blocks = finfo->fsize ? ((finfo->fsize - 1) / SS(fs) / fs->csize + 1) : 0;
1461 } else {
1462 sp->st_blocks = fs->csize;
1463 }
1464 time = fattime_transfer(finfo->fdate, finfo->ftime);
1465 sp->st_mtime = time;
1466
1467 /* Adapt to kstat member "long tv_sec" */
1468 sp->__st_mtim32.tv_sec = (long)time;
1469
1470 unlock_fs(fs, FR_OK);
1471 return 0;
1472}
1473
1474void fatfs_chtime(DIR *dp, struct IATTR *attr)
1475{
1476 BYTE *dir = dp->dir;
1477 DWORD ftime;
1478 if (attr->attr_chg_valid & CHG_ATIME) {
1479 ftime = fattime_format(attr->attr_chg_atime);
1480 st_word(dir + DIR_LstAccDate, (ftime >> FTIME_DATE_OFFSET));
1481 }
1482
1483 if (attr->attr_chg_valid & CHG_CTIME) {
1484 ftime = fattime_format(attr->attr_chg_ctime);
1485 st_dword(dir + DIR_CrtTime, ftime);
1486 }
1487
1488 if (attr->attr_chg_valid & CHG_MTIME) {
1489 ftime = fattime_format(attr->attr_chg_mtime);
1490 st_dword(dir + DIR_ModTime, ftime);
1491 }
1492}
1493
1494int fatfs_chattr(struct Vnode *vp, struct IATTR *attr)
1495{
1496 FATFS *fs = (FATFS *)vp->originMount->data;
1497 DIR_FILE *dfp = (DIR_FILE *)vp->data;
1498 DIR *dp = &(dfp->f_dir);
1499 FILINFO *finfo = &(dfp->fno);
1500 BYTE *dir = dp->dir;
1501 DWORD ftime;
1502 FRESULT result;
1503 int ret;
1504
1505 if (finfo->fname[0] == '/') { /* Is root dir of fatfs ? */
1506 return 0;
1507 }
1508
1509 ret = lock_fs(fs);
1510 if (ret == FALSE) {
1511 result = FR_TIMEOUT;
1512 goto ERROR_OUT;
1513 }
1514
1515 result = move_window(fs, dp->sect);
1516 if (result != FR_OK) {
1517 goto ERROR_UNLOCK;
1518 }
1519
1520 if (attr->attr_chg_valid & CHG_MODE) {
1521 /* FAT only support readonly flag */
1522 if ((attr->attr_chg_mode & S_IWUSR) == 0 && (finfo->fattrib & AM_RDO) == 0) {
1523 dir[DIR_Attr] |= AM_RDO;
1524 finfo->fattrib |= AM_RDO;
1525 fs->wflag = 1;
1526 } else if ((attr->attr_chg_mode & S_IWUSR) != 0 && (finfo->fattrib & AM_RDO) != 0) {
1527 dir[DIR_Attr] &= ~AM_RDO;
1528 finfo->fattrib &= ~AM_RDO;
1529 fs->wflag = 1;
1530 }
1531 vp->mode = fatfs_get_mode(finfo->fattrib, fs->fs_mode);
1532 }
1533
1534 if (attr->attr_chg_valid & (CHG_ATIME | CHG_CTIME | CHG_MTIME)) {
1535 fatfs_chtime(dp, attr);
1536 ftime = ld_dword(dp->dir + DIR_ModTime);
1537 finfo->fdate = (WORD)(ftime >> FTIME_DATE_OFFSET);
1538 finfo->ftime = (WORD)ftime;
1539 }
1540
1541 result = sync_window(fs);
1542 if (result != FR_OK) {
1543 goto ERROR_UNLOCK;
1544 }
1545
1546 unlock_fs(fs, FR_OK);
1547 return fatfs_sync(vp->originMount->mountFlags, fs);
1548ERROR_UNLOCK:
1549 unlock_fs(fs, result);
1550ERROR_OUT:
1551 return -fatfs_2_vfs(result);
1552}
1553
1554int fatfs_opendir(struct Vnode *vp, struct fs_dirent_s *idir)
1555{
1556 FATFS *fs = vp->originMount->data;
1557 DIR_FILE *dfp = (DIR_FILE *)vp->data;
1558 FILINFO *finfo = &(dfp->fno);
1559 DIR *dp;
1560 DWORD clst;
1561 FRESULT result;
1562 int ret;
1563
1564 dp = (DIR*)zalloc(sizeof(DIR));
1565 if (dp == NULL) {
1566 return -ENOMEM;
1567 }
1568
1569 ret = lock_fs(fs);
1570 if (ret == FALSE) {
1571 return -EBUSY;
1572 }
1573 clst = finfo->sclst;
1574 dp->obj.fs = fs;
1575 dp->obj.sclust = clst;
1576
1577 result = dir_sdi(dp, 0);
1578 if (result != FR_OK) {
1579 free(dp);
1580 unlock_fs(fs, result);
1581 return -fatfs_2_vfs(result);
1582 }
1583 unlock_fs(fs, result);
1584 idir->u.fs_dir = dp;
1585
1586 return 0;
1587}
1588
1589int fatfs_readdir(struct Vnode *vp, struct fs_dirent_s *idir)
1590{
1591 FATFS *fs = vp->originMount->data;
1592 FILINFO fno;
1593 DIR* dp = (DIR*)idir->u.fs_dir;
1594 struct dirent *dirp = NULL;
1595 FRESULT result;
1596 int ret, i;
1597
1598 ret = lock_fs(fs);
1599 if (ret == FALSE) { /* Lock fs failed */
1600 return -EBUSY;
1601 }
1602 DEF_NAMBUF;
1603 INIT_NAMBUF(fs);
1604 for (i = 0; i < idir->read_cnt; i++) {
1605 /* using dir_read_massive to promote performance */
1606 result = dir_read_massive(dp, 0);
1607 if (result == FR_NO_FILE) {
1608 break;
1609 } else if (result != FR_OK) {
1610 goto ERROR_UNLOCK;
1611 }
1612 get_fileinfo(dp, &fno);
1613 /* 0x00 for end of directory and 0xFF for directory is empty */
1614 if (fno.fname[0] == 0x00 || fno.fname[0] == (TCHAR)0xFF) {
1615 break;
1616 }
1617
1618 dirp = &(idir->fd_dir[i]);
1619 if (fno.fattrib & AM_DIR) { /* is dir */
1620 dirp->d_type = DT_DIR;
1621 } else {
1622 dirp->d_type = DT_REG;
1623 }
1624 if (strncpy_s(dirp->d_name, sizeof(dirp->d_name), fno.fname, strlen(fno.fname)) != EOK) {
1625 result = FR_NOT_ENOUGH_CORE;
1626 goto ERROR_UNLOCK;
1627 }
1628 result = dir_next(dp, 0);
1629 if (result != FR_OK && result != FR_NO_FILE) {
1630 goto ERROR_UNLOCK;
1631 }
1632 idir->fd_position++;
1633 idir->fd_dir[i].d_off = idir->fd_position;
1634 idir->fd_dir[i].d_reclen = (uint16_t)sizeof(struct dirent);
1635 }
1636 unlock_fs(fs, FR_OK);
1637 FREE_NAMBUF();
1638 return i;
1639ERROR_UNLOCK:
1640 unlock_fs(fs, result);
1641 FREE_NAMBUF();
1642 return -fatfs_2_vfs(result);
1643}
1644
1645int fatfs_rewinddir(struct Vnode *vp, struct fs_dirent_s *dir)
1646{
1647 DIR *dp = (DIR *)dir->u.fs_dir;
1648 FATFS *fs = dp->obj.fs;
1649 FRESULT result;
1650 int ret;
1651
1652 ret = lock_fs(fs);
1653 if (ret == FALSE) {
1654 return -EBUSY;
1655 }
1656
1657 result = dir_sdi(dp, 0);
1658 unlock_fs(fs, result);
1659 return -fatfs_2_vfs(result);
1660}
1661
1662int fatfs_closedir(struct Vnode *vp, struct fs_dirent_s *dir)
1663{
1664 DIR *dp = (DIR *)dir->u.fs_dir;
1665 free(dp);
1666 dir->u.fs_dir = NULL;
1667 return 0;
1668}
1669
1670static FRESULT rename_check(DIR *dp_new, FILINFO *finfo_new, DIR *dp_old, FILINFO *finfo_old)
1671{
1672 DIR dir_sub;
1673 FRESULT result;
1674 if (finfo_new->fattrib & AM_ARC) { /* new path is file */
1675 if (finfo_old->fattrib & AM_DIR) { /* but old path is dir */
1676 return FR_NO_DIR;
1677 }
1678 } else if (finfo_new->fattrib & AM_DIR) { /* new path is dir */
1679 if (finfo_old->fattrib & AM_ARC) { /* old path is file */
1680 return FR_IS_DIR;
1681 }
1682 dir_sub.obj.fs = dp_old->obj.fs;
1683 dir_sub.obj.sclust = finfo_new->sclst;
1684 result = dir_sdi(&dir_sub, 0);
1685 if (result != FR_OK) {
1686 return result;
1687 }
1688 result = dir_read(&dir_sub, 0);
1689 if (result == FR_OK) { /* new path isn't empty file */
1690 return FR_NO_EMPTY_DIR;
1691 }
1692 } else { /* System file or volume label */
1693 return FR_DENIED;
1694 }
1695 return FR_OK;
1696}
1697
1698int fatfs_rename(struct Vnode *old_vnode, struct Vnode *new_parent, const char *oldname, const char *newname)
1699{
1700 FATFS *fs = (FATFS *)(old_vnode->originMount->data);
1701 DIR_FILE *dfp_old = (DIR_FILE *)old_vnode->data;
1702 DIR *dp_old = &(dfp_old->f_dir);
1703 FILINFO *finfo_old = &(dfp_old->fno);
1704 DIR_FILE *dfp_new = NULL;
1705 DIR* dp_new = NULL;
1706 FILINFO* finfo_new = NULL;
1707 DWORD clust;
1708 FRESULT result;
1709 int ret;
1710
1711 ret = lock_fs(fs);
1712 if (ret == FALSE) { /* Lock fs failed */
1713 return -EBUSY;
1714 }
1715
1716 dfp_new = (DIR_FILE *)zalloc(sizeof(DIR_FILE));
1717 if (dfp_new == NULL) {
1718 result = FR_NOT_ENOUGH_CORE;
1719 goto ERROR_UNLOCK;
1720 }
1721 dp_new = &(dfp_new->f_dir);
1722 finfo_new = &(dfp_new->fno);
1723
1724 dp_new->obj.sclust = ((DIR_FILE *)(new_parent->data))->fno.sclst;
1725 dp_new->obj.fs = fs;
1726
1727 /* Find new path */
1728 DEF_NAMBUF;
1729 INIT_NAMBUF(fs);
1730 result = create_name(dp_new, &newname);
1731 if (result != FR_OK) {
1732 goto ERROR_FREE;
1733 }
1734 result = dir_find(dp_new);
1735 if (result == FR_OK) { /* new path name exist */
1736 get_fileinfo(dp_new, finfo_new);
1737 result = rename_check(dp_new, finfo_new, dp_old, finfo_old);
1738 if (result != FR_OK) {
1739 goto ERROR_FREE;
1740 }
1741 result = dir_remove(dp_old);
1742 if (result != FR_OK) {
1743 goto ERROR_FREE;
1744 }
1745 clust = finfo_new->sclst;
1746 if (clust != 0) { /* remove the new path cluster chain if exists */
1747 result = remove_chain(&(dp_new->obj), clust, 0);
1748 if (result != FR_OK) {
1749 goto ERROR_FREE;
1750 }
1751 }
1752 } else { /* new path name not exist */
1753 result = dir_remove(dp_old);
1754 if (result != FR_OK) {
1755 goto ERROR_FREE;
1756 }
1757 result = dir_register(dp_new);
1758 if (result != FR_OK) {
1759 goto ERROR_FREE;
1760 }
1761 }
1762
1763 /* update new dir entry with old info */
1764 result = update_dir(dp_new, finfo_old);
1765 if (result != FR_OK) {
1766 goto ERROR_FREE;
1767 }
1768 result = dir_read(dp_new, 0);
1769 if (result != FR_OK) {
1770 goto ERROR_FREE;
1771 }
1772 dp_new->blk_ofs = dir_ofs(dp_new);
1773 get_fileinfo(dp_new, finfo_new);
1774
1775 dfp_new->fno.fp_list.pstNext = dfp_old->fno.fp_list.pstNext;
1776 dfp_new->fno.fp_list.pstPrev = dfp_old->fno.fp_list.pstPrev;
1777 ret = memcpy_s(dfp_old, sizeof(DIR_FILE), dfp_new, sizeof(DIR_FILE));
1778 if (ret != 0) {
1779 result = FR_NOT_ENOUGH_CORE;
1780 goto ERROR_FREE;
1781 }
1782 free(dfp_new);
1783 unlock_fs(fs, FR_OK);
1784 FREE_NAMBUF();
1785 return fatfs_sync(old_vnode->originMount->mountFlags, fs);
1786
1787ERROR_FREE:
1788 free(dfp_new);
1789ERROR_UNLOCK:
1790 unlock_fs(fs, result);
1791 FREE_NAMBUF();
1792 return -fatfs_2_vfs(result);
1793}
1794
1795
1796static int fatfs_erase(los_part *part, int option)
1797{
1798 int opt = option;
1799 if ((UINT)opt & FMT_ERASE) {
1800 opt = (UINT)opt & (~FMT_ERASE);
1801 if (EraseDiskByID(part->disk_id, part->sector_start, part->sector_count) != LOS_OK) {
1802 PRINTK("Disk erase error.\n");
1803 return -1;
1804 }
1805 }
1806
1807 if (opt != FM_FAT && opt != FM_FAT32) {
1808 opt = FM_ANY;
1809 }
1810
1811 return opt;
1812}
1813///设置FAT分区信息
1815{
1816 los_disk *disk = NULL;
1817 char *buf = NULL;
1818 int ret;
1819
1820 /* If there is no MBR before, the partition info needs to be changed after mkfs */
1821 if (part->type != EMMC && part->part_no_mbr == 0) {
1822 disk = get_disk(part->disk_id);
1823 if (disk == NULL) {
1824 return -EIO;
1825 }
1826 buf = (char *)zalloc(disk->sector_size);
1827 if (buf == NULL) {
1828 return -ENOMEM;
1829 }
1830 (void)memset_s(buf, disk->sector_size, 0, disk->sector_size);//第一个扇区是描述磁盘信息
1831 ret = los_disk_read(part->disk_id, buf, 0, 1, TRUE); /* TRUE when not reading large data */
1832 if (ret < 0) {
1833 free(buf);
1834 return -EIO;
1835 }
1836 part->sector_start = LD_DWORD_DISK(&buf[PAR_OFFSET + PAR_START_OFFSET]);//开始扇区
1837 part->sector_count = LD_DWORD_DISK(&buf[PAR_OFFSET + PAR_COUNT_OFFSET]);//扇区大小
1838 part->part_no_mbr = 1; //主分区编号
1839 part->filesystem_type = buf[PAR_OFFSET + PAR_TYPE_OFFSET]; //文件系统类型
1840
1841 free(buf);
1842 }
1843 return 0;
1844}
1845
1846static FRESULT fatfs_setlabel(los_part *part)
1847{
1848 QWORD start_sector = 0;
1849 BYTE fmt = 0;
1850 FATFS fs;
1851 FRESULT result;
1852
1853#ifdef LOSCFG_FS_FAT_VIRTUAL_PARTITION
1854 fs.vir_flag = FS_PARENT;
1855 fs.parent_fs = &fs;
1856 fs.vir_amount = DISK_ERROR;
1857 fs.vir_avail = FS_VIRDISABLE;
1858#endif
1859 if (disk_ioctl(fs.pdrv, GET_SECTOR_SIZE, &(fs.ssize)) != RES_OK) {
1860 return -EIO;
1861 }
1862 fs.win = (BYTE *)ff_memalloc(fs.ssize);
1863 if (fs.win == NULL) {
1864 return -ENOMEM;
1865 }
1866
1867 result = find_fat_partition(&fs, part, &fmt, &start_sector);
1868 if (result != FR_OK) {
1869 free(fs.win);
1870 return -fatfs_2_vfs(result);
1871 }
1872
1873 result = init_fatobj(&fs, fmt, start_sector);
1874 if (result != FR_OK) {
1875 free(fs.win);
1876 return -fatfs_2_vfs(result);
1877 }
1878
1879 result = set_volumn_label(&fs, FatLabel);
1880 free(fs.win);
1881
1882 return result;
1883}
1884
1885int fatfs_mkfs (struct Vnode *device, int sectors, int option)
1886{
1887 BYTE *work_buff = NULL;
1888 los_part *part = NULL;
1889 FRESULT result;
1890 MKFS_PARM opt = {0};
1891 int ret;
1892
1893 part = los_part_find(device);
1894 if (part == NULL || device->data == NULL) {
1895 return -ENODEV;
1896 }
1897
1898 if (sectors < 0 || sectors > FAT32_MAX_CLUSTER_SIZE || ((DWORD)sectors & ((DWORD)sectors - 1))) {
1899 return -EINVAL;
1900 }
1901
1902 if (option != FMT_FAT && option != FMT_FAT32 && option != FMT_ANY && option != FMT_ERASE) {
1903 return -EINVAL;
1904 }
1905
1906 if (part->part_name != NULL) { /* The part is mounted */
1907 return -EBUSY;
1908 }
1909 option = fatfs_erase(part, option);
1910 work_buff = (BYTE *)zalloc(FF_MAX_SS);
1911 if (work_buff == NULL) {
1912 return -ENOMEM;
1913 }
1914
1915 opt.n_sect = sectors;
1916 opt.fmt = (BYTE)option;
1917 result = _mkfs(part, &opt, work_buff, FF_MAX_SS);
1918 free(work_buff);
1919 if (result != FR_OK) {
1920 return -fatfs_2_vfs(result);
1921 }
1922
1923 result = fatfs_setlabel(part);
1924 if (result == FR_OK) {
1925#ifdef LOSCFG_FS_FAT_CACHE
1926 ret = OsSdSync(part->disk_id);
1927 if (ret != 0) {
1928 return -EIO;
1929 }
1930#endif
1931 }
1932
1933 ret = fatfs_set_part_info(part);
1934 if (ret != 0) {
1935 return -EIO;
1936 }
1937
1938 return -fatfs_2_vfs(result);
1939}
1940
1941int fatfs_mkdir(struct Vnode *parent, const char *name, mode_t mode, struct Vnode **vpp)
1942{
1943 return fatfs_create_obj(parent, name, mode, vpp, AM_DIR, NULL);
1944}
1945
1946int fatfs_rmdir(struct Vnode *parent, struct Vnode *vp, const char *name)
1947{
1948 FATFS *fs = (FATFS *)vp->originMount->data;
1949 DIR_FILE *dfp = (DIR_FILE *)vp->data;
1950 FILINFO *finfo = &(dfp->fno);
1951 DIR *dp = &(dfp->f_dir);
1952 DIR dir_sub;
1953 FRESULT result = FR_OK;
1954 int ret;
1955
1956 if (finfo->fattrib & AM_ARC) {
1957 result = FR_NO_DIR;
1958 goto ERROR_OUT;
1959 }
1960
1961 DEF_NAMBUF;
1962 INIT_NAMBUF(fs);
1963
1964 ret = lock_fs(fs);
1965 if (ret == FALSE) {
1966 result = FR_TIMEOUT;
1967 goto ERROR_OUT;
1968 }
1969 dir_sub.obj.fs = fs;
1970 dir_sub.obj.sclust = finfo->sclst;
1971 result = dir_sdi(&dir_sub, 0);
1972 if (result != FR_OK) {
1973 goto ERROR_UNLOCK;
1974 }
1975 result = dir_read(&dir_sub, 0);
1976 if (result == FR_OK) {
1977 result = FR_NO_EMPTY_DIR;
1978 goto ERROR_UNLOCK;
1979 }
1980 result = dir_remove(dp); /* remove directory entry */
1981 if (result != FR_OK) {
1982 goto ERROR_UNLOCK;
1983 }
1984 /* Directory entry contains at least one cluster */
1985 result = remove_chain(&(dp->obj), finfo->sclst, 0);
1986 if (result != FR_OK) {
1987 goto ERROR_UNLOCK;
1988 }
1989
1990 unlock_fs(fs, FR_OK);
1991 FREE_NAMBUF();
1992 return fatfs_sync(vp->originMount->mountFlags, fs);
1993
1994ERROR_UNLOCK:
1995 unlock_fs(fs, result);
1996 FREE_NAMBUF();
1997ERROR_OUT:
1998 return -fatfs_2_vfs(result);
1999}
2000///回收节点
2001int fatfs_reclaim(struct Vnode *vp)
2002{
2003 free(vp->data);
2004 vp->data = NULL;
2005 return 0;
2006}
2007
2008int fatfs_unlink(struct Vnode *parent, struct Vnode *vp, const char *name)
2009{
2010 FATFS *fs = (FATFS *)vp->originMount->data;
2011 DIR_FILE *dfp = (DIR_FILE *)vp->data;
2012 FILINFO *finfo = &(dfp->fno);
2013 DIR *dp = &(dfp->f_dir);
2014 FRESULT result = FR_OK;
2015 int ret;
2016
2017 if (finfo->fattrib & AM_DIR) {
2018 result = FR_IS_DIR;
2019 goto ERROR_OUT;
2020 }
2021 ret = lock_fs(fs);
2022 if (ret == FALSE) {
2023 result = FR_TIMEOUT;
2024 goto ERROR_OUT;
2025 }
2026 result = dir_remove(dp); /* remove directory entry */
2027 if (result != FR_OK) {
2028 goto ERROR_UNLOCK;
2029 }
2030 if (finfo->sclst != 0) { /* if cluster chain exists */
2031 result = remove_chain(&(dp->obj), finfo->sclst, 0);
2032 if (result != FR_OK) {
2033 goto ERROR_UNLOCK;
2034 }
2035 }
2036 result = sync_fs(fs);
2037 if (result != FR_OK) {
2038 goto ERROR_UNLOCK;
2039 }
2040 unlock_fs(fs, FR_OK);
2041 return fatfs_sync(vp->originMount->mountFlags, fs);
2042
2043ERROR_UNLOCK:
2044 unlock_fs(fs, result);
2045ERROR_OUT:
2046 return -fatfs_2_vfs(result);
2047}
2048
2049int fatfs_ioctl(struct file *filep, int req, unsigned long arg)
2050{
2051 return -ENOSYS;
2052}
2053
2054#define CHECK_FILE_NUM 3
2055static inline DWORD combine_time(FILINFO *finfo)
2056{
2057 return (finfo->fdate << FTIME_DATE_OFFSET) | finfo->ftime;
2058}
2059
2060static UINT get_oldest_time(DIR_FILE df[], DWORD *oldest_time, UINT len)
2061{
2062 int i;
2063 DWORD old_time = combine_time(&(df[0].fno));
2064 DWORD time;
2065 UINT index = 0;
2066 for (i = 1; i < len; i++) {
2067 time = combine_time(&(df[i].fno));
2068 if (time < old_time) {
2069 old_time = time;
2070 index = i;
2071 }
2072 }
2073 *oldest_time = old_time;
2074 return index;
2075}
2076
2077static FRESULT fscheck(DIR *dp)
2078{
2079 DIR_FILE df[CHECK_FILE_NUM] = {0};
2080 FILINFO fno;
2081 UINT index = 0;
2082 UINT count;
2083 DWORD time;
2084 DWORD old_time = -1;
2085 FRESULT result;
2086 for (count = 0; count < CHECK_FILE_NUM; count++) {
2087 if ((result = f_readdir(dp, &fno)) != FR_OK) {
2088 return result;
2089 } else {
2090 if (fno.fname[0] == 0 || fno.fname[0] == (TCHAR)0xFF) {
2091 break;
2092 }
2093 (void)memcpy_s(&df[count].f_dir, sizeof(DIR), dp, sizeof(DIR));
2094 (void)memcpy_s(&df[count].fno, sizeof(FILINFO), &fno, sizeof(FILINFO));
2095 time = combine_time(&(df[count].fno));
2096 if (time < old_time) {
2097 old_time = time;
2098 index = count;
2099 }
2100 }
2101 }
2102 while ((result = f_readdir(dp, &fno)) == FR_OK) {
2103 if (fno.fname[0] == 0 || fno.fname[0] == (TCHAR)0xFF) {
2104 break;
2105 }
2106 time = combine_time(&fno);
2107 if (time < old_time) {
2108 (void)memcpy_s(&df[index].f_dir, sizeof(DIR), dp, sizeof(DIR));
2109 (void)memcpy_s(&df[index].fno, sizeof(FILINFO), &fno, sizeof(FILINFO));
2110 index = get_oldest_time(df, &old_time, CHECK_FILE_NUM);
2111 }
2112 }
2113 index = 0;
2114 while (result == FR_OK && index < count) {
2115 result = f_fcheckfat(&df[index]);
2116 ++index;
2117 }
2118
2119 return result;
2120}
2121
2122int fatfs_fscheck(struct Vnode* vp, struct fs_dirent_s *dir)
2123{
2124 FATFS *fs = (FATFS *)vp->originMount->data;
2125 DIR *dp = NULL;
2126 FILINFO *finfo = &(((DIR_FILE *)(vp->data))->fno);
2127#ifdef LOSCFG_FS_FAT_CACHE
2128 los_part *part = NULL;
2129#endif
2130 FRESULT result;
2131 int ret;
2132
2133 if (fs->fs_type != FS_FAT32) {
2134 return -EINVAL;
2135 }
2136
2137 if ((finfo->fattrib & AM_DIR) == 0) {
2138 return -ENOTDIR;
2139 }
2140
2141 ret = fatfs_opendir(vp, dir);
2142 if (ret < 0) {
2143 return ret;
2144 }
2145
2146 ret = lock_fs(fs);
2147 if (ret == FALSE) {
2148 result = FR_TIMEOUT;
2149 goto ERROR_WITH_DIR;
2150 }
2151
2152 dp = (DIR *)dir->u.fs_dir;
2153 dp->obj.id = fs->id;
2154 result = fscheck(dp);
2155 if (result != FR_OK) {
2156 goto ERROR_UNLOCK;
2157 }
2158
2159 unlock_fs(fs, FR_OK);
2160
2161 ret = fatfs_closedir(vp, dir);
2162 if (ret < 0) {
2163 return ret;
2164 }
2165
2166#ifdef LOSCFG_FS_FAT_CACHE
2167 part = get_part((INT)fs->pdrv);
2168 if (part != NULL) {
2169 (void)OsSdSync(part->disk_id);
2170 }
2171#endif
2172
2173 return 0;
2174
2175ERROR_UNLOCK:
2176 unlock_fs(fs, result);
2177ERROR_WITH_DIR:
2178 fatfs_closedir(vp, dir);
2179 return -fatfs_2_vfs(result);
2180}
2181int fatfs_symlink(struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target)
2182{
2183 return fatfs_create_obj(parentVnode, path, 0, newVnode, AM_LNK, target);
2184}
2185
2186ssize_t fatfs_readlink(struct Vnode *vnode, char *buffer, size_t bufLen)
2187{
2188 int ret;
2189 FRESULT res = FR_OK;
2190 DWORD clust;
2191 QWORD sect;
2192 DIR_FILE *dfp = (DIR_FILE *)(vnode->data);
2193 DIR *dp = &(dfp->f_dir);
2194 FATFS *fs = dp->obj.fs;
2195 FILINFO *finfo = &(dfp->fno);
2196 size_t targetLen = finfo->fsize;
2197 size_t cnt;
2198
2199 ret = lock_fs(fs);
2200 if (ret == FALSE) {
2201 return -EBUSY;
2202 }
2203
2204 clust = finfo->sclst;
2205 sect = clst2sect(fs, clust); /* Get current sector */
2206 if (sect == 0) {
2207 res = FR_DISK_ERR;
2208 goto ERROUT;
2209 }
2210
2211 if (move_window(fs, sect) != FR_OK) {
2212 res = FR_DISK_ERR;
2213 goto ERROUT;
2214 }
2215
2216 cnt = (bufLen - 1) < targetLen ? (bufLen - 1) : targetLen;
2217 ret = LOS_CopyFromKernel(buffer, bufLen, fs->win, cnt);
2218 if (ret != EOK) {
2219 res = FR_INVALID_PARAMETER;
2220 goto ERROUT;
2221 }
2222 buffer[cnt] = '\0';
2223
2224 unlock_fs(fs, FR_OK);
2225 return cnt;
2226
2227ERROUT:
2228 unlock_fs(fs, res);
2229 return -fatfs_2_vfs(res);
2230}
2231
2232ssize_t fatfs_readpage(struct Vnode *vnode, char *buff, off_t pos)
2233{
2234 FATFS *fs = (FATFS *)(vnode->originMount->data);
2235 DIR_FILE *dfp = (DIR_FILE *)(vnode->data);
2236 FILINFO *finfo = &(dfp->fno);
2237 FAT_ENTRY *ep = &(dfp->fat_entry);
2238 DWORD clust;
2239 DWORD sclust;
2240 QWORD sect;
2241 QWORD step;
2242 QWORD n;
2243 size_t position; /* byte offset */
2244 BYTE *buf = (BYTE *)buff;
2245 size_t buflen = PAGE_SIZE;
2246 FRESULT result;
2247 int ret;
2248
2249 ret = lock_fs(fs);
2250 if (ret == FALSE) {
2251 result = FR_TIMEOUT;
2252 goto ERROR_OUT;
2253 }
2254
2255 if (finfo->fsize <= pos) {
2256 result = FR_OK;
2257 goto ERROR_UNLOCK;
2258 }
2259
2260 if (ep->clst == 0) {
2261 ep->clst = finfo->sclst;
2262 }
2263
2264 if (pos >= ep->pos) {
2265 clust = ep->clst;
2266 position = ep->pos;
2267 } else {
2268 clust = finfo->sclst;
2269 position = 0;
2270 }
2271
2272 /* Get to the current cluster */
2273 n = pos / SS(fs) / fs->csize - position / SS(fs) / fs->csize;
2274 while (n--) {
2275 clust = get_fat(&(dfp->f_dir.obj), clust);
2276 if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
2277 result = FR_DISK_ERR;
2278 goto ERROR_UNLOCK;
2279 }
2280 }
2281
2282 /* Get to the currnet sector */
2283 sect = clst2sect(fs, clust);
2284 sect += (pos / SS(fs)) & (fs->csize - 1);
2285
2286 /* How many sectors do we need to read once */
2287 if (fs->csize < buflen / SS(fs)) {
2288 step = fs->csize;
2289 } else {
2290 step = buflen / SS(fs);
2291 }
2292
2293 n = 0;
2294 sclust = clust;
2295 while (n < buflen / SS(fs)) {
2296 if (disk_read(fs->pdrv, buf, sect, step) != RES_OK) {
2297 result = FR_DISK_ERR;
2298 goto ERROR_UNLOCK;
2299 }
2300 n += step;
2301 if (n >= buflen / SS(fs)) {
2302 break;
2303 }
2304
2305 /* As cluster size is aligned, it must jump to next cluster when cluster size is less than pagesize */
2306 clust = get_fat(&(dfp->f_dir.obj), clust);
2307 if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
2308 result = FR_DISK_ERR;
2309 goto ERROR_UNLOCK;
2310 } else if (fatfs_is_last_cluster(fs, clust)) {
2311 break; /* read end */
2312 }
2313 sect = clst2sect(fs, clust);
2314 buf += step * SS(fs);
2315 }
2316
2317 ep->clst = sclust;
2318 ep->pos = pos;
2319
2320 unlock_fs(fs, FR_OK);
2321
2322 return (ssize_t)min(finfo->fsize - pos, n * SS(fs));
2323
2324ERROR_UNLOCK:
2325 unlock_fs(fs, result);
2326ERROR_OUT:
2327 return -fatfs_2_vfs(result);
2328}
2329
2330ssize_t fatfs_writepage(struct Vnode *vnode, char *buff, off_t pos, size_t buflen)
2331{
2332 FATFS *fs = (FATFS *)(vnode->originMount->data);
2333 DIR_FILE *dfp = (DIR_FILE *)(vnode->data);
2334 FILINFO *finfo = &(dfp->fno);
2335 FAT_ENTRY *ep = &(dfp->fat_entry);
2336 DWORD clust;
2337 DWORD sclst;
2338 QWORD sect;
2339 QWORD step;
2340 QWORD n;
2341 size_t position; /* byte offset */
2342 BYTE *buf = (BYTE *)buff;
2343 FRESULT result;
2344 FIL fil;
2345 int ret;
2346
2347 ret = lock_fs(fs);
2348 if (ret == FALSE) {
2349 result = FR_TIMEOUT;
2350 goto ERROR_OUT;
2351 }
2352
2353 if (finfo->fsize <= pos) {
2354 result = FR_OK;
2355 goto ERROR_UNLOCK;
2356 }
2357
2358 if (ep->clst == 0) {
2359 ep->clst = finfo->sclst;
2360 }
2361
2362 if (pos >= ep->pos) {
2363 clust = ep->clst;
2364 position = ep->pos;
2365 } else {
2366 clust = finfo->sclst;
2367 position = 0;
2368 }
2369
2370 /* Get to the current cluster */
2371 n = pos / SS(fs) / fs->csize - position / SS(fs) / fs->csize;
2372 while (n--) {
2373 clust = get_fat(&(dfp->f_dir.obj), clust);
2374 if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
2375 result = FR_DISK_ERR;
2376 goto ERROR_UNLOCK;
2377 }
2378 }
2379
2380 /* Get to the currnet sector */
2381 sect = clst2sect(fs, clust);
2382 sect += (pos / SS(fs)) & (fs->csize - 1);
2383
2384 /* How many sectors do we need to read once */
2385 if (fs->csize < buflen / SS(fs)) {
2386 step = fs->csize;
2387 } else {
2388 step = buflen / SS(fs);
2389 }
2390
2391 n = 0;
2392 sclst = clust;
2393 while (n < buflen / SS(fs)) {
2394 if (disk_write(fs->pdrv, buf, sect, step) != RES_OK) {
2395 result = FR_DISK_ERR;
2396 goto ERROR_UNLOCK;
2397 }
2398 n += step;
2399 if (n >= buflen / SS(fs)) {
2400 break;
2401 }
2402
2403 /* As cluster size is aligned, it must jump to next cluster when cluster size is less than pagesize */
2404 clust = get_fat(&(dfp->f_dir.obj), clust);
2405 if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
2406 result = FR_DISK_ERR;
2407 goto ERROR_UNLOCK;
2408 } else if (fatfs_is_last_cluster(fs, clust)) {
2409 break; /* read end */
2410 }
2411 sect = clst2sect(fs, clust);
2412 buf += step * SS(fs);
2413 }
2414
2415 ep->clst = sclst;
2416 ep->pos = pos;
2417
2418 fil.obj.fs = fs;
2419 if (update_filbuff(finfo, &fil, NULL) < 0) {
2420 result = FR_DISK_ERR;
2421 goto ERROR_UNLOCK;
2422 }
2423
2424 unlock_fs(fs, FR_OK);
2425
2426 return (ssize_t)min(finfo->fsize - pos, n * SS(fs));
2427ERROR_UNLOCK:
2428 unlock_fs(fs, result);
2429ERROR_OUT:
2430 return -fatfs_2_vfs(result);
2431}
2432///fat 文件系统 vnode实现
2433struct VnodeOps fatfs_vops = {
2434 /* file ops */
2436 .Chattr = fatfs_chattr,
2437 .Lookup = fatfs_lookup,
2438 .Rename = fatfs_rename,
2439 .Create = fatfs_create,
2440 .ReadPage = fatfs_readpage,
2441 .WritePage = fatfs_writepage,
2442 .Unlink = fatfs_unlink,
2443 .Reclaim = fatfs_reclaim,
2444 .Truncate = fatfs_truncate,
2445 .Truncate64 = fatfs_truncate64,
2446 /* dir ops */
2447 .Opendir = fatfs_opendir,
2448 .Readdir = fatfs_readdir,
2449 .Rewinddir = fatfs_rewinddir,
2450 .Closedir = fatfs_closedir,
2451 .Mkdir = fatfs_mkdir,
2452 .Rmdir = fatfs_rmdir,
2453 .Fscheck = fatfs_fscheck,
2454 .Symlink = fatfs_symlink,
2455 .Readlink = fatfs_readlink,
2456};
2457//fat 文件系统 挂载实现
2459 .Mount = fatfs_mount,
2460 .Unmount = fatfs_umount,
2461 .Statfs = fatfs_statfs,
2462 .Sync = fatfs_sync_adapt,
2463};
2464//fat 文件系统 文件操作实现
2465struct file_operations_vfs fatfs_fops = {
2466 .open = fatfs_open,
2467 .read = fatfs_read,
2468 .write = fatfs_write,
2469 .seek = fatfs_lseek,
2470 .close = fatfs_close,
2471 .mmap = OsVfsFileMmap,
2472 .fallocate = fatfs_fallocate,
2473 .fallocate64 = fatfs_fallocate64,
2474 .fsync = fatfs_fsync,
2475 .ioctl = fatfs_ioctl,
2476};
2477
2478FSMAP_ENTRY(fat_fsmap, "vfat", fatfs_mops, FALSE, TRUE);//注册文件映射
2479
2480#endif /* LOSCFG_FS_FAT */
macro EXC_SP_SET reg1 mrc 获取CPU信息 and mov mul reg0 计算当前CPU栈的偏移位置 ldr reg1 相减得到栈顶 mov sp
Definition: asm.h:57
INT32 OsSdSync(INT32 id)
Definition: bcache.c:956
INT32 EraseDiskByID(UINT32 diskID, size_t startSector, UINT32 sectors)
Definition: disk.c:1831
INT32 SetDiskPartName(los_part *part, const CHAR *src)
设置分区名称
Definition: disk.c:1726
static int fatfs_create_obj(struct Vnode *parent, const char *name, int mode, struct Vnode **vpp, BYTE type, const char *target)
Definition: fatfs.c:366
off_t fatfs_lseek(struct file *filep, off_t offset, int whence)
Definition: fatfs.c:832
struct MountOps fatfs_mops
Definition: fatfs.c:2458
off64_t fatfs_lseek64(struct file *filep, off64_t offset, int whence)
Definition: fatfs.c:753
static int GET_MINUTES(WORD ftime)
Definition: fatfs.c:1386
static UINT get_oldest_time(DIR_FILE df[], DWORD *oldest_time, UINT len)
Definition: fatfs.c:2060
static int GET_DAY(WORD fdate)
Definition: fatfs.c:1394
ssize_t fatfs_readlink(struct Vnode *vnode, char *buffer, size_t bufLen)
Definition: fatfs.c:2186
struct VnodeOps fatfs_vops
fat 文件系统 vnode实现
Definition: fatfs.c:81
FSMAP_ENTRY(fat_fsmap, "vfat", fatfs_mops, FALSE, TRUE)
static DWORD combine_time(FILINFO *finfo)
Definition: fatfs.c:2055
static int GET_YEAR(WORD fdate)
Definition: fatfs.c:1402
void fatfs_chtime(DIR *dp, struct IATTR *attr)
Definition: fatfs.c:1474
int fatfs_hash_cmp(struct Vnode *vp, void *arg)
哈希值比较函数,返回int
Definition: fatfs.c:228
int fatfs_fscheck(struct Vnode *vp, struct fs_dirent_s *dir)
Definition: fatfs.c:2122
static int GET_MONTH(WORD fdate)
Definition: fatfs.c:1398
int fatfs_mkdir(struct Vnode *parent, const char *name, mode_t mode, struct Vnode **vpp)
Definition: fatfs.c:1941
int fatfs_chattr(struct Vnode *vp, struct IATTR *attr)
Definition: fatfs.c:1494
static FRESULT update_dir(DIR *dp, FILINFO *finfo)
Definition: fatfs.c:723
int fatfs_fsync(struct file *filep)
Definition: fatfs.c:896
static FRESULT fatfs_setlabel(los_part *part)
Definition: fatfs.c:1846
static FRESULT fscheck(DIR *dp)
Definition: fatfs.c:2077
static int fat_bind_check(struct Vnode *blk_driver, los_part **partition)
Definition: fatfs.c:1063
int fatfs_2_vfs(int result)
Definition: fatfs.c:96
int fatfs_open(struct file *filep)
Definition: fatfs.c:620
static FRESULT rename_check(DIR *dp_new, FILINFO *finfo_new, DIR *dp_old, FILINFO *finfo_old)
Definition: fatfs.c:1670
int fatfs_symlink(struct Vnode *parentVnode, struct Vnode **newVnode, const char *path, const char *target)
Definition: fatfs.c:2181
static FRESULT init_cluster(DIR_FILE *pdfp, DIR *dp_new, FATFS *fs, int type, const char *target, DWORD *clust)
Definition: fatfs.c:280
static bool fatfs_is_last_cluster(FATFS *fs, DWORD cclust)
Definition: fatfs.c:198
int fatfs_ioctl(struct file *filep, int req, unsigned long arg)
Definition: fatfs.c:2049
struct file_operations_vfs fatfs_fops
Definition: fatfs.c:82
int fatfs_truncate(struct Vnode *vp, off_t len)
Definition: fatfs.c:1058
int fatfs_sync_adapt(struct Mount *mnt)
Definition: fatfs.c:1316
static FRESULT realloc_cluster(FILINFO *finfo, FFOBJID *obj, FSIZE_t size)
Definition: fatfs.c:951
static int fatfs_set_part_info(los_part *part)
设置FAT分区信息
Definition: fatfs.c:1814
int fatfs_umount(struct Mount *mnt, struct Vnode **blkdriver)
Definition: fatfs.c:1254
int fatfs_create(struct Vnode *parent, const char *name, int mode, struct Vnode **vpp)
创建 fat vnode 节点
Definition: fatfs.c:614
int fatfs_reclaim(struct Vnode *vp)
回收节点
Definition: fatfs.c:2001
int fatfs_fallocate64(struct file *filep, int mode, off64_t offset, off64_t len)
Definition: fatfs.c:913
int fatfs_fallocate(struct file *filep, int mode, off_t offset, off_t len)
Definition: fatfs.c:1010
int fatfs_rename(struct Vnode *old_vnode, struct Vnode *new_parent, const char *oldname, const char *newname)
Definition: fatfs.c:1698
int fatfs_readdir(struct Vnode *vp, struct fs_dirent_s *idir)
Definition: fatfs.c:1589
int fatfs_opendir(struct Vnode *vp, struct fs_dirent_s *idir)
Definition: fatfs.c:1554
static int fatfs_erase(los_part *part, int option)
Definition: fatfs.c:1796
int fatfs_stat(struct Vnode *vp, struct stat *sp)
Definition: fatfs.c:1439
static int GET_HOURS(WORD ftime)
Definition: fatfs.c:1390
int fatfs_read(struct file *filep, char *buff, size_t count)
Definition: fatfs.c:697
int fatfs_truncate64(struct Vnode *vp, off64_t len)
Definition: fatfs.c:1015
int fatfs_closedir(struct Vnode *vp, struct fs_dirent_s *dir)
Definition: fatfs.c:1662
int fatfs_rmdir(struct Vnode *parent, struct Vnode *vp, const char *name)
Definition: fatfs.c:1946
ssize_t fatfs_writepage(struct Vnode *vnode, char *buff, off_t pos, size_t buflen)
Definition: fatfs.c:2330
static enum VnodeType fatfstype_2_vnodetype(BYTE type)
类型转换
Definition: fatfs.c:265
int fatfs_mkfs(struct Vnode *device, int sectors, int option)
Definition: fatfs.c:1885
static int fatfs_sync(unsigned long mountflags, FATFS *fs)
Definition: fatfs.c:211
static mode_t fatfs_get_mode(BYTE attribute, mode_t fs_mode)
Definition: fatfs.c:248
int fatfs_write(struct file *filep, const char *buff, size_t count)
Definition: fatfs.c:858
int fatfs_lookup(struct Vnode *parent, const char *path, int len, struct Vnode **vpp)
fat文件系统对 Lookup 接口的实现
Definition: fatfs.c:516
DWORD fattime_format(time_t time)
Definition: fatfs.c:1420
static int update_filbuff(FILINFO *finfo, FIL *wfp, const char *data)
Definition: fatfs.c:837
int fatfs_statfs(struct Mount *mnt, struct statfs *info)
Definition: fatfs.c:1339
int fatfs_close(struct file *filep)
Definition: fatfs.c:667
ssize_t fatfs_readpage(struct Vnode *vnode, char *buff, off_t pos)
Definition: fatfs.c:2232
int fatfs_mount(struct Mount *mnt, struct Vnode *blk_device, const void *data)
fat将分区文件系统挂载 举例: mount /dev/mmcblk0p0 /bin1/vs/sd vfat
Definition: fatfs.c:1103
static int GET_SECONDS(WORD ftime)
Definition: fatfs.c:1382
int fatfs_rewinddir(struct Vnode *vp, struct fs_dirent_s *dir)
Definition: fatfs.c:1645
static DWORD fatfs_hash(QWORD sect, DWORD dptr, DWORD sclst)
生成hash值的过程
Definition: fatfs.c:238
static time_t fattime_transfer(WORD fdate, WORD ftime)
Definition: fatfs.c:1407
int fatfs_unlink(struct Vnode *parent, struct Vnode *vp, const char *name)
Definition: fatfs.c:2008
FRESULT find_fat_partition(FATFS *fs, los_part *part, BYTE *format, QWORD *start_sector)
char FatLabel[LABEL_LEN]
Definition: format.c:41
FRESULT _mkfs(los_part *partition, const MKFS_PARM *opt, BYTE *work, UINT len)
FRESULT init_fatobj(FATFS *fs, BYTE fmt, QWORD start_sector)
INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count, BOOL useRead)
Read data from disk driver.
Definition: disk.c:911
los_disk * get_disk(INT32 id)
Find disk driver.
Definition: disk.c:263
los_part * get_part(INT32 id)
Find disk partition.
Definition: disk.c:272
los_part * los_part_find(struct Vnode *blkDriver)
Find disk partition.
Definition: disk.c:1682
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a new node to a doubly linked list.
Definition: los_list.h:217
LITE_OS_SEC_ALW_INLINE STATIC INLINE UINT32 LOS_HashFNV32aBuf(const VOID *buf, size_t len, UINT32 hval)
Definition: los_hash.h:79
INT64 ssize_t
Definition: los_typedef.h:79
INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
void * zalloc(size_t size)
Definition: malloc.c:91
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
UINT32 sector_size
Definition: disk.h:185
UINT32 part_id
Definition: disk.h:199
UINT32 disk_id
Definition: disk.h:198
UINT64 sector_count
Definition: disk.h:211
CHAR * part_name
Definition: disk.h:206
UINT8 filesystem_type
Definition: disk.h:203
UINT32 part_no_mbr
Definition: disk.h:201
UINT64 sector_start
Definition: disk.h:207
UINT8 type
Definition: disk.h:204
此结构用于记录 vnode 的属性
Definition: vnode.h:81
unsigned attr_chg_ctime
节点自身被修改时间
Definition: vnode.h:91
unsigned attr_chg_atime
节点最近访问时间
Definition: vnode.h:89
unsigned attr_chg_mode
确定了文件的类型,以及它的所有者、它的group、其它用户访问此文件的权限 (S_IWUSR | ...)
Definition: vnode.h:85
unsigned attr_chg_mtime
节点对应的文件内容被修改时间
Definition: vnode.h:90
unsigned int attr_chg_valid
节点改变有效性 (CHG_MODE | CHG_UID | ... )
Definition: vnode.h:83
举例: mount /dev/mmcblk0p0 /bin1/vs/sd vfat 将/dev/mmcblk0p0 挂载到/bin1/vs/sd目录
Definition: mount.h:68
void * data
Definition: mount.h:78
struct Vnode * vnodeCovered
Definition: mount.h:72
struct Vnode * vnodeDev
Definition: mount.h:73
struct Vnode * vnodeBeCovered
Definition: mount.h:71
unsigned long mountFlags
Definition: mount.h:80
挂载操作
Definition: mount.h:89
int(* Mount)(struct Mount *mount, struct Vnode *vnode, const void *data)
挂载分区
Definition: mount.h:90
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
uint32_t hash
Definition: vnode.h:167
uint gid
Definition: vnode.h:169
enum VnodeType type
Definition: vnode.h:165
mode_t mode
Definition: vnode.h:170
void * data
Definition: vnode.h:176
struct file_operations_vfs * fop
Definition: vnode.h:175
struct Mount * originMount
Definition: vnode.h:180
uint uid
Definition: vnode.h:168
struct Vnode * parent
Definition: vnode.h:173
int(* Getattr)(struct Vnode *vnode, struct stat *st)
获取节点属性
Definition: vnode.h:212
loff_t f_pos
void * f_priv
int f_oflags
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 ARG_NUM_0 ARG_NUM_2 ARG_NUM_1 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_4 ARG_NUM_5 ARG_NUM_6 ARG_NUM_3 ARG_NUM_5 ARG_NUM_7 ARG_NUM_1 ARG_NUM_4 ARG_NUM_5 ARG_NUM_4 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_7 ARG_NUM_3 ARG_NUM_3 ARG_NUM_3 ARG_NUM_7 ARG_NUM_3 ARG_NUM_2 char ARG_NUM_2 ARG_NUM_1 ARG_NUM_0 ARG_NUM_0 ARG_NUM_3 void ARG_NUM_1 ARG_NUM_0 unsigned ARG_NUM_0 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_5 ARG_NUM_3 ARG_NUM_3 ARG_NUM_4 ARG_NUM_1 ARG_NUM_1 ARG_NUM_3 ARG_NUM_2 ARG_NUM_1 ARG_NUM_4 ARG_NUM_4 ARG_NUM_5 ARG_NUM_3 ARG_NUM_2 void ARG_NUM_6 unsigned ARG_NUM_0 unsigned ARG_NUM_0 ARG_NUM_3 ARG_NUM_3 ARG_NUM_2 ARG_NUM_2 ARG_NUM_1 ARG_NUM_2 ARG_NUM_1 char ARG_NUM_0 ARG_NUM_4 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_4 ARG_NUM_5 ARG_NUM_2 ARG_NUM_3 ARG_NUM_3 ARG_NUM_3 ARG_NUM_3 ARG_NUM_6 ARG_NUM_6 ARG_NUM_5 ARG_NUM_3 void ARG_NUM_3 ARG_NUM_3 ARG_NUM_5 ARG_NUM_1 unsigned ARG_NUM_3 long
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 ARG_NUM_0 ARG_NUM_2 ARG_NUM_1 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_4 off64_t
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 ARG_NUM_0 ARG_NUM_2 ARG_NUM_1 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_4 ARG_NUM_5 ARG_NUM_6 ARG_NUM_3 ARG_NUM_5 ARG_NUM_7 ARG_NUM_1 ARG_NUM_4 ARG_NUM_5 ARG_NUM_4 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_7 ARG_NUM_3 ARG_NUM_3 ARG_NUM_3 ARG_NUM_7 ARG_NUM_3 ARG_NUM_2 char ARG_NUM_2 ARG_NUM_1 ARG_NUM_0 ARG_NUM_0 ARG_NUM_3 void ARG_NUM_1 ARG_NUM_0 unsigned ARG_NUM_0 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_5 ARG_NUM_3 ARG_NUM_3 ARG_NUM_4 ARG_NUM_1 ARG_NUM_1 ARG_NUM_3 ARG_NUM_2 mode_t
time_t time(time_t *t)
Definition: time.c:1224
INT32 LOS_CopyFromKernel(VOID *dest, UINT32 max, const VOID *src, UINT32 count)
将内核数据拷贝到用户空间
Definition: user_copy.c:88
VnodeType
Definition: vnode.h:134
@ VNODE_TYPE_LNK
Definition: vnode.h:142
@ VNODE_TYPE_DIR
Definition: vnode.h:137
@ VNODE_TYPE_UNKNOWN
Definition: vnode.h:135
@ VNODE_TYPE_REG
Definition: vnode.h:136
int VfsHashGet(const struct Mount *mount, uint32_t hash, struct Vnode **vnode, VfsHashCmp *fun, void *arg)
通过哈希值获取节点信息
Definition: vnode_hash.c:89
int VfsHashInsert(struct Vnode *vnode, uint32_t hash)
插入哈希表
Definition: vnode_hash.c:128
mode_t GetUmask(void)
获取用户创建文件掩码
Definition: vfs_other.c:715
int VnodeAlloc(struct VnodeOps *vop, struct Vnode **vnode)
申请分配一个 vnode 节点,vop为操作节点的驱动程序
Definition: vnode.c:166