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

📄 dir.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 2 页
字号:
	void * buf,	const char * name,	int name_len,	off_t offset,	ino_t ino){	struct UMSDOS_DIRENT_K *d = (struct UMSDOS_DIRENT_K *)buf;	d->f_pos = offset;	d->ino = ino;	return 0;}struct UMSDOS_DIR_SEARCH{	struct umsdos_dirent *entry;	int found;	ino_t search_ino;};static int umsdos_dir_search (	void * buf,	const char * name,	int name_len,	off_t offset,	ino_t ino){	int ret = 0;	struct UMSDOS_DIR_SEARCH *d = (struct UMSDOS_DIR_SEARCH *)buf;	if (d->search_ino == ino){		d->found = 1;		memcpy (d->entry->name,name,name_len);		d->entry->name[name_len] = '\0';		d->entry->name_len = name_len;		ret = 1;	/* So fat_readdir will terminate */	}	return ret;}/*	Locate entry of an inode in a directory.	Return 0 or a negative error code.	Normally, this function must succeed. It means a strange corruption	in the file system if not.*/int umsdos_inode2entry (	struct inode *dir,	struct inode *inode,	struct umsdos_dirent *entry)	/* Will hold the entry */{	int ret = -ENOENT;	if (inode == pseudo_root){		/*			Quick way to find the name.			Also umsdos_readdir_x won't show /linux anyway		*/		memcpy (entry->name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN+1);		entry->name_len = UMSDOS_PSDROOT_LEN;		ret = 0;	}else{		struct inode *emddir = umsdos_emd_dir_lookup(dir,0);		iput (emddir);		if (emddir == NULL){			/* This is a DOS directory */			struct UMSDOS_DIR_SEARCH bufk;			struct file filp;			filp.f_reada = 1;			filp.f_pos = 0;			bufk.entry = entry;			bufk.search_ino = inode->i_ino;			fat_readdir (dir,&filp,&bufk,umsdos_dir_search);			if (bufk.found){				ret = 0;				inode->u.umsdos_i.i_dir_owner = dir->i_ino;				inode->u.umsdos_i.i_emd_owner = 0;				umsdos_setup_dir_inode(inode);			}		}else{			/* skip . and .. see umsdos_readdir_x() */			struct file filp;			filp.f_reada = 1;			filp.f_pos = UMSDOS_SPECIAL_DIRFPOS;			while (1){				struct UMSDOS_DIRENT_K bufk;				if (umsdos_readdir_x(dir,&filp,&bufk					,1,entry,0,umsdos_filldir_k) < 0){					printk ("UMSDOS: can't locate inode %ld in EMD file???\n"						,inode->i_ino);					break;				}else if (bufk.ino == inode->i_ino){					ret = 0;					umsdos_lookup_patch (dir,inode,entry,bufk.f_pos);					break;				}			}		}	}	return ret;}/*	Locate the parent of a directory and the info on that directory	Return 0 or a negative error code.*/static int umsdos_locate_ancestor (	struct inode *dir,	struct inode **result,	struct umsdos_dirent *entry){	int ret;	umsdos_patch_inode (dir,NULL,0);	ret = umsdos_real_lookup (dir,"..",2,result);	PRINTK (("result %d %p ",ret,*result));	if (ret == 0){		struct inode *adir = *result;		ret = umsdos_inode2entry (adir,dir,entry);	}	PRINTK (("\n"));	return ret;}/*	Build the path name of an inode (relative to the file system.	This function is need to set (pseudo) hard link.	It uses the same strategy as the standard getcwd().*/int umsdos_locate_path (	struct inode *inode,	char *path){	int ret = 0;	struct inode *dir = inode;	char *bpath = (char*)kmalloc(PATH_MAX,GFP_KERNEL);	if (bpath == NULL){		ret = -ENOMEM;	}else{		struct umsdos_dirent entry;		char *ptbpath = bpath+PATH_MAX-1;		*ptbpath = '\0';		PRINTK (("locate_path mode %x ",inode->i_mode));		if (!S_ISDIR(inode->i_mode)){			ret = umsdos_get_dirowner (inode,&dir);			PRINTK (("locate_path ret %d ",ret));			if (ret == 0){				ret = umsdos_inode2entry (dir,inode,&entry);				if (ret == 0){					ptbpath -= entry.name_len;					memcpy (ptbpath,entry.name,entry.name_len);					PRINTK (("ptbpath :%s: ",ptbpath));				}			}		}else{			dir->i_count++;		}		if (ret == 0){			while (dir != dir->i_sb->s_mounted){				struct inode *adir;				ret = umsdos_locate_ancestor (dir,&adir,&entry);				iput (dir);				dir = NULL;				PRINTK (("ancestor %d ",ret));				if (ret == 0){					*--ptbpath = '/';					ptbpath -= entry.name_len;					memcpy (ptbpath,entry.name,entry.name_len);					dir = adir;					PRINTK (("ptbpath :%s: ",ptbpath));				}else{					break;				}			}		}		strcpy (path,ptbpath);		kfree (bpath);	}	PRINTK (("\n"));	iput (dir);	return ret;}/*	Return != 0 if an entry is the pseudo DOS entry in the pseudo root.*/int umsdos_is_pseudodos (	struct inode *dir,	const char *name,	int len){	/* #Specification: pseudo root / DOS hard coded		The pseudo sub-directory DOS in the pseudo root is hard coded.		The name is DOS. This is done this way to help standardised		the umsdos layout. The idea is that from now on /DOS is		a reserved path and nobody will think of using such a path		for a package.	*/	return dir == pseudo_root		&& len == 3		&& name[0] == 'D' && name[1] == 'O' && name[2] == 'S';}/*	Check if a file exist in the current directory.	Return 0 if ok, negative error code if not (ex: -ENOENT).*/static int umsdos_lookup_x (	struct inode *dir,	const char *name,	int len,	struct inode **result,	/* Will hold inode of the file, if successful */	int nopseudo)			/* Don't care about pseudo root mode */{	int ret = -ENOENT;	*result = NULL;	umsdos_startlookup(dir);		if (len == 1 && name[0] == '.'){		*result = dir;		dir->i_count++;		ret = 0;	}else if (len == 2 && name[0] == '.' && name[1] == '.'){		if (pseudo_root != NULL && dir == pseudo_root->i_sb->s_mounted){			/* #Specification: pseudo root / .. in real root				Whenever a lookup is those in the real root for				the directory .., and pseudo root is active, the				pseudo root is returned.			*/			ret = 0;			*result = pseudo_root;			pseudo_root->i_count++;		}else{			/* #Specification: locating .. / strategy				We use the msdos filesystem to locate the parent directory.				But it is more complicated than that.								We have to step back even further to				get the parent of the parent, so we can get the EMD				of the parent of the parent. Using the EMD file, we can				locate all the info on the parent, such a permissions				and owner.			*/			ret = umsdos_real_lookup (dir,"..",2,result);			PRINTK (("ancestor ret %d dir %p *result %p ",ret,dir,*result));			if (ret == 0				&& *result != dir->i_sb->s_mounted				&& *result != pseudo_root){				struct inode *aadir;				struct umsdos_dirent entry;				ret = umsdos_locate_ancestor (*result,&aadir,&entry);				iput (aadir);			}		}	}else if (umsdos_is_pseudodos(dir,name,len)){		/* #Specification: pseudo root / lookup(DOS)			A lookup of DOS in the pseudo root will always succeed			and return the inode of the real root.		*/		*result = dir->i_sb->s_mounted;		(*result)->i_count++;		ret = 0;	}else{		struct umsdos_info info;		ret = umsdos_parse (name,len,&info);		if (ret == 0) ret = umsdos_findentry (dir,&info,0);		PRINTK (("lookup %s pos %lu ret %d len %d ",info.fake.fname,info.f_pos,ret			,info.fake.len));		if (ret == 0){			/* #Specification: umsdos / lookup				A lookup for a file is done in two step. First, we locate				the file in the EMD file. If not present, we return				an error code (-ENOENT). If it is there, we repeat the				operation on the msdos file system. If this fails, it means				that the file system is not in sync with the emd file.				We silently remove this entry from the emd file,				and return ENOENT.			*/			struct inode *inode;			ret = umsdos_real_lookup (dir,info.fake.fname,info.fake.len,result);			inode = *result;			if (inode == NULL){				printk ("UMSDOS: Erase entry %s, out of sync with MsDOS\n"					,info.fake.fname);				umsdos_delentry (dir,&info,S_ISDIR(info.entry.mode));			}else{				umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);				PRINTK (("lookup ino %ld flags %d\n",inode->i_ino					,info.entry.flags));				if (info.entry.flags & UMSDOS_HLINK){					ret = umsdos_hlink2inode (inode,result);				}				if (*result == pseudo_root && !nopseudo){					/* #Specification: pseudo root / dir lookup						For the same reason as readdir, a lookup in /DOS for						the pseudo root directory (linux) will fail.					*/					/*						This has to be allowed for resolving hard link						which are recorded independently of the pseudo-root						mode.					*/					iput (pseudo_root);					*result = NULL;					ret = -ENOENT;				}			}		}	}	umsdos_endlookup(dir);		iput (dir);	return ret;}/*	Check if a file exist in the current directory.	Return 0 if ok, negative error code if not (ex: -ENOENT).*/int UMSDOS_lookup (	struct inode *dir,	const char *name,	int len,	struct inode **result)	/* Will hold inode of the file, if successful */{	return umsdos_lookup_x(dir,name,len,result,0);}/*	Locate the inode pointed by a (pseudo) hard link	Return 0 if ok, a negative error code if not.*/int umsdos_hlink2inode (struct inode *hlink, struct inode **result){	int ret = -EIO;	char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);	*result = NULL;	if (path == NULL){		ret = -ENOMEM;		iput (hlink);	}else{		struct file filp;		filp.f_reada = 1;		filp.f_pos = 0;		PRINTK (("hlink2inode "));		if (umsdos_file_read_kmem (hlink,&filp,path,hlink->i_size)			==hlink->i_size){			struct inode *dir;			char *pt = path;			dir = hlink->i_sb->s_mounted;			path[hlink->i_size] = '\0';			iput (hlink);			dir->i_count++;			while (1){				char *start = pt;				int len;				while (*pt != '\0' && *pt != '/') pt++;				len = (int)(pt - start);				if (*pt == '/') *pt++ = '\0';				if (dir->u.umsdos_i.i_emd_dir == 0){					/* This is a DOS directory */					ret = umsdos_rlookup_x(dir,start,len,result,1);				}else{					ret = umsdos_lookup_x(dir,start,len,result,1);				}				PRINTK (("h2n lookup :%s: -> %d ",start,ret));				if (ret == 0 && *pt != '\0'){					dir = *result;				}else{					break;				}			}		}else{			iput (hlink);		}		PRINTK (("hlink2inode ret = %d %p -> %p\n",ret,hlink,*result));		kfree (path);	}	return ret;}static struct file_operations umsdos_dir_operations = {	NULL,				/* lseek - default */	UMSDOS_dir_read,	/* read */	NULL,				/* write - bad */	UMSDOS_readdir,		/* readdir */	NULL,				/* select - default */	UMSDOS_ioctl_dir,	/* ioctl - default */	NULL,				/* mmap */	NULL,				/* no special open code */	NULL,				/* no special release code */	NULL				/* fsync */};struct inode_operations umsdos_dir_inode_operations = {	&umsdos_dir_operations,	/* default directory file-ops */	UMSDOS_create,		/* create */	UMSDOS_lookup,		/* lookup */	UMSDOS_link,		/* link */	UMSDOS_unlink,		/* unlink */	UMSDOS_symlink,		/* symlink */	UMSDOS_mkdir,		/* mkdir */	UMSDOS_rmdir,		/* rmdir */	UMSDOS_mknod,		/* mknod */	UMSDOS_rename,		/* rename */	NULL,			/* readlink */	NULL,			/* follow_link */	NULL,			/* readpage */	NULL,			/* writepage */	NULL,			/* bmap */	NULL,			/* truncate */	NULL			/* permission */};

⌨️ 快捷键说明

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