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

📄 dir.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 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, 2001 by Wolfram Pienkoss <wp@bszh.de> */#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>#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, NLS_MAX_CHARSET_SIZE)) > 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_short2uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni){	int charlen;	charlen = t->char2uni(c, clen, uni);	if (charlen < 0) {		*uni = 0x003f;	/* a question mark */		charlen = 1;	}	return charlen;}static inline intfat_short2lower_uni(struct nls_table *t, unsigned char *c, int clen, wchar_t *uni){	int charlen;	wchar_t wc;	charlen = t->char2uni(c, clen, &wc);	if (charlen < 0) {		*uni = 0x003f;	/* a question mark */		charlen = 1;	} else if (charlen <= 1) {		unsigned char nc = t->charset2lower[*c];				if (!nc)			nc = *c;				if ( (charlen = t->char2uni(&nc, 1, uni)) < 0) {			*uni = 0x003f;	/* a question mark */			charlen = 1;		}	} else		*uni = wc;		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;}static inline intfat_shortname2uni(struct nls_table *nls, char *buf, int buf_size,		  wchar_t *uni_buf, unsigned short opt, int lower){	int len = 0;	if (opt & VFAT_SFN_DISPLAY_LOWER)		len =  fat_short2lower_uni(nls, buf, buf_size, uni_buf);	else if (opt & VFAT_SFN_DISPLAY_WIN95)		len = fat_short2uni(nls, buf, buf_size, uni_buf);	else if (opt & VFAT_SFN_DISPLAY_WINNT) {		if (lower)			len = fat_short2lower_uni(nls, buf, buf_size, uni_buf);		else 			len = fat_short2uni(nls, buf, buf_size, uni_buf);	} else		len = fat_short2uni(nls, buf, buf_size, uni_buf);	return len;}/* * 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;	wchar_t *unicode = NULL;	char work[8], bufname[260];	/* 256 + 4 */	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;	int utf8 = MSDOS_SB(sb)->options.utf8;	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;	int ino, chl, i, j, last_u, 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;			unsigned char id;			unsigned char slot;			unsigned char slots;			unsigned char sum;			unsigned char alias_checksum;			if (!unicode) {				unicode = (wchar_t *)					__get_free_page(GFP_KERNEL);				if (!unicode) {					fat_brelse(sb, bh);					return -ENOMEM;				}			}parse_long:			slots = 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) {				int offset;				slot--;				offset = slot * 13;				fat16_towchar(unicode + offset, ds->name0_4, 5);				fat16_towchar(unicode + offset + 5, ds->name5_10, 6);				fat16_towchar(unicode + offset + 11, ds->name11_12, 2);				if (ds->id & 0x40) {					unicode[offset + 13] = 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; i < 8; i++) {			/* see namei.c, msdos_format_name */			if (de->name[i] == 0x05)				work[i] = 0xE5;			else				work[i] = de->name[i];		}		for (i = 0, j = 0, last_u = 0; i < 8;) {			if (!work[i]) break;			chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,						&bufuname[j++], opt_shortname,						de->lcase & CASE_LOWER_BASE);			if (chl <= 1) {				if (work[i] != ' ')					last_u = j;			} else {				last_u = j;			}			i += chl;		}		j = last_u;		fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);		for (i = 0; i < 3;) {			if (!de->ext[i]) break;			chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i,						&bufuname[j++], opt_shortname,						de->lcase & CASE_LOWER_EXT);			if (chl <= 1) {				if (de->ext[i] != ' ')					last_u = j;			} else {				last_u = j;			}			i += chl;		}		if (!last_u)			continue;		bufuname[last_u] = 0x0000;		xlate_len = utf8			?utf8_wcstombs(bufname, bufuname, sizeof(bufname))			: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, unicode, sizeof(bufname))				:uni16_to_x8(bufname, 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];	unsigned char long_slots;	wchar_t *unicode = NULL;	char c, work[8], 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;	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;	int ino, inum, chi, chl, i, i2, j, last, last_u, 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)

⌨️ 快捷键说明

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