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

📄 dir.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  dir.c * *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */#include <linux/sched.h>#include <linux/errno.h>#include <linux/stat.h>#include <linux/kernel.h>#include <linux/malloc.h>#include <linux/mm.h>#include <linux/smb_fs.h>#include <linux/smbno.h>#include <asm/segment.h>#include <asm/semaphore.h>#include <linux/errno.h>static int smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count);static int smb_readdir(struct inode *inode, struct file *filp,	     void *dirent, filldir_t filldir);static struct smb_inode_info * smb_find_dir_inode(struct inode *parent, const char *name, int len);static int smb_lookup(struct inode *dir, const char *__name,	    int len, struct inode **result);static int smb_create(struct inode *dir, const char *name, int len, int mode,	    struct inode **result);static int smb_mkdir(struct inode *dir, const char *name, int len, int mode);static int smb_rmdir(struct inode *dir, const char *name, int len);static int smb_unlink(struct inode *dir, const char *name, int len);static int smb_rename(struct inode *old_dir, const char *old_name, int old_len,	    struct inode *new_dir, const char *new_name, int new_len,	    int must_be_dir);static struct file_operations smb_dir_operations ={	NULL,			/* lseek - default */	smb_dir_read,		/* read - bad */	NULL,			/* write - bad */	smb_readdir,		/* readdir */	NULL,			/* select - default */	smb_ioctl,		/* ioctl - default */	NULL,			/* mmap */	NULL,			/* no special open code */	NULL,			/* no special release code */	NULL			/* fsync */};struct inode_operations smb_dir_inode_operations ={	&smb_dir_operations,	/* default directory file ops */	smb_create,		/* create */	smb_lookup,		/* lookup */	NULL,			/* link */	smb_unlink,		/* unlink */	NULL,			/* symlink */	smb_mkdir,		/* mkdir */	smb_rmdir,		/* rmdir */	NULL,			/* mknod */	smb_rename,		/* rename */	NULL,			/* readlink */	NULL,			/* follow_link */	NULL,			/* readpage */	NULL,			/* writepage */	NULL,			/* bmap */	NULL,			/* truncate */	NULL,			/* permission */	NULL			/* smap */};static intstrncasecmp(const char *s1, const char *s2, int len){	int result = 0;	for (; len > 0; len -= 1)	{		char c1, c2;		c1 = (*s1 >= 'a' && *s1 <= 'z') ? *s1 - ('a' - 'A') : *s1;		c2 = (*s2 >= 'a' && *s2 <= 'z') ? *s2 - ('a' - 'A') : *s2;		s1 += 1;		s2 += 1;		if ((result = c1 - c2) != 0 || c1 == 0)		{			return result;		}	}	return result;}struct smb_inode_info *smb_find_inode(struct smb_server *server, ino_t ino){	struct smb_inode_info *root = &(server->root);	struct smb_inode_info *this = root;	do	{		if (ino == smb_info_ino(this))		{			return this;		}		this = this->next;	}	while (this != root);	return NULL;}static ino_tsmb_fresh_inodes(struct smb_server *server, int no){	static ino_t seed = 1;	struct smb_inode_info *root = &(server->root);	struct smb_inode_info *this;      retry:	if (seed + no <= no)	{		/* avoid inode number of 0 at wrap-around */		seed += no;	}	this = root;	do	{		/* We assume that ino_t is unsigned! */		if (this->finfo.f_ino - seed < no)		{			seed += no;			goto retry;		}		this = this->next;	}	while (this != root);	seed += no;	return seed - no;}static intsmb_dir_read(struct inode *inode, struct file *filp, char *buf, int count){	return -EISDIR;}static unsigned long c_ino = 0;static kdev_t c_dev;static int c_size;static int c_seen_eof;static int c_last_returned_index;static struct smb_dirent *c_entry = NULL;static struct smb_dirent *smb_search_in_cache(struct inode *dir, unsigned long f_pos){	int i;	if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino))	{		return NULL;	}	for (i = 0; i < c_size; i++)	{		if (f_pos == c_entry[i].f_pos)		{			c_last_returned_index = i;			return &(c_entry[i]);		}	}	return NULL;}static intsmb_refill_dir_cache(struct smb_server *server, struct inode *dir,		     unsigned long f_pos){	int result;	static struct semaphore sem = MUTEX;	int i;	ino_t ino;	do	{		down(&sem);		result = smb_proc_readdir(server, dir, f_pos,					  SMB_READDIR_CACHE_SIZE, c_entry);		if (result <= 0)		{			smb_invalid_dir_cache(dir->i_ino);			up(&sem);			return result;		}		c_seen_eof = (result < SMB_READDIR_CACHE_SIZE);		c_dev = dir->i_dev;		c_ino = dir->i_ino;		c_size = result;		c_last_returned_index = 0;		ino = smb_fresh_inodes(server, c_size);		for (i = 0; i < c_size; i++)		{			c_entry[i].f_ino = ino;			ino += 1;		}		up(&sem);	}	while ((c_dev != dir->i_dev) || (c_ino != dir->i_ino));	return result;}static intsmb_readdir(struct inode *dir, struct file *filp,	    void *dirent, filldir_t filldir){	int result, i = 0;	struct smb_dirent *entry = NULL;	struct smb_server *server = SMB_SERVER(dir);	DPRINTK("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos);	DDPRINTK("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n",		 dir->i_ino, c_ino);	if ((dir == NULL) || !S_ISDIR(dir->i_mode))	{		printk("smb_readdir: dir is NULL or not a directory\n");		return -EBADF;	}	if (c_entry == NULL)	{		i = sizeof(struct smb_dirent) * SMB_READDIR_CACHE_SIZE;		c_entry = (struct smb_dirent *) smb_vmalloc(i);		if (c_entry == NULL)		{			printk("smb_readdir: no MEMORY for cache\n");			return -ENOMEM;		}	}	if (filp->f_pos == 0)	{		c_ino = 0;		c_dev = 0;		c_seen_eof = 0;		if (filldir(dirent, ".", 1, filp->f_pos,			    smb_info_ino(SMB_INOP(dir))) < 0)		{			return 0;		}		filp->f_pos += 1;	}	if (filp->f_pos == 1)	{		if (filldir(dirent, "..", 2, filp->f_pos,			    smb_info_ino(SMB_INOP(dir)->dir)) < 0)		{			return 0;		}		filp->f_pos += 1;	}	entry = smb_search_in_cache(dir, filp->f_pos);	if (entry == NULL)	{		if (c_seen_eof)		{			/* End of directory */			return 0;		}		result = smb_refill_dir_cache(server, dir, filp->f_pos);		if (result <= 0)		{			return result;		}		entry = c_entry;	}	while (entry < &(c_entry[c_size]))	{		/* We found it.  For getwd(), we have to return the		   correct inode in d_ino if the inode is currently in		   use. Otherwise the inode number does not		   matter. (You can argue a lot about this..) */		struct smb_inode_info *ino_info		= smb_find_dir_inode(dir, entry->name, entry->len);		ino_t ino = entry->f_ino;		if (ino_info != NULL)		{			ino = smb_info_ino(ino_info);		}		DDPRINTK("smb_readdir: entry->name = %s\n", entry->name);		DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos);		if (filldir(dirent, entry->name, strlen(entry->name),			    entry->f_pos, ino) < 0)		{			break;		}		if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino)		    || (entry->f_pos != filp->f_pos))		{			/* Someone has destroyed the cache while we slept			   in filldir */			break;		}		filp->f_pos += 1;		entry += 1;	}	return 0;}voidsmb_init_dir_cache(void){	c_ino = 0;	c_dev = 0;	c_entry = NULL;}voidsmb_invalid_dir_cache(unsigned long ino){	/* TODO: check for dev as well */	if (ino == c_ino)	{		c_ino = 0;		c_seen_eof = 0;	}}voidsmb_free_dir_cache(void){	if (c_entry != NULL)	{		smb_vfree(c_entry);	}	c_entry = NULL;}/* Insert a NEW smb_inode_info into the inode tree of our filesystem,   under dir. The caller must assure that it's not already there. We   assume that path is allocated for us. */static struct inode *smb_iget(struct inode *dir, struct smb_inode_info *new_inode_info){	struct inode *inode;	struct smb_inode_info *root;	if ((dir == NULL) || (new_inode_info == NULL))	{		printk("smb_iget: parameter is NULL\n");		return NULL;	}	new_inode_info->state = SMB_INODE_LOOKED_UP;	new_inode_info->nused = 0;	new_inode_info->dir = SMB_INOP(dir);	SMB_INOP(dir)->nused += 1;	/*	 * We have to link the new inode_info into the doubly linked	 * list of inode_infos to make a complete linear search possible.	 */	root = &(SMB_SERVER(dir)->root);	new_inode_info->prev = root;	new_inode_info->next = root->next;	root->next->prev = new_inode_info;	root->next = new_inode_info;	if (!(inode = iget(dir->i_sb, smb_info_ino(new_inode_info))))	{		printk("smb_iget: iget failed!");		/*		 * If we blocked in iget(), another task may have referenced		 * the info structure ... clean up with smb_free_inode_info.		 */		smb_free_inode_info(new_inode_info);		return NULL;	}	return inode;}voidsmb_free_inode_info(struct smb_inode_info *i){	if (i == NULL)	{		printk("smb_free_inode: i == NULL\n");		return;	}	i->state = SMB_INODE_CACHED;	while ((i->nused == 0) && (i->state == SMB_INODE_CACHED))	{		struct smb_inode_info *dir = i->dir;		i->next->prev = i->prev;		i->prev->next = i->next;		smb_kfree_s(i, sizeof(struct smb_inode_info));		if (dir == NULL)

⌨️ 快捷键说明

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