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

📄 dir.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/fat/dir.c * *  directory handling functions for fat-based filesystems * *  Written 1992,1993 by Werner Almesberger * *  Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu> * *  VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu> *  Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk> *  Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV *  Short name translation 1999 by Wolfram Pienkoss <wp@bszh.de> */#define ASC_LINUX_VERSION(V, P, S)	(((V) * 65536) + ((P) * 256) + (S))#include <linux/version.h>#include <linux/fs.h>#include <linux/msdos_fs.h>#include <linux/nls.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/stat.h>#include <linux/string.h>#include <linux/ioctl.h>#include <linux/dirent.h>#include <linux/mm.h>#include <linux/ctype.h>#include <asm/uaccess.h>#include "msbuffer.h"#define PRINTK(X)struct file_operations fat_dir_operations = {	read:		generic_read_dir,	readdir:	fat_readdir,	ioctl:		fat_dir_ioctl,	fsync:		file_fsync,};/* * Convert Unicode 16 to UTF8, translated Unicode, or ASCII. * If uni_xlate is enabled and we can't get a 1:1 conversion, use a * colon as an escape character since it is normally invalid on the vfat * filesystem. The following four characters are the hexadecimal digits * of Unicode value. This lets us do a full dump and restore of Unicode * filenames. We could get into some trouble with long Unicode names, * but ignore that right now. * Ahem... Stack smashing in ring 0 isn't fun. Fixed. */static intuni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate,	    struct nls_table *nls){	wchar_t *ip, ec;	unsigned char *op, nc;	int charlen;	int k;	ip = uni;	op = ascii;	while (*ip) {		ec = *ip++;		if ( (charlen = nls->uni2char(ec, op, 3)) > 0) {			op += charlen;		} else {			if (uni_xlate == 1) {				*op = ':';				for (k = 4; k > 0; k--) {					nc = ec & 0xF;					op[k] = nc > 9	? nc + ('a' - 10)							: nc + '0';					ec >>= 4;				}				op += 5;			} else {				*op++ = '?';			}		}		/* We have some slack there, so it's OK */		if (op>ascii+256) {			op = ascii + 256;			break;		}	}	*op = 0;	return (op - ascii);}#if 0static void dump_de(struct msdos_dir_entry *de){	int i;	unsigned char *p = (unsigned char *) de;	printk("[");	for (i = 0; i < 32; i++, p++) {		printk("%02x ", *p);	}	printk("]\n");}#endifstatic inline unsigned charfat_tolower(struct nls_table *t, unsigned char c){	unsigned char nc = t->charset2lower[c];	return nc ? nc : c;}static inline intfat_short2lower_uni(struct nls_table *t, unsigned char c, wchar_t *uni){	int charlen;	unsigned char nc = t->charset2lower[c];		if (!nc)		nc = c;	if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) {		*uni = 0x003f;	/* a question mark */	}	return charlen;}static intfat_strnicmp(struct nls_table *t, const unsigned char *s1,					const unsigned char *s2, int len){	while(len--)		if (fat_tolower(t, *s1++) != fat_tolower(t, *s2++))			return 1;	return 0;}/* * Return values: negative -> error, 0 -> not found, positive -> found, * value is the total amount of slots, including the shortname entry. */int fat_search_long(struct inode *inode, const char *name, int name_len,			int anycase, loff_t *spos, loff_t *lpos){	struct super_block *sb = inode->i_sb;	struct buffer_head *bh = NULL;	struct msdos_dir_entry *de;	struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;	struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;	wchar_t bufuname[14];	unsigned char xlate_len, long_slots, *unicode = NULL;	char c, bufname[260];	/* 256 + 4 */	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;	int utf8 = MSDOS_SB(sb)->options.utf8;	int ino, i, i2, last, res = 0;	loff_t cpos = 0;	while(1) {		if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)			goto EODir;parse_record:		long_slots = 0;		if (de->name[0] == (__s8) DELETED_FLAG)			continue;		if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))			continue;		if (de->attr != ATTR_EXT && IS_FREE(de->name))			continue;		if (de->attr == ATTR_EXT) {			struct msdos_dir_slot *ds;			int offset;			unsigned char id;			unsigned char slot;			unsigned char slots;			unsigned char sum;			unsigned char alias_checksum;			if (!unicode) {				unicode = (unsigned char *)					__get_free_page(GFP_KERNEL);				if (!unicode) {					fat_brelse(sb, bh);					return -ENOMEM;				}			}parse_long:			slots = 0;			offset = 0;			ds = (struct msdos_dir_slot *) de;			id = ds->id;			if (!(id & 0x40))				continue;			slots = id & ~0x40;			if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */				continue;			long_slots = slots;			alias_checksum = ds->alias_checksum;			slot = slots;			while (1) {				slot--;				offset = slot * 26;				memcpy(&unicode[offset], ds->name0_4, 10);				memcpy(&unicode[offset+10], ds->name5_10, 12);				memcpy(&unicode[offset+22], ds->name11_12, 4);				offset += 26;				if (ds->id & 0x40) {					unicode[offset] = 0;					unicode[offset+1] = 0;				}				if (fat_get_entry(inode,&cpos,&bh,&de,&ino)<0)					goto EODir;				if (slot == 0)					break;				ds = (struct msdos_dir_slot *) de;				if (ds->attr !=  ATTR_EXT)					goto parse_record;				if ((ds->id & ~0x40) != slot)					goto parse_long;				if (ds->alias_checksum != alias_checksum)					goto parse_long;			}			if (de->name[0] == (__s8) DELETED_FLAG)				continue;			if (de->attr ==  ATTR_EXT)				goto parse_long;			if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))				continue;			for (sum = 0, i = 0; i < 11; i++)				sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];			if (sum != alias_checksum)				long_slots = 0;		}		for (i = 0, last = 0; i < 8;) {			if (!(c = de->name[i])) break;			if (c == 0x05) c = 0xE5;			fat_short2lower_uni(nls_disk, c, &bufuname[i++]);			if (c != ' ')				last = i;		}		i = last;		fat_short2lower_uni(nls_disk, '.', &bufuname[i++]);		for (i2 = 0; i2 < 3; i2++) {			if (!(c = de->ext[i2])) break;			fat_short2lower_uni(nls_disk, c, &bufuname[i++]);			if (c != ' ')				last = i;		}		if (!last)			continue;		memset(&bufuname[last], 0, sizeof(wchar_t));		xlate_len = utf8			?utf8_wcstombs(bufname, bufuname, 260)			:uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);		if (xlate_len == name_len)			if ((!anycase && !memcmp(name, bufname, xlate_len)) ||			    (anycase && !fat_strnicmp(nls_io, name, bufname,								xlate_len)))				goto Found;		if (long_slots) {			xlate_len = utf8				?utf8_wcstombs(bufname, (wchar_t *) unicode, 260)				:uni16_to_x8(bufname, (wchar_t *) unicode, uni_xlate, nls_io);			if (xlate_len != name_len)				continue;			if ((!anycase && !memcmp(name, bufname, xlate_len)) ||			    (anycase && !fat_strnicmp(nls_io, name, bufname,								xlate_len)))				goto Found;		}	}Found:	res = long_slots + 1;	*spos = cpos - sizeof(struct msdos_dir_entry);	*lpos = cpos - res*sizeof(struct msdos_dir_entry);EODir:	fat_brelse(sb, bh);	if (unicode) {		free_page((unsigned long) unicode);	}	return res;}static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,			filldir_t filldir, int shortnames, int both){	struct super_block *sb = inode->i_sb;	struct buffer_head *bh;	struct msdos_dir_entry *de;	struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;	struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;	wchar_t bufuname[14], *ptuname = &bufuname[0];	unsigned char long_slots, *unicode = NULL;	char c, bufname[56], *ptname = bufname;	unsigned long lpos, dummy, *furrfu = &lpos;	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;	int isvfat = MSDOS_SB(sb)->options.isvfat;	int utf8 = MSDOS_SB(sb)->options.utf8;	int nocase = MSDOS_SB(sb)->options.nocase;	int ino,inum,i,i2,last, dotoffset = 0;	loff_t cpos;	cpos = filp->f_pos;/* Fake . and .. for the root directory. */	if (inode->i_ino == MSDOS_ROOT_INO) {		while (cpos < 2) {			if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO, DT_DIR) < 0)				return 0;			cpos++;			filp->f_pos++;		}		if (cpos == 2) {			dummy = 2;			furrfu = &dummy;			cpos = 0;		}	}	if (cpos & (sizeof(struct msdos_dir_entry)-1))		return -ENOENT; 	bh = NULL;GetNew:	long_slots = 0;	if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)		goto EODir;	/* Check for long filename entry */	if (isvfat) {		if (de->name[0] == (__s8) DELETED_FLAG)			goto RecEnd;		if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))			goto RecEnd;		if (de->attr != ATTR_EXT && IS_FREE(de->name))			goto RecEnd;	} else {		if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))			goto RecEnd;	}	if (isvfat && de->attr == ATTR_EXT) {		struct msdos_dir_slot *ds;		int offset;		unsigned char id;		unsigned char slot;		unsigned char slots;

⌨️ 快捷键说明

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