diff -r f8a4e40ab1d6 fs.c --- a/fs.c Thu Aug 30 14:32:06 2007 -0400 +++ b/fs.c Thu Aug 30 14:29:02 2007 -0400 @@ -577,12 +577,18 @@ skipelem(char *path, char *name) // If parent != 0, return the inode for the parent and copy the final // path element into name, which must have room for DIRSIZ bytes. static struct inode* -_namei(char *path, int parent, char *name) +_namei(struct inode *root, char *path, int parent, char *name, int depth) { struct inode *ip, *next; + char buf[100], tname[DIRSIZ]; + + if(depth > 5) + return 0; if(*path == '/') ip = iget(ROOTDEV, 1); + else if(root) + ip = idup(root); else ip = idup(cp->cwd); @@ -598,10 +604,24 @@ _namei(char *path, int parent, char *nam return ip; } if((next = dirlookup(ip, name, 0)) == 0){ + cprintf("did not find %s\n", name); iunlockput(ip); return 0; } - iunlockput(ip); + iunlock(ip); + ilock(next); + if(next->type == T_SYMLINK){ + if(next->size >= sizeof(buf) || readi(next, buf, 0, next->size) != next->size){ + iunlockput(next); + iput(ip); + return 0; + } + buf[next->size] = 0; + iunlockput(next); + next = _namei(ip, buf, 0, tname, depth+1); + }else + iunlock(next); + iput(ip); ip = next; } if(parent){ @@ -615,11 +635,11 @@ namei(char *path) namei(char *path) { char name[DIRSIZ]; - return _namei(path, 0, name); + return _namei(0, path, 0, name, 0); } struct inode* nameiparent(char *path, char *name) { - return _namei(path, 1, name); -} + return _namei(0, path, 1, name, 0); +} diff -r f8a4e40ab1d6 fs.h --- a/fs.h Thu Aug 30 14:32:06 2007 -0400 +++ b/fs.h Thu Aug 30 13:05:43 2007 -0400 @@ -33,6 +33,7 @@ struct dinode { #define T_DIR 1 // Directory #define T_FILE 2 // File #define T_DEV 3 // Special device +#define T_SYMLINK 4 // Symlink // Inodes per block. #define IPB (BSIZE / sizeof(struct dinode)) diff -r f8a4e40ab1d6 syscall.c --- a/syscall.c Thu Aug 30 14:32:06 2007 -0400 +++ b/syscall.c Thu Aug 30 13:05:29 2007 -0400 @@ -96,6 +96,7 @@ extern int sys_unlink(void); extern int sys_unlink(void); extern int sys_wait(void); extern int sys_write(void); +extern int sys_symlink(void); static int (*syscalls[])(void) = { [SYS_chdir] sys_chdir, @@ -118,6 +119,7 @@ static int (*syscalls[])(void) = { [SYS_unlink] sys_unlink, [SYS_wait] sys_wait, [SYS_write] sys_write, +[SYS_symlink] sys_symlink, }; void diff -r f8a4e40ab1d6 syscall.h --- a/syscall.h Thu Aug 30 14:32:06 2007 -0400 +++ b/syscall.h Thu Aug 30 13:02:48 2007 -0400 @@ -19,3 +19,4 @@ #define SYS_getpid 18 #define SYS_sbrk 19 #define SYS_sleep 20 +#define SYS_symlink 21 diff -r f8a4e40ab1d6 sysfile.c --- a/sysfile.c Thu Aug 30 14:32:06 2007 -0400 +++ b/sysfile.c Thu Aug 30 13:10:31 2007 -0400 @@ -257,6 +257,21 @@ create(char *path, int canexist, short t } int +sys_symlink(void) +{ + char *old, *new; + struct inode *ip; + + if(argstr(0, &old) < 0 || argstr(1, &new) < 0) + return -1; + if((ip = create(new, 0, T_SYMLINK, 0, 0)) == 0) + return -1; + writei(ip, old, 0, strlen(old)); + iunlockput(ip); + return 0; +} + +int sys_open(void) { char *path; @@ -393,3 +408,4 @@ sys_pipe(void) fd[1] = fd1; return 0; } + diff -r f8a4e40ab1d6 user.h --- a/user.h Thu Aug 30 14:32:06 2007 -0400 +++ b/user.h Thu Aug 30 13:02:34 2007 -0400 @@ -21,6 +21,7 @@ int getpid(); int getpid(); char* sbrk(int); int sleep(int); +int symlink(int); // ulib.c int stat(char*, struct stat*); diff -r f8a4e40ab1d6 usys.S --- a/usys.S Thu Aug 30 14:32:06 2007 -0400 +++ b/usys.S Thu Aug 30 13:05:54 2007 -0400 @@ -28,3 +28,4 @@ STUB(getpid) STUB(getpid) STUB(sbrk) STUB(sleep) +STUB(symlink)