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

📄 inode.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/fs/isofs/inode.c * *  (C) 1991  Linus Torvalds - minix filesystem *      1992, 1993, 1994  Eric Youngdale Modified for ISO 9660 filesystem. *      1994  Eberhard Moenkeberg - multi session handling. *      1995  Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs. *	1997  Gordon Chaffee - Joliet CDs *	1998  Eric Lammerts - ISO 9660 Level 3 */#include <linux/config.h>#include <linux/module.h>#include <linux/stat.h>#include <linux/sched.h>#include <linux/iso_fs.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/locks.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/cdrom.h>#include <linux/init.h>#include <linux/nls.h>#include <linux/ctype.h>#include <linux/smp_lock.h>#include <linux/blkdev.h>#include <asm/system.h>#include <asm/uaccess.h>#include "zisofs.h"/* * We have no support for "multi volume" CDs, but more and more disks carry * wrong information within the volume descriptors. */#define IGNORE_WRONG_MULTI_VOLUME_SPECS#define BEQUIET#ifdef LEAK_CHECKstatic int check_malloc = 0;static int check_bread = 0;#endifstatic int isofs_hashi(struct dentry *parent, struct qstr *qstr);static int isofs_hash(struct dentry *parent, struct qstr *qstr);static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);#ifdef CONFIG_JOLIETstatic int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b);#endifstatic void isofs_put_super(struct super_block *sb){#ifdef CONFIG_JOLIET	if (sb->u.isofs_sb.s_nls_iocharset) {		unload_nls(sb->u.isofs_sb.s_nls_iocharset);		sb->u.isofs_sb.s_nls_iocharset = NULL;	}#endif#ifdef LEAK_CHECK	printk("Outstanding mallocs:%d, outstanding buffers: %d\n",	       check_malloc, check_bread);#endif	return;}static void isofs_read_inode(struct inode *);static int isofs_statfs (struct super_block *, struct statfs *);static struct super_operations isofs_sops = {	read_inode:	isofs_read_inode,	put_super:	isofs_put_super,	statfs:		isofs_statfs,};static struct dentry_operations isofs_dentry_ops[] = {	{		d_hash:		isofs_hash,		d_compare:	isofs_dentry_cmp,	},	{		d_hash:		isofs_hashi,		d_compare:	isofs_dentry_cmpi,	},#ifdef CONFIG_JOLIET	{		d_hash:		isofs_hash_ms,		d_compare:	isofs_dentry_cmp_ms,	},	{		d_hash:		isofs_hashi_ms,		d_compare:	isofs_dentry_cmpi_ms,	}#endif};struct iso9660_options{	char map;	char rock;	char joliet;	char cruft;	char unhide;	char nocompress;	unsigned char check;	unsigned int blocksize;	mode_t mode;	gid_t gid;	uid_t uid;	char *iocharset;	unsigned char utf8;        /* LVE */        s32 session;        s32 sbsector;};/* * Compute the hash for the isofs name corresponding to the dentry. */static intisofs_hash_common(struct dentry *dentry, struct qstr *qstr, int ms){	const char *name;	int len;	len = qstr->len;	name = qstr->name;	if (ms) {		while (len && name[len-1] == '.')			len--;	}	qstr->hash = full_name_hash(name, len);	return 0;}/* * Compute the hash for the isofs name corresponding to the dentry. */static intisofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms){	const char *name;	int len;	char c;	unsigned long hash;	len = qstr->len;	name = qstr->name;	if (ms) {		while (len && name[len-1] == '.')			len--;	}	hash = init_name_hash();	while (len--) {		c = tolower(*name++);		hash = partial_name_hash(tolower(c), hash);	}	qstr->hash = end_name_hash(hash);	return 0;}/* * Case insensitive compare of two isofs names. */static intisofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms){	int alen, blen;	/* A filename cannot end in '.' or we treat it like it has none */	alen = a->len;	blen = b->len;	if (ms) {		while (alen && a->name[alen-1] == '.')			alen--;		while (blen && b->name[blen-1] == '.')			blen--;	}	if (alen == blen) {		if (strnicmp(a->name, b->name, alen) == 0)			return 0;	}	return 1;}/* * Case sensitive compare of two isofs names. */static intisofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms){	int alen, blen;	/* A filename cannot end in '.' or we treat it like it has none */	alen = a->len;	blen = b->len;	if (ms) {		while (alen && a->name[alen-1] == '.')			alen--;		while (blen && b->name[blen-1] == '.')			blen--;	}	if (alen == blen) {		if (strncmp(a->name, b->name, alen) == 0)			return 0;	}	return 1;}static intisofs_hash(struct dentry *dentry, struct qstr *qstr){	return isofs_hash_common(dentry, qstr, 0);}static intisofs_hashi(struct dentry *dentry, struct qstr *qstr){	return isofs_hashi_common(dentry, qstr, 0);}static intisofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b){	return isofs_dentry_cmp_common(dentry, a, b, 0);}static intisofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b){	return isofs_dentry_cmpi_common(dentry, a, b, 0);}#ifdef CONFIG_JOLIETstatic intisofs_hash_ms(struct dentry *dentry, struct qstr *qstr){	return isofs_hash_common(dentry, qstr, 1);}static intisofs_hashi_ms(struct dentry *dentry, struct qstr *qstr){	return isofs_hashi_common(dentry, qstr, 1);}static intisofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b){	return isofs_dentry_cmp_common(dentry, a, b, 1);}static intisofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b){	return isofs_dentry_cmpi_common(dentry, a, b, 1);}#endifstatic int parse_options(char *options, struct iso9660_options * popt){	char *this_char,*value;	popt->map = 'n';	popt->rock = 'y';	popt->joliet = 'y';	popt->cruft = 'n';	popt->unhide = 'n';	popt->check = 'u';		/* unset */	popt->nocompress = 0;	popt->blocksize = 1024;	popt->mode = S_IRUGO | S_IXUGO; /* r-x for all.  The disc could					   be shared with DOS machines so					   virtually anything could be					   a valid executable. */	popt->gid = 0;	popt->uid = 0;	popt->iocharset = NULL;	popt->utf8 = 0;	popt->session=-1;	popt->sbsector=-1;	if (!options) return 1;	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {	        if (strncmp(this_char,"norock",6) == 0) {		  popt->rock = 'n';		  continue;		}	        if (strncmp(this_char,"nojoliet",8) == 0) {		  popt->joliet = 'n';		  continue;		}	        if (strncmp(this_char,"unhide",6) == 0) {		  popt->unhide = 'y';		  continue;		}	        if (strncmp(this_char,"cruft",5) == 0) {		  popt->cruft = 'y';		  continue;		}	        if (strncmp(this_char,"utf8",4) == 0) {		  popt->utf8 = 1;		  continue;		}	        if (strncmp(this_char,"nocompress",10) == 0) {		  popt->nocompress = 1;		  continue;		}		if ((value = strchr(this_char,'=')) != NULL)			*value++ = 0;#ifdef CONFIG_JOLIET		if (!strcmp(this_char,"iocharset") && value) {			popt->iocharset = value;			while (*value && *value != ',')				value++;			if (value == popt->iocharset)				return 0;			*value = 0;		} else#endif		if (!strcmp(this_char,"map") && value) {			if (value[0] && !value[1] && strchr("ano",*value))				popt->map = *value;			else if (!strcmp(value,"off")) popt->map = 'o';			else if (!strcmp(value,"normal")) popt->map = 'n';			else if (!strcmp(value,"acorn")) popt->map = 'a';			else return 0;		}		if (!strcmp(this_char,"session") && value) {			char * vpnt = value;			unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);			if(ivalue < 0 || ivalue >99) return 0;			popt->session=ivalue+1;		}		if (!strcmp(this_char,"sbsector") && value) {			char * vpnt = value;			unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);			if(ivalue < 0 || ivalue >660*512) return 0;			popt->sbsector=ivalue;		}		else if (!strcmp(this_char,"check") && value) {			if (value[0] && !value[1] && strchr("rs",*value))				popt->check = *value;			else if (!strcmp(value,"relaxed")) popt->check = 'r';			else if (!strcmp(value,"strict")) popt->check = 's';			else return 0;		}		else if (!strcmp(this_char,"conv") && value) {			/* no conversion is done anymore;			   we still accept the same mount options,			   but ignore them */			if (value[0] && !value[1] && strchr("btma",*value)) ;			else if (!strcmp(value,"binary")) ;			else if (!strcmp(value,"text")) ;			else if (!strcmp(value,"mtext")) ;			else if (!strcmp(value,"auto")) ;			else return 0;		}		else if (value &&			 (!strcmp(this_char,"block") ||			  !strcmp(this_char,"mode") ||			  !strcmp(this_char,"uid") ||			  !strcmp(this_char,"gid"))) {		  char * vpnt = value;		  unsigned int ivalue = simple_strtoul(vpnt, &vpnt, 0);		  if (*vpnt) return 0;		  switch(*this_char) {		  case 'b':		    if (   ivalue != 512			&& ivalue != 1024			&& ivalue != 2048) return 0;		    popt->blocksize = ivalue;		    break;		  case 'u':		    popt->uid = ivalue;		    break;		  case 'g':		    popt->gid = ivalue;		    break;		  case 'm':		    popt->mode = ivalue;		    break;		  }		}		else return 1;	}	return 1;}/* * look if the driver can tell the multi session redirection value * * don't change this if you don't know what you do, please! * Multisession is legal only with XA disks. * A non-XA disk with more than one volume descriptor may do it right, but * usually is written in a nowhere standardized "multi-partition" manner. * Multisession uses absolute addressing (solely the first frame of the whole * track is #0), multi-partition uses relative addressing (each first frame of * each track is #0), and a track is not a session. * * A broken CDwriter software or drive firmware does not set new standards, * at least not if conflicting with the existing ones. * * emoenke@gwdg.de */#define WE_OBEY_THE_WRITTEN_STANDARDS 1static unsigned int isofs_get_last_session(struct super_block *sb,s32 session ){	struct cdrom_multisession ms_info;	unsigned int vol_desc_start;	struct block_device *bdev = sb->s_bdev;	int i;	vol_desc_start=0;	ms_info.addr_format=CDROM_LBA;	if(session >= 0 && session <= 99) {		struct cdrom_tocentry Te;		Te.cdte_track=session;		Te.cdte_format=CDROM_LBA;		i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);		if (!i) {			printk(KERN_DEBUG "Session %d start %d type %d\n",			       session, Te.cdte_addr.lba,			       Te.cdte_ctrl&CDROM_DATA_TRACK);			if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)				return Te.cdte_addr.lba;		}					printk(KERN_ERR "Invalid session number or type of track\n");	}	i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);	if(session > 0) printk(KERN_ERR "Invalid session number\n");#if 0	printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);	if (i==0) {		printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");		printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);	}#endif	if (i==0)#if WE_OBEY_THE_WRITTEN_STANDARDS        if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */#endif		vol_desc_start=ms_info.addr.lba;	return vol_desc_start;}/* * Initialize the superblock and read the root inode. * * Note: a check_disk_change() has been done immediately prior * to this call, so we don't need to check again. */

⌨️ 快捷键说明

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