>Submitter-Id:   net
>Originator:     [EMAIL PROTECTED]
>Organization:  MasterLink, INC
net
>Confidential:  no 
>Synopsis:      CVS hoses self in unexpected sticky directory
>Severity:      serious
>Priority:      medium
>Category:      cvs
>Class:         change-request
>Release:       cvs-1.10
>Environment:
                linux, should happen on all flavors/hw architectures
System: Linux monster 2.2.13 #19 SMP Thu May 18 21:00:09 EDT 2000 i686 unknown
Architecture: i686

>Description:
        If a cvs directory is sticky, and commits fail because of it, then
        there will be a temporary file left that will prevent future commits
        of that file.
>How-To-Repeat:
        1)  Create a repository/project
        2)      Make the repository world readable/writable, and set the sticky bit
        3)      add some files as the owner of the directory
        4)  do a checkout as somebody else
        5)  change a file in the checked out copy
        6)  commit
        // This will fail, because in a sticky directory, user 1 is not allowed
        // to delete files owned by user 2, unless user 1 is the owner of the
        // directory
        7)  change the same file in a copy checked out as the owner
        8) commit
        // This will fail, because the first failure left a lockfile behind
>Fix:
        // Here is a patch that will correct the problem:


diff -r -u cvs-1.10/src/cvs.h cvs-1.10.hacked/src/cvs.h
--- cvs-1.10/src/cvs.h  Sun Jul 26 22:54:11 1998
+++ cvs-1.10.hacked/src/cvs.h   Wed Jun 28 06:10:32 2000
@@ -532,6 +532,7 @@
 void make_directory PROTO((const char *name));
 extern int mkdir_if_needed PROTO ((char *name));
 void rename_file PROTO((const char *from, const char *to));
+void rename_or_delete_file PROTO((const char *from, const char *to));
 /* Expand wildcards in each element of (ARGC,ARGV).  This is according to the
    files which exist in the current directory, and accordingly to OS-specific
    conventions regarding wildcard syntax.  It might be desirable to change the
diff -r -u cvs-1.10/src/filesubr.c cvs-1.10.hacked/src/filesubr.c
--- cvs-1.10/src/filesubr.c     Mon May 11 14:19:25 1998
+++ cvs-1.10.hacked/src/filesubr.c      Wed Jun 28 06:16:35 2000
@@ -414,6 +414,34 @@
        error (1, errno, "cannot rename file %s to %s", from, to);
 }
 
+/* 
+ * This is the same as rename file, but it deltes the file it is trying
+ * to rename on failure.  Since rename_file above exits on failure, there
+ * isn't any place above to catch the exception and delete the (now stale)
+ * lockfile
+ */
+void
+rename_or_delete_file (from, to)
+    const char *from;
+    const char *to;
+{
+    if (trace)
+#ifdef SERVER_SUPPORT
+       (void) fprintf (stderr, "%c-> rename(%s,%s)\n",
+                       (server_active) ? 'S' : ' ', from, to);
+#else
+       (void) fprintf (stderr, "-> rename(%s,%s)\n", from, to);
+#endif
+    if (noexec)
+       return;
+
+    if (rename (from, to) < 0) {
+               int save_errno = errno;
+               unlink(from);
+               error (1, save_errno, "cannot rename file %s to %s", from, to);
+       };
+}
+
 /*
  * unlink a file, if possible.
  */
diff -r -u cvs-1.10/src/rcs.c cvs-1.10.hacked/src/rcs.c
--- cvs-1.10/src/rcs.c  Thu Aug  6 20:38:26 1998
+++ cvs-1.10.hacked/src/rcs.c   Wed Jun 28 06:10:05 2000
@@ -8416,7 +8416,7 @@
     if (fclose (fp) == EOF)
        error (1, errno, "error closing lock file %s", lockfile);
 
-    rename_file (lockfile, rcsfile);
+    rename_or_delete_file (lockfile, rcsfile);
     free (lockfile);
 }
 

Reply via email to