首页 > 代码库 > FATFS 初学之 f_lseek
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 #endif104 fp->clust = clst;105 }106 if (clst != 0) {107 while (ofs > bcs) { /* Cluster following loop */108 #if !_FS_READONLY109 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 } else115 #endif116 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_TINY133 #if !_FS_READONLY134 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 #endif140 if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */141 ABORT(fp->fs, FR_DISK_ERR);142 #endif143 fp->dsect = nsect;144 }145 #if !_FS_READONLY146 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 #endif151 }152 153 LEAVE_FF(fp->fs, res);154 }
函数功能:移动一个打开的文件对象的文件读/写指针。也可以被用来扩展文件大小(簇预分配)。
描述:
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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。