summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--symlink.patch151
1 files changed, 151 insertions, 0 deletions
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)