📄 fatfs_supp.c
字号:
*len -= size; printf( "total len=%d", *len); return err;}//==========================================================================// Misc functions // -------------------------------------------------------------------------// init_node()// Initializes file attributes of a new node. static voidinit_node_fattr(fatfs_node_t *node, const char *name, int namelen, mode_t mode, cyg_uint32 parent_cluster, fatfs_data_pos_t *dentry_pos){ if (namelen == 0) namelen = 12; strncpy(node->filename, name, namelen); node->filename[namelen] = '\0'; node->mode = mode; node->ctime = node->atime = node->mtime = timeGetTime(); node->priv_data = 0; node->size = 0; node->cluster = 0; node->parent_cluster = parent_cluster; node->dentry_pos = *dentry_pos;}// -------------------------------------------------------------------------// is_node_root_node()// Check if the given node is the root dir node static boolis_node_root_node(fatfs_node_t *node){ return (node->filename[0] == '\0' && node->cluster == 0);}//==========================================================================//==========================================================================// Exported functions // -------------------------------------------------------------------------// fatfs_get_disk_info()// Gets disk info. intfatfs_get_disk_info(fatfs_disk_t *disk){ int err; cyg_uint32 sec_num, root_dir_sec_num; cyg_uint32 data_sec_num, data_clu_num; fat_boot_record_t boot_rec; CYG_CHECK_DATA_PTRC(disk); err = read_boot_record(disk, &boot_rec); if (err != ENOERR) return err; // Check some known boot record values if (0x29 != boot_rec.ext_sig || 0x55 != boot_rec.exe_marker[0] || 0xAA != boot_rec.exe_marker[1]) return EINVAL; // Determine number of sectors if (boot_rec.sec_num_32 != 0) sec_num = boot_rec.sec_num_32; else sec_num = boot_rec.sec_num; // Number of sectors used by root directory root_dir_sec_num = ((boot_rec.max_root_dents * DENTRY_SIZE) + (boot_rec.bytes_per_sec - 1)) / boot_rec.bytes_per_sec; // Number of data sectors data_sec_num = sec_num - (boot_rec.res_sec_num + (boot_rec.fat_tbls_num * boot_rec.sec_per_fat) + root_dir_sec_num); // Number of data clusters data_clu_num = data_sec_num / boot_rec.sec_per_clust; // Determine the type of FAT based on number of data clusters if (data_clu_num < 4085) disk->fat_type = FATFS_FAT12; else if (data_clu_num < 65525) disk->fat_type = FATFS_FAT16; else // FAT32 return EINVAL; // Sector and cluster sizes disk->sector_size = boot_rec.bytes_per_sec; disk->sector_size_log2 = get_val_log2(disk->sector_size); disk->cluster_size = boot_rec.bytes_per_sec * boot_rec.sec_per_clust; disk->cluster_size_log2 = get_val_log2(disk->cluster_size); // Sector and cluster size should always be a power of 2 if (0 == disk->sector_size_log2 || 0 == disk->cluster_size_log2) return EINVAL; // FAT table and root dir sizes and position disk->fat_tbl_pos = boot_rec.bytes_per_sec * boot_rec.res_sec_num; disk->fat_tbl_size = boot_rec.bytes_per_sec * boot_rec.sec_per_fat; disk->fat_tbl_nents = data_clu_num + 2; disk->fat_tbls_num = boot_rec.fat_tbls_num; disk->fat_root_dir_pos = disk->fat_tbl_pos + disk->fat_tbls_num * disk->fat_tbl_size; disk->fat_root_dir_size = boot_rec.max_root_dents * DENTRY_SIZE; disk->fat_root_dir_nents = boot_rec.max_root_dents; disk->fat_data_pos = disk->fat_root_dir_pos + disk->fat_root_dir_size; return ENOERR;}// -------------------------------------------------------------------------// fatfs_get_root_node()// Gets root dir node. voidfatfs_get_root_node(fatfs_disk_t *disk, fatfs_node_t *node){ CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); node->mode = __stat_mode_DIR; node->size = disk->fat_root_dir_size; node->ctime = 0; node->atime = 0; node->mtime = 0; node->filename[0] = '\0'; node->cluster = 0; node->parent_cluster = 0; node->dentry_pos.cluster = 0; node->dentry_pos.cluster_snum = 0; node->dentry_pos.cluster_pos = 0;}// -------------------------------------------------------------------------// fatfs_is_node_root_node()// Check if the given node is root dir node. boolfatfs_is_node_root_node(fatfs_node_t *node){ return(is_node_root_node(node));}// -------------------------------------------------------------------------// fatfs_get_dir_entry_node()// Gets dir entry node at given position.// If there is no dir entry at given position the next closest// dir entry and its position are returned. // If EEOF error is returned, then there are no more dir// entries in given dir. intfatfs_get_dir_entry_node(fatfs_disk_t *disk, fatfs_node_t *dir, cyg_uint32 *pos, fatfs_node_t *node){ fat_dir_entry_t dentry; int err; CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(dir); CYG_CHECK_DATA_PTRC(pos); CYG_CHECK_DATA_PTRC(node); err = get_next_dentry(disk, dir, pos, &dentry); if (err != ENOERR) return err; dentry_to_node(&dentry, node); node->parent_cluster = dir->cluster; return ENOERR;}// -------------------------------------------------------------------------// fatfs_write_node()// Writes node attributes to its dir entry (to disk). intfatfs_write_file_attr(fatfs_disk_t *disk, fatfs_node_t *node){ fat_dir_entry_t dentry; int err; CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); node_to_dentry(node, &dentry); err = write_dentry(disk, &dentry.pos, &dentry); return err;}// -------------------------------------------------------------------------// fatfs_delete_file()// Marks file dir entry as deleted. intfatfs_delete_file(fatfs_disk_t *disk, fatfs_node_t *node){ fat_dir_entry_t dentry; int err; CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); // Can't delete root if (is_node_root_node(node)) return EINVAL; printf( "filename='%s'", node->filename); node_to_dentry(node, &dentry); // Check if we are about to delete a directory if (DENTRY_IS_DIR(&dentry)) { fat_dir_entry_t cdentry; cyg_uint32 pos = 0; int i = 0; printf( "got directory"); // Count number of entries in this dir while (true) { err = get_next_dentry(disk, node, &pos, &cdentry); if (EEOF == err) break; else if (err != ENOERR) return err; i++; pos++; } printf( "child count=%d", i); // Check if the dir is empty (except '.' and '..') if (i > 2) return EPERM; } // Free file clusters free_cluster_chain(disk, dentry.cluster); dentry_set_deleted(disk, &dentry); err = write_dentry(disk, &dentry.pos, &dentry); return err;} // -------------------------------------------------------------------------// fatfs_create_file()// Creates a new file. intfatfs_create_file(fatfs_disk_t *disk, fatfs_node_t *dir, const char *name, int namelen, fatfs_node_t *node){ fat_dir_entry_t dentry; int err; CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(dir); CYG_CHECK_DATA_PTRC(name); CYG_CHECK_DATA_PTRC(node); printf( "filename='%s' parent='%s'", name, dir->filename); dentry.pos.cluster = dir->cluster; dentry.pos.cluster_snum = 0; dentry.pos.cluster_pos = 0; // Get free dir entry in parent dir err = get_free_dentry(disk, &dentry.pos, &dir->tcache); if (err != ENOERR) return err; // Set new file attributes init_node_fattr(node, name, namelen, __stat_mode_REG, dir->cluster, &dentry.pos); // Write new dir dentry node_to_dentry(node, &dentry); err = write_dentry(disk, &dentry.pos, &dentry); if (err != ENOERR) return err; return ENOERR; }// -------------------------------------------------------------------------// fatfs_create_dir()// Creates a new directory. intfatfs_create_dir(fatfs_disk_t *disk, fatfs_node_t *dir, const char *name, int namelen, fatfs_node_t *node){ fat_dir_entry_t dentry; fatfs_node_t cnode; cyg_uint32 free_cluster; int err; CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(dir); CYG_CHECK_DATA_PTRC(name); CYG_CHECK_DATA_PTRC(node); printf( "filename='%s' parent='%s'", name, dir->filename); // Get free cluster err = find_next_free_cluster(disk, 0, &free_cluster, CO_MARK_LAST | CO_ERASE_NEW); if (err != ENOERR) return err; dentry.pos.cluster = dir->cluster; dentry.pos.cluster_snum = 0; dentry.pos.cluster_pos = 0; // Get free dir entry in parent dir err = get_free_dentry(disk, &dentry.pos, &dir->tcache); if (err != ENOERR) return err; // Set new dir attributes init_node_fattr(node, name, namelen, __stat_mode_DIR, dir->cluster, &dentry.pos); node->cluster = free_cluster; // Write new dir dentry node_to_dentry(node, &dentry); err = write_dentry(disk, &dentry.pos, &dentry); if (err != ENOERR) return err; // Starting position of new dir entries dentry.pos.cluster = node->cluster; dentry.pos.cluster_snum = 0; dentry.pos.cluster_pos = 0; printf( "Creating '.' entry"); // Set '.' dir attributes init_node_fattr(&cnode, ".", 0, __stat_mode_DIR, node->cluster, &dentry.pos); cnode.cluster = node->cluster; // Write '.' dentry node_to_dentry(&cnode, &dentry); err = write_dentry(disk, &dentry.pos, &dentry); if (err != ENOERR) return err; dentry.pos.cluster_pos += DENTRY_SIZE; printf( "Creating '..' entry"); // Set '..' dir attributes init_node_fattr(&cnode, "..", 0, __stat_mode_DIR, node->cluster, &dentry.pos); cnode.cluster = dir->cluster; // Write '..' dentry node_to_dentry(&cnode, &dentry); err = write_dentry(disk, &dentry.pos, &dentry); if (err != ENOERR) return err; return ENOERR; }// -------------------------------------------------------------------------// fatfs_trunc_file()// Truncates a file to zero length.intfatfs_trunc_file(fatfs_disk_t *disk, fatfs_node_t *node){ fat_dir_entry_t dentry; int err; CYG_CHECK_DATA_PTRC(disk); CYG_CHECK_DATA_PTRC(node); printf( "file='%s'", node->filename); // Check for dir if (S_ISDIR(node->mode)) return EINVAL; // Trivial case check if (0 == node->size) return ENOERR; // Free cluster chain err = free_cluster_chain(disk, node->cluster); if (err != ENOERR) return err; // Flush tcache fatfs_tcache_flush(disk, &node->tcache); // Update node attributes node->cluster = 0; node->size = 0; node->mtime = node->atime = timeGetTime(); // Write dentry node_to_dentry(node, &dentry); err = write_dentry(disk, &dentry.pos, &dentry); if (err != ENOERR) return err; return ENOERR;}// -------------------------------------------------------------------------// fat
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -