Subject: Re: [NOT FIXED] Symbolic links & RCS -- READ IT!
From: "David O'Riva" <[email-masked]>
To: [email-masked]
Cc: Andre Oliveira da Costa <[email-masked]>, [email-masked]
Date: Mon, 15 Nov 1999 09:52:27 -0800

Well, shoot.

The patch I just put up has a problem - bad_nw_rename wasn't configuring
at all.  This revised patch takes care of that and is a bit clearer
about what the problem is (utime(UNWRITEABLEFILE,struct utime) fails).

Sigh...  This one actually passes all my tests, and should be everything
the previous one was supposed to be. ;-)

-- 
-dave        _________________________
------------/      David O'Riva       \--------------
408-        | Staff Software Engineer | oriva@
 473-9413   |    Atari Games, Inc.    |   agames.com
            \_________________________/

#  patches rcs-5.7 to work with cygwin b19/20/20.1
#  doesn't break the configure script for other systems
#  To apply: cd rcs-5.7 ; patch -p 1 -i rcs-5.7-cygwinb20.patchb

diff -rc rcs-5.7/src/conf.sh rcs-5.7-good/src/conf.sh
*** rcs-5.7/src/conf.sh	Mon Nov 15 07:17:49 1999
--- rcs-5.7-good/src/conf.sh	Mon Nov 15 08:49:40 1999
***************
*** 311,325 ****
  # We must do has_readlink next, because it might generate
  # #include directives that affect later definitions.
  
! $ech >&3 "$0: configuring has_readlink, readlink_isreg_errno $dots"
  cat >a.c <<EOF
  #include "$A_H"
  static char b[7];
  int
! main() {
  	if (readlink("a.sym2",b,7) == 6  &&  strcmp(b,"a.sym1") == 0  &&
  		readlink("a.c",b,7) == -1  &&  errno != ENOENT
  	) {
  		if (errno == EINVAL)
  			printf("EINVAL\n");
  		else
--- 311,338 ----
  # We must do has_readlink next, because it might generate
  # #include directives that affect later definitions.
  
! $ech >&3 "$0: configuring has_readlink, readlink_isreg_errno, bad_readlink_enoent $dots"
  cat >a.c <<EOF
  #include "$A_H"
  static char b[7];
  int
! main(argc, argv) int argc; char **argv; {
  	if (readlink("a.sym2",b,7) == 6  &&  strcmp(b,"a.sym1") == 0  &&
  		readlink("a.c",b,7) == -1  &&  errno != ENOENT
  	) {
+ 		/*
+ 		* test for readlink returning same errno for
+ 		* regular files and non-existent files
+ 		*/
+ 		if (1 < argc) {
+ 			int e=errno;
+ 			readlink("a.sym3",b,7);
+ 			if( errno==e )
+ 				printf( "1\n" );
+ 			else
+ 				printf( "0\n" );
+ 			exitmain(ferror(stdout) || fclose(stdout)!=0);
+ 		}
  		if (errno == EINVAL)
  			printf("EINVAL\n");
  		else
***************
*** 335,343 ****
  then h=1
  else h=0
  fi
! echo >&3 $h, $readlink_isreg_errno
  cat <<EOF
  #define has_readlink $h /* Does readlink() work?  */
  #define readlink_isreg_errno $readlink_isreg_errno /* errno after readlink on regular file */
  
  #if has_readlink && !defined(MAXSYMLINKS)
--- 348,361 ----
  then h=1
  else h=0
  fi
! case $h in
! 1) bh=`$aout t`;;
! *) bh=0;;
! esac
! echo >&3 $h, $readlink_isreg_errno, $bh
  cat <<EOF
  #define has_readlink $h /* Does readlink() work?  */
+ #define bad_readlink_enoent $bh /* Does readlink() return ENOENT correctly?  */
  #define readlink_isreg_errno $readlink_isreg_errno /* errno after readlink on regular file */
  
  #if has_readlink && !defined(MAXSYMLINKS)
***************
*** 1053,1059 ****
  		# when someone unexpectedly truncates a file
  		# while RCS has it mmapped.
  		rm -f a.e && cp a.c a.e &&
! 		mmap_signal=`$aout a.e <a.e` || exit
  	esac
  esac
  echo >&3 $has_map_fd, $has_mmap, $has_madvise, $mmap_signal
--- 1071,1077 ----
  		# when someone unexpectedly truncates a file
  		# while RCS has it mmapped.
  		rm -f a.e && cp a.c a.e &&
! 		mmap_signal=`$aout a.e <a.e` || mmap_signal=
  	esac
  esac
  echo >&3 $has_map_fd, $has_mmap, $has_madvise, $mmap_signal
***************
*** 1103,1108 ****
--- 1121,1151 ----
  echo "#define bad_a_rename $a /* Does rename(A,B) fail if A is unwritable?  */"
  echo "#define bad_b_rename $b /* Does rename(A,B) fail if B is unwritable?  */"
  echo "#define bad_NFS_rename 0 /* Can rename(A,B) falsely report success?  */"
+ 
+ $ech >&3 "$0: configuring bad_nw_utime $dots"
+ cat >a.c <<EOF
+ #include "$A_H"
+ int main() {
+ 	static struct utimbuf amtime; /* static so unused fields are zero */
+ 	static time_t t;
+ 	time(&t);
+ 	amtime.actime = t;
+ 	amtime.modtime = t;
+ 	exitmain(utime("a.a",&amtime) != 0); }
+ EOF
+ if $CL a.c $L >&2
+ then
+ 	rm -f a.a &&
+ 	echo a >a.a && chmod -w a.a || exit
+ 	if $aout
+ 	then a=0
+ 	else a=1
+ 	fi
+ 	rm -f a.a || exit
+ else a=0
+ fi
+ echo >&3 $a
+ echo "#define bad_nw_utime $a /* Does utime() work on unwriteable files?  */"
  
  $ech >&3 "$0: configuring void, VOID $dots"
  cat >a.c <<EOF
diff -rc rcs-5.7/src/rcsedit.c rcs-5.7-good/src/rcsedit.c
*** rcs-5.7/src/rcsedit.c	Mon Nov 15 07:17:49 1999
--- rcs-5.7-good/src/rcsedit.c	Mon Nov 15 07:51:40 1999
***************
*** 1279,1285 ****
  	bufautoend(&bigbuf);
  	errno = e;
  	switch (e) {
! 	    case readlink_isreg_errno: return 1;
  	    case ENOENT: return 0;
  	    default: return -1;
  	}
--- 1279,1300 ----
  	bufautoend(&bigbuf);
  	errno = e;
  	switch (e) {
! 	    case readlink_isreg_errno:
! #			if bad_readlink_enoent
! 			/*
! 			* Cygwin32 betas 19 & 20 report EINVAL if the
! 			* file doesn't exist, instead of ENOENT.
! 			* Make sure the file really does exist.
! 			*/
! 			{
! 		 		struct stat st;
!  				if ( stat(L->string, &st) == 0 )
! 					/* File exists, but no symlink */
! 					return 1;
! 			}
! #			else
! 				return 1;
! #			endif
  	    case ENOENT: return 0;
  	    default: return -1;
  	}
***************
*** 1595,1601 ****
  	    }
  #	endif
  
! #	if bad_a_rename
  		/*
  		* There's a short window of inconsistency
  		* during which the lock file is writable.
--- 1610,1617 ----
  	    }
  #	endif
  
! 	if ( bad_a_rename || (bad_nw_utime && mtime!=-1) )
! 	{
  		/*
  		* There's a short window of inconsistency
  		* during which the lock file is writable.
***************
*** 1603,1609 ****
  		mode_while_renaming = mode|S_IWUSR;
  		if (mode != mode_while_renaming)
  		    set_mode = 1;
! #	endif
  
  #	if has_fchmod
  	    if (0<set_mode  &&  fchmod(fileno(*fromp),mode_while_renaming) == 0)
--- 1619,1625 ----
  		mode_while_renaming = mode|S_IWUSR;
  		if (mode != mode_while_renaming)
  		    set_mode = 1;
! 	}
  
  #	if has_fchmod
  	    if (0<set_mode  &&  fchmod(fileno(*fromp),mode_while_renaming) == 0)
***************
*** 1616,1621 ****
--- 1632,1647 ----
  
  	if (setmtime(from, mtime) != 0)
  		return -1;
+ 
+ 	/*
+ 	* if rename unwriteable works but utime unwriteable doesn't, we can
+ 	* change the mode back now.  Otherwise wait until after rename.
+ 	*/
+ 	if ( !bad_a_rename && (bad_nw_utime && mtime!=-1) )
+ 	{
+ 	    if (0 < set_mode  &&  chmod(from, mode) != 0)
+ 		return -1;
+ 	}
  
  #	if !has_rename || bad_b_rename
  		/*
diff -rc rcs-5.7/src/rcslex.c rcs-5.7-good/src/rcslex.c
*** rcs-5.7/src/rcslex.c	Mon Nov 15 07:17:49 1999
--- rcs-5.7-good/src/rcslex.c	Fri Nov 12 11:56:47 1999
***************
*** 1113,1119 ****
  /* Open NAME for reading, yield its descriptor, and set *STATUS.  */
  {
  	int fd = fdSafer(open(name, O_RDONLY
! #		if OPEN_O_BINARY
  			|  (strchr(type,'b') ? OPEN_O_BINARY : 0)
  #		endif
  	));
--- 1113,1119 ----
  /* Open NAME for reading, yield its descriptor, and set *STATUS.  */
  {
  	int fd = fdSafer(open(name, O_RDONLY
! #		if OPEN_O_BINARY && !(large_memory && maps_memory)
  			|  (strchr(type,'b') ? OPEN_O_BINARY : 0)
  #		endif
  	));

--
Want to unsubscribe from this list?
Send a message to [email-masked]