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

📄 mangle.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/umsdos/mangle.c * *      Written 1993 by Jacques Gelinas  * * Control the mangling of file name to fit msdos name space. * Many optimisations by GLU == dglaude@is1.vub.ac.be (Glaude David) */#include <linux/errno.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/umsdos_fs.h>/* (This file is used outside of the kernel) */#ifndef __KERNEL__#define KERN_WARNING#endif/* * Complete the mangling of the MSDOS fake name * based on the position of the entry in the EMD file. *  * Simply complete the job of umsdos_parse; fill the extension. *  * Beware that info->f_pos must be set. */void umsdos_manglename (struct umsdos_info *info){	if (info->msdos_reject) {		/* #Specification: file name / non MSDOS conforming / mangling		 * Each non MSDOS conforming file has a special extension		 * build from the entry position in the EMD file.		 * 		 * This number is then transform in a base 32 number, where		 * each digit is expressed like hexadecimal number, using		 * digit and letter, except it uses 22 letters from 'a' to 'v'.		 * The number 32 comes from 2**5. It is faster to split a binary		 * number using a base which is a power of two. And I was 32		 * when I started this project. Pick your answer :-) .		 * 		 * If the result is '0', it is replace with '_', simply		 * to make it odd.		 * 		 * This is true for the first two character of the extension.		 * The last one is taken from a list of odd character, which		 * are:		 * 		 * { } ( ) ! ` ^ & @		 * 		 * With this scheme, we can produce 9216 ( 9* 32 * 32)		 * different extensions which should not clash with any useful		 * extension already popular or meaningful. Since most directory		 * have much less than 32 * 32 files in it, the first character		 * of the extension of any mangled name will be {.		 * 		 * Here are the reason to do this (this kind of mangling).		 * 		 * -The mangling is deterministic. Just by the extension, we		 * are able to locate the entry in the EMD file.		 * 		 * -By keeping to beginning of the file name almost unchanged,		 * we are helping the MSDOS user.		 * 		 * -The mangling produces names not too ugly, so an msdos user		 * may live with it (remember it, type it, etc...).		 * 		 * -The mangling produces names ugly enough so no one will		 * ever think of using such a name in real life. This is not		 * fool proof. I don't think there is a total solution to this.		 */		int entry_num;		char *pt = info->fake.fname + info->fake.len;		/* lookup for encoding the last character of the extension 		 * It contains valid character after the ugly one to make sure 		 * even if someone overflows the 32 * 32 * 9 limit, it still 		 * does something 		 */#define SPECIAL_MANGLING '{','}','(',')','!','`','^','&','@'		static char lookup3[] =		{			SPECIAL_MANGLING,		/* This is the start of lookup12 */			'_', '1', '2', '3', '4', '5', '6', '7', '8', '9',			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',			'p', 'q', 'r', 's', 't', 'u', 'v'		};#define lookup12 (lookup3+9)		entry_num = info->f_pos / UMSDOS_REC_SIZE;		if (entry_num > (9* 32 * 32)){			printk (KERN_WARNING "UMSDOS: more than 9216 files in a directory.\n"				"This may break the mangling strategy.\n"				"Not a killer problem. See doc.\n");		}		*pt++ = '.';		*pt++ = lookup3 [(entry_num >> 10) & 31];		*pt++ = lookup12[(entry_num >> 5) & 31];		*pt++ = lookup12[entry_num & 31];		*pt = '\0';		/* help doing printk */			info->fake.len += 4;		info->msdos_reject = 0;		/* Avoid mangling twice */	}}/* * Evaluate the record size needed to store of name of len character. * The value returned is a multiple of UMSDOS_REC_SIZE. */int umsdos_evalrecsize (int len){	struct umsdos_dirent dirent;	int nbrec = 1 + ((len - 1 + (dirent.name - (char *) &dirent))			 / UMSDOS_REC_SIZE);	return nbrec * UMSDOS_REC_SIZE;	/*	 * GLU        This should be inlined or something to speed it up to the max.	 * GLU        nbrec is absolutely not needed to return the value.	 */}#ifdef TESTint umsdos_evalrecsize_old (int len){	struct umsdos_dirent dirent;	int size = len + (dirent.name - (char *) &dirent);	int nbrec = size / UMSDOS_REC_SIZE;	int extra = size % UMSDOS_REC_SIZE;	if (extra > 0)		nbrec++;	return nbrec * UMSDOS_REC_SIZE;}#endif/* * Fill the struct info with the full and msdos name of a file * Return 0 if all is OK, a negative error code otherwise. */int umsdos_parse (			 const char *fname,			 int len,			 struct umsdos_info *info){	int ret = -ENAMETOOLONG;	/* #Specification: file name / too long	 * If a file name exceed UMSDOS maxima, the file name is silently	 * truncated. This makes it conformant with the other file system	 * of Linux (minix and ext2 at least).	 */	if (len > UMSDOS_MAXNAME)		len = UMSDOS_MAXNAME;	{		const char *firstpt = NULL;	/* First place we saw a "." in fname */		/* #Specification: file name / non MSDOS conforming / base length 0		 * file names beginning with a period '.' are invalid for MS-DOS.		 * It needs absolutely a base name. So the file name is mangled		 */		int ivldchar = fname[0] == '.';		/* At least one invalid character */		int msdos_len = len;		int base_len;		/*		 * cardinal_per_size tells if there exists at least one		 * DOS pseudo device on length n.  See the test below.		 */		static const char cardinal_per_size[9] =		{			0, 0, 0, 1, 1, 0, 1, 0, 1		};		/*		 * lkp translate all character to acceptable character (for DOS).		 * When lkp[n] == n, it means also it is an acceptable one.		 * So it serves both as a flag and as a translator.		 */		static char lkp[256];		static char is_init = 0;		if (!is_init) {			/*			 * Initialisation of the array is easier and less error                         * prone like this.			 */			int i;			static const char *spc = "\"*+,/:;<=>?[\\]|~";			is_init = 1;			for (i = 0; i <= 32; i++)				lkp[i] = '#';			for (i = 33; i < 'A'; i++)				lkp[i] = (char) i;			for (i = 'A'; i <= 'Z'; i++)				lkp[i] = (char) (i + ('a' - 'A'));			for (i = 'Z' + 1; i < 127; i++)				lkp[i] = (char) i;			for (i = 128; i < 256; i++)				lkp[i] = '#';			lkp['.'] = '_';			while (*spc != '\0')				lkp[(unsigned char) (*spc++)] = '#';		}		/*  GLU		 * File names longer than 8+'.'+3 are invalid for MS-DOS,		 * so the file name is to be mangled--no further test is needed.		 * This speeds up handling of long names.		 * The position of the last point is no more necessary anyway.		 */		if (len <= (8 + 1 + 3)) {			const char *pt = fname;			const char *endpt = fname + len;			while (pt < endpt) {				if (*pt == '.') {					if (firstpt != NULL) {						/* 2 . in a file name. Reject */						ivldchar = 1;						break;					} else {						int extlen = (int) (endpt - pt);						firstpt = pt;						if (firstpt - fname > 8) {							/* base name longer than 8: reject */							ivldchar = 1;							break;						} else if (extlen > 4) {							/* Extension longer than 4 (including .): reject */							ivldchar = 1;							break;						} else if (extlen == 1) {							/* #Specification: file name / non MSDOS conforming / last char == .							 * If the last character of a file name is							 * a period, mangling is applied. MS-DOS does							 * not support those file names.							 */							ivldchar = 1;							break;						} else if (extlen == 4) {							/* #Specification: file name / non MSDOS conforming / mangling clash							 * To avoid clash with    the umsdos mangling, any file							 * with a special character as the first character							 * of the extension will be mangled. This solves the							 * following problem:							 * 							 * #							 * touch FILE							 * # FILE is invalid for DOS, so mangling is applied							 * # file.{_1 is created in the DOS directory							 * touch file.{_1							 * # To UMSDOS file point to a single DOS entry.							 * # So file.{_1 has to be mangled.							 * #							 */							static char special[] =							{								SPECIAL_MANGLING, '\0'							};

⌨️ 快捷键说明

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