Fix dangling symlink resolving for AVFS and add test61

This commit is contained in:
Thomas Veerman 2011-12-08 15:01:47 +00:00
parent 21168577a5
commit 706873142e
4 changed files with 97 additions and 6 deletions

View 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 /* 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. */ * symlink results in a new path that needs to be re-resolved entirely. */
if (path[0] == '/') { if (path[0] == '/') {
printf("XXX: dangling symlink needs re-resolving\n");
unlock_vnode(dirp); unlock_vnode(dirp);
unlock_vmnt(dir_vmp); unlock_vmnt(dir_vmp);
put_vnode(dirp); put_vnode(dirp);
@ -391,15 +390,19 @@ printf("XXX: dangling symlink needs re-resolving\n");
/* Try to create the inode the dangling symlink was /* Try to create the inode the dangling symlink was
* pointing to. We have to use dirp as starting point * pointing to. We have to use dirp as starting point
* as there might be multiple successive symlinks * 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 */ old_wd = fp->fp_wd; /* Save orig. working dirp */
fp->fp_wd = dirp; fp->fp_wd = dirp;
vp = new_node(resolve, oflags, bits); vp = new_node(resolve, oflags, bits);
fp->fp_wd = old_wd; /* Restore */ fp->fp_wd = old_wd; /* Restore */
if (vp != NULL) { if (vp != NULL) {
unlock_vnode(dirp);
unlock_vmnt(dir_vmp);
put_vnode(dirp); put_vnode(dirp);
*(resolve->l_vnode) = vp; *(resolve->l_vnode) = vp;
return(vp); return(vp);

View file

@ -19,7 +19,7 @@ OBJ= test1 test2 test3 test4 test5 test6 test7 test8 test9 \
test54 test56 test58 t60a t60b test54 test56 test58 t60a t60b
BIGOBJ= test20 test24 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 GCCOBJ= test45-gcc test48 test49-gcc test55
GCCFPUOBJ= test51-gcc test52-gcc GCCFPUOBJ= test51-gcc test52-gcc
OTHEROBJ= test57 test59 OTHEROBJ= test57 test59
@ -133,3 +133,4 @@ test59: test59.c
test60: test60.c test60: test60.c
t60a: t60a.c t60a: t60a.c
t60b: t60b.c t60b: t60b.c
test61: test61.c

View file

@ -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 \ 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 \ 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\ 51 51-gcc 52 52-gcc 53 54 55 56 57 58 59\
60 \ 60 61 \
sh1.sh sh2.sh" sh1.sh sh2.sh"
tests_no=`expr 0` tests_no=`expr 0`

87
test/test61.c Normal file
View file

@ -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 */
}