Message-ID: <39A577FD.834F90D1@softhome.net> Date: Thu, 24 Aug 2000 21:31:09 +0200 From: Laurynas Biveinis X-Mailer: Mozilla 4.74 [en] (Win98; U) X-Accept-Language: lt,en MIME-Version: 1.0 To: DJGPP Workers Subject: Update __solve_dir_symlinks() patch Content-Type: text/plain; charset=iso-8859-4 Content-Transfer-Encoding: 7bit Reply-To: djgpp-workers AT delorie DOT com It solves drive letter handling issues pointed out by Eli. Also there are related testsuite additions. If this patch is OK, I commit other patches for remove() etc. Any comments? Laurynas Index: djgpp/src/libc/compat/unistd/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/compat/unistd/makefile,v retrieving revision 1.7 diff -u -p -r1.7 makefile --- makefile 2000/08/20 15:46:38 1.7 +++ makefile 2000/08/24 19:20:11 @@ -15,6 +15,7 @@ SRC += lchown.c SRC += llseek.c SRC += nice.c SRC += readlink.c +SRC += sdirlink.c SRC += symlink.c SRC += sync.c SRC += truncate.c Index: djgpp/src/libc/compat/unistd/sdirlink.c =================================================================== RCS file: sdirlink.c diff -N sdirlink.c --- /dev/null Tue May 5 16:32:27 1998 +++ sdirlink.c Thu Aug 24 15:20:11 2000 @@ -0,0 +1,49 @@ +/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include +#include +#include + +int __solve_dir_symlinks(const char * __symlink_path, char * __real_path) +{ + char path_copy[FILENAME_MAX]; + char * last_part; + strcpy(path_copy, __symlink_path); + last_part = basename(path_copy); + if (*last_part == '\0') + { + /* If basename() returned pointer to the end of string, cut the last + * dir separator and try again. Exception: for paths like 'C:', just + * copy it to the result and return. + */ + if (*(last_part - 1) == ':') + { + strcpy(__real_path, path_copy); + return 1; + } + *(last_part - 1) = '\0'; + last_part = basename(path_copy); + } + if (last_part == path_copy) + { + /* The path is made from single part */ + strcpy(__real_path, path_copy); + return 1; + } + /* If the have path like c:/file or c:file, just copy it to the result + * and return. + */ + if (*(last_part - 1) == ':') + { + strcpy(__real_path, path_copy); + return 1; + } + *(last_part - 1) = '\0'; + if (!__solve_symlinks(path_copy, __real_path)) + return 0; + strcat(__real_path, "/"); + strcat(__real_path, last_part); + return 1; +} + Index: djgpp/src/libc/compat/unistd/sdirlink.txh =================================================================== RCS file: sdirlink.txh diff -N sdirlink.txh --- /dev/null Tue May 5 16:32:27 1998 +++ sdirlink.txh Thu Aug 24 15:20:11 2000 @@ -0,0 +1,37 @@ +@node __solve_dir_symlinks, io +@subheading Syntax + +@example +#include + +int __solve_dir_symlinks(const char *symlink_path, char *real_path); +@end example + +@subheading Description +This function resolves given symlink in @var{symlink_path}---all path +components @strong{except} the last one and all symlink levels are +resolved. If @var{symlink_path} does not contain symlinks at all, it is +simply copied to @var{real_path}. + +@subheading Return Value + +Zero in case of error (and @code{errno} set to the appropriate +error code), non-zero in case of success. + +@subheading Portability + +@portability !ansi, !posix + +@subheading Example + +@example + + #include + #include + + __solve_dir_symlinks(fn, file_name); + printf("The real path to %s is %s\n", fn, file_name); + + +@end example + Index: djgpp/tests/libc/compat/unistd/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/tests/libc/compat/unistd/makefile,v retrieving revision 1.2 diff -u -p -r1.2 makefile --- makefile 2000/08/14 08:51:31 1.2 +++ makefile 2000/08/24 19:20:33 @@ -1,6 +1,7 @@ TOP=../.. SRC += readlink.c +SRC += sdirlink.c SRC += symlink.c SRC += xsymlink.c Index: djgpp/tests/libc/compat/unistd/sdirlink.c =================================================================== RCS file: sdirlink.c diff -N sdirlink.c --- /dev/null Tue May 5 16:32:27 1998 +++ sdirlink.c Thu Aug 24 15:20:33 2000 @@ -0,0 +1,77 @@ +/* Testsuite for __solve_dir_symlinks() + * There are following success tests: + * 1. Simple case with symlink in current directory + * 2. Symlink with a trailing slash + * 3. Symlink in subdirectory + * 4. Real file in symlinked directory + * 5. Symlink in symlinked directory + * 6. Real file in a symlink subdir in a symlink subdir + * Any unhandled cases are more than welcome. + * + */ +#include +#include +#include +#include +#include +#include + +static void test_success(int num, const char * slink, const char * expect); + +int main(void) +{ + if (!__file_exists("test1") || !__file_exists("test4") || + !__file_exists("test5") || !__file_exists("dirtest") || + !__file_exists("fail1") || !__file_exists("fail2") || + !__file_exists("fail3") || !__file_exists("dir1/fail1") || + !__file_exists("dir1/test1") || !__file_exists("dir1/test2") || + !__file_exists("dir1/test3") || !__file_exists("dir1/test4") || + !__file_exists("dir1/test5") || !__file_exists("dir1/test6") || + !__file_exists("dir1/test7") || access("dir1/dir2", D_OK)) + { + fprintf(stderr, "Required data files not found"); + exit(1); + } + printf("Running __solve_dir_symlink() testsuite:\n"); + test_success( 1, "test1", "test1"); + test_success( 2, "test1/", "test1"); + test_success( 3, "dir1/test1", "dir1/test1"); + test_success( 4, "dirtest/file1", "dir1/file1"); + test_success( 5, "dirtest/test1", "dir1/test1"); + test_success( 6, "dirtest/test6/file", "dir1/dir2/file"); + test_success( 7, "c:test1", "c:test1"); + symlink("c:/file", "c:/linkfile"); + test_success( 8, "c:/linkfile", "c:/linkfile"); + remove("c:/linkfile"); + test_success( 9, "c:/djgpp/tests/libc/compat/unistd/file1", + "c:/djgpp/tests/libc/compat/unistd/file1"); + printf("Done.\n"); + return 0; +} + +static void test_success(int num, const char * slink, const char * expect) +{ + char real_name[FILENAME_MAX + 1]; + char real_fixed[FILENAME_MAX + 1]; + char expect_fixed[FILENAME_MAX + 1]; + char err_buf[50]; + if (!__solve_dir_symlinks(slink, real_name)) + { + sprintf(err_buf, "Test %d failed ", num); + perror(err_buf); + exit(1); + } + _fixpath(expect, expect_fixed); + _fixpath(real_name, real_fixed); + if (strcmp(real_fixed, expect_fixed)) + { + fprintf(stderr, + "Test %d failed - __solve_dir_symlinks returns wrong resolved path\n", + num); + fprintf(stderr, "Expected %s\n", expect_fixed); + fprintf(stderr, "It returns %s\n", real_fixed); + exit(1); + } + printf("Test %d passed\n", num); +} +