fatfs_supp.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,180 行 · 第 1/5 页
C
2,180 行
if (TENTRY_FREE == get_tentry_type(disk, tentry)) { CYG_TRACE1(TCL, "free_cluster=%d", c); *free_cluster = c; if (opts & CO_MARK_LAST) err = mark_cluster(disk, c, TENTRY_LAST); if ((err == ENOERR) && (opts & CO_ERASE_NEW)) err = erase_cluster(disk, c); return err; } c++; } // No free clusters found CYG_TRACE0(TCL, "!!! no free clusters found"); // Return out of space return ENOSPC;}// -------------------------------------------------------------------------// find_and_append_cluster()// Finds a free cluster on disk and appends it to the given cluster. // New cluster is marked as LAST. static intfind_and_append_cluster(fatfs_disk_t *disk, cyg_uint32 cluster, cyg_uint32 *new_cluster, cluster_opts_t opts){ cyg_uint32 free_cluster; int err; CYG_TRACE1(TCL, "cluster=%d", cluster); err = find_next_free_cluster(disk, cluster, &free_cluster, opts | CO_MARK_LAST); if (err != ENOERR) return err; CYG_TRACE1(TCL, "free_cluster=%d", free_cluster); // Link clusters err = link_cluster(disk, cluster, free_cluster); if (err != ENOERR) return err; *new_cluster = free_cluster; CYG_TRACE1(TCL, "new_cluster=%d", free_cluster); return ENOERR;}// -------------------------------------------------------------------------// find_nth_cluster0()// Finds nth cluster in chain (ie nth cluster of file).// Searching from given position. static intfind_nth_cluster0(fatfs_disk_t *disk, fatfs_data_pos_t *dpos, cyg_uint32 n, fatfs_tcache_t *tcache){ cyg_uint32 cluster, cluster_snum; int err = ENOERR; // Trivial case check if (dpos->cluster_snum == n) return ENOERR; // First look in cache if (NULL != tcache) { cyg_uint32 c, ln; if (fatfs_tcache_get(disk, tcache, n, &c)) { // Cluster in cache dpos->cluster = c; dpos->cluster_snum = n; CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d in cache", c, n); return ENOERR; } else if (fatfs_tcache_get_last(disk, tcache, &ln, &c)) { // Cluster not in cache - get last // in cache and search from there dpos->cluster = c; dpos->cluster_snum = ln; CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d last in cache", c, ln); } else { // Empty cache - put first cluster in fatfs_tcache_set(disk, tcache, dpos->cluster_snum, dpos->cluster); } } cluster = dpos->cluster; cluster_snum = dpos->cluster_snum; CYG_TRACE4(TCL, "cluster=%d cluster_snum=%d n=%d n_to_search=%d", cluster, cluster_snum, n, n-cluster_snum); // Adjust the number of clusters that should be // walked according to the given position n -= cluster_snum; // Walk the cluster chain for n clusters or // until last cluster while (n > 0) { cyg_uint32 tentry; err = read_tentry(disk, cluster, &tentry); if (err != ENOERR) return err; switch (get_tentry_type(disk, tentry)) { case TENTRY_REGULAR: break; case TENTRY_LAST: // Oops early last cluster CYG_TRACE1(TCL, "chain end n=%d", n); err = EEOF; // File has less clusters than given n // this err should be caught by the // calling function goto out; default: // Inconsistant FAT table state !!! CYG_TRACE2(TCL, "!!! inconsistant FAT tentry=%x n=%d", tentry, n); err = EIO; goto out; } cluster = get_tentry_next_cluster(disk, tentry); cluster_snum++; if (NULL != tcache) fatfs_tcache_set(disk, tcache, cluster_snum, cluster); n--; } out: dpos->cluster = cluster; dpos->cluster_snum = cluster_snum; CYG_TRACE2(TCL, "nth cluster=%d cluster_snum=%d", cluster, cluster_snum); return err;}// -------------------------------------------------------------------------// find_nth_cluster()// Finds nth cluster in chain (ie nth cluster of file) searching // from given position. If the chain ends one cluster before the // given nth cluster and the CO_EXTEND is specifide, than the // chain is extended by one cluster. static intfind_nth_cluster(fatfs_disk_t *disk, fatfs_data_pos_t *dpos, cyg_uint32 n, fatfs_tcache_t *tcache, cluster_opts_t opts){ int err; // Find nth cluster err = find_nth_cluster0(disk, dpos, n, tcache); // EEOF meens that the cluster chain ended early if ((err != EEOF) || !(opts & CO_EXTEND)) return err; CYG_TRACE2(TCL, "cluster_snum=%d n=%d", dpos->cluster_snum, n); // Check if one cluster short if (dpos->cluster_snum == (n - 1)) { // Extend the chain for one cluster cyg_uint32 new_cluster; // Append new cluster to the end of chain err = find_and_append_cluster(disk, dpos->cluster, &new_cluster, opts); if (err != ENOERR) return err; // Update position dpos->cluster = new_cluster; dpos->cluster_snum++; dpos->cluster_pos = 0; CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d", dpos->cluster, dpos->cluster_snum); // Update cache if (NULL != tcache) fatfs_tcache_set(disk, tcache, dpos->cluster_snum, dpos->cluster); } return err;}// -------------------------------------------------------------------------// get_next_cluster()// Gets next cluster in chain (ie next cluster of file).// If CO_EXTEND is specified and the current cluster is last in // chain then the chain is extended by one cluster.static intget_next_cluster(fatfs_disk_t *disk, fatfs_data_pos_t *dpos, fatfs_tcache_t *tcache, cluster_opts_t opts){ int err; CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d", dpos->cluster, dpos->cluster_snum); err = find_nth_cluster(disk, dpos, dpos->cluster_snum + 1, tcache, opts); if (err != ENOERR) return err; // Update position dpos->cluster_pos = 0; CYG_TRACE2(TCL, "cluster=%d cluster_snum=%d", dpos->cluster, dpos->cluster_snum); return ENOERR;}// -------------------------------------------------------------------------// get_data_position_from_off()// Gets data position from given file offset.// If CO_EXTEND is specified the file is extended if // one cluster too short. static int get_data_position_from_off(fatfs_disk_t *disk, cyg_uint32 first_cluster, cyg_uint32 offset, fatfs_data_pos_t *dpos, fatfs_tcache_t *tcache, cluster_opts_t opts){ cyg_uint32 n; int err; // Position inside the cluster dpos->cluster_pos = offset & (disk->cluster_size - 1); // Cluster seq number to be searched for n = offset >> disk->cluster_size_log2; // Start searching from first cluster dpos->cluster = first_cluster; dpos->cluster_snum = 0; CYG_TRACE4(TCL, "off=%d first_cluster=%d cluster_pos=%d n=%d\n", offset, first_cluster, dpos->cluster_pos, n); err = find_nth_cluster(disk, dpos, n, tcache, opts); // Err could be EEOF wich means that the given // offset if out of given file (cluster chain) return err;}// -------------------------------------------------------------------------// free_cluster_chain()// Marks all clusters FREE from given cluster to the last cluster in chain.static intfree_cluster_chain(fatfs_disk_t *disk, cyg_uint32 start_cluster){ cyg_uint32 c, next_c, tentry; bool last; int err; CYG_TRACE1(TCL, "start_cluster=%d", start_cluster); c = next_c = start_cluster; last = false; while (!last) { err = read_tentry(disk, c, &tentry); if (err != ENOERR) return err; switch (get_tentry_type(disk, tentry)) { case TENTRY_LAST: // Last cluster in chain last = true; break; case TENTRY_REGULAR: // Get next cluster in chain next_c = get_tentry_next_cluster(disk, tentry); break; default: CYG_TRACE2(TCL, "!!! inconsistant FAT tentry=%x c=%d", tentry, c); return EIO; } // Set the current tentry to FREE set_tentry_type(disk, &tentry, TENTRY_FREE); err = write_tentry(disk, c, &tentry); if (err != ENOERR) return err; // Next cluster in chain c = next_c; } CYG_TRACE1(TCL, "last_cluster=%d", c); return ENOERR;}//==========================================================================// FAT dir entry functions // -------------------------------------------------------------------------// print_dentry()// Prints FAT directory entry. #if TDEstatic voidprint_dentry(fat_dir_entry_t* fde){ if (DENTRY_IS_DELETED(fde)) diag_printf("FAT: FDE name: '?%.7s'\n", &fde->name[1]); else diag_printf("FAT: FDE name: '%.8s'\n", fde->name); diag_printf("FAT: FDE ext: '%.3s'\n", fde->ext); diag_printf("FAT: FDE attr: %c%c%c%c%c%c\n", (DENTRY_IS_RDONLY(fde) ? 'R' : '-'), (DENTRY_IS_HIDDEN(fde) ? 'H' : '-'), (DENTRY_IS_SYSTEM(fde) ? 'S' : '-'), (DENTRY_IS_VOLUME(fde) ? 'V' : '-'), (DENTRY_IS_DIR(fde) ? 'D' : '-'), (DENTRY_IS_ARCHIVE(fde) ? 'A' : '-')); diag_printf("FAT: FDE crt time: %u\n", fde->crt_time); diag_printf("FAT: FDE crt date: %u\n", fde->crt_date); diag_printf("FAT: FDE acc date: %u\n", fde->acc_date); diag_printf("FAT: FDE wrt time: %u\n", fde->wrt_time); diag_printf("FAT: FDE wrt date: %u\n", fde->wrt_date); diag_printf("FAT: FDE cluster: %u\n", fde->cluster); diag_printf("FAT: FDE size: %u\n", fde->size);}#endif // TDE// -------------------------------------------------------------------------// read_dentry()// Reads dir entry from disk. // If cluster is 0 reads from root dir. static intread_dentry(fatfs_disk_t *disk, fatfs_data_pos_t *dpos, fat_dir_entry_t *fde){ unsigned char data[DENTRY_SIZE]; cyg_uint32 apos; int len, err; // Check if we are reading the root directory if (0 == dpos->cluster) apos = disk->fat_root_dir_pos + dpos->cluster_pos; else apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos); CYG_TRACE3(TDE, "cluster=%d pos=%d apos=%d", dpos->cluster, dpos->cluster_pos, apos); len = DENTRY_SIZE; err = cyg_blib_read(&disk->blib, (void*)data, &len, 0, apos); if (err != ENOERR) return err; GET_BYTES(data, fde->name, 8, 0x00); GET_BYTES(data, fde->ext, 3, 0x08); GET_BYTE(data, fde->attr, 0x0B); GET_BYTE(data, fde->nt_reserved, 0x0C); GET_BYTE(data, fde->crt_sec_100, 0x0D); GET_WORD(data, fde->crt_time, 0x0E); GET_WORD(data, fde->crt_date, 0x10); GET_WORD(data, fde->acc_date, 0x12); GET_WORD(data, fde->cluster_HI, 0x14); GET_WORD(data, fde->wrt_time, 0x16); GET_WORD(data, fde->wrt_date, 0x18); GET_WORD(data, fde->cluster, 0x1A); GET_DWORD(data, fde->size, 0x1C); // Zero terminate strings fde->name[8] = '\0'; fde->ext[3] = '\0'; // Store position fde->pos = *dpos; #if TDE print_dentry(fde);#endif return ENOERR;}// -------------------------------------------------------------------------// write_dentry()// Writes dir entry to disk. // If cluster is 0 writes to root dir. static intwrite_dentry(fatfs_disk_t *disk, fatfs_data_pos_t *dpos, fat_dir_entry_t *fde){ unsigned char data[DENTRY_SIZE]; cyg_uint32 apos; int len, err; // Check if we are writting to the root directory if (0 == dpos->cluster) apos = disk->fat_root_dir_pos + dpos->cluster_pos; else apos = get_data_disk_apos(disk, dpos->cluster, dpos->cluster_pos);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?