]> Zhao Yanbai Git Server - minix.git/commitdiff
Fix dangling symlink resolving for AVFS and add test61
authorThomas Veerman <thomas@minix3.org>
Thu, 8 Dec 2011 15:01:47 +0000 (15:01 +0000)
committerThomas Veerman <thomas@minix3.org>
Fri, 9 Dec 2011 10:34:23 +0000 (10:34 +0000)
servers/avfs/open.c
test/Makefile
test/run
test/test61.c [new file with mode: 0644]

index 2b301dae70b4dfb1aaa6ab90785bb79393f29662..5358c3171e2f86cb1ad50ac7709bf876eb86fc67 100644 (file)
@@ -326,7 +326,6 @@ PRIVATE struct vnode *new_node(struct lookup *resolve, int oflags, mode_t bits)
   /* The combination of a symlink with absolute path followed by a danglink
    * symlink results in a new path that needs to be re-resolved entirely. */
   if (path[0] == '/') {
-printf("XXX: dangling symlink needs re-resolving\n");
        unlock_vnode(dirp);
        unlock_vmnt(dir_vmp);
        put_vnode(dirp);
@@ -391,15 +390,19 @@ printf("XXX: dangling symlink needs re-resolving\n");
                        /* Try to create the inode the dangling symlink was
                         * pointing to. We have to use dirp as starting point
                         * as there might be multiple successive symlinks
-                        * crossing multiple mountpoints. */
+                        * crossing multiple mountpoints.
+                        * Unlock vnodes and vmnts as we're going to recurse.
+                        */
+                       unlock_vnode(dirp);
+                       unlock_vnode(vp);
+                       unlock_vmnt(dir_vmp);
+
                        old_wd = fp->fp_wd; /* Save orig. working dirp */
                        fp->fp_wd = dirp;
                        vp = new_node(resolve, oflags, bits);
                        fp->fp_wd = old_wd; /* Restore */
 
                        if (vp != NULL) {
-                               unlock_vnode(dirp);
-                               unlock_vmnt(dir_vmp);
                                put_vnode(dirp);
                                *(resolve->l_vnode) = vp;
                                return(vp);
index 485c6fb90da70bf122d28224df87d7ef6f7234f7..e020324970667b128de76e207e959c7929bcce22 100644 (file)
@@ -19,7 +19,7 @@ OBJ=  test1  test2  test3  test4  test5  test6  test7  test8  test9  \
        test54 test56 test58 t60a t60b
 
 BIGOBJ=  test20 test24
-ROOTOBJ= test11 test33 test43 test44 test46 test60
+ROOTOBJ= test11 test33 test43 test44 test46 test60 test61
 GCCOBJ=  test45-gcc test48 test49-gcc test55
 GCCFPUOBJ= test51-gcc test52-gcc
 OTHEROBJ= test57 test59
@@ -133,3 +133,4 @@ test59: test59.c
 test60: test60.c
 t60a: t60a.c
 t60b: t60b.c
+test61: test61.c
index fdf893be4cce2606945b017257ef90a65ed6195c..eed3970cae3f9890aa8660c40380b2bf72b09995 100755 (executable)
--- a/test/run
+++ b/test/run
@@ -15,7 +15,7 @@ tests="   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 \
          21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
          41 42 43 44 45 45-gcc 46 47 48 49 49-gcc 50 \
          51 51-gcc 52 52-gcc 53 54 55 56 57 58 59\
-         60 \
+         60 61 \
         sh1.sh sh2.sh"
 tests_no=`expr 0`
 
diff --git a/test/test61.c b/test/test61.c
new file mode 100644 (file)
index 0000000..42c3746
--- /dev/null
@@ -0,0 +1,87 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define MAX_ERROR 5
+#include "common.c"
+
+void dangling_slink(int sub_test, char const slink_to[PATH_MAX]);
+
+void dangling_slink(int sub_test, char const slink_to[PATH_MAX])
+{
+  pid_t child;
+
+  subtest = sub_test;
+
+  child = fork();
+  if (child == (pid_t) -1) {
+       e(1);
+       return;
+  } else if (child == (pid_t) 0) {
+       /* I'm the child. Create a dangling symlink with an absolute path */
+       int fd;
+       char buf[4];
+
+
+       /* We don't want to actually write to '/', so instead we pretend */
+       if (chroot(".") != 0) e(2);
+
+       /* Create file 'slink_to' with contents "bar" */
+       if ((fd = open(slink_to, O_CREAT|O_WRONLY)) == -1) e(3);
+       if (write(fd, "bar", strlen("bar")) != strlen("bar")) e(4);
+       close(fd);
+
+       if (symlink(slink_to, "a") == -1) e(5); /* Create the symlink */
+       if (rename(slink_to, "c") == -1) e(6); /* Make it a dangling symlink */
+
+       /* Write "foo" to symlink; this should recreate file 'slink_to' with
+        * contents "foo" */
+       if ((fd = open("a", O_CREAT|O_WRONLY)) == -1) e(7);
+       if (write(fd, "foo", strlen("foo")) != strlen("foo")) e(8);
+       close(fd);
+
+       /* Verify 'a' and 'slink_to' contain "foo" */
+       memset(buf, '\0', sizeof(buf));
+       if ((fd = open("a", O_RDONLY)) == -1) e(9);
+       if (read(fd, buf, 3) != 3) e(10);
+       if (strncmp(buf, "foo", strlen("foo"))) e(11);
+       close(fd);
+       memset(buf, '\0', sizeof(buf));
+       if ((fd = open(slink_to, O_RDONLY)) == -1) e(12);
+       if (read(fd, buf, 3) != 3) e(13);
+       if (strncmp(buf, "foo", strlen("foo"))) e(14);
+       close(fd);
+
+       /* Verify 'c' contains 'bar' */
+       memset(buf, '\0', sizeof(buf));
+       if ((fd = open("c", O_RDONLY)) == -1) e(15);
+       if (read(fd, buf, 3) != 3) e(16);
+       if (strncmp(buf, "bar", strlen("bar"))) e(17);
+       close(fd);
+
+       /* Cleanup created files */
+       if (unlink(slink_to) == -1) e(18);
+       if (unlink("a") == -1) e(19);
+       if (unlink("c") == -1) e(20);
+
+       exit(EXIT_SUCCESS);
+  } else {
+       int status;
+       if (wait(&status) == -1) e(7);
+  }
+
+
+}
+
+int main(int argc, char *argv[])
+{
+  start(61);
+  dangling_slink(1, "/abs"); /* Create dangling symlink with absolute path */
+  dangling_slink(2, "rel"); /* Create dangling symlink with relative path */
+  quit();
+  return(-1);  /* Unreachable */
+}
+