aboutsummaryrefslogtreecommitdiff
path: root/libdiskfs/dir-rename.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdiskfs/dir-rename.c')
-rw-r--r--libdiskfs/dir-rename.c24
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;
}