diff options
Diffstat (limited to 'libdiskfs/dir-rename.c')
-rw-r--r-- | libdiskfs/dir-rename.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/libdiskfs/dir-rename.c b/libdiskfs/dir-rename.c index 7e993def..867e395d 100644 --- a/libdiskfs/dir-rename.c +++ b/libdiskfs/dir-rename.c @@ -1,5 +1,7 @@ /* libdiskfs implementation of fs.defs: dir_rename - Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation + + Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 2007 + Free Software Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -17,6 +19,7 @@ #include "priv.h" #include "fs_S.h" +#include <string.h> /* To avoid races in checkpath, and to prevent a directory from being simultaneously renamed by two processes, we serialize all renames of @@ -39,7 +42,15 @@ diskfs_S_dir_rename (struct protid *fromcred, return EOPNOTSUPP; /* Verify that tocred really is a port to us. */ - if (!tocred) + if (! tocred) + return EXDEV; + + if (!strcmp (fromname, ".") || !strcmp (fromname, "..") + || !strcmp (toname, ".") || !strcmp (toname, "..")) + return EINVAL; + + if (tocred->po->shadow_root != fromcred->po->shadow_root) + /* Same translator, but in different shadow trees. */ return EXDEV; if (diskfs_check_readonly ()) @@ -55,6 +66,8 @@ diskfs_S_dir_rename (struct protid *fromcred, mutex_lock (&fdp->lock); err = diskfs_lookup (fdp, fromname, LOOKUP, &fnp, 0, fromcred); mutex_unlock (&fdp->lock); + if (err == EAGAIN) + err = EINVAL; if (err) return err; @@ -100,7 +113,9 @@ diskfs_S_dir_rename (struct protid *fromcred, mutex_lock (&tdp->lock); err = diskfs_lookup (tdp, toname, RENAME, &tnp, ds, tocred); - if (!err && excl) + if (err == EAGAIN) + err = EINVAL; + else if (!err && excl) { err = EEXIST; diskfs_nput (tnp); @@ -130,6 +145,7 @@ diskfs_S_dir_rename (struct protid *fromcred, { diskfs_drop_dirstat (tdp, ds); diskfs_nrele (fnp); + diskfs_nput (tnp); mutex_unlock (&tdp->lock); return EISDIR; } @@ -141,6 +157,8 @@ diskfs_S_dir_rename (struct protid *fromcred, { diskfs_drop_dirstat (tdp, ds); diskfs_nput (fnp); + if (tnp) + diskfs_nput (tnp); mutex_unlock (&tdp->lock); return EMLINK; } |