⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 newos is new operation system
💻 C
字号:
/*** Copyright 2003, Travis Geiselbrecht. All rights reserved.** Distributed under the terms of the NewOS License.*/#include <kernel/kernel.h>#include <kernel/vfs.h>#include <kernel/khash.h>#include <kernel/heap.h>#include <kernel/lock.h>#include <kernel/vm.h>#include <kernel/debug.h>#include <kernel/sem.h>#include <string.h>#include "fat.h"#define debug_level_flow 10#define debug_level_error 10#define debug_level_info 10#define DEBUG_MSG_PREFIX "FAT -- "#include <kernel/debug_ext.h>static uint16 get_16(uint8 *buf) {#if _LITTLE_ENDIAN	return buf[0] | (buf[1] << 8);#else	return buf[1] | (buf[0] << 8);#endif}static uint32 get_32(uint8 *buf) {#if _LITTLE_ENDIAN	return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);#else	return buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24);#endif}static int fat_read_bpb(fat_fs *fs){	int err;	uint8 raw_bpb[FAT_BPB_LEN];	uint8 raw_bpb16[FAT_BPB16_LEN];	uint8 raw_bpb32[FAT_BPB32_LEN];	uint32 data_sectors;	uint32 cluster_count;	SHOW_FLOW(3, "fs %p", fs);	// read in the bios parameter block	err = sys_read(fs->fd, raw_bpb, FAT_BPB_OFFSET, FAT_BPB_LEN);	if(err < 0)		return err;	// read in the 16-bit part of the second half of the bios parameter block	err = sys_read(fs->fd, raw_bpb16, FAT_BPB16_OFFSET, FAT_BPB16_LEN);	if(err < 0)		return err;	// read in the 32-bit part of the second half of the bios parameter block	err = sys_read(fs->fd, raw_bpb32, FAT_BPB32_OFFSET, FAT_BPB32_LEN);	if(err < 0)		return err;	// manually unpack the data into the expanded version of these data structures	memcpy(&fs->bpb.jmpboot, raw_bpb + 0, 3);	memcpy(&fs->bpb.oemname, raw_bpb + 3, 8);	fs->bpb.bytes_per_sector = get_16(raw_bpb + 11);	fs->bpb.sectors_per_cluster = raw_bpb[13];	fs->bpb.rsvd_sector_count = get_16(raw_bpb + 14);	fs->bpb.num_fats = raw_bpb[16];	fs->bpb.root_entry_count = get_16(raw_bpb + 17);	fs->bpb.total_sectors16 = get_16(raw_bpb + 19);	fs->bpb.media_type = raw_bpb[21];	fs->bpb.fat_size_16 = get_16(raw_bpb + 22);	fs->bpb.sectors_per_track = get_16(raw_bpb + 24);	fs->bpb.num_heads = get_16(raw_bpb + 26);	fs->bpb.hidden_sectors = get_32(raw_bpb + 28);	fs->bpb.total_sectors32 = get_32(raw_bpb + 32);	fs->bpb16.drive_num = raw_bpb16[0];	fs->bpb16.boot_sig = raw_bpb16[2];	fs->bpb16.vol_id = get_32(raw_bpb16 + 3);	memcpy(&fs->bpb16.vol_lab, raw_bpb16 + 7, 11);	memcpy(&fs->bpb16.fs_type, raw_bpb16 + 18, 8);	fs->bpb32.fat_size_32 = get_32(raw_bpb32);	fs->bpb32.extended_flags = get_16(raw_bpb32 + 4);	fs->bpb32.fs_ver = get_16(raw_bpb32 + 6);	fs->bpb32.root_cluster = get_32(raw_bpb32 + 8);	fs->bpb32.fs_info_cluster = get_16(raw_bpb32 + 12);	fs->bpb32.backup_bootsect = get_16(raw_bpb32 + 14);	fs->bpb32.drive_num = raw_bpb32[28];	fs->bpb32.boot_sig = raw_bpb32[30];	fs->bpb32.vol_id = get_32(raw_bpb32 + 31);	memcpy(&fs->bpb32.vol_lab, raw_bpb32 + 35, 11);	memcpy(&fs->bpb32.fs_type, raw_bpb32 + 46, 8);	// calculate some constants	fs->root_dir_sectors = ((fs->bpb.root_entry_count * 32) + (fs->bpb.bytes_per_sector - 1)) / fs->bpb.bytes_per_sector;	fs->first_data_sector = fs->bpb.rsvd_sector_count + 		(fs->bpb.num_fats * ((fs->bpb.fat_size_16 > 0) ? fs->bpb.fat_size_16 : fs->bpb32.fat_size_32)) + fs->root_dir_sectors;	data_sectors = ((fs->bpb.total_sectors16 > 0) ? fs->bpb.total_sectors16 : fs->bpb.total_sectors32) - fs->first_data_sector;	cluster_count = data_sectors / fs->bpb.sectors_per_cluster;	// figure if we're FAT 12/16/32	if(cluster_count < 4095) {		fs->fat_type = 12;	} else if(cluster_count < 65525) {		fs->fat_type = 16;	} else {		fs->fat_type = 32;	}	fs->fat_sector_offset = fs->bpb.rsvd_sector_count;	fs->cluster_size = fs->bpb.sectors_per_cluster * fs->bpb.bytes_per_sector;	SHOW_INFO(5, "fat_type %d", fs->fat_type);	SHOW_INFO(5, "root_dir_sectors %d", fs->root_dir_sectors);	SHOW_INFO(5, "first_data_sector %d", fs->first_data_sector);	SHOW_INFO(5, "data_sectors %d", data_sectors);	SHOW_INFO(5, "cluster_count %d", cluster_count);	SHOW_INFO(5, "fat_sector_offset %d", fs->fat_sector_offset);	SHOW_INFO(5, "sectors_per_cluster %d (%d bytes)", fs->bpb.sectors_per_cluster, 		fs->cluster_size);	// do some sanity checks	if((fs->cluster_size & (fs->cluster_size - 1)) != 0) 		return ERR_IO_ERROR; // is it a power of 2	if(fs->fat_type == 32) {		if(fs->bpb32.fs_ver != 0) 			return ERR_IO_ERROR; // unsupported fs version	}	return 0;}int fat_mount(fs_cookie *fs, fs_id id, const char *device, void *args, vnode_id *root_vnid){	fat_fs *fat;	int err;	SHOW_FLOW(3, "device %s", device);	fat = kmalloc(sizeof(fat_fs));	if(!fat) {		err = ERR_NO_MEMORY;		goto err;	}	memset(fat, 0, sizeof(fat_fs));	fat->id = id;	fat->fd = sys_open(device, 0);	if(fat->fd < 0) {		err = fat->fd;		goto err1;	}	err = vfs_get_vnode_from_fd(fat->fd, true, &fat->dev_vnode);	if(err < 0)		goto err2;	// see if we can page from this device	if(!vfs_canpage(fat->dev_vnode)) {		err = ERR_VFS_WRONG_STREAM_TYPE;		goto err3;	}	// read in the bios parameter block	err = fat_read_bpb(fat);	if(err < 0)		goto err3;	// create a semaphore to lock the fs	fat->sem = sem_create(FAT_WRITE_COUNT, "fat lock");	if(fat->sem < 0)		goto err3;	if(fat->fat_type == 32) {		fat->root_vnid = CLUSTERS_TO_VNID(fat->bpb32.root_cluster, fat->bpb32.root_cluster);	} else {		fat->root_vnid = CLUSTERS_TO_VNID(1, 1);	}	*fs = fat;	*root_vnid = fat->root_vnid;	return 0;err3:	vfs_put_vnode_ptr(fat->dev_vnode);err2:	sys_close(fat->fd);err1:	kfree(fat);err:	return err;}int fat_unmount(fs_cookie fs){	fat_fs *fat = (fat_fs *)fs;	SHOW_FLOW(3, "fat_unmount: fat %p", fat);	vfs_put_vnode_ptr(fat->dev_vnode);	sys_close(fat->fd);	sem_delete(fat->sem);	kfree(fat);	return 0;}int fat_sync(fs_cookie fs){	SHOW_FLOW(3, "fat_sync: fat %p", fs);	return 0;}static struct fs_calls fat_calls = {	&fat_mount,	&fat_unmount,	&fat_sync,	&fat_lookup,	&fat_getvnode,	&fat_putvnode,	&fat_removevnode,	&fat_opendir,	&fat_closedir,	&fat_rewinddir,	&fat_readdir,	&fat_open,	&fat_close,	&fat_freecookie,	&fat_fsync,	&fat_read,	&fat_write,	&fat_seek,	&fat_ioctl,	&fat_canpage,	&fat_readpage,	&fat_writepage,	&fat_create,	&fat_unlink,	&fat_rename,	&fat_mkdir,	&fat_rmdir,	&fat_rstat,	&fat_wstat};int fs_bootstrap(void);int fs_bootstrap(void){	return vfs_register_filesystem("fat", &fat_calls);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -