printf
convert userfs to use printf bfree ifree writei start on unlink
This commit is contained in:
parent
939f9edeac
commit
28d9ef04dd
11 changed files with 238 additions and 42 deletions
2
Makefile
2
Makefile
|
@ -57,7 +57,7 @@ kernel : $(OBJS) bootother.S user1 usertests userfs
|
||||||
vectors.S : vectors.pl
|
vectors.S : vectors.pl
|
||||||
perl vectors.pl > vectors.S
|
perl vectors.pl > vectors.S
|
||||||
|
|
||||||
ULIB = ulib.o usys.o
|
ULIB = ulib.o usys.o printf.o
|
||||||
|
|
||||||
user1 : user1.o $(ULIB)
|
user1 : user1.o $(ULIB)
|
||||||
$(LD) -N -e main -Ttext 0 -o user1 user1.o $(ULIB)
|
$(LD) -N -e main -Ttext 0 -o user1 user1.o $(ULIB)
|
||||||
|
|
|
@ -163,10 +163,14 @@ console_write (int minor, void *buf, int n)
|
||||||
int i;
|
int i;
|
||||||
uchar *b = buf;
|
uchar *b = buf;
|
||||||
|
|
||||||
|
acquire(&console_lock);
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
cons_putc((int) b[i]);
|
cons_putc((int) b[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
release(&console_lock);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
defs.h
2
defs.h
|
@ -109,5 +109,5 @@ void idecref(struct inode *ip);
|
||||||
void iput(struct inode *ip);
|
void iput(struct inode *ip);
|
||||||
struct inode * namei(char *path);
|
struct inode * namei(char *path);
|
||||||
int readi(struct inode *ip, void *xdst, uint off, uint n);
|
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);
|
struct inode *mknod(struct inode *, char *, short, short, short);
|
||||||
|
|
8
fd.c
8
fd.c
|
@ -59,7 +59,13 @@ fd_write(struct fd *fd, char *addr, int n)
|
||||||
if(fd->type == FD_PIPE){
|
if(fd->type == FD_PIPE){
|
||||||
return pipe_write(fd->pipe, addr, n);
|
return pipe_write(fd->pipe, addr, n);
|
||||||
} else if (fd->type == FD_FILE) {
|
} 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 {
|
} else {
|
||||||
panic("fd_write");
|
panic("fd_write");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
97
fs.c
97
fs.c
|
@ -23,7 +23,7 @@ balloc(uint dev)
|
||||||
int b;
|
int b;
|
||||||
struct buf *bp;
|
struct buf *bp;
|
||||||
struct superblock *sb;
|
struct superblock *sb;
|
||||||
int bi;
|
int bi = 0;
|
||||||
int size;
|
int size;
|
||||||
int ninodes;
|
int ninodes;
|
||||||
uchar m;
|
uchar m;
|
||||||
|
@ -50,9 +50,32 @@ balloc(uint dev)
|
||||||
cprintf ("balloc: allocate block %d\n", b);
|
cprintf ("balloc: allocate block %d\n", b);
|
||||||
bp->data[bi/8] |= 0x1 << (bi % 8);
|
bp->data[bi/8] |= 0x1 << (bi % 8);
|
||||||
bwrite (dev, bp, BBLOCK(b, ninodes)); // mark it allocated on disk
|
bwrite (dev, bp, BBLOCK(b, ninodes)); // mark it allocated on disk
|
||||||
|
brelse(bp);
|
||||||
return b;
|
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.
|
// returns an inode with busy set and incremented reference count.
|
||||||
struct inode *
|
struct inode *
|
||||||
|
@ -102,7 +125,24 @@ iget(uint dev, uint inum)
|
||||||
return nip;
|
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 *
|
struct inode *
|
||||||
ialloc(uint dev, short type)
|
ialloc(uint dev, short type)
|
||||||
{
|
{
|
||||||
|
@ -139,21 +179,11 @@ ialloc(uint dev, short type)
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
iupdate (struct inode *ip)
|
ifree(uint dev, struct inode *ip)
|
||||||
{
|
{
|
||||||
struct buf *bp;
|
ip->type = 0;
|
||||||
struct dinode *dip;
|
iupdate(ip);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -259,13 +289,44 @@ readi(struct inode *ip, void *xdst, uint off, uint n)
|
||||||
return target - n;
|
return target - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MIN(a, b) ((a < b) ? a : b)
|
||||||
|
|
||||||
int
|
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->type == T_DEV) {
|
||||||
if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write)
|
if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write)
|
||||||
return -1;
|
return -1;
|
||||||
return devsw[ip->major].d_write (ip->minor, addr, n);
|
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 {
|
} else {
|
||||||
panic ("writei: unknown type\n");
|
panic ("writei: unknown type\n");
|
||||||
}
|
}
|
||||||
|
@ -358,7 +419,7 @@ mknod(struct inode *dp, char *cp, short type, short major, short minor)
|
||||||
}
|
}
|
||||||
brelse(bp);
|
brelse(bp);
|
||||||
}
|
}
|
||||||
panic("mknod: no dir entry free\n");
|
panic("mknod: XXXX no dir entry free\n");
|
||||||
|
|
||||||
found:
|
found:
|
||||||
ep->inum = ip->inum;
|
ep->inum = ip->inum;
|
||||||
|
|
76
printf.c
Normal file
76
printf.c
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
syscall.c
27
syscall.c
|
@ -330,6 +330,30 @@ sys_mknod(void)
|
||||||
return 0;
|
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
|
int
|
||||||
sys_exec(void)
|
sys_exec(void)
|
||||||
{
|
{
|
||||||
|
@ -561,6 +585,9 @@ syscall(void)
|
||||||
case SYS_mknod:
|
case SYS_mknod:
|
||||||
ret = sys_mknod();
|
ret = sys_mknod();
|
||||||
break;
|
break;
|
||||||
|
case SYS_unlink:
|
||||||
|
ret = sys_unlink();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cprintf("unknown sys call %d\n", num);
|
cprintf("unknown sys call %d\n", num);
|
||||||
// XXX fault
|
// XXX fault
|
||||||
|
|
|
@ -13,3 +13,5 @@
|
||||||
#define SYS_exec 13
|
#define SYS_exec 13
|
||||||
#define SYS_open 14
|
#define SYS_open 14
|
||||||
#define SYS_mknod 15
|
#define SYS_mknod 15
|
||||||
|
#define SYS_unlink 16
|
||||||
|
|
||||||
|
|
3
user.h
3
user.h
|
@ -13,6 +13,9 @@ int cons_puts(char*);
|
||||||
int exec(char *, char **);
|
int exec(char *, char **);
|
||||||
int open(char *, int);
|
int open(char *, int);
|
||||||
int mknod (char*,short,short,short);
|
int mknod (char*,short,short,short);
|
||||||
|
int unlink (char*);
|
||||||
int puts(char*);
|
int puts(char*);
|
||||||
int puts1(char*);
|
int puts1(char*);
|
||||||
char* strcpy(char*, char*);
|
char* strcpy(char*, char*);
|
||||||
|
void printf(int fd, char *fmt, ...);
|
||||||
|
|
||||||
|
|
58
userfs.c
58
userfs.c
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// file system tests
|
// file system tests
|
||||||
|
|
||||||
char buf[1024];
|
char buf[2000];
|
||||||
char *echo_args[] = { "echo", "hello", "goodbye", 0 };
|
char *echo_args[] = { "echo", "hello", "goodbye", 0 };
|
||||||
char *cat_args[] = { "cat", "README", 0 };
|
char *cat_args[] = { "cat", "README", 0 };
|
||||||
|
|
||||||
|
@ -12,48 +12,64 @@ int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
int i;
|
||||||
|
int stdout;
|
||||||
|
|
||||||
puts("userfs running\n");
|
// printf(stdout, "userfs running\n");
|
||||||
block();
|
|
||||||
|
|
||||||
if (mknod ("console", T_DEV, 1, 1) < 0)
|
if (mknod ("console", T_DEV, 1, 1) < 0)
|
||||||
puts ("mknod failed\n");
|
puts ("mknod failed\n");
|
||||||
else
|
else
|
||||||
puts ("made a node\n");
|
puts ("made a node\n");
|
||||||
fd = open("console", O_WRONLY);
|
stdout = open("console", O_WRONLY);
|
||||||
if(fd >= 0){
|
printf(stdout, "userfs is running\n");
|
||||||
puts("open console ok\n");
|
|
||||||
} else {
|
block();
|
||||||
puts("open console failed!\n");
|
|
||||||
}
|
|
||||||
if (write (fd, "hello\n", 6) != 6) {
|
|
||||||
puts ("write to console failed\n");
|
|
||||||
}
|
|
||||||
close (fd);
|
|
||||||
|
|
||||||
fd = open("echo", 0);
|
fd = open("echo", 0);
|
||||||
if(fd >= 0){
|
if(fd >= 0){
|
||||||
puts("open echo ok\n");
|
printf(stdout, "open echo ok\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
} else {
|
} else {
|
||||||
puts("open echo failed!\n");
|
printf(stdout, "open echo failed!\n");
|
||||||
}
|
}
|
||||||
fd = open("doesnotexist", 0);
|
fd = open("doesnotexist", 0);
|
||||||
if(fd >= 0){
|
if(fd >= 0){
|
||||||
puts("open doesnotexist succeeded!\n");
|
printf(stdout, "open doesnotexist succeeded!\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
} else {
|
} else {
|
||||||
puts("open doesnotexist failed\n");
|
printf(stdout, "open doesnotexist failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open("doesnotexist", O_CREATE|O_RDWR);
|
fd = open("doesnotexist", O_CREATE|O_RDWR);
|
||||||
if(fd >= 0){
|
if(fd >= 0){
|
||||||
puts("creat doesnotexist succeeded\n");
|
printf(stdout, "creat doesnotexist succeeded\n");
|
||||||
} else {
|
} 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);
|
close(fd);
|
||||||
//exec("echo", echo_args);
|
//exec("echo", echo_args);
|
||||||
|
printf(stdout, "about to do exec\n");
|
||||||
exec("cat", cat_args);
|
exec("cat", cat_args);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
1
usys.S
1
usys.S
|
@ -23,3 +23,4 @@ STUB(cons_puts)
|
||||||
STUB(exec)
|
STUB(exec)
|
||||||
STUB(open)
|
STUB(open)
|
||||||
STUB(mknod)
|
STUB(mknod)
|
||||||
|
STUB(unlink)
|
||||||
|
|
Loading…
Reference in a new issue