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

📄 namei.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (atomic_read(&olddir->i_sem.count) < 1)			goto out_free;		down(&olddir->i_sem);	}	/*	 * Parse the name and get the visible directory entry.	 */	ret = umsdos_parse (olddentry->d_name.name, olddentry->d_name.len,				&old_info);	if (ret)		goto out_unlock;	ret = umsdos_findentry (olddentry->d_parent, &old_info, 1);	if (ret) {printk("UMSDOS_link: %s/%s not in EMD, ret=%d\n",olddentry->d_parent->d_name.name, olddentry->d_name.name, ret);		goto out_unlock;	}	/*	 * If the visible dentry is a pseudo-hardlink, the original	 * file must be already hidden.	 */	if (!(old_info.entry.flags & UMSDOS_HLINK)) {		int err;		/* create a hidden link name */		ret = umsdos_newhidden (olddentry->d_parent, &hid_info);		if (ret) {printk("umsdos_link: can't make hidden %s/%s, ret=%d\n",olddentry->d_parent->d_name.name, hid_info.entry.name, ret);			goto out_unlock;		}		/*		 * Make a dentry and rename the original file ...		 */		temp = umsdos_lookup_dentry(olddentry->d_parent,						hid_info.entry.name,						hid_info.entry.name_len, 0); 		ret = PTR_ERR(temp);		if (IS_ERR(temp)) {printk("umsdos_link: lookup %s/%s failed, ret=%d\n",dentry->d_parent->d_name.name, hid_info.entry.name, ret);			goto cleanup;		}		/* rename the link to the hidden location ... */		ret = umsdos_rename_f(olddir, olddentry, olddir, temp,					UMSDOS_HIDDEN);		d_move(olddentry, temp);		dput(temp);		if (ret) {printk("umsdos_link: rename to %s/%s failed, ret=%d\n",temp->d_parent->d_name.name, temp->d_name.name, ret);			goto cleanup;		}		/* mark the inode as a hardlink */		oldinode->u.umsdos_i.i_is_hlink = 1;		/*		 * Capture the path to the hidden link.		 */		path = umsdos_d_path(olddentry, (char *) buffer, PAGE_SIZE);Printk(("umsdos_link: hidden link path=%s\n", path));		/*		 * Recreate a dentry for the original name and symlink it,		 * then symlink the new dentry. Don't give up if one fails,		 * or we'll lose the file completely!		 *		 * Note: this counts as the "original" reference, so we 		 * don't increment i_nlink for this one.		 */ 		temp = umsdos_lookup_dentry(olddentry->d_parent,						old_info.entry.name,						old_info.entry.name_len, 0); 		ret = PTR_ERR(temp);		if (!IS_ERR(temp)) {			ret = umsdos_symlink_x (olddir, temp, path, 						S_IFREG | 0777, UMSDOS_HLINK);			dput(temp);		}		/* This symlink increments i_nlink (see below.) */		err = umsdos_symlink_x (dir, dentry, path,					S_IFREG | 0777, UMSDOS_HLINK);		/* fold the two errors */		if (!ret)			ret = err;		goto out_unlock;		/* creation failed ... remove the link entry */	cleanup:printk("umsdos_link: link failed, ret=%d, removing %s/%s\n",ret, olddentry->d_parent->d_name.name, hid_info.entry.name);		err = umsdos_delentry(olddentry->d_parent, &hid_info, 0);		goto out_unlock;	}Printk(("UMSDOS_link: %s/%s already hidden\n",olddentry->d_parent->d_name.name, olddentry->d_name.name));	/*	 * The original file is already hidden, and we need to get 	 * the dentry for its real name, not the visible name.	 * N.B. make sure it's the hidden inode ...	 */	if (!oldinode->u.umsdos_i.i_is_hlink)		printk("UMSDOS_link: %s/%s hidden, ino=%ld not hlink??\n",			olddentry->d_parent->d_name.name,			olddentry->d_name.name, oldinode->i_ino);	/*	 * In order to get the correct (real) inode, we just drop	 * the original dentry.	 */ 	d_drop(olddentry);Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n",olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname));	/* Do a real lookup to get the short name dentry */	temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname, 					old_info.fake.len);	ret = PTR_ERR(temp);	if (IS_ERR(temp))		goto out_unlock;	/* now resolve the link ... */	temp = umsdos_solve_hlink(temp);	ret = PTR_ERR(temp);	if (IS_ERR(temp))		goto out_unlock;	path = umsdos_d_path(temp, (char *) buffer, PAGE_SIZE);	dput(temp);Printk(("umsdos_link: %s/%s already hidden, path=%s\n",olddentry->d_parent->d_name.name, olddentry->d_name.name, path));	/* finally we can symlink it ... */	ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777,UMSDOS_HLINK);out_unlock:	/* remain locked for the call to notify_change ... */	if (ret == 0) {		struct iattr newattrs;		/* Do a real lookup to get the short name dentry */		temp = umsdos_covered(olddentry->d_parent,					old_info.fake.fname,					old_info.fake.len);		ret = PTR_ERR(temp);		if (IS_ERR(temp))			goto out_unlock2;		/* now resolve the link ... */		temp = umsdos_solve_hlink(temp);		ret = PTR_ERR(temp);		if (IS_ERR(temp))			goto out_unlock2;#ifdef UMSDOS_PARANOIAif (!oldinode->u.umsdos_i.i_is_hlink)printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n",olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino);#endif		temp->d_inode->i_nlink++;Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n",olddentry->d_parent->d_name.name, olddentry->d_name.name,oldinode->i_ino, oldinode->i_nlink));		newattrs.ia_valid = 0;		ret = umsdos_notify_change_locked(temp, &newattrs); 		if (ret == 0)			mark_inode_dirty(temp->d_inode);		dput(temp);out_unlock2:			if (ret == 0)			mark_inode_dirty(olddentry->d_inode);	}	if (olddir != dir)		up(&olddir->i_sem);out_free:	free_page(buffer);out:	Printk (("umsdos_link %d\n", ret));	return ret;}/* * Add a sub-directory in a directory *//* #Specification: mkdir / Directory already exist in DOS * We do the same thing as for file creation. * For all user it is an error. *//* #Specification: mkdir / umsdos directory / create EMD * When we created a new sub-directory in a UMSDOS * directory (one with full UMSDOS semantics), we * create immediately an EMD file in the new * sub-directory so it inherits UMSDOS semantics. */int UMSDOS_mkdir (struct inode *dir, struct dentry *dentry, int mode){	struct dentry *temp;	struct inode *inode;	int ret, err;	struct umsdos_info info;	ret = umsdos_nevercreat (dir, dentry, -EEXIST);	if (ret)		goto out;	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);	if (ret)		goto out;	info.entry.mode = mode | S_IFDIR;	info.entry.rdev = 0;	info.entry.uid = current->fsuid;	info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;	info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME;	info.entry.flags = 0;	info.entry.nlink = 1;	ret = umsdos_newentry (dentry->d_parent, &info);	if (ret)		goto out;	/* lookup the short name dentry */	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);	ret = PTR_ERR(temp);	if (IS_ERR(temp))		goto out_remove;	/* Make sure the short name doesn't exist */	ret = -EEXIST;	if (temp->d_inode) {printk("umsdos_mkdir: short name %s/%s exists\n",dentry->d_parent->d_name.name, info.fake.fname);		goto out_remove_dput;	}	ret = msdos_mkdir (dir, temp, mode);	if (ret)		goto out_remove_dput;	/*	 * Lock the inode to protect the EMD creation ...	 */	inode = temp->d_inode;	down(&inode->i_sem);	atomic_inc(&inode->i_count);	d_instantiate(dentry, inode);	/* N.B. this should have an option to create the EMD ... */	umsdos_lookup_patch_new(dentry, &info);	/* 	 * Create the EMD file, and set up the dir so it is	 * promoted to EMD with the EMD file invisible.	 *	 * N.B. error return if EMD fails?	 */	err = umsdos_make_emd(dentry);	umsdos_setup_dir(dentry);	up(&inode->i_sem);	dput(temp);out:	Printk(("umsdos_mkdir: %s/%s, ret=%d\n",		dentry->d_parent->d_name.name, dentry->d_name.name, ret));	return ret;	/* an error occurred ... remove EMD entry. */out_remove_dput:	dput(temp);out_remove:	umsdos_delentry (dentry->d_parent, &info, 1);	goto out;}/* * Add a new device special file into a directory. * * #Specification: Special files / strategy * Device special file, pipes, etc ... are created like normal * file in the msdos file system. Of course they remain empty. *  * One strategy was to create those files only in the EMD file * since they were not important for MSDOS. The problem with * that, is that there were not getting inode number allocated. * The MSDOS filesystems is playing a nice game to fake inode * number, so why not use it. *  * The absence of inode number compatible with those allocated * for ordinary files was causing major trouble with hard link * in particular and other parts of the kernel I guess. */int UMSDOS_mknod (struct inode *dir, struct dentry *dentry,		 int mode, int rdev){	return umsdos_create_any (dir, dentry, mode, rdev, 0);}/* * Remove a sub-directory. */int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry){	struct dentry *temp;	int ret, err, empty;	struct umsdos_info info;	ret = umsdos_nevercreat (dir, dentry, -EPERM);	if (ret)		goto out;	ret = -EBUSY;	if (!d_unhashed(dentry))		goto out;	/* check whether the EMD is empty */	ret = -ENOTEMPTY;	empty = umsdos_isempty (dentry);	/* Have to remove the EMD file? */	if (empty == 1) {		struct dentry *demd;		demd = umsdos_get_emd_dentry(dentry);		if (!IS_ERR(demd)) {			err = -ENOENT;			if (demd->d_inode)				err = msdos_unlink (dentry->d_inode, demd);Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err));#ifdef UMSDOS_PARANOIAif (err)printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n",demd->d_parent->d_name.name, demd->d_name.name, err);#endif			if (!err) {				d_delete(demd);				ret = 0;			}			dput(demd);		}	} else if (empty == 2)		ret = 0;	if (ret)		goto out;	umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);	/* Call findentry to complete the mangling */	umsdos_findentry (dentry->d_parent, &info, 2);	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);	ret = PTR_ERR(temp);	if (IS_ERR(temp))		goto out;	/*	 * Attempt to remove the msdos name.	 */	ret = msdos_rmdir (dir, temp);	if (ret && ret != -ENOENT)		goto out_dput;	d_delete(temp);	/* OK so far ... remove the name from the EMD */	ret = umsdos_delentry (dentry->d_parent, &info, 1);#ifdef UMSDOS_PARANOIAif (ret)printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret);#endif	/* dput() temp if we didn't do it above */out_dput:	dput(temp);out:	Printk (("umsdos_rmdir %d\n", ret));	return ret;}/* * Remove a file from the directory. * * #Specification: hard link / deleting a link * When we delete a file and this file is a link, * we must subtract 1 from the nlink field of the * hidden link. *  * If the count goes to 0, we delete this hidden * link too. */int UMSDOS_unlink (struct inode *dir, struct dentry *dentry){	struct dentry *temp, *link = NULL;	struct inode *inode;	int ret;	struct umsdos_info info;Printk(("UMSDOS_unlink: entering %s/%s\n",dentry->d_parent->d_name.name, dentry->d_name.name));	ret = umsdos_nevercreat (dir, dentry, -EPERM);	if (ret)		goto out;	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);	if (ret)		goto out;	umsdos_lockcreate (dir);	ret = umsdos_findentry (dentry->d_parent, &info, 1);	if (ret) {printk("UMSDOS_unlink: %s/%s not in EMD, ret=%d\n",dentry->d_parent->d_name.name, dentry->d_name.name, ret);		goto out_unlock;	}Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname));	/*	 * Note! If this is a hardlink and the names are aliased,	 * the short-name lookup will return the hardlink dentry.	 * In order to get the correct (real) inode, we just drop	 * the original dentry.	 */ 	if (info.entry.flags & UMSDOS_HLINK) {		d_drop(dentry);	}	/* Do a real lookup to get the short name dentry */	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);	ret = PTR_ERR(temp);	if (IS_ERR(temp))		goto out_unlock;	/*	 * Resolve hardlinks now, but defer processing until later.	 */	if (info.entry.flags & UMSDOS_HLINK) {		link = umsdos_solve_hlink(dget(temp));	}	/* Delete the EMD entry */	ret = umsdos_delentry (dentry->d_parent, &info, 0);	if (ret && ret != -ENOENT) {		printk(KERN_WARNING "UMSDOS_unlink: delentry %s, error=%d\n",			info.entry.name, ret);		goto out_dput;	}	ret = msdos_unlink(dir, temp);	if (!ret)		d_delete(temp);#ifdef UMSDOS_PARANOIAif (ret)printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n",temp->d_parent->d_name.name, temp->d_name.name, ret);#endif	/* dput() temp if we didn't do it above */out_dput:	dput(temp);out_unlock:	umsdos_unlockcreate (dir);	/*	 * Now check for deferred handling of a hardlink.	 */	if (!link)		goto out;	if (IS_ERR(link)) {printk("umsdos_unlink: failed to resolve %s/%s\n",dentry->d_parent->d_name.name, dentry->d_name.name);		if (!ret)			ret = PTR_ERR(link);		goto out;	}Printk(("umsdos_unlink: link %s/%s deferred, pending ret=%d\n",link->d_parent->d_name.name, link->d_name.name, ret));	/* already have an error? */	if (ret)		goto out_cleanup;	/* make sure the link exists ... */	inode = link->d_inode;	if (!inode) {		printk(KERN_WARNING "umsdos_unlink: hard link not found\n");		goto out_cleanup;	}	/*	 * If this was the last linked reference, delete it now.	 *	 * N.B. Deadlock problem? We should be holding the lock	 * for the hardlink's parent, but another process might	 * be holding that lock waiting for us to finish ...	 */	if (inode->i_nlink <= 1) {		ret = UMSDOS_unlink (link->d_parent->d_inode, link);		if (ret) {			printk(KERN_WARNING				"umsdos_unlink: link removal failed, ret=%d\n",				 ret);		} else			d_delete(link);	} else {		struct iattr newattrs;		inode->i_nlink--;		newattrs.ia_valid = 0;		ret = umsdos_notify_change_locked(link, &newattrs);		if (!ret)			mark_inode_dirty(link->d_inode);	}out_cleanup:	d_drop(link);	dput(link);out:	Printk (("umsdos_unlink %d\n", ret));	return ret;}/* * Rename (move) a file. */int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry,		   struct inode *new_dir, struct dentry *new_dentry){	int ret;	ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST);	if (ret)		return ret;		/*		 * If the target already exists, delete it first.		 */	if (new_dentry->d_inode) {		dget(new_dentry);		if (S_ISDIR(old_dentry->d_inode->i_mode))			ret = UMSDOS_rmdir (new_dir, new_dentry);		else			ret = UMSDOS_unlink (new_dir, new_dentry);		if (!ret)			d_drop(new_dentry);		dput(new_dentry);		if (ret)			return ret;	}	ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0);	return ret;}

⌨️ 快捷键说明

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