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

📄 inode.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 2 页
字号:
			save_and_cli (flags);			error = prom_setprop (node, op->name,					      op->value, op->len + 1);			restore_flags (flags);			if (error <= 0)				printk (KERN_WARNING "openpromfs: "					"Couldn't write property %s\n",					op->name);		} else if ((op->flag & OPP_BINARY) || !op->len) {			save_and_cli (flags);			error = prom_setprop (node, op->name,					      op->value, op->len);			restore_flags (flags);			if (error <= 0)				printk (KERN_WARNING "openpromfs: "					"Couldn't write property %s\n",					op->name);		} else {			printk (KERN_WARNING "openpromfs: "				"Unknown property type of %s\n",				op->name);		}	}	unlock_kernel();	kfree (filp->private_data);	return 0;}static struct file_operations openpromfs_prop_ops = {	read:		property_read,	write:		property_write,	release:	property_release,};static struct file_operations openpromfs_nodenum_ops = {	read:		nodenum_read,};static struct file_operations openprom_operations = {	read:		generic_read_dir,	readdir:	openpromfs_readdir,};static struct inode_operations openprom_alias_inode_operations = {	create:		openpromfs_create,	lookup:		openpromfs_lookup,	unlink:		openpromfs_unlink,};static struct inode_operations openprom_inode_operations = {	lookup:		openpromfs_lookup,};static int lookup_children(u16 n, const char * name, int len){	int ret;	u16 node;	for (; n != 0xffff; n = nodes[n].next) {		node = nodes[n].child;		if (node != 0xffff) {			char buffer[128];			int i;			char *p;						while (node != 0xffff) {				if (prom_getname (nodes[node].node,						  buffer, 128) >= 0) {					i = strlen (buffer);					if ((len == i)					    && !strncmp (buffer, name, len))						return NODE2INO(node);					p = strchr (buffer, '@');					if (p && (len == p - buffer)					    && !strncmp (buffer, name, len))						return NODE2INO(node);				}				node = nodes[node].next;			}		} else			continue;		ret = lookup_children (nodes[n].child, name, len);		if (ret) return ret;	}	return 0;}static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry){	int ino = 0;#define OPFSL_DIR	0#define OPFSL_PROPERTY	1#define OPFSL_NODENUM	2	int type = 0;	char buffer[128];	char *p;	const char *name;	u32 n;	u16 dirnode;	unsigned int len;	int i;	struct inode *inode;	char buffer2[64];		inode = NULL;	name = dentry->d_name.name;	len = dentry->d_name.len;	if (name [0] == '.' && len == 5 && !strncmp (name + 1, "node", 4)) {		ino = NODEP2INO(NODE(dir->i_ino).first_prop);		type = OPFSL_NODENUM;	}	if (!ino) {		u16 node = NODE(dir->i_ino).child;		while (node != 0xffff) {			if (prom_getname (nodes[node].node, buffer, 128) >= 0) {				i = strlen (buffer);				if (len == i && !strncmp (buffer, name, len)) {					ino = NODE2INO(node);					type = OPFSL_DIR;					break;				}				p = strchr (buffer, '@');				if (p && (len == p - buffer)				    && !strncmp (buffer, name, len)) {					ino = NODE2INO(node);					type = OPFSL_DIR;					break;				}			}			node = nodes[node].next;		}	}	n = NODE(dir->i_ino).node;	dirnode = dir->i_ino - OPENPROM_FIRST_INO;	if (!ino) {		int j = NODEP2INO(NODE(dir->i_ino).first_prop);		if (dirnode != aliases) {			for (p = prom_firstprop (n, buffer2);			     p && *p;			     p = prom_nextprop (n, p, buffer2)) {				j++;				if ((len == strlen (p))				    && !strncmp (p, name, len)) {					ino = j;					type = OPFSL_PROPERTY;					break;				}			}		} else {			int k;			for (k = 0; k < aliases_nodes; k++) {				j++;				if (alias_names [k]				    && (len == strlen (alias_names [k]))				    && !strncmp (alias_names [k], name, len)) {					ino = j;					type = OPFSL_PROPERTY;					break;				}			}		}	}	if (!ino) {		ino = lookup_children (NODE(dir->i_ino).child, name, len);		if (ino)			type = OPFSL_DIR;		else			return ERR_PTR(-ENOENT);	}	inode = iget (dir->i_sb, ino);	if (!inode)		return ERR_PTR(-EINVAL);	switch (type) {	case OPFSL_DIR:		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;		if (ino == OPENPROM_FIRST_INO + aliases) {			inode->i_mode |= S_IWUSR;			inode->i_op = &openprom_alias_inode_operations;		} else			inode->i_op = &openprom_inode_operations;		inode->i_fop = &openprom_operations;		inode->i_nlink = 2;		break;	case OPFSL_NODENUM:		inode->i_mode = S_IFREG | S_IRUGO;		inode->i_fop = &openpromfs_nodenum_ops;		inode->i_nlink = 1;		inode->u.generic_ip = (void *)(long)(n);		break;	case OPFSL_PROPERTY:		if ((dirnode == options) && (len == 17)		    && !strncmp (name, "security-password", 17))			inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;		else {			inode->i_mode = S_IFREG | S_IRUGO;			if (dirnode == options || dirnode == aliases) {				if (len != 4 || strncmp (name, "name", 4))					inode->i_mode |= S_IWUSR;			}		}		inode->i_fop = &openpromfs_prop_ops;		inode->i_nlink = 1;		if (inode->i_size < 0)			inode->i_size = 0;		inode->u.generic_ip = (void *)(long)(((u16)dirnode) | 			(((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));		break;	}	inode->i_gid = 0;	inode->i_uid = 0;	d_add(dentry, inode);	return NULL;}static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir){	struct inode *inode = filp->f_dentry->d_inode;	unsigned int ino;	u32 n;	int i, j;	char buffer[128];	u16 node;	char *p;	char buffer2[64];		ino = inode->i_ino;	i = filp->f_pos;	switch (i) {	case 0:		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) return 0;		i++;		filp->f_pos++;		/* fall thru */	case 1:		if (filldir(dirent, "..", 2, i, 			(NODE(ino).parent == 0xffff) ? 			OPENPROM_ROOT_INO : NODE2INO(NODE(ino).parent), DT_DIR) < 0) 			return 0;		i++;		filp->f_pos++;		/* fall thru */	default:		i -= 2;		node = NODE(ino).child;		while (i && node != 0xffff) {			node = nodes[node].next;			i--;		}		while (node != 0xffff) {			if (prom_getname (nodes[node].node, buffer, 128) < 0)				return 0;			if (filldir(dirent, buffer, strlen(buffer),				    filp->f_pos, NODE2INO(node), DT_DIR) < 0)				return 0;			filp->f_pos++;			node = nodes[node].next;		}		j = NODEP2INO(NODE(ino).first_prop);		if (!i) {			if (filldir(dirent, ".node", 5, filp->f_pos, j, DT_REG) < 0)				return 0;			filp->f_pos++;		} else			i--;		n = NODE(ino).node;		if (ino == OPENPROM_FIRST_INO + aliases) {			for (j++; i < aliases_nodes; i++, j++) {				if (alias_names [i]) {					if (filldir (dirent, alias_names [i], 						strlen (alias_names [i]), 						filp->f_pos, j, DT_REG) < 0) return 0;					filp->f_pos++;				}			}		} else {			for (p = prom_firstprop (n, buffer2);			     p && *p;			     p = prom_nextprop (n, p, buffer2)) {				j++;				if (i) i--;				else {					if (filldir(dirent, p, strlen(p),						    filp->f_pos, j, DT_REG) < 0)						return 0;					filp->f_pos++;				}			}		}	}	return 0;}static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode){	char *p;	struct inode *inode;		if (!dir)		return -ENOENT;	if (dentry->d_name.len > 256)		return -EINVAL;	if (aliases_nodes == ALIASES_NNODES)		return -EIO;	p = kmalloc (dentry->d_name.len + 1, GFP_KERNEL);	if (!p)		return -ENOMEM;	strncpy (p, dentry->d_name.name, dentry->d_name.len);	p [dentry->d_name.len] = 0;	alias_names [aliases_nodes++] = p;	inode = iget (dir->i_sb,			NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes);	if (!inode)		return -EINVAL;	inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;	inode->i_fop = &openpromfs_prop_ops;	inode->i_nlink = 1;	if (inode->i_size < 0) inode->i_size = 0;	inode->u.generic_ip = (void *)(long)(((u16)aliases) | 			(((u16)(aliases_nodes - 1)) << 16));	d_instantiate(dentry, inode);	return 0;}static int openpromfs_unlink (struct inode *dir, struct dentry *dentry){	unsigned int len;	char *p;	const char *name;	int i;		name = dentry->d_name.name;	len = dentry->d_name.len;	for (i = 0; i < aliases_nodes; i++)		if ((strlen (alias_names [i]) == len)		    && !strncmp (name, alias_names[i], len)) {			char buffer[512];						p = alias_names [i];			alias_names [i] = NULL;			kfree (p);			strcpy (buffer, "nvunalias ");			memcpy (buffer + 10, name, len);			buffer [10 + len] = 0;			prom_feval (buffer);		}	return 0;}/* {{{ init section */#ifndef MODULEstatic int __init check_space (u16 n)#elsestatic int check_space (u16 n)#endif{	unsigned long pages;	if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) {		pages = __get_free_pages (GFP_KERNEL, alloced + 1);		if (!pages)			return -1;		if (nodes) {			memcpy ((char *)pages, (char *)nodes,				(1 << alloced) * PAGE_SIZE);			free_pages ((unsigned long)nodes, alloced);		}		alloced++;		nodes = (openpromfs_node *)pages;	}	return 0;}#ifndef MODULEstatic u16 __init get_nodes (u16 parent, u32 node)#elsestatic u16 get_nodes (u16 parent, u32 node)#endif{	char *p;	u16 n = last_node++, i;	char buffer[64];	if (check_space (n) < 0)		return 0xffff;	nodes[n].parent = parent;	nodes[n].node = node;	nodes[n].next = 0xffff;	nodes[n].child = 0xffff;	nodes[n].first_prop = first_prop++;	if (!parent) {		char buffer[8];		int j;				if ((j = prom_getproperty (node, "name", buffer, 8)) >= 0) {		    buffer[j] = 0;		    if (!strcmp (buffer, "options"))			options = n;		    else if (!strcmp (buffer, "aliases"))		        aliases = n;		}	}	if (n != aliases)		for (p = prom_firstprop (node, buffer);		     p && p != (char *)-1 && *p;		     p = prom_nextprop (node, p, buffer))			first_prop++;	else {		char *q;		for (p = prom_firstprop (node, buffer);		     p && p != (char *)-1 && *p;		     p = prom_nextprop (node, p, buffer)) {			if (aliases_nodes == ALIASES_NNODES)				break;			for (i = 0; i < aliases_nodes; i++)				if (!strcmp (p, alias_names [i]))					break;			if (i < aliases_nodes)				continue;			q = kmalloc (strlen (p) + 1, GFP_KERNEL);			if (!q)				return 0xffff;			strcpy (q, p);			alias_names [aliases_nodes++] = q;		}		first_prop += ALIASES_NNODES;	}	node = prom_getchild (node);	if (node) {		parent = get_nodes (n, node);		if (parent == 0xffff)			return 0xffff;		nodes[n].child = parent;		while ((node = prom_getsibling (node)) != 0) {			i = get_nodes (n, node);			if (i == 0xffff)				return 0xffff;			nodes[parent].next = i;			parent = i;		}	}	return n;}static void openprom_read_inode(struct inode * inode){	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;	if (inode->i_ino == OPENPROM_ROOT_INO) {		inode->i_op = &openprom_inode_operations;		inode->i_fop = &openprom_operations;		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;	}}static int openprom_statfs(struct super_block *sb, struct statfs *buf){	buf->f_type = OPENPROM_SUPER_MAGIC;	buf->f_bsize = PAGE_SIZE/sizeof(long);	/* ??? */	buf->f_bfree = 0;	buf->f_bavail = 0;	buf->f_ffree = 0;	buf->f_namelen = NAME_MAX;	return 0;}static struct super_operations openprom_sops = { 	read_inode:	openprom_read_inode,	statfs:		openprom_statfs,};struct super_block *openprom_read_super(struct super_block *s,void *data, 				    int silent){	struct inode * root_inode;	s->s_blocksize = 1024;	s->s_blocksize_bits = 10;	s->s_magic = OPENPROM_SUPER_MAGIC;	s->s_op = &openprom_sops;	root_inode = iget(s, OPENPROM_ROOT_INO);	if (!root_inode)		goto out_no_root;	s->s_root = d_alloc_root(root_inode);	if (!s->s_root)		goto out_no_root;	return s;out_no_root:	printk("openprom_read_super: get root inode failed\n");	iput(root_inode);	return NULL;}static DECLARE_FSTYPE(openprom_fs_type, "openpromfs", openprom_read_super, 0);static int __init init_openprom_fs(void){	nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);	if (!nodes) {		printk (KERN_WARNING "openpromfs: can't get free page\n");		return -EIO;	}	if (get_nodes (0xffff, prom_root_node) == 0xffff) {		printk (KERN_WARNING "openpromfs: couldn't setup tree\n");		return -EIO;	}	nodes[last_node].first_prop = first_prop;	return register_filesystem(&openprom_fs_type);}static void __exit exit_openprom_fs(void){	int i;	unregister_filesystem(&openprom_fs_type);	free_pages ((unsigned long)nodes, alloced);	for (i = 0; i < aliases_nodes; i++)		if (alias_names [i])			kfree (alias_names [i]);	nodes = NULL;}EXPORT_NO_SYMBOLS;module_init(init_openprom_fs)module_exit(exit_openprom_fs)MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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