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
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
2
defs.h
2
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);
|
||||
|
|
8
fd.c
8
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;
|
||||
|
|
97
fs.c
97
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;
|
||||
|
|
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -13,3 +13,5 @@
|
|||
#define SYS_exec 13
|
||||
#define SYS_open 14
|
||||
#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 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, ...);
|
||||
|
||||
|
|
58
userfs.c
58
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;
|
||||
}
|
||||
|
|
1
usys.S
1
usys.S
|
@ -23,3 +23,4 @@ STUB(cons_puts)
|
|||
STUB(exec)
|
||||
STUB(open)
|
||||
STUB(mknod)
|
||||
STUB(unlink)
|
||||
|
|
Loading…
Reference in a new issue