Index: redirect.txt =================================================================== RCS file: /cvsroot/translucency/translucency/redirect.txt,v retrieving revision 1.11 diff -u -r1.11 redirect.txt --- redirect.txt 18 Oct 2003 20:04:40 -0000 1.11 +++ redirect.txt 20 Oct 2003 13:58:54 -0000 @@ -24,13 +24,13 @@ ^:::++int rename(const char *oldpath, const char *newpath); ^::++int unlink(const char *pathname); -:+int mknod(const char *pathname, mode_t mode, dev_t dev); +^:+int mknod(const char *pathname, mode_t mode, dev_t dev); ^:+int link(const char *oldpath, const char *newpath); ^:+int symlink(const char *oldpath, const char *newpath); -:+int mkdir(const char *pathname, mode_t mode); +^:+int mkdir(const char *pathname, mode_t mode); --int chdir(const char *path); --int fchdir(int fd); -::int rmdir(const char *pathname); +^::int rmdir(const char *pathname); ++int chmod(const char *path, mode_t mode); ++int chown(const char *path, uid_t owner, gid_t group); ^++int lchown(const char *path, uid_t owner, gid_t group); Index: base.c =================================================================== RCS file: /cvsroot/translucency/translucency/base.c,v retrieving revision 1.28 diff -u -r1.28 base.c --- base.c 20 Oct 2003 13:17:38 -0000 1.28 +++ base.c 20 Oct 2003 13:58:55 -0000 @@ -337,6 +337,50 @@ return outfd; } +int loopcount=0; +int translucent_handle_symlink(char *path, struct nameidata *n, int rflags) +{ + int result; + if(loopcount>9) return 0; + { // brace only for limiting scope of variables + char *buf=malloc(2*REDIR_BUFSIZE), *buf2=buf+REDIR_BUFSIZE, *p=namei_to_path(n,buf); + BEGIN_KMEM + result=orig_sys_readlink(p, buf2, REDIR_BUFSIZE); + END_KMEM + if(result>=REDIR_BUFSIZE) result=REDIR_BUFSIZE-1; + buf2[result]=0; + // printk("symlink %.8o %s -> %s\n", n->dentry->d_inode->i_mode, p, buf2); + if(buf2[0]=='/') memcpy(path, buf2, REDIR_BUFSIZE); + else { + char *p2=strrchr(path, '/'); + int i_Len; + if(p2==NULL) { + printk(SYSLOGID ": should not get here1\n"); + free(buf); + return 0; + } + *(++p2)=0; + i_Len=p2-path; + strncat(path, buf2, REDIR_BUFSIZE-i_Len); + } + //printk(SYSLOGID ": from %s ",p); + free(buf); + } + //printk("symlink %s ", path); + loopcount++; + result=redirect_path(path, 0, rflags); + loopcount--; + //printk("to %s %i %.8X %.8X\n", path, result, rflags, n->flags); + if(result>0) { //re-init n //TODO: check condition when awake + rflags=n->flags; + path_release(n); + path_init(path, rflags, n); + result=path_walk(path, n); + result=1; + } else result=0; + return result; +} + void absolutize(char *name, struct dentry *d, struct vfsmount *m) { char *p, *buf; int l,l2 = strlen(name); @@ -350,7 +394,7 @@ name[l] = '/'; } else { printk(SYSLOGID ": buffer too small\n"); - } + } free(buf); } @@ -527,6 +571,9 @@ // return index of uppermost layer with valid entry for(j=i-1; j>=0; --j) if(valid[j]) { path_release(&n[j]); valid[j]=0; } if (endp) *endp=(slash?lastnp:NULL); + if((!(lflags&LOOKUP_NOFOLLOW)) && i>=0 && valid[i] && have_inode(&n[i]) && S_ISLNK(n[i].dentry->d_inode->i_mode)) { + if(translucent_handle_symlink(name, n+i, lflags)) something_redirected=1; + } if(!something_redirected && i>=0) {path_release(&n[i]); return (-1);} return (i); }