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

📄 dir.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Return != 0 if an entry is the pseudo DOS entry in the pseudo root. */int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry){	/* #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	    && dentry->d_name.len == 3	    && dentry->d_name.name[0] == 'D'	    && dentry->d_name.name[1] == 'O'	    && dentry->d_name.name[2] == 'S';}/* * Check whether a file exists in the current directory. * Return 0 if OK, negative error code if not (ex: -ENOENT). * * fills dentry->d_inode with found inode, and increments its count. * if not found, return -ENOENT. *//* #Specification: umsdos / lookup * A lookup for a file is done in two steps.  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 dentry *umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo){					struct dentry *dret = NULL;	struct inode *inode;	int ret = -ENOENT;	struct umsdos_info info;#ifdef UMSDOS_DEBUG_VERBOSEprintk("umsdos_lookup_x: looking for %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name);#endif	umsdos_startlookup (dir);	if (umsdos_is_pseudodos (dir, dentry)) {		/* #Specification: pseudo root / lookup(DOS)		 * A lookup of DOS in the pseudo root will always succeed		 * and return the inode of the real root.		 */		Printk ((KERN_DEBUG "umsdos_lookup_x: following /DOS\n"));		inode = saved_root->d_inode;		goto out_add;	}	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);	if (ret) {printk("umsdos_lookup_x: %s/%s parse failed, ret=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, ret);		goto out;	}	ret = umsdos_findentry (dentry->d_parent, &info, 0);	if (ret) {if (ret != -ENOENT)printk("umsdos_lookup_x: %s/%s findentry failed, ret=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, ret);		goto out;	}Printk (("lookup %.*s pos %lu ret %d len %d ", info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len));	/* do a real lookup to get the short name ... */	dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);	ret = PTR_ERR(dret);	if (IS_ERR(dret)) {printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n", dentry->d_parent->d_name.name, dentry->d_name.name, ret);		goto out;	}	inode = dret->d_inode;	if (!inode)		goto out_remove;	umsdos_lookup_patch_new(dret, &info);#ifdef UMSDOS_DEBUG_VERBOSEprintk("umsdos_lookup_x: found %s/%s, ino=%ld\n", dret->d_parent->d_name.name, dret->d_name.name, dret->d_inode->i_ino);#endif	/* Check for a hard link */	if ((info.entry.flags & UMSDOS_HLINK) &&	    !inode->u.umsdos_i.i_is_hlink) {		dret = umsdos_solve_hlink (dret);		ret = PTR_ERR(dret);		if (IS_ERR(dret))			goto out;		ret = -ENOENT;		inode = dret->d_inode;		if (!inode) {printk("umsdos_lookup_x: %s/%s negative after link\n", dret->d_parent->d_name.name, dret->d_name.name);			goto out_dput;		}	}	if (inode == 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 links		 * which are recorded independently of the pseudo-root		 * mode.		 */printk("umsdos_lookup_x: skipping DOS/linux\n");		ret = -ENOENT;		goto out_dput;	}	/*	 * We've found it OK.  Now hash the dentry with the inode.	 */out_add:	atomic_inc(&inode->i_count);	d_add (dentry, inode);	dentry->d_op = &umsdos_dentry_operations;	ret = 0;out_dput:	if (dret && dret != dentry)		d_drop(dret);	dput(dret);out:	umsdos_endlookup (dir);	return ERR_PTR(ret);out_remove:	printk(KERN_WARNING "UMSDOS:  entry %s/%s out of sync, erased\n",		dentry->d_parent->d_name.name, dentry->d_name.name);	umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode));	ret = -ENOENT;	goto out_dput;}/* * Check whether a file exists in the current directory. * Return 0 if OK, negative error code if not (ex: -ENOENT). *  * Called by VFS; should fill dentry->d_inode via d_add. */struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry){	struct dentry *ret;	ret = umsdos_lookup_x (dir, dentry, 0);	/* Create negative dentry if not found. */	if (ret == ERR_PTR(-ENOENT)) {		Printk ((KERN_DEBUG 			"UMSDOS_lookup: converting -ENOENT to negative\n"));		d_add (dentry, NULL);		dentry->d_op = &umsdos_dentry_operations;		ret = NULL;	}	return ret;}struct dentry *umsdos_covered(struct dentry *parent, char *name, int len){	struct dentry *result, *dentry;	struct qstr qstr;	qstr.name = name;	qstr.len  = len;	qstr.hash = full_name_hash(name, len);	result = ERR_PTR(-ENOMEM);	dentry = d_alloc(parent, &qstr);	if (dentry) {		/* XXXXXXXXXXXXXXXXXXX Race alert! */		result = UMSDOS_rlookup(parent->d_inode, dentry);		d_drop(dentry);		if (result)			goto out_fail;		return dentry;	}out:	return result;out_fail:	dput(dentry);	goto out;}/* * Lookup or create a dentry from within the filesystem. * * We need to use this instead of lookup_dentry, as the  * directory semaphore lock is already held. */struct dentry *umsdos_lookup_dentry(struct dentry *parent, char *name, int len,					int real){	struct dentry *result, *dentry;	struct qstr qstr;	qstr.name = name;	qstr.len  = len;	qstr.hash = full_name_hash(name, len);	result = d_lookup(parent, &qstr);	if (!result) {		result = ERR_PTR(-ENOMEM);		dentry = d_alloc(parent, &qstr);		if (dentry) {			result = real ?				UMSDOS_rlookup(parent->d_inode, dentry) :				UMSDOS_lookup(parent->d_inode, dentry);			if (result)				goto out_fail;			return dentry;		}	}out:	return result;out_fail:	dput(dentry);	goto out;}/* * Return a path relative to our root. */char * umsdos_d_path(struct dentry *dentry, char * buffer, int len){	struct dentry * old_root;	char * path;	read_lock(&current->fs->lock);	old_root = dget(current->fs->root);	read_unlock(&current->fs->lock);	spin_lock(&dcache_lock);	path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */	spin_unlock(&dcache_lock);	if (*path == '/')		path++; /* skip leading '/' */	if (current->fs->root->d_inode == pseudo_root)	{		*(path-1) = '/';		path -= (UMSDOS_PSDROOT_LEN+1);		memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN);	}	dput(old_root);	return path;}/* * Return the dentry which points to a pseudo-hardlink. * * it should try to find file it points to * if file is found, return new dentry/inode * The resolved inode will have i_is_hlink set. * * Note: the original dentry is always dput(), even if an error occurs. */struct dentry *umsdos_solve_hlink (struct dentry *hlink){	/* root is our root for resolving pseudo-hardlink */	struct dentry *base = hlink->d_sb->s_root;	struct dentry *dentry_dst;	char *path, *pt;	int len;	struct address_space *mapping = hlink->d_inode->i_mapping;	struct page *page;	page=read_cache_page(mapping,0,(filler_t *)mapping->a_ops->readpage,NULL);	dentry_dst=(struct dentry *)page;	if (IS_ERR(page))		goto out;	wait_on_page(page);	if (!Page_Uptodate(page))		goto async_fail;	dentry_dst = ERR_PTR(-ENOMEM);	path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);	if (path == NULL)		goto out_release;	memcpy(path, kmap(page), hlink->d_inode->i_size);	kunmap(page);	page_cache_release(page);	len = hlink->d_inode->i_size;	/* start at root dentry */	dentry_dst = dget(base);	path[len] = '\0';		pt = path;	if (*path == '/')		pt++; /* skip leading '/' */		if (base->d_inode == pseudo_root)		pt += (UMSDOS_PSDROOT_LEN + 1);		while (1) {		struct dentry *dir = dentry_dst, *demd;		char *start = pt;		int real;		while (*pt != '\0' && *pt != '/') pt++;		len = (int) (pt - start);		if (*pt == '/') *pt++ = '\0';		real = 1;		demd = umsdos_get_emd_dentry(dir);		if (!IS_ERR(demd)) {			if (demd->d_inode)				real = 0;			dput(demd);		}#ifdef UMSDOS_DEBUG_VERBOSEprintk ("umsdos_solve_hlink: dir %s/%s, name=%s, real=%d\n",dir->d_parent->d_name.name, dir->d_name.name, start, real);#endif		dentry_dst = umsdos_lookup_dentry(dir, start, len, real);/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */		if (real)			d_drop(dir);		dput (dir);		if (IS_ERR(dentry_dst))			break;		/* not found? stop search ... */		if (!dentry_dst->d_inode) {			break;		}		if (*pt == '\0')	/* we're finished! */			break;	} /* end while */	if (!IS_ERR(dentry_dst)) {		struct inode *inode = dentry_dst->d_inode;		if (inode) {			inode->u.umsdos_i.i_is_hlink = 1;#ifdef UMSDOS_DEBUG_VERBOSEprintk ("umsdos_solve_hlink: resolved link %s/%s, ino=%ld\n",dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name, inode->i_ino);#endif		} else {#ifdef UMSDOS_DEBUG_VERBOSEprintk ("umsdos_solve_hlink: resolved link %s/%s negative!\n",dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name);#endif		}	} else		printk(KERN_WARNING			"umsdos_solve_hlink: err=%ld\n", PTR_ERR(dentry_dst));	kfree (path);out:	dput(hlink);	/* original hlink no longer needed */	return dentry_dst;async_fail:	dentry_dst = ERR_PTR(-EIO);out_release:	page_cache_release(page);	goto out;}	struct file_operations umsdos_dir_operations ={	read:		generic_read_dir,	readdir:	UMSDOS_readdir,	ioctl:		UMSDOS_ioctl_dir,};struct inode_operations umsdos_dir_inode_operations ={	create:		UMSDOS_create,	lookup:		UMSDOS_lookup,	link:		UMSDOS_link,	unlink:		UMSDOS_unlink,	symlink:	UMSDOS_symlink,	mkdir:		UMSDOS_mkdir,	rmdir:		UMSDOS_rmdir,	mknod:		UMSDOS_mknod,	rename:		UMSDOS_rename,	setattr:	UMSDOS_notify_change,};

⌨️ 快捷键说明

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