Message-ID: <3E286C07.7040200@mif.vu.lt> Date: Fri, 17 Jan 2003 21:48:07 +0100 From: Laurynas Biveinis Organization: VU MIF User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2.1) Gecko/20021130 X-Accept-Language: lt, en, en-us MIME-Version: 1.0 To: DJGPP Workers , Richard Dawe Subject: Take on __solve_symlinks() Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 17 Jan 2003 19:46:13.0709 (UTC) FILETIME=[179D5FD0:01C2BE61] Reply-To: djgpp-workers AT delorie DOT com Well, maybe I'm on drugs, but I was unable to find good testcases for debugging it. It passes with flying colours every single test I made, except for this case: symlink("c:/autoexec.bat", "/link"); test_success("/link", "c:/autoexec.bat"); I.e. it didn't resolve /link properly. But I failed to create any more failing tests, including situations described by you. Maybe you could give me the testcase a patch to tests/libc/compat/unistd/xsymlink.c or precisely describe particular directory and file layout for uncovering the bugs? Below are the new testcases from testsuite I've used, and the patch I'm commiting in a second to fix /link case. The fix is trivial. symlink("c:/autoexec.bat", "/link"); test_success("c:/link", "c:/autoexec.bat"); test_success("/link", "c:/autoexec.bat"); test_success("c://link", "c:/autoexec.bat"); test_success("//link", "c:/autoexec.bat"); test_success("c:/./link", "c:/autoexec.bat"); test_success("/../link", "c:/autoexec.bat"); test_success("c:/../link", "c:/autoexec.bat"); test_success("/../../link", "c:/autoexec.bat"); test_success("c:/../../link", "c:/autoexec.bat"); /* FIXME below, but note that you're insane to run this test really that deep :) */ test_success("c:../../../../../../../../../../../../../../../link", "c:/autoexec.bat"); mkdir("c:/tdir", S_IWUSR); symlink("c:/config.sys", "c:/tdir/link"); test_success("c:/tdir/link", "c:/config.sys"); test_success("/tdir/link", "c:/config.sys"); test_success("c:/tdir/../.././tdir/link", "c:/config.sys"); test_success("/tdir/..//../.././../../tdir/link", "c:/config.sys"); /* FIXME below, but note that you're insane to run this test really that deep :) */ test_success("c:../../../../../../../../../../../../../../../tdir/link", "c:/config.sys"); unlink("c:/tdir/link"); rmdir("c:/tdir"); unlink("/link"); symlink("/dev/env/DJDIR/djgpp.env", "/dev/env/DJDIR/link"); test_success("/dev/env/DJDIR/link", "/dev/env/DJDIR/djgpp.env"); test_success("/dev/env/DJDIR/../djgpp/link", "/dev/env/DJDIR/djgpp.env"); /* FIXME */ unlink("/dev/env/DJDIR/link"); Index: xsymlink.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/compat/unistd/xsymlink.c,v retrieving revision 1.6 diff -c -3 -p -r1.6 xsymlink.c *** xsymlink.c 23 Dec 2002 11:44:49 -0000 1.6 --- xsymlink.c 17 Jan 2003 19:22:25 -0000 *************** int __solve_symlinks(const char * __syml *** 50,58 **** } strcpy(__real_path, __symlink_path); start = __real_path; end = strpbrk(__real_path, "/\\"); ! if (!end) end = __real_path + strlen(__real_path); while (start && *start) { --- 50,63 ---- } strcpy(__real_path, __symlink_path); + /* Begin by start pointing at the first character and end pointing + at the first path separator. In the cases like "/foo" end will + point to the next path separator. In all cases, if there are no + path separators left, end will point to the end of string. + */ start = __real_path; end = strpbrk(__real_path, "/\\"); ! if (!end || (start == end)) end = __real_path + strlen(__real_path); while (start && *start) { *************** int __solve_symlinks(const char * __syml *** 164,170 **** return 1; } ! /* Advance to the next portion of the path. Cope with multiple slashes. */ static void advance(char ** s, char ** e) { *s = strpbrk(*s + 1, "/\\"); --- 169,176 ---- return 1; } ! /* Advance to the next portion of the path in the case we won't need ! previously resolved part anymore. Cope with multiple slashes. */ static void advance(char ** s, char ** e) { *s = strpbrk(*s + 1, "/\\"); -- Laurynas