Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT sourceware DOT cygnus DOT com Delivered-To: mailing list cygwin-developers AT sourceware DOT cygnus DOT com Message-ID: <00F8D6E8AB0DD3118F1A006008186C9607C7EC@server1.axonet.com.au> From: Andrew Dalgleish To: cygwin-developers AT sourceware DOT cygnus DOT com Subject: symlink() bug + patch Date: Fri, 17 Dec 1999 19:03:12 +1100 X-Priority: 3 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.0.1458.49) Content-Type: text/plain There is a bug in symlink() if "path2" (SUSV2 docs) already exists. If path2 is already a symlink, then the target of that symlink is replaced instead of path2. "ln -s" is not affected by this bug. I first noticed this when I screwed up my gcc specs file and re-extracted Mumit's tar file. The symlink "libstdc++.a" contains a few "../", so tar created a file several directories up the tree. A simpler example is this: bash.exe-2.02$ touch foo bash.exe-2.02$ ln -s foo bar bash.exe-2.02$ tar czf hum foo bar bash.exe-2.02$ ls -l total 2 lrw-r--r-- 1 andrewd Domain U 14 Dec 17 18:15 bar -> foo -rw-r--r-- 1 andrewd Domain U 0 Dec 17 18:15 foo -rw-r--r-- 1 andrewd Domain U 158 Dec 17 18:15 hum bash.exe-2.02$ tar xzf hum bash.exe-2.02$ ls -l total 3 lrw-r--r-- 1 andrewd Domain U 14 Dec 17 18:15 bar -> foo lrw-r--r-- 1 andrewd Domain U 14 Dec 17 18:15 foo -> foo -rw-r--r-- 1 andrewd Domain U 158 Dec 17 18:15 hum bash.exe-2.02$ Currently symlink() sets errno to EBADRQC or ELOOP (eg foo -> foo). Here is a patch to make symlink() behave correctly. (ie return -1 and set errno to EEXIST) This patch is relative to cygwin-src-19991215.tar.gz Regards, Andrew Dalgleish --- winsup/path.cc.orig Sun Dec 12 03:14:38 1999 +++ winsup/path.cc Fri Dec 17 17:50:04 1999 @@ -1999,7 +1999,7 @@ goto done; } - fd = _open (frompath, O_WRONLY | O_CREAT | O_BINARY, 0); + fd = _open (frompath, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0); if (fd >= 0) { char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];