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

📄 fatent.c

📁 linux环境下基于FAT的文件系统的通用代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2004, OGAWA Hirofumi * Released under GPL v2. */#include <linux/module.h>#include <linux/fs.h>#include <linux/msdos_fs.h>#include <linux/blkdev.h>#include "fat.h"struct fatent_operations {	void (*ent_blocknr)(struct super_block *, int, int *, sector_t *);	void (*ent_set_ptr)(struct fat_entry *, int);	int (*ent_bread)(struct super_block *, struct fat_entry *,			 int, sector_t);	int (*ent_get)(struct fat_entry *);	void (*ent_put)(struct fat_entry *, int);	int (*ent_next)(struct fat_entry *);};static DEFINE_SPINLOCK(fat12_entry_lock);static void fat12_ent_blocknr(struct super_block *sb, int entry,			      int *offset, sector_t *blocknr){	struct msdos_sb_info *sbi = MSDOS_SB(sb);	int bytes = entry + (entry >> 1);	WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);	*offset = bytes & (sb->s_blocksize - 1);	*blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);}static void fat_ent_blocknr(struct super_block *sb, int entry,			    int *offset, sector_t *blocknr){	struct msdos_sb_info *sbi = MSDOS_SB(sb);	int bytes = (entry << sbi->fatent_shift);	WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);	*offset = bytes & (sb->s_blocksize - 1);	*blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);}static void fat12_ent_set_ptr(struct fat_entry *fatent, int offset){	struct buffer_head **bhs = fatent->bhs;	if (fatent->nr_bhs == 1) {		WARN_ON(offset >= (bhs[0]->b_size - 1));		fatent->u.ent12_p[0] = bhs[0]->b_data + offset;		fatent->u.ent12_p[1] = bhs[0]->b_data + (offset + 1);	} else {		WARN_ON(offset != (bhs[0]->b_size - 1));		fatent->u.ent12_p[0] = bhs[0]->b_data + offset;		fatent->u.ent12_p[1] = bhs[1]->b_data;	}}static void fat16_ent_set_ptr(struct fat_entry *fatent, int offset){	WARN_ON(offset & (2 - 1));	fatent->u.ent16_p = (__le16 *)(fatent->bhs[0]->b_data + offset);}static void fat32_ent_set_ptr(struct fat_entry *fatent, int offset){	WARN_ON(offset & (4 - 1));	fatent->u.ent32_p = (__le32 *)(fatent->bhs[0]->b_data + offset);}static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,			   int offset, sector_t blocknr){	struct buffer_head **bhs = fatent->bhs;	WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);	bhs[0] = sb_bread(sb, blocknr);	if (!bhs[0])		goto err;	if ((offset + 1) < sb->s_blocksize)		fatent->nr_bhs = 1;	else {		/* This entry is block boundary, it needs the next block */		blocknr++;		bhs[1] = sb_bread(sb, blocknr);		if (!bhs[1])			goto err_brelse;		fatent->nr_bhs = 2;	}	fat12_ent_set_ptr(fatent, offset);	return 0;err_brelse:	brelse(bhs[0]);err:	printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", (llu)blocknr);	return -EIO;}static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,			 int offset, sector_t blocknr){	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;	WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);	fatent->bhs[0] = sb_bread(sb, blocknr);	if (!fatent->bhs[0]) {		printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",		       (llu)blocknr);		return -EIO;	}	fatent->nr_bhs = 1;	ops->ent_set_ptr(fatent, offset);	return 0;}static int fat12_ent_get(struct fat_entry *fatent){	u8 **ent12_p = fatent->u.ent12_p;	int next;	spin_lock(&fat12_entry_lock);	if (fatent->entry & 1)		next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);	else		next = (*ent12_p[1] << 8) | *ent12_p[0];	spin_unlock(&fat12_entry_lock);	next &= 0x0fff;	if (next >= BAD_FAT12)		next = FAT_ENT_EOF;	return next;}static int fat16_ent_get(struct fat_entry *fatent){	int next = le16_to_cpu(*fatent->u.ent16_p);	WARN_ON((unsigned long)fatent->u.ent16_p & (2 - 1));	if (next >= BAD_FAT16)		next = FAT_ENT_EOF;	return next;}static int fat32_ent_get(struct fat_entry *fatent){	int next = le32_to_cpu(*fatent->u.ent32_p) & 0x0fffffff;	WARN_ON((unsigned long)fatent->u.ent32_p & (4 - 1));	if (next >= BAD_FAT32)		next = FAT_ENT_EOF;	return next;}static void fat12_ent_put(struct fat_entry *fatent, int new){	u8 **ent12_p = fatent->u.ent12_p;	if (new == FAT_ENT_EOF)		new = EOF_FAT12;	spin_lock(&fat12_entry_lock);	if (fatent->entry & 1) {		*ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);		*ent12_p[1] = new >> 4;	} else {		*ent12_p[0] = new & 0xff;		*ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);	}	spin_unlock(&fat12_entry_lock);	mark_buffer_dirty(fatent->bhs[0]);	if (fatent->nr_bhs == 2)		mark_buffer_dirty(fatent->bhs[1]);}static void fat16_ent_put(struct fat_entry *fatent, int new){	if (new == FAT_ENT_EOF)		new = EOF_FAT16;	*fatent->u.ent16_p = cpu_to_le16(new);	mark_buffer_dirty(fatent->bhs[0]);}static void fat32_ent_put(struct fat_entry *fatent, int new){	if (new == FAT_ENT_EOF)		new = EOF_FAT32;	WARN_ON(new & 0xf0000000);	new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff;	*fatent->u.ent32_p = cpu_to_le32(new);	mark_buffer_dirty(fatent->bhs[0]);}static int fat12_ent_next(struct fat_entry *fatent){	u8 **ent12_p = fatent->u.ent12_p;	struct buffer_head **bhs = fatent->bhs;	u8 *nextp = ent12_p[1] + 1 + (fatent->entry & 1);	fatent->entry++;	if (fatent->nr_bhs == 1) {		WARN_ON(ent12_p[0] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 2)));		WARN_ON(ent12_p[1] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));		if (nextp < (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1))) {			ent12_p[0] = nextp - 1;			ent12_p[1] = nextp;			return 1;		}	} else {		WARN_ON(ent12_p[0] != (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));		WARN_ON(ent12_p[1] != (u8 *)bhs[1]->b_data);		ent12_p[0] = nextp - 1;		ent12_p[1] = nextp;		brelse(bhs[0]);		bhs[0] = bhs[1];		fatent->nr_bhs = 1;		return 1;	}	ent12_p[0] = NULL;	ent12_p[1] = NULL;	return 0;}static int fat16_ent_next(struct fat_entry *fatent){	const struct buffer_head *bh = fatent->bhs[0];	fatent->entry++;	if (fatent->u.ent16_p < (__le16 *)(bh->b_data + (bh->b_size - 2))) {		fatent->u.ent16_p++;		return 1;	}	fatent->u.ent16_p = NULL;	return 0;}static int fat32_ent_next(struct fat_entry *fatent){	const struct buffer_head *bh = fatent->bhs[0];	fatent->entry++;	if (fatent->u.ent32_p < (__le32 *)(bh->b_data + (bh->b_size - 4))) {		fatent->u.ent32_p++;		return 1;	}	fatent->u.ent32_p = NULL;	return 0;}static struct fatent_operations fat12_ops = {	.ent_blocknr	= fat12_ent_blocknr,	.ent_set_ptr	= fat12_ent_set_ptr,	.ent_bread	= fat12_ent_bread,	.ent_get	= fat12_ent_get,	.ent_put	= fat12_ent_put,	.ent_next	= fat12_ent_next,};static struct fatent_operations fat16_ops = {	.ent_blocknr	= fat_ent_blocknr,	.ent_set_ptr	= fat16_ent_set_ptr,	.ent_bread	= fat_ent_bread,	.ent_get	= fat16_ent_get,	.ent_put	= fat16_ent_put,	.ent_next	= fat16_ent_next,};static struct fatent_operations fat32_ops = {	.ent_blocknr	= fat_ent_blocknr,	.ent_set_ptr	= fat32_ent_set_ptr,	.ent_bread	= fat_ent_bread,	.ent_get	= fat32_ent_get,	.ent_put	= fat32_ent_put,	.ent_next	= fat32_ent_next,};static inline void lock_fat(struct msdos_sb_info *sbi){	mutex_lock(&sbi->fat_lock);}static inline void unlock_fat(struct msdos_sb_info *sbi){	mutex_unlock(&sbi->fat_lock);}void fat_ent_access_init(struct super_block *sb){	struct msdos_sb_info *sbi = MSDOS_SB(sb);	mutex_init(&sbi->fat_lock);	switch (sbi->fat_bits) {	case 32:		sbi->fatent_shift = 2;		sbi->fatent_ops = &fat32_ops;		break;	case 16:		sbi->fatent_shift = 1;		sbi->fatent_ops = &fat16_ops;		break;	case 12:		sbi->fatent_shift = -1;		sbi->fatent_ops = &fat12_ops;		break;	}}static inline int fat_ent_update_ptr(struct super_block *sb,				     struct fat_entry *fatent,				     int offset, sector_t blocknr){	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct fatent_operations *ops = sbi->fatent_ops;	struct buffer_head **bhs = fatent->bhs;	/* Is this fatent's blocks including this entry? */	if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr)		return 0;	if (sbi->fat_bits == 12) {		if ((offset + 1) < sb->s_blocksize) {			/* This entry is on bhs[0]. */			if (fatent->nr_bhs == 2) {				brelse(bhs[1]);				fatent->nr_bhs = 1;			}		} else {			/* This entry needs the next block. */			if (fatent->nr_bhs != 2)				return 0;			if (bhs[1]->b_blocknr != (blocknr + 1))				return 0;		}	}	ops->ent_set_ptr(fatent, offset);	return 1;}int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry){

⌨️ 快捷键说明

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