diff --git a/Makefile b/Makefile index 943f719..059434f 100644 --- a/Makefile +++ b/Makefile @@ -87,11 +87,15 @@ sh : sh.o $(ULIB) $(LD) -N -e main -Ttext 0 -o sh sh.o $(ULIB) $(OBJDUMP) -S sh > sh.asm +ls : ls.o $(ULIB) + $(LD) -N -e main -Ttext 0 -o ls ls.o $(ULIB) + $(OBJDUMP) -S ls > ls.asm + mkfs : mkfs.c fs.h cc -o mkfs mkfs.c -fs.img : mkfs userfs usertests echo cat README init sh - ./mkfs fs.img userfs usertests echo cat README init sh +fs.img : mkfs userfs usertests echo cat README init sh ls + ./mkfs fs.img userfs usertests echo cat README init sh ls -include *.d diff --git a/defs.h b/defs.h index 566380d..3674c45 100644 --- a/defs.h +++ b/defs.h @@ -85,12 +85,14 @@ int pipe_write(struct pipe *p, char *addr, int n); int pipe_read(struct pipe *p, char *addr, int n); // fd.c +struct stat; void fd_init(void); int fd_ualloc(void); struct fd * fd_alloc(void); void fd_close(struct fd *); int fd_read(struct fd *fd, char *addr, int n); int fd_write(struct fd *fd, char *addr, int n); +int fd_stat(struct fd *fd, struct stat *); void fd_incref(struct fd *fd); // ide.c @@ -115,6 +117,7 @@ void iunlock(struct inode *ip); void idecref(struct inode *ip); void iput(struct inode *ip); struct inode * namei(char *path, uint *); +void stati(struct inode *ip, struct stat *st); int readi(struct inode *ip, char *xdst, uint off, uint n); int writei(struct inode *ip, char *addr, uint off, uint n); struct inode *mknod(char *, short, short, short); diff --git a/fd.c b/fd.c index d162813..c5c3e57 100644 --- a/fd.c +++ b/fd.c @@ -1,4 +1,5 @@ #include "types.h" +#include "stat.h" #include "param.h" #include "x86.h" #include "mmu.h" @@ -121,6 +122,18 @@ fd_close(struct fd *fd) release(&fd_table_lock); } +int +fd_stat(struct fd *fd, struct stat *st) +{ + if(fd->type == FD_FILE){ + ilock(fd->ip); + stati(fd->ip, st); + iunlock(fd->ip); + return 0; + } else + return -1; +} + void fd_incref(struct fd *fd) { diff --git a/fs.c b/fs.c index 0c00c6f..fa71c6e 100644 --- a/fs.c +++ b/fs.c @@ -1,4 +1,5 @@ #include "types.h" +#include "stat.h" #include "param.h" #include "x86.h" #include "mmu.h" @@ -270,6 +271,16 @@ bmap(struct inode *ip, uint bn) #define min(a, b) ((a) < (b) ? (a) : (b)) +void +stati(struct inode *ip, struct stat *st) +{ + st->st_dev = ip->dev; + st->st_ino = ip->inum; + st->st_type = ip->type; + st->st_nlink = ip->nlink; + st->st_size = ip->size; +} + int readi(struct inode *ip, char *dst, uint off, uint n) { diff --git a/ls.c b/ls.c new file mode 100644 index 0000000..ce08840 --- /dev/null +++ b/ls.c @@ -0,0 +1,43 @@ +#include "types.h" +#include "stat.h" +#include "user.h" +#include "fs.h" + +char buf[512]; +struct stat stat; +struct dirent dirent; + +int +main(int argc, char *argv[]) +{ + int fd; + uint off; + + if(argc > 1){ + puts("Usage: ls\n"); + exit(); + } + + fd = open(".", 0); + if(fd < 0){ + printf(2, "ls: cannot open .\n"); + exit(); + } + if (fstat(fd, &stat) < 0) { + printf(2, "ls: cannot open .\n"); + exit(); + } + if (stat.st_type != T_DIR) { + printf(2, "ls: . is not a dir\n"); + } + for(off = 0; off < stat.st_size; off += sizeof(struct dirent)) { + if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) { + printf(2, "ls: read error\n"); + exit(); + } + printf(1, "%s\n", dirent.name); + } + close(fd); + + exit(); +} diff --git a/stat.h b/stat.h new file mode 100644 index 0000000..caf0416 --- /dev/null +++ b/stat.h @@ -0,0 +1,7 @@ +struct stat { + int st_dev; + uint st_ino; + short st_type; + short st_nlink; + uint st_size; +}; diff --git a/syscall.c b/syscall.c index dfd86c4..0f90bd6 100644 --- a/syscall.c +++ b/syscall.c @@ -1,4 +1,5 @@ #include "types.h" +#include "stat.h" #include "param.h" #include "mmu.h" #include "proc.h" @@ -334,6 +335,28 @@ sys_unlink(void) return r; } + +int +sys_fstat(void) +{ + struct proc *cp = curproc[cpu()]; + uint fd, addr; + int r; + + if(fetcharg(0, &fd) < 0) + return -1; + if(fetcharg(1, &addr) < 0) + return -1; + if(fd < 0 || fd >= NOFILE) + return -1; + if(cp->fds[fd] == 0) + return -1; + if(addr + sizeof(struct stat) > cp->sz) + return -1; + r = fd_stat (cp->fds[fd], (struct stat *)(cp->mem + addr)); + return r; +} + int sys_exec(void) { @@ -570,6 +593,9 @@ syscall(void) case SYS_unlink: ret = sys_unlink(); break; + case SYS_fstat: + ret = sys_fstat(); + break; default: cprintf("unknown sys call %d\n", num); // XXX fault diff --git a/syscall.h b/syscall.h index e6019ad..9924c7f 100644 --- a/syscall.h +++ b/syscall.h @@ -14,4 +14,5 @@ #define SYS_open 14 #define SYS_mknod 15 #define SYS_unlink 16 +#define SYS_fstat 17 diff --git a/user.h b/user.h index 8154aeb..d91b4df 100644 --- a/user.h +++ b/user.h @@ -14,7 +14,7 @@ int exec(char *, char **); int open(char *, int); int mknod (char*,short,short,short); int unlink (char*); - +int fstat (int fd, struct stat *stat); int puts(char*); char* strcpy(char*, char*); void printf(int fd, char *fmt, ...); diff --git a/userfs.c b/userfs.c index 046768d..90aa1fa 100644 --- a/userfs.c +++ b/userfs.c @@ -1,5 +1,6 @@ -#include "user.h" #include "types.h" +#include "stat.h" +#include "user.h" #include "fs.h" #include "fcntl.h" diff --git a/usys.S b/usys.S index 8cf7581..aa3a22e 100644 --- a/usys.S +++ b/usys.S @@ -23,4 +23,5 @@ STUB(cons_puts) STUB(exec) STUB(open) STUB(mknod) -STUB(unlink) +STUB(unlink) +STUB(fstat)