diff --git a/Makefile b/Makefile index 943f7191ff2d4db78343fe9c0e58c00cffbf4eec..059434fc1c148f8f0edf6ac05ad8a6569d7bbb25 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 566380dc07c76a56a0977177ec005c9f1d94a0b8..3674c459be7dc3080d093353206921d4fd8ccfd1 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 d162813109ee7db21320504e0c3d06ce021b9816..c5c3e576b287c2c9a7664d1b20dc54db8842d2e7 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 0c00c6ffb32006fa5a46a9828431cbd5488a04ac..fa71c6e805baf7d280e5af9e2172593165780245 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 0000000000000000000000000000000000000000..ce088402f37d753a42eeadde0256bcfb79e105a1 --- /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 0000000000000000000000000000000000000000..caf0416e1fbb257c3a6f1b7a7ad0f68c9dd50821 --- /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 dfd86c4fea7cb04c560d730a9bd428aeb6a4e083..0f90bd6d65d7fdc7862b106614b06a19fdbae1c5 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 e6019ad05510c05fb9b3330db4871b5011228f01..9924c7fd9f257a75dd29d28cc0ef0429d2c51b3c 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 8154aeb67580b8513056c3bcc0b12d287ca61721..d91b4df5b933fa1f3793d7281e538ab49948defe 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 046768d58d5e535ea2b6209fa5c3bf3d14e8a633..90aa1fa5330590cef84ce8c4a079dc2303c1b7c9 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 8cf7581fcd76e63bcc010148fad6195b1336fa90..aa3a22e209f67474b7c69f6ff4d7ff8d8537e2cd 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)