Mail Archives: djgpp-workers/2000/08/24/15:24:17
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 <libc/stubs.h>
+#include <libc/symlink.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+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 <libc/symlink.h>
+
+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 <libc/symlink.h>
+ #include <stdio.h>
+
+ __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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libc/symlink.h>
+#include <sys/stat.h>
+
+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);
+}
+
- Raw text -