diff --git a/Makefile b/Makefile index b7fb22d..ff2e30c 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ endif # riscv64-unknown-elf- or riscv64-linux-gnu- # perhaps in /opt/riscv/bin -#TOOLPREFIX = +TOOLPREFIX = /opt/riscv/bin/riscv64-unknown-elf- # Try to infer the correct TOOLPREFIX if not set ifndef TOOLPREFIX @@ -257,7 +257,8 @@ endif ifeq ($(LAB),fs) UPROGS += \ - $U/_bigfile + $U/_bigfile\ + $U/_symlinktest endif diff --git a/gradelib.py b/gradelib.py index f0d4934..21dd2bc 100644 --- a/gradelib.py +++ b/gradelib.py @@ -238,7 +238,7 @@ def make(*target): post_make() def show_command(cmd): - from pipes import quote + from shlex import quote print("\n$", " ".join(map(quote, cmd))) def maybe_unlink(*paths): diff --git a/kernel/defs.h b/kernel/defs.h index d1b6bb9..bed1531 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -187,3 +187,5 @@ void virtio_disk_intr(void); // number of elements in fixed-size array #define NELEM(x) (sizeof(x)/sizeof((x)[0])) + +#define DEBUG() printf("File: %s, Line: %d, Function: %s\n", __FILE__, __LINE__, __func__) diff --git a/kernel/fcntl.h b/kernel/fcntl.h index 44861b9..5aadb74 100644 --- a/kernel/fcntl.h +++ b/kernel/fcntl.h @@ -3,3 +3,4 @@ #define O_RDWR 0x002 #define O_CREATE 0x200 #define O_TRUNC 0x400 +#define O_NOFOLLOW 0x004 \ No newline at end of file diff --git a/kernel/file.h b/kernel/file.h index b076d1d..5c4eb3a 100644 --- a/kernel/file.h +++ b/kernel/file.h @@ -26,7 +26,7 @@ struct inode { short minor; short nlink; uint size; - uint addrs[NDIRECT+1]; + uint addrs[NDIRECT+2]; }; // map major device number to device functions. diff --git a/kernel/fs.c b/kernel/fs.c index c6bab15..d81e703 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -398,23 +398,59 @@ bmap(struct inode *ip, uint bn) if(bn < NINDIRECT){ // Load indirect block, allocating if necessary. - if((addr = ip->addrs[NDIRECT]) == 0){ - addr = balloc(ip->dev); - if(addr == 0) - return 0; - ip->addrs[NDIRECT] = addr; - } - bp = bread(ip->dev, addr); - a = (uint*)bp->data; - if((addr = a[bn]) == 0){ - addr = balloc(ip->dev); - if(addr){ - a[bn] = addr; - log_write(bp); + if(bnaddrs[NDIRECT]) == 0){ + addr = balloc(ip->dev); + if(addr == 0) + return 0; + ip->addrs[NDIRECT] = addr; } + bp = bread(ip->dev, addr); + a = (uint*)bp->data; + if((addr = a[bn]) == 0){ + addr = balloc(ip->dev); + if(addr){ + a[bn] = addr; + log_write(bp); + } + } + brelse(bp); + return addr; + }else{ + bn-=NINDIRECT1; + if((addr = ip->addrs[NDIRECT+1])==0){ + addr = balloc(ip->dev); + if(addr == 0) + return 0; + ip->addrs[NDIRECT+1] = addr; + } + bp=bread(ip->dev,addr); + a = (uint *)bp->data; + const uint offset=bn%NINDIRECT1; + bn/=NINDIRECT1; + if((addr = a[bn])==0){ + addr=balloc(ip->dev); + if(addr){ + a[bn] = addr; + log_write(bp); + } + } + { + struct buf *bp=bread(ip->dev,addr); + a = (uint *)bp->data; + if((addr = a[offset])==0){ + addr=balloc(ip->dev); + if(addr){ + a[offset]=addr; + log_write(bp); + } + } + brelse(bp); + } + brelse(bp); + return addr; } - brelse(bp); - return addr; + } panic("bmap: out of range"); @@ -439,7 +475,7 @@ itrunc(struct inode *ip) if(ip->addrs[NDIRECT]){ bp = bread(ip->dev, ip->addrs[NDIRECT]); a = (uint*)bp->data; - for(j = 0; j < NINDIRECT; j++){ + for(j = 0; j < NINDIRECT1; j++){ if(a[j]) bfree(ip->dev, a[j]); } @@ -447,7 +483,25 @@ itrunc(struct inode *ip) bfree(ip->dev, ip->addrs[NDIRECT]); ip->addrs[NDIRECT] = 0; } - + if(ip->addrs[NDIRECT+1]){ + bp = bread(ip->dev,ip->addrs[NDIRECT+1]); + a = (uint*)bp->data; + for(j = 0;jdev,a[j]); + for(int j=0;jdata; + if(a[j]) + bfree(ip->dev,a[j]); + } + brelse(bp); + bfree(ip->dev,a[j]); + } + } + brelse(bp); + bfree(ip->dev,ip->addrs[NDIRECT+1]); + ip->addrs[NDIRECT+1] = 0; + } ip->size = 0; iupdate(ip); } @@ -508,11 +562,12 @@ writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) uint tot, m; struct buf *bp; - if(off > ip->size || off + n < off) + if(off > ip->size || off + n < off){ return -1; - if(off + n > MAXFILE*BSIZE) + } + if(off + n > MAXFILE*BSIZE){ return -1; - + } for(tot=0; tottype!=T_SYMLINK){ + iunlock(ip); + break; + } + readi(ip,0,(uint64)path,0,MAXPATH); + iunlockput(ip); + if((ip = namei(path)) == 0){ + end_op(); + return -1; + } + ++dep; + if(dep>=10){ + end_op(); + return -1; + } + } + } ilock(ip); if(ip->type == T_DIR && omode != O_RDONLY){ iunlockput(ip); @@ -348,7 +369,7 @@ sys_open(void) end_op(); return -1; } - + if(ip->type == T_DEVICE){ f->type = FD_DEVICE; f->major = ip->major; @@ -474,6 +495,31 @@ sys_exec(void) return -1; } +uint64 sys_symlink(){ + char target[MAXPATH],path[MAXPATH]; + if(argstr(0, target, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0) + goto ERR1; + begin_op(); + struct inode *ip; + if((ip = namei(path)) == 0){ + if((ip = create(path, T_SYMLINK,0,0))==0) + goto ERR2; + }else + ilock(ip); + if(writei(ip,0,(uint64)target,0,MAXPATH)<0){ + goto ERR3; + } + iunlockput(ip); + end_op(); + return 0; + ERR3: + iunlockput(ip); + ERR2: + end_op(); + ERR1: + return -1; +} + uint64 sys_pipe(void) { diff --git a/time.txt b/time.txt new file mode 100644 index 0000000..1e8b314 --- /dev/null +++ b/time.txt @@ -0,0 +1 @@ +6 diff --git a/user/symlinktest.c b/user/symlinktest.c index 781fc9e..632f90c 100644 --- a/user/symlinktest.c +++ b/user/symlinktest.c @@ -135,10 +135,10 @@ testsymlink(void) if(c!=c2) fail("Value read from 4 differed from value written to 1\n"); + close(fd1); close(fd2); fd1 = fd2 = -1; - // // check that many symlinks can co-exist. // diff --git a/user/user.h b/user/user.h index f16fe27..5c8290c 100644 --- a/user/user.h +++ b/user/user.h @@ -22,7 +22,7 @@ int getpid(void); char* sbrk(int); int sleep(int); int uptime(void); - +int symlink(const char *,const char *); // ulib.c int stat(const char*, struct stat*); char* strcpy(char*, const char*); diff --git a/user/usys.pl b/user/usys.pl index 01e426e..65a8d6b 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -36,3 +36,4 @@ entry("getpid"); entry("sbrk"); entry("sleep"); entry("uptime"); +entry("symlink"); \ No newline at end of file