summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--console.c4
-rw-r--r--defs.h2
-rw-r--r--fd.c8
-rw-r--r--fs.c97
-rw-r--r--printf.c76
-rw-r--r--syscall.c27
-rw-r--r--syscall.h2
-rw-r--r--user.h3
-rw-r--r--userfs.c58
-rw-r--r--usys.S1
11 files changed, 238 insertions, 42 deletions
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
@@ -331,6 +331,30 @@ sys_mknod(void)
}
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)
{
struct proc *cp = curproc[cpu()];
@@ -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 {
+ 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 {
- puts("error: creat doesnotexist failed!\n");
+ 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)