Bug 455259. Don't use access() to check if a file is writeable, since with at least some Linux kernels it will return OK for a file that will give 'text file busy' when written. Just try to open the file and take the rename/unlink path if we can't open it. r=bsmedberg
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 22 Sep 2008 14:09:53 +1200
changeset 19485 974c9bb54ffa6db49776651a3b836550bd001d5d
parent 19484 9b42a617a49523eb74f46060ce7d9b6b24648b33
child 19486 4e439bf89ec87c5e7fe3b32393d5c17722ffdf5c
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg
bugs455259
milestone1.9.1b1pre
Bug 455259. Don't use access() to check if a file is writeable, since with at least some Linux kernels it will return OK for a file that will give 'text file busy' when written. Just try to open the file and take the rename/unlink path if we can't open it. r=bsmedberg
config/nsinstall.c
--- a/config/nsinstall.c
+++ b/config/nsinstall.c
@@ -159,31 +159,40 @@ togid(char *group)
 	fail("cannot find gid for %s", group);
     return gid;
 }
 
 static void
 copyfile( char *name, char *toname, mode_t mode, char *group, char *owner,
           int dotimes, uid_t uid, gid_t gid )
 {
-  int fromfd, tofd, cc, wc, exists;
+  int fromfd, tofd = -1, cc, wc, exists;
   char buf[BUFSIZ], *bp;
   struct stat sb, tosb;
   struct utimbuf utb;
 
   exists = (lstat(toname, &tosb) == 0);
 
   fromfd = open(name, O_RDONLY);
   if (fromfd < 0 || fstat(fromfd, &sb) < 0)
     fail("cannot access %s", name);
-  if (exists && (!S_ISREG(tosb.st_mode) || access(toname, W_OK) < 0))
-    (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
-  tofd = open(toname, O_CREAT | O_WRONLY, 0666);
-  if (tofd < 0)
-    fail("cannot create %s", toname);
+  if (exists) {
+    if (S_ISREG(tosb.st_mode)) {
+      /* See if we can open it. This is more reliable than 'access'. */
+      tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+    }
+    if (tofd < 0) {
+      (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+    }
+  }
+  if (tofd < 0) {
+    tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+    if (tofd < 0)
+      fail("cannot create %s", toname);
+  }
 
   bp = buf;
   while ((cc = read(fromfd, bp, sizeof buf)) > 0)
   {
     while ((wc = write(tofd, bp, (unsigned int)cc)) > 0)
     {
       if ((cc -= wc) == 0)
         break;