diff --git a/Makefile b/Makefile index cc83f3e..3f5a3ce 100644 --- a/Makefile +++ b/Makefile @@ -57,7 +57,7 @@ kernel : $(OBJS) bootother.S user1 usertests userfs vectors.S : vectors.pl perl vectors.pl > vectors.S -ULIB = ulib.o usys.o +ULIB = ulib.o usys.o printf.o user1 : user1.o $(ULIB) $(LD) -N -e main -Ttext 0 -o user1 user1.o $(ULIB) diff --git a/console.c b/console.c index 206a380..eca0225 100644 --- a/console.c +++ b/console.c @@ -163,10 +163,14 @@ console_write (int minor, void *buf, int n) int i; uchar *b = buf; + acquire(&console_lock); + for (i = 0; i < n; i++) { cons_putc((int) b[i]); } + release(&console_lock); + return n; } diff --git a/defs.h b/defs.h index 728b2a4..99a3119 100644 --- a/defs.h +++ b/defs.h @@ -109,5 +109,5 @@ void idecref(struct inode *ip); void iput(struct inode *ip); struct inode * namei(char *path); int readi(struct inode *ip, void *xdst, uint off, uint n); -int writei(struct inode *ip, void *addr, uint n); +int writei(struct inode *ip, void *addr, uint off, uint n); struct inode *mknod(struct inode *, char *, short, short, short); diff --git a/fd.c b/fd.c index 47b0f20..983497f 100644 --- a/fd.c +++ b/fd.c @@ -59,7 +59,13 @@ fd_write(struct fd *fd, char *addr, int n) if(fd->type == FD_PIPE){ return pipe_write(fd->pipe, addr, n); } else if (fd->type == FD_FILE) { - return writei (fd->ip, addr, n); + ilock(fd->ip); + int r = writei (fd->ip, addr, fd->off, n); + if (r > 0) { + fd->off += r; + } + iunlock(fd->ip); + return r; } else { panic("fd_write"); return -1; diff --git a/fs.c b/fs.c index 63b480c..7e54876 100644 --- a/fs.c +++ b/fs.c @@ -23,7 +23,7 @@ balloc(uint dev) int b; struct buf *bp; struct superblock *sb; - int bi; + int bi = 0; int size; int ninodes; uchar m; @@ -50,9 +50,32 @@ balloc(uint dev) cprintf ("balloc: allocate block %d\n", b); bp->data[bi/8] |= 0x1 << (bi % 8); bwrite (dev, bp, BBLOCK(b, ninodes)); // mark it allocated on disk + brelse(bp); return b; } +static void +bfree(int dev, uint b) +{ + struct buf *bp; + struct superblock *sb; + int bi; + int ninodes; + uchar m; + + cprintf ("bfree: free block %d\n", b); + bp = bread(dev, 1); + sb = (struct superblock *) bp->data; + ninodes = sb->ninodes; + brelse(bp); + + bp = bread(dev, BBLOCK(b, ninodes)); + bi = b % BPB; + m = ~(0x1 << (bi %8)); + bp->data[bi/8] &= m; + bwrite (dev, bp, BBLOCK(b, ninodes)); // mark it free on disk + brelse(bp); +} // returns an inode with busy set and incremented reference count. struct inode * @@ -102,7 +125,24 @@ iget(uint dev, uint inum) return nip; } -// allocate an inode on disk +void +iupdate (struct inode *ip) +{ + struct buf *bp; + struct dinode *dip; + + bp = bread(ip->dev, IBLOCK(ip->inum)); + dip = &((struct dinode *)(bp->data))[ip->inum % IPB]; + dip->type = ip->type; + dip->major = ip->major; + dip->minor = ip->minor; + dip->nlink = ip->nlink; + dip->size = ip->size; + memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); + bwrite (ip->dev, bp, IBLOCK(ip->inum)); // mark it allocated on the disk + brelse(bp); +} + struct inode * ialloc(uint dev, short type) { @@ -139,21 +179,11 @@ ialloc(uint dev, short type) return ip; } -void -iupdate (struct inode *ip) +static void +ifree(uint dev, struct inode *ip) { - struct buf *bp; - struct dinode *dip; - - bp = bread(ip->dev, IBLOCK(ip->inum)); - dip = &((struct dinode *)(bp->data))[ip->inum % IPB]; - dip->type = ip->type; - dip->major = ip->major; - dip->minor = ip->minor; - dip->nlink = ip->nlink; - dip->size = ip->size; - bwrite (ip->dev, bp, IBLOCK(ip->inum)); // mark it allocated on the disk - brelse(bp); + ip->type = 0; + iupdate(ip); } void @@ -259,13 +289,44 @@ readi(struct inode *ip, void *xdst, uint off, uint n) return target - n; } +#define MIN(a, b) ((a < b) ? a : b) + int -writei(struct inode *ip, void *addr, uint n) +writei(struct inode *ip, void *addr, uint off, uint n) { if (ip->type == T_DEV) { if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write) return -1; return devsw[ip->major].d_write (ip->minor, addr, n); + } else if (ip->type == T_FILE || ip->type == T_DIR) { // XXX dir here too? + struct buf *bp; + int r = 0; + int m; + int lbn; + uint b; + while (r < n) { + lbn = off / BSIZE; + if (lbn >= NDIRECT) return r; + if (ip->addrs[lbn] == 0) { + b = balloc(ip->dev); + if (b <= 0) return r; + ip->addrs[lbn] = b; + } + m = MIN(BSIZE - off % BSIZE, n-r); + bp = bread(ip->dev, bmap(ip, off / BSIZE)); + memmove (bp->data + off % BSIZE, addr, m); + bwrite (ip->dev, bp, bmap(ip, off/BSIZE)); + brelse (bp); + r += m; + off += m; + } + if (r > 0) { + if (off > ip->size) { + ip->size = off; + } + iupdate(ip); + } + return r; } else { panic ("writei: unknown type\n"); } @@ -358,7 +419,7 @@ mknod(struct inode *dp, char *cp, short type, short major, short minor) } brelse(bp); } - panic("mknod: no dir entry free\n"); + panic("mknod: XXXX no dir entry free\n"); found: ep->inum = ip->inum; diff --git a/printf.c b/printf.c new file mode 100644 index 0000000..0d42236 --- /dev/null +++ b/printf.c @@ -0,0 +1,76 @@ +#include "user.h" +#include "types.h" + +static void +putc(int fd, char c) +{ + write (fd, &c, 1); +} + +static void +printint(int fd, int xx, int base, int sgn) +{ + char buf[16]; + char digits[] = "0123456789ABCDEF"; + int i = 0, neg = 0; + uint x; + + if(sgn && xx < 0){ + neg = 1; + x = 0 - xx; + } else { + x = xx; + } + + do { + buf[i++] = digits[x % base]; + } while((x /= base) != 0); + if(neg) + buf[i++] = '-'; + + while(--i >= 0) + putc(fd, buf[i]); +} + +/* + * printf to the stdout. only understands %d, %x, %p, %s. + */ +void +printf(int fd, char *fmt, ...) +{ + int i, state = 0, c; + uint *ap = (uint *)(void*)&fmt + 1; + + for(i = 0; fmt[i]; i++){ + c = fmt[i] & 0xff; + if(state == 0){ + if(c == '%'){ + state = '%'; + } else { + putc(fd, c); + } + } else if(state == '%'){ + if(c == 'd'){ + printint(fd, *ap, 10, 1); + ap++; + } else if(c == 'x' || c == 'p'){ + printint(fd, *ap, 16, 0); + ap++; + } else if(c == 's'){ + char *s = (char*)*ap; + ap++; + while(*s != 0){ + putc(fd, *s); + s++; + } + } else if(c == '%'){ + putc(fd, c); + } else { + // Unknown % sequence. Print it to draw attention. + putc(fd, '%'); + putc(fd, c); + } + state = 0; + } + } +} diff --git a/syscall.c b/syscall.c index eb7ecf3..685fa46 100644 --- a/syscall.c +++ b/syscall.c @@ -330,6 +330,30 @@ sys_mknod(void) return 0; } +int +sys_unlink(void) +{ + struct proc *cp = curproc[cpu()]; + struct inode *ip; + uint arg0; + + if(fetcharg(0, &arg0) < 0) + return -1; + + if(checkstring(arg0) < 0) + return -1; + + ip = namei(cp->mem + arg0); + ip->nlink--; + if (ip->nlink <= 0) { + panic("sys_link: unimplemented\n"); + } + iupdate(ip); + iput(ip); + + return 0; +} + int sys_exec(void) { @@ -561,6 +585,9 @@ syscall(void) case SYS_mknod: ret = sys_mknod(); break; + case SYS_unlink: + ret = sys_unlink(); + break; default: cprintf("unknown sys call %d\n", num); // XXX fault diff --git a/syscall.h b/syscall.h index 959f015..e6019ad 100644 --- a/syscall.h +++ b/syscall.h @@ -13,3 +13,5 @@ #define SYS_exec 13 #define SYS_open 14 #define SYS_mknod 15 +#define SYS_unlink 16 + diff --git a/user.h b/user.h index d869338..351b970 100644 --- a/user.h +++ b/user.h @@ -13,6 +13,9 @@ int cons_puts(char*); int exec(char *, char **); int open(char *, int); int mknod (char*,short,short,short); +int unlink (char*); int puts(char*); int puts1(char*); char* strcpy(char*, char*); +void printf(int fd, char *fmt, ...); + diff --git a/userfs.c b/userfs.c index 56be4fc..516a7c9 100644 --- a/userfs.c +++ b/userfs.c @@ -4,7 +4,7 @@ // file system tests -char buf[1024]; +char buf[2000]; char *echo_args[] = { "echo", "hello", "goodbye", 0 }; char *cat_args[] = { "cat", "README", 0 }; @@ -12,48 +12,64 @@ int main(void) { int fd; + int i; + int stdout; - puts("userfs running\n"); - block(); - + // printf(stdout, "userfs running\n"); if (mknod ("console", T_DEV, 1, 1) < 0) puts ("mknod failed\n"); else puts ("made a node\n"); - fd = open("console", O_WRONLY); - if(fd >= 0){ - puts("open console ok\n"); - } else { - puts("open console failed!\n"); - } - if (write (fd, "hello\n", 6) != 6) { - puts ("write to console failed\n"); - } - close (fd); + stdout = open("console", O_WRONLY); + printf(stdout, "userfs is running\n"); + + block(); fd = open("echo", 0); if(fd >= 0){ - puts("open echo ok\n"); + printf(stdout, "open echo ok\n"); close(fd); } else { - puts("open echo failed!\n"); + printf(stdout, "open echo failed!\n"); } fd = open("doesnotexist", 0); if(fd >= 0){ - puts("open doesnotexist succeeded!\n"); + printf(stdout, "open doesnotexist succeeded!\n"); close(fd); } else { - puts("open doesnotexist failed\n"); + printf(stdout, "open doesnotexist failed\n"); } - fd = open("doesnotexist", O_CREATE|O_RDWR); if(fd >= 0){ - puts("creat doesnotexist succeeded\n"); + printf(stdout, "creat doesnotexist succeeded\n"); } else { - puts("error: creat doesnotexist failed!\n"); + printf(stdout, "error: creat doesnotexist failed!\n"); + } + for (i = 0; i < 100; i++) { + if (write (fd, "aaaaaaaaaa", 10) != 10) { + printf(stdout, "error: write new file failed\n"); + } + if (write (fd, "bbbbbbbbbb", 10) != 10) { + printf(stdout, "error: write new file failed\n"); + } + } + printf(stdout, "writes done\n"); + close(fd); + fd = open("doesnotexist", O_RDONLY); + if(fd >= 0){ + printf(stdout, "open doesnotexist succeeded\n"); + } else { + printf(stdout, "error: open doesnotexist failed!\n"); + } + i = read(fd, buf, 10000); + if (i == 2000) { + printf(stdout, "read succeeded\\n"); + } else { + printf(stdout, "read failed\n"); } close(fd); //exec("echo", echo_args); + printf(stdout, "about to do exec\n"); exec("cat", cat_args); return 0; } diff --git a/usys.S b/usys.S index 3622f82..8cf7581 100644 --- a/usys.S +++ b/usys.S @@ -23,3 +23,4 @@ STUB(cons_puts) STUB(exec) STUB(open) STUB(mknod) +STUB(unlink)