summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaashoek <kaashoek>2006-08-12 04:33:50 +0000
committerkaashoek <kaashoek>2006-08-12 04:33:50 +0000
commit1f544842ceb5af73b1f2b13222d72dd4ad7cd08a (patch)
tree49ad1096c0ad43c591c493166ff752a3e7cfd7cd
parent0633b9715e106ac97fafcf3a68c06da1f0cf873a (diff)
downloadxv6-labs-1f544842ceb5af73b1f2b13222d72dd4ad7cd08a.tar.gz
xv6-labs-1f544842ceb5af73b1f2b13222d72dd4ad7cd08a.tar.bz2
xv6-labs-1f544842ceb5af73b1f2b13222d72dd4ad7cd08a.zip
fstat
primitive ls
-rw-r--r--Makefile8
-rw-r--r--defs.h3
-rw-r--r--fd.c13
-rw-r--r--fs.c11
-rw-r--r--ls.c43
-rw-r--r--stat.h7
-rw-r--r--syscall.c26
-rw-r--r--syscall.h1
-rw-r--r--user.h2
-rw-r--r--userfs.c3
-rw-r--r--usys.S3
11 files changed, 115 insertions, 5 deletions
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)