diff --git a/fs/Makefile b/fs/Makefile index 7229ab7efee63f1382048225dcc2764bd7ddd3a3..86ea0fd7b8c97aa91d49d5eb59342ff559e7a8aa 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -4,7 +4,7 @@ CCFLAG := -I../include -nostdinc -ffreestanding -Wall -fomit-frame-pointer -fno- LDFLAG := -Ttext 0x0 -s --oformat binary -m elf_i386 INCDIR := ../include OBJS := read_write.o buffer.o super.o open.o file_table.o inode.o namei.o fcntl.o char_dev.o \ - bitmap.o truncate.o exec.o ioctl.o + bitmap.o truncate.o exec.o ioctl.o stat.o file_dev.o fs.o : $(OBJS) $(LD) -m elf_i386 -r -o $@ $^ @@ -48,6 +48,12 @@ exec.o : exec.c ioctl.o : ioctl.c $(GCC) $(CCFLAG) -o $@ $< +stat.o : stat.c + $(GCC) $(CCFLAG) -o $@ $< + +file_dev.o : file_dev.c + $(GCC) $(CCFLAG) -o $@ $< + clean : -rm *.o diff --git a/fs/file_dev.c b/fs/file_dev.c new file mode 100644 index 0000000000000000000000000000000000000000..b4f0d2f81555b54b0300f13bc2a2364aeed409c0 --- /dev/null +++ b/fs/file_dev.c @@ -0,0 +1,47 @@ +#include +#include + +#include +#include +#include + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) { + int left,chars,nr; + struct buffer_head * bh; + + if ((left=count)<=0) + return 0; + + while (left) { + if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) { + if (!(bh=bread(inode->i_dev,nr))) + break; + } + else { + bh = NULL; + } + + nr = filp->f_pos % BLOCK_SIZE; + chars = MIN( BLOCK_SIZE-nr , left ); + filp->f_pos += chars; + left -= chars; + + if (bh) { + char * p = nr + bh->b_data; + while (chars-->0) + put_fs_byte(*(p++),buf++); + brelse(bh); + } + else { + while (chars-->0) + put_fs_byte(0,buf++); + } + } + + inode->i_atime = CURRENT_TIME; + return (count-left)?(count-left):-ERROR; +} + diff --git a/fs/open.c b/fs/open.c index b0d56d6bc5991a07c12b79e7e07243f4698dbc98..dc8dbc1f93fab03cb433a23c26efa0edb5554787 100644 --- a/fs/open.c +++ b/fs/open.c @@ -121,43 +121,6 @@ int sys_open(const char * filename,int flag,int mode) { return fd; } -int sys_fstat() { - int block, i, j; - int entries; - struct buffer_head * bh; - struct dir_entry * de; - struct m_inode* inode = current->pwd; - - if (S_ISDIR(inode->i_mode)) { - entries = inode->i_size / (sizeof (struct dir_entry)); - - if (!(block = inode->i_zone[0])) { - printk("empty i_zone\n"); - return -1; - } - - if (!(bh = bread(inode->i_dev,block))) { - printk("can not read block %d\n", block); - return -1; - } - - de = (struct dir_entry *) bh->b_data; - - for (i = 0; i < entries; i++) { - if (!de->inode) { - continue; - } - for (j = 0; j < 14; j++) { - printk("%c", de->name[j]); - } - printk("\n"); - de++; - } - } - - return 0; -} - int sys_close(unsigned int fd) { struct file * filp; if (fd >= NR_OPEN) diff --git a/fs/read_write.c b/fs/read_write.c index 0109a381ff296f15a0c20638a434c6cda3a855b1..7c61f34acbf3191d5a487bea222367e85307de9b 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -6,6 +6,8 @@ #include extern int rw_char(int rw,int dev, char * buf, int count, off_t * pos); +extern int file_read(struct m_inode * inode, struct file * filp, + char * buf, int count); int sys_read(unsigned int fd,char * buf,int count) { struct file * file; @@ -16,11 +18,20 @@ int sys_read(unsigned int fd,char * buf,int count) { if (!count) return 0; + verify_area(buf,count); inode = file->f_inode; if (S_ISCHR(inode->i_mode)) { return rw_char(READ, inode->i_zone[0], buf, count, &file->f_pos); } + if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode)) { + if (count+file->f_pos > inode->i_size) + count = inode->i_size - file->f_pos; + if (count<=0) + return 0; + return file_read(inode,file,buf,count); + } + printk("(Read)inode->i_mode=%06o\n\r",inode->i_mode); return -EINVAL; } diff --git a/fs/stat.c b/fs/stat.c new file mode 100644 index 0000000000000000000000000000000000000000..6508e458121615b0f4145610c3732e93f2c8fa35 --- /dev/null +++ b/fs/stat.c @@ -0,0 +1,41 @@ +#include +#include + +#include +#include +#include +#include + +static void cp_stat(struct m_inode * inode, struct stat * statbuf) { + struct stat tmp; + int i; + + verify_area(statbuf,sizeof (struct stat)); + + tmp.st_dev = inode->i_dev; + tmp.st_ino = inode->i_num; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlinks; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = inode->i_zone[0]; + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + + for (i=0 ; i= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode)) + return -EBADF; + cp_stat(inode,statbuf); + return 0; +} + diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 8e23acca007146cdfecf0b78fa37c95a8a2d13bb..00249dc1c06fd74650aaf88b8845adc0d41fdea9 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -1,6 +1,7 @@ #ifndef _KERNEL_H #define _KERNEL_H +void verify_area(void * addr,int count); void panic(const char * str); int printk(const char* fmt, ...); diff --git a/include/sys/stat.h b/include/sys/stat.h index 2c6a15e3e9832e00a127e3d8ba7e9d7ee4febbd5..a7c8cdb532f60f89993179748f51bbc72b669cd1 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -3,6 +3,20 @@ #include +struct stat { + dev_t st_dev; + ino_t st_ino; + umode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; + #define S_IFMT 00170000 #define S_IFLNK 0120000 #define S_IFREG 0100000 @@ -20,6 +34,9 @@ #define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +extern int chmod(const char *_path, mode_t mode); +extern int fstat(int fildes, struct stat *stat_buf); extern int mkdir(const char *_path, mode_t mode); +extern mode_t umask(mode_t mask); #endif diff --git a/include/sys/types.h b/include/sys/types.h index c138035fc4318c837a57bff360a871167a8139f2..b75fb69c89ccd35e68b1340dbe04c246218a9a20 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -1,14 +1,35 @@ #ifndef _SYS_TYPES_H #define _SYS_TYPES_H +#ifndef _SIZE_T +#define _SIZE_T +typedef unsigned int size_t; +#endif + +#ifndef _TIME_T +#define _TIME_T +typedef long time_t; +#endif + +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef long ptrdiff_t; +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + typedef long off_t; typedef int pid_t; +typedef unsigned short uid_t; typedef unsigned short mode_t; typedef unsigned short ino_t; typedef unsigned short gid_t; typedef unsigned short dev_t; typedef unsigned short umode_t; +typedef unsigned char nlink_t; typedef unsigned char cc_t; typedef unsigned int speed_t; typedef unsigned long tcflag_t; diff --git a/kernel/fork.c b/kernel/fork.c index 732318d876d4306daf0d9e8e4c8cae3a5a4b73a9..280319a1980dd75863e904dbaf204d04ec0dadcc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -5,6 +5,23 @@ long last_pid = 0; +extern void write_verify(unsigned long address); + +void verify_area(void * addr,int size) { + unsigned long start; + + start = (unsigned long) addr; + size += start & 0xfff; + start &= 0xfffff000; + + start += get_base(current->ldt[2]); + while (size>0) { + size -= 4096; + write_verify(start); + start += 4096; + } +} + int copy_mem(int nr, struct task_struct* p) { unsigned long old_data_base,new_data_base,data_limit; unsigned long old_code_base,new_code_base,code_limit; diff --git a/kernel/main.c b/kernel/main.c index ffd784b7c2fb516872246f03f1fd3fe90ef21507..b353a25f894efd5ec096a89d53e3b125a86a0b74 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -80,7 +80,8 @@ static void time_init() { static char * argv_rc[] = { "/bin/sh", NULL }; static char * envp_rc[] = { "HOME=/", NULL ,NULL }; -static char * argv[] = { "-/bin/sh",NULL }; +//static char * argv[] = { "-/bin/sh",NULL }; +static char * argv[] = { "/etc/rc",NULL }; static char * envp[] = { "HOME=/usr/root", NULL, NULL }; void main() { @@ -156,9 +157,6 @@ static void easy_shell() { else if (strcmp(a, "ch") == 0) { chdir("/bin/"); } - else if (strcmp(a, "ls") == 0) { - fstat(); - } else if (strcmp(a, "q") == 0) { break; } @@ -172,7 +170,7 @@ static void run_sh() { int pid; if (!(pid=fork())) { printf("read to start shell\n"); - execve("/tmp/et",argv,envp); + execve("/usr/bin/cat",argv,envp); } } diff --git a/lib/write.c b/lib/write.c index cbade07acd4be9ce1fb888165f5c12f54ac50c8b..88bf6f8099f0dd66bc3e0a68e4842a1c7c89caee 100644 --- a/lib/write.c +++ b/lib/write.c @@ -3,7 +3,6 @@ _syscall3(int,write,int,fd,const char *,buf,off_t,count) _syscall3(int,read,int,fd,const char *,buf,off_t,count) -_syscall0(int, fstat) _syscall2(int, mkdir, const char *, pathname, mode_t, mode) _syscall1(int, rmdir, const char *, pathname) _syscall1(int, chdir, const char *, filename) diff --git a/mm/memory.c b/mm/memory.c index 9b6fa72895264d3175276afdb2046441a92fa9d8..009cd63beaf9ccd9f2a4aad188f33e756900d1a2 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -173,6 +173,19 @@ unsigned long put_dirty_page(unsigned long page, unsigned long address) { return page; } +void write_verify(unsigned long address) { + unsigned long page; + + if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1)) + return; + + page &= 0xfffff000; + page += ((address>>10) & 0xffc); + if ((3 & *(unsigned long *) page) == 1) + un_wp_page((unsigned long *) page); + return; +} + void get_empty_page(unsigned long address) { unsigned long tmp; if (!(tmp = get_free_page()) || !put_page(tmp, address)) {