From ef2185247d468309a375b0e16d73e8723cdf29a0 Mon Sep 17 00:00:00 2001
From: rsc <rsc>
Date: Thu, 30 Aug 2007 18:36:38 +0000
Subject: [PATCH] symlink implementation

---
 symlink.patch | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 151 insertions(+)
 create mode 100644 symlink.patch

diff --git a/symlink.patch b/symlink.patch
new file mode 100644
index 0000000..c7caf23
--- /dev/null
+++ b/symlink.patch
@@ -0,0 +1,151 @@
+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)