zoukankan      html  css  js  c++  java
  • FATFS 初学之 f_lseek

      1 /*-----------------------------------------------------------------------*/
      2 /* Seek File R/W Pointer                                                 */
      3 /*-----------------------------------------------------------------------*/
      4 
      5 FRESULT f_lseek (
      6     FIL *fp,        /* Pointer to the file object */
      7     DWORD ofs        /* File pointer from top of file */
      8 )
      9 {
     10     FRESULT res;
     11 
     12 
     13     res = validate(fp->fs, fp->id);        /* Check validity of the object */
     14     if (res != FR_OK) LEAVE_FF(fp->fs, res);
     15     if (fp->flag & FA__ERROR)            /* Check abort flag */
     16         LEAVE_FF(fp->fs, FR_INT_ERR);
     17 
     18 #if _USE_FASTSEEK
     19     if (fp->cltbl) {    /* Fast seek */
     20         DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
     21 
     22         if (ofs == CREATE_LINKMAP) {    /* Create CLMT */
     23             tbl = fp->cltbl;
     24             tlen = *tbl++; ulen = 2;    /* Given table size and required table size */
     25             cl = fp->sclust;            /* Top of the chain */
     26             if (cl) {
     27                 do {
     28                     /* Get a fragment */
     29                     tcl = cl; ncl = 0; ulen += 2;    /* Top, length and used items */
     30                     do {
     31                         pcl = cl; ncl++;
     32                         cl = get_fat(fp->fs, cl);
     33                         if (cl <= 1) ABORT(fp->fs, FR_INT_ERR);
     34                         if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
     35                     } while (cl == pcl + 1);
     36                     if (ulen <= tlen) {        /* Store the length and top of the fragment */
     37                         *tbl++ = ncl; *tbl++ = tcl;
     38                     }
     39                 } while (cl < fp->fs->n_fatent);    /* Repeat until end of chain */
     40             }
     41             *fp->cltbl = ulen;    /* Number of items used */
     42             if (ulen <= tlen)
     43                 *tbl = 0;        /* Terminate table */
     44             else
     45                 res = FR_NOT_ENOUGH_CORE;    /* Given table size is smaller than required */
     46 
     47         } else {                        /* Fast seek */
     48             if (ofs > fp->fsize)        /* Clip offset at the file size */
     49                 ofs = fp->fsize;
     50             fp->fptr = ofs;                /* Set file pointer */
     51             if (ofs) {
     52                 fp->clust = clmt_clust(fp, ofs - 1);
     53                 dsc = clust2sect(fp->fs, fp->clust);
     54                 if (!dsc) ABORT(fp->fs, FR_INT_ERR);
     55                 dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1);
     56                 if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) {    /* Refill sector cache if needed */
     57 #if !_FS_TINY
     58 #if !_FS_READONLY
     59                     if (fp->flag & FA__DIRTY) {        /* Write-back dirty sector cache */
     60                         if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
     61                             ABORT(fp->fs, FR_DISK_ERR);
     62                         fp->flag &= ~FA__DIRTY;
     63                     }
     64 #endif
     65                     if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK)    /* Load current sector */
     66                         ABORT(fp->fs, FR_DISK_ERR);
     67 #endif
     68                     fp->dsect = dsc;
     69                 }
     70             }
     71         }
     72     } else
     73 #endif
     74 
     75     /* Normal Seek */
     76     {
     77         DWORD clst, bcs, nsect, ifptr;
     78 
     79         if (ofs > fp->fsize                    /* In read-only mode, clip offset with the file size */
     80 #if !_FS_READONLY
     81              && !(fp->flag & FA_WRITE)
     82 #endif
     83             ) ofs = fp->fsize;
     84 
     85         ifptr = fp->fptr;
     86         fp->fptr = nsect = 0;
     87         if (ofs) {
     88             bcs = (DWORD)fp->fs->csize * SS(fp->fs);    /* Cluster size (byte) */
     89             if (ifptr > 0 &&
     90                 (ofs - 1) / bcs >= (ifptr - 1) / bcs) {    /* When seek to same or following cluster, */
     91                 fp->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */
     92                 ofs -= fp->fptr;
     93                 clst = fp->clust;
     94             } else {                                    /* When seek to back cluster, */
     95                 clst = fp->sclust;                        /* start from the first cluster */
     96 #if !_FS_READONLY
     97                 if (clst == 0) {                        /* If no cluster chain, create a new chain */
     98                     clst = create_chain(fp->fs, 0);
     99                     if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
    100                     if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
    101                     fp->sclust = clst;
    102                 }
    103 #endif
    104                 fp->clust = clst;
    105             }
    106             if (clst != 0) {
    107                 while (ofs > bcs) {                        /* Cluster following loop */
    108 #if !_FS_READONLY
    109                     if (fp->flag & FA_WRITE) {            /* Check if in write mode or not */
    110                         clst = create_chain(fp->fs, clst);    /* Force stretch if in write mode */
    111                         if (clst == 0) {                /* When disk gets full, clip file size */
    112                             ofs = bcs; break;
    113                         }
    114                     } else
    115 #endif
    116                         clst = get_fat(fp->fs, clst);    /* Follow cluster chain if not in write mode */
    117                     if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
    118                     if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
    119                     fp->clust = clst;
    120                     fp->fptr += bcs;
    121                     ofs -= bcs;
    122                 }
    123                 fp->fptr += ofs;
    124                 if (ofs % SS(fp->fs)) {
    125                     nsect = clust2sect(fp->fs, clst);    /* Current sector */
    126                     if (!nsect) ABORT(fp->fs, FR_INT_ERR);
    127                     nsect += ofs / SS(fp->fs);
    128                 }
    129             }
    130         }
    131         if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) {    /* Fill sector cache if needed */
    132 #if !_FS_TINY
    133 #if !_FS_READONLY
    134             if (fp->flag & FA__DIRTY) {            /* Write-back dirty sector cache */
    135                 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
    136                     ABORT(fp->fs, FR_DISK_ERR);
    137                 fp->flag &= ~FA__DIRTY;
    138             }
    139 #endif
    140             if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK)    /* Fill sector cache */
    141                 ABORT(fp->fs, FR_DISK_ERR);
    142 #endif
    143             fp->dsect = nsect;
    144         }
    145 #if !_FS_READONLY
    146         if (fp->fptr > fp->fsize) {            /* Set file change flag if the file size is extended */
    147             fp->fsize = fp->fptr;
    148             fp->flag |= FA__WRITTEN;
    149         }
    150 #endif
    151     }
    152 
    153     LEAVE_FF(fp->fs, res);
    154 }
    View Code

    函数功能:移动一个打开的文件对象的文件读/写指针。也可以被用来扩展文件大小(簇预分配)。

    描述:

    f_lseek函数当FS_MINIMIZE <= 2时可用。
    offset只能被指定为相对于文件起始处的字节数。当在写模式下指定了一个超过文件大小的offset时,文件的大小将被扩展,并且该扩展的区域中的数据是未定义的。这适用于为快速写操作迅速地创建一个大的文件。
    f_lseek函数成功后,为了确保读/写指针已被正确地移动,必须检查文件对象中的成员fptr。如果fptr不是所期望的值,则发生了下列情况之一。
    文件结束。指定的offset被钳在文件大小,因为文件已被以只读模式打开。
    磁盘满。卷上没有足够的空闲空间去扩展文件大小。

    例:

     1     /* 移动文件读/写指针到相对于文件起始处偏移为5000字节处 */
     2     res = f_lseek(file, 5000);
     3     
     4     /* 移动文件读/写指针到文件结束处,以便添加数据 */
     5     res = f_lseek(file, file->fsize);
     6     
     7     /* 向前3000字节 */
     8     res = f_lseek(file, file->fptr + 3000);
     9     
    10     /* 向后(倒带)2000字节(注意溢出) */
    11     res = f_lseek(file, file->fptr - 2000);
    12     
    13     /* 簇预分配(为了防止在流写时缓冲区上溢 */
    14     res = f_open(file, recfile, FA_CREATE_NEW | FA_WRITE); /* 创建一个文件 */
    15     
    16     res = f_lseek(file, PRE_SIZE);         /* 预分配簇 */
    17     if (res || file->fptr != PRE_SIZE) ... /* 检查文件大小是否已被正确扩展 */
    18     
    19     res = f_lseek(file, DATA_START);       /* 没有簇分配延迟地记录数据流 */
    20     ...
    21     
    22     res = f_truncate(file);                /* 截断未使用的区域 */
    23     res = f_lseek(file, 0);                /* 移动到文件起始处 */
    24     ...
    25     
    26     res = f_close(file);
    27     
    View Code
  • 相关阅读:
    多态
    封装
    继承
    面向对象
    2.机器学习相关数学基础
    作业1 机器学习概述
    作业15 语法制导的语义翻译
    作业14 算符优先分析
    作业13 自下而上语法分析
    作业12 实验二 递归下降语法分析
  • 原文地址:https://www.cnblogs.com/Danhuise/p/3910059.html
Copyright © 2011-2022 走看看