Пример #1
0
/* #Specification: pseudo root / rmdir /DOS
 * The pseudo sub-directory /DOS can't be removed!
 * This is done even if the pseudo root is not a Umsdos
 * directory anymore (very unlikely), but an accident (under
 * MS-DOS) is always possible.
 * 
 * EPERM is returned.
 */
static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
{
	int ret, empty;

	ret = -EPERM;
	if (umsdos_is_pseudodos (dir, dentry))
		goto out;

	ret = -EBUSY;
	if (!d_unhashed(dentry))
		goto out;

	ret = msdos_rmdir (dir, dentry);
	if (ret != -ENOTEMPTY)
		goto out;

	empty = umsdos_isempty (dentry);
	if (empty == 1) {
		struct dentry *demd;
		/* We have to remove the EMD file. */
		demd = umsdos_get_emd_dentry(dentry);
		ret = PTR_ERR(demd);
		if (!IS_ERR(demd)) {
			ret = 0;
			if (demd->d_inode)
				ret = msdos_unlink (dentry->d_inode, demd);
			if (!ret)
				d_delete(demd);
			dput(demd);
		}
	}
	if (ret)
		goto out;

	/* now retry the original ... */
	ret = msdos_rmdir (dir, dentry);

out:
	return ret;
}
Пример #2
0
static int UMSDOS_rrmdir (
	struct inode *dir,
	const char *name,
	int len)
{
	/* #Specification: dual mode / rmdir in a DOS directory
		In a DOS (not EMD in it) directory, we use a reverse strategy
		compared with an Umsdos directory. We assume that a subdirectory
		of a DOS directory is also a DOS directory. This is not always
		true (umssync may be used anywhere), but make sense.

		So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
		then we check if it is a Umsdos directory. We check if it is
		really empty (only . .. and --linux-.--- in it). If it is true
		we remove the EMD and do a msdos_rmdir() again.

		In a Umsdos directory, we assume all subdirectory are also
		Umsdos directory, so we check the EMD file first.
	*/
	int ret;
	if (umsdos_is_pseudodos(dir,name,len)){
		/* #Specification: pseudo root / rmdir /DOS
			The pseudo sub-directory /DOS can't be removed!
			This is done even if the pseudo root is not a Umsdos
			directory anymore (very unlikely), but an accident (under
			MsDOS) is always possible.

			EPERM is returned.
		*/
		ret = -EPERM;
	}else{
		umsdos_lockcreate (dir);
		dir->i_count++;
		ret = msdos_rmdir (dir,name,len);
		if (ret == -ENOTEMPTY){
			struct inode *sdir;
			dir->i_count++;
			ret = UMSDOS_rlookup (dir,name,len,&sdir);
			PRINTK (("rrmdir lookup %d ",ret));
			if (ret == 0){
				int empty;
				if ((empty = umsdos_isempty (sdir)) != 0){
					PRINTK (("isempty %d i_count %d ",empty,sdir->i_count));
					if (empty == 2){
						/*
							Not a Umsdos directory, so the previous msdos_rmdir
							was not lying :-)
						*/
						ret = -ENOTEMPTY;
					}else if (empty == 1){
						/* We have to removed the EMD file */
						ret = msdos_unlink(sdir,UMSDOS_EMD_FILE
							,UMSDOS_EMD_NAMELEN);
						sdir = NULL;
						if (ret == 0){
							dir->i_count++;
							ret = msdos_rmdir (dir,name,len);
						}
					}
				}else{
					ret = -ENOTEMPTY;
				}
				iput (sdir);
			}
		}
		umsdos_unlockcreate (dir);
	}
	iput (dir);
	return ret;
}
Пример #3
0
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_VERBOSE
printk("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_VERBOSE
printk("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;
}