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

📄 dir.c

📁 linux环境下基于FAT的文件系统的通用代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	loff_t cpos;	int count = 0;	bh = NULL;	cpos = 0;	while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {		if (de->attr & ATTR_DIR)			count++;	}	brelse(bh);	return count;}/* * Scans a directory for a given file (name points to its formatted name). * Returns an error code or zero. */int fat_scan(struct inode *dir, const unsigned char *name,	     struct fat_slot_info *sinfo){	struct super_block *sb = dir->i_sb;	sinfo->slot_off = 0;	sinfo->bh = NULL;	while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh,				   &sinfo->de) >= 0) {		if (!strncmp(sinfo->de->name, name, MSDOS_NAME)) {			sinfo->slot_off -= sizeof(*sinfo->de);			sinfo->nr_slots = 1;			sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);			return 0;		}	}	return -ENOENT;}EXPORT_SYMBOL_GPL(fat_scan);static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots){	struct super_block *sb = dir->i_sb;	struct buffer_head *bh;	struct msdos_dir_entry *de, *endp;	int err = 0, orig_slots;	while (nr_slots) {		bh = NULL;		if (fat_get_entry(dir, &pos, &bh, &de) < 0) {			err = -EIO;			break;		}		orig_slots = nr_slots;		endp = (struct msdos_dir_entry *)(bh->b_data + sb->s_blocksize);		while (nr_slots && de < endp) {			de->name[0] = DELETED_FLAG;			de++;			nr_slots--;		}		mark_buffer_dirty(bh);		if (IS_DIRSYNC(dir))			err = sync_dirty_buffer(bh);		brelse(bh);		if (err)			break;		/* pos is *next* de's position, so this does `- sizeof(de)' */		pos += ((orig_slots - nr_slots) * sizeof(*de)) - sizeof(*de);	}	return err;}int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo){	struct msdos_dir_entry *de;	struct buffer_head *bh;	int err = 0, nr_slots;	/*	 * First stage: Remove the shortname. By this, the directory	 * entry is removed.	 */	nr_slots = sinfo->nr_slots;	de = sinfo->de;	sinfo->de = NULL;	bh = sinfo->bh;	sinfo->bh = NULL;	while (nr_slots && de >= (struct msdos_dir_entry *)bh->b_data) {		de->name[0] = DELETED_FLAG;		de--;		nr_slots--;	}	mark_buffer_dirty(bh);	if (IS_DIRSYNC(dir))		err = sync_dirty_buffer(bh);	brelse(bh);	if (err)		return err;	dir->i_version++;	if (nr_slots) {		/*		 * Second stage: remove the remaining longname slots.		 * (This directory entry is already removed, and so return		 * the success)		 */		err = __fat_remove_entries(dir, sinfo->slot_off, nr_slots);		if (err) {			printk(KERN_WARNING			       "FAT: Couldn't remove the long name slots\n");		}	}	dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;	if (IS_DIRSYNC(dir))		(void)fat_sync_inode(dir);	else		mark_inode_dirty(dir);	return 0;}EXPORT_SYMBOL_GPL(fat_remove_entries);static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used,			      struct buffer_head **bhs, int nr_bhs){	struct super_block *sb = dir->i_sb;	sector_t last_blknr = blknr + MSDOS_SB(sb)->sec_per_clus;	int err, i, n;	/* Zeroing the unused blocks on this cluster */	blknr += nr_used;	n = nr_used;	while (blknr < last_blknr) {		bhs[n] = sb_getblk(sb, blknr);		if (!bhs[n]) {			err = -ENOMEM;			goto error;		}		memset(bhs[n]->b_data, 0, sb->s_blocksize);		set_buffer_uptodate(bhs[n]);		mark_buffer_dirty(bhs[n]);		n++;		blknr++;		if (n == nr_bhs) {			if (IS_DIRSYNC(dir)) {				err = fat_sync_bhs(bhs, n);				if (err)					goto error;			}			for (i = 0; i < n; i++)				brelse(bhs[i]);			n = 0;		}	}	if (IS_DIRSYNC(dir)) {		err = fat_sync_bhs(bhs, n);		if (err)			goto error;	}	for (i = 0; i < n; i++)		brelse(bhs[i]);	return 0;error:	for (i = 0; i < n; i++)		bforget(bhs[i]);	return err;}int fat_alloc_new_dir(struct inode *dir, struct timespec *ts){	struct super_block *sb = dir->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct buffer_head *bhs[MAX_BUF_PER_PAGE];	struct msdos_dir_entry *de;	sector_t blknr;	__le16 date, time;	u8 time_cs;	int err, cluster;	err = fat_alloc_clusters(dir, &cluster, 1);	if (err)		goto error;	blknr = fat_clus_to_blknr(sbi, cluster);	bhs[0] = sb_getblk(sb, blknr);	if (!bhs[0]) {		err = -ENOMEM;		goto error_free;	}	fat_time_unix2fat(sbi, ts, &time, &date, &time_cs);	de = (struct msdos_dir_entry *)bhs[0]->b_data;	/* filling the new directory slots ("." and ".." entries) */	memcpy(de[0].name, MSDOS_DOT, MSDOS_NAME);	memcpy(de[1].name, MSDOS_DOTDOT, MSDOS_NAME);	de->attr = de[1].attr = ATTR_DIR;	de[0].lcase = de[1].lcase = 0;	de[0].time = de[1].time = time;	de[0].date = de[1].date = date;	if (sbi->options.isvfat) {		/* extra timestamps */		de[0].ctime = de[1].ctime = time;		de[0].ctime_cs = de[1].ctime_cs = time_cs;		de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date;	} else {		de[0].ctime = de[1].ctime = 0;		de[0].ctime_cs = de[1].ctime_cs = 0;		de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0;	}	de[0].start = cpu_to_le16(cluster);	de[0].starthi = cpu_to_le16(cluster >> 16);	de[1].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);	de[1].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart >> 16);	de[0].size = de[1].size = 0;	memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de));	set_buffer_uptodate(bhs[0]);	mark_buffer_dirty(bhs[0]);	err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE);	if (err)		goto error_free;	return cluster;error_free:	fat_free_clusters(dir, cluster);error:	return err;}EXPORT_SYMBOL_GPL(fat_alloc_new_dir);static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots,			       int *nr_cluster, struct msdos_dir_entry **de,			       struct buffer_head **bh, loff_t *i_pos){	struct super_block *sb = dir->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct buffer_head *bhs[MAX_BUF_PER_PAGE];	sector_t blknr, start_blknr, last_blknr;	unsigned long size, copy;	int err, i, n, offset, cluster[2];	/*	 * The minimum cluster size is 512bytes, and maximum entry	 * size is 32*slots (672bytes).  So, iff the cluster size is	 * 512bytes, we may need two clusters.	 */	size = nr_slots * sizeof(struct msdos_dir_entry);	*nr_cluster = (size + (sbi->cluster_size - 1)) >> sbi->cluster_bits;	BUG_ON(*nr_cluster > 2);	err = fat_alloc_clusters(dir, cluster, *nr_cluster);	if (err)		goto error;	/*	 * First stage: Fill the directory entry.  NOTE: This cluster	 * is not referenced from any inode yet, so updates order is	 * not important.	 */	i = n = copy = 0;	do {		start_blknr = blknr = fat_clus_to_blknr(sbi, cluster[i]);		last_blknr = start_blknr + sbi->sec_per_clus;		while (blknr < last_blknr) {			bhs[n] = sb_getblk(sb, blknr);			if (!bhs[n]) {				err = -ENOMEM;				goto error_nomem;			}			/* fill the directory entry */			copy = min(size, sb->s_blocksize);			memcpy(bhs[n]->b_data, slots, copy);			slots += copy;			size -= copy;			set_buffer_uptodate(bhs[n]);			mark_buffer_dirty(bhs[n]);			if (!size)				break;			n++;			blknr++;		}	} while (++i < *nr_cluster);	memset(bhs[n]->b_data + copy, 0, sb->s_blocksize - copy);	offset = copy - sizeof(struct msdos_dir_entry);	get_bh(bhs[n]);	*bh = bhs[n];	*de = (struct msdos_dir_entry *)((*bh)->b_data + offset);	*i_pos = fat_make_i_pos(sb, *bh, *de);	/* Second stage: clear the rest of cluster, and write outs */	err = fat_zeroed_cluster(dir, start_blknr, ++n, bhs, MAX_BUF_PER_PAGE);	if (err)		goto error_free;	return cluster[0];error_free:	brelse(*bh);	*bh = NULL;	n = 0;error_nomem:	for (i = 0; i < n; i++)		bforget(bhs[i]);	fat_free_clusters(dir, cluster[0]);error:	return err;}int fat_add_entries(struct inode *dir, void *slots, int nr_slots,		    struct fat_slot_info *sinfo){	struct super_block *sb = dir->i_sb;	struct msdos_sb_info *sbi = MSDOS_SB(sb);	struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */	struct msdos_dir_entry *de;	int err, free_slots, i, nr_bhs;	loff_t pos, i_pos;	sinfo->nr_slots = nr_slots;	/* First stage: search free direcotry entries */	free_slots = nr_bhs = 0;	bh = prev = NULL;	pos = 0;	err = -ENOSPC;	while (fat_get_entry(dir, &pos, &bh, &de) > -1) {		/* check the maximum size of directory */		if (pos >= FAT_MAX_DIR_SIZE)			goto error;		if (IS_FREE(de->name)) {			if (prev != bh) {				get_bh(bh);				bhs[nr_bhs] = prev = bh;				nr_bhs++;			}			free_slots++;			if (free_slots == nr_slots)				goto found;		} else {			for (i = 0; i < nr_bhs; i++)				brelse(bhs[i]);			prev = NULL;			free_slots = nr_bhs = 0;		}	}	if (dir->i_ino == MSDOS_ROOT_INO) {		if (sbi->fat_bits != 32)			goto error;	} else if (MSDOS_I(dir)->i_start == 0) {		printk(KERN_ERR "FAT: Corrupted directory (i_pos %lld)\n",		       MSDOS_I(dir)->i_pos);		err = -EIO;		goto error;	}found:	err = 0;	pos -= free_slots * sizeof(*de);	nr_slots -= free_slots;	if (free_slots) {		/*		 * Second stage: filling the free entries with new entries.		 * NOTE: If this slots has shortname, first, we write		 * the long name slots, then write the short name.		 */		int size = free_slots * sizeof(*de);		int offset = pos & (sb->s_blocksize - 1);		int long_bhs = nr_bhs - (nr_slots == 0);		/* Fill the long name slots. */		for (i = 0; i < long_bhs; i++) {			int copy = min_t(int, sb->s_blocksize - offset, size);			memcpy(bhs[i]->b_data + offset, slots, copy);			mark_buffer_dirty(bhs[i]);			offset = 0;			slots += copy;			size -= copy;		}		if (long_bhs && IS_DIRSYNC(dir))			err = fat_sync_bhs(bhs, long_bhs);		if (!err && i < nr_bhs) {			/* Fill the short name slot. */			int copy = min_t(int, sb->s_blocksize - offset, size);			memcpy(bhs[i]->b_data + offset, slots, copy);			mark_buffer_dirty(bhs[i]);			if (IS_DIRSYNC(dir))				err = sync_dirty_buffer(bhs[i]);		}		for (i = 0; i < nr_bhs; i++)			brelse(bhs[i]);		if (err)			goto error_remove;	}	if (nr_slots) {		int cluster, nr_cluster;		/*		 * Third stage: allocate the cluster for new entries.		 * And initialize the cluster with new entries, then		 * add the cluster to dir.		 */		cluster = fat_add_new_entries(dir, slots, nr_slots, &nr_cluster,					      &de, &bh, &i_pos);		if (cluster < 0) {			err = cluster;			goto error_remove;		}		err = fat_chain_add(dir, cluster, nr_cluster);		if (err) {			fat_free_clusters(dir, cluster);			goto error_remove;		}		if (dir->i_size & (sbi->cluster_size - 1)) {			fat_fs_panic(sb, "Odd directory size");			dir->i_size = (dir->i_size + sbi->cluster_size - 1)				& ~((loff_t)sbi->cluster_size - 1);		}		dir->i_size += nr_cluster << sbi->cluster_bits;		MSDOS_I(dir)->mmu_private += nr_cluster << sbi->cluster_bits;	}	sinfo->slot_off = pos;	sinfo->de = de;	sinfo->bh = bh;	sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);	return 0;error:	brelse(bh);	for (i = 0; i < nr_bhs; i++)		brelse(bhs[i]);	return err;error_remove:	brelse(bh);	if (free_slots)		__fat_remove_entries(dir, pos, free_slots);	return err;}EXPORT_SYMBOL_GPL(fat_add_entries);

⌨️ 快捷键说明

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