You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
6.9 KiB
290 lines
6.9 KiB
#define __LIBRARY__
|
|
#include <unistd.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/sched.h>
|
|
#include <asm/segment.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#define BUF_MAX 4096
|
|
#define DIRBUF 8192
|
|
#define NAME_MAX 14
|
|
|
|
struct dirent {
|
|
long d_ino;
|
|
off_t d_off;
|
|
unsigned short d_reclen;
|
|
char d_name[NAME_MAX+1];
|
|
};
|
|
|
|
/*参数count指定该缓冲区的大小*/
|
|
int sys_getdents(unsigned int fd,struct linux_dirent *dirp,unsigned int count)
|
|
{
|
|
if(!count)return -1;/*count is zero*/
|
|
if(fd>=NR_OPEN)return -EINVAL;/*fd is over range*/
|
|
|
|
struct file *file;
|
|
struct m_inode * inode;
|
|
int ret;
|
|
struct buffer_head *hd;
|
|
struct dir_entry *de;
|
|
struct dirent * temp;
|
|
char * buf;
|
|
int desize,ldsize,i,ldi;
|
|
|
|
file=current->filp[fd];
|
|
if(!file)return ENOTDIR;/*the file is not exist or not file*/
|
|
ldsize = sizeof(struct dirent);
|
|
desize = sizeof(struct dir_entry);
|
|
inode = file ->f_inode;
|
|
temp = (struct dirent *)malloc(ldsize);/* //the inter veriable */
|
|
buf = (char*)malloc(ldsize);
|
|
|
|
/*get the inode's bread*/
|
|
hd = bread(inode->i_dev , inode->i_zone[0]);
|
|
|
|
ldi=0;
|
|
ret=0;
|
|
|
|
for (;ret<inode->i_size;ret += desize){
|
|
if (ldi >= count-ldsize)
|
|
break; /* full */
|
|
de = (struct dir_entry *)(hd->b_data + ret);/* de is set to the current dir_entry */
|
|
if (!de -> inode )/* to skip if there is no data in de */
|
|
continue;
|
|
/*To write, copying current dirent, */
|
|
temp->d_ino = de->inode;
|
|
temp->d_off = 0;
|
|
temp->d_reclen = ldsize;
|
|
strcpy(temp->d_name,de->name);
|
|
|
|
|
|
/* by put_fs_byte to write back data to the usr */
|
|
memcpy(buf, temp, ldsize);
|
|
for (i=0;i < ldsize;i++){
|
|
put_fs_byte(*(buf+i), ((char*)dirp)+i+ldi);
|
|
}
|
|
/* memcpy(temp, buf, ldsize); */
|
|
ldi += ldsize;
|
|
}
|
|
return ldi;
|
|
}
|
|
|
|
|
|
int do_execve2(unsigned long * eip,long tmp,char * filename,
|
|
char ** argv, char ** envp)
|
|
{
|
|
struct m_inode * inode;
|
|
struct buffer_head * bh;
|
|
struct exec ex;
|
|
unsigned long page[MAX_ARG_PAGES];
|
|
int i,argc,envc;
|
|
int e_uid, e_gid;
|
|
int retval;
|
|
int sh_bang = 0;
|
|
unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
|
|
|
|
if ((0xffff & eip[1]) != 0x000f)
|
|
panic("execve called from supervisor mode");
|
|
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
|
|
page[i]=0;
|
|
if (!(inode=namei(filename))) /* get executables inode */
|
|
return -ENOENT;
|
|
argc = count(argv);
|
|
envc = count(envp);
|
|
|
|
restart_interp:
|
|
if (!S_ISREG(inode->i_mode)) { /* must be regular file */
|
|
retval = -EACCES;
|
|
goto exec_error2;
|
|
}
|
|
i = inode->i_mode;
|
|
e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
|
|
e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
|
|
if (current->euid == inode->i_uid)
|
|
i >>= 6;
|
|
else if (current->egid == inode->i_gid)
|
|
i >>= 3;
|
|
if (!(i & 1) &&
|
|
!((inode->i_mode & 0111) && suser())) {
|
|
retval = -ENOEXEC;
|
|
goto exec_error2;
|
|
}
|
|
if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
|
|
retval = -EACCES;
|
|
goto exec_error2;
|
|
}
|
|
ex = *((struct exec *) bh->b_data); /* read exec-header */
|
|
if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
|
|
/*
|
|
* This section does the #! interpretation.
|
|
* Sorta complicated, but hopefully it will work. -TYT
|
|
*/
|
|
|
|
char buf[1023], *cp, *interp, *i_name, *i_arg;
|
|
unsigned long old_fs;
|
|
|
|
strncpy(buf, bh->b_data+2, 1022);
|
|
brelse(bh);
|
|
iput(inode);
|
|
buf[1022] = '\0';
|
|
if (cp = strchr(buf, '\n')) {
|
|
*cp = '\0';
|
|
for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
|
|
}
|
|
if (!cp || *cp == '\0') {
|
|
retval = -ENOEXEC; /* No interpreter name found */
|
|
goto exec_error1;
|
|
}
|
|
interp = i_name = cp;
|
|
i_arg = 0;
|
|
for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
|
|
if (*cp == '/')
|
|
i_name = cp+1;
|
|
}
|
|
if (*cp) {
|
|
*cp++ = '\0';
|
|
i_arg = cp;
|
|
}
|
|
/*
|
|
* OK, we've parsed out the interpreter name and
|
|
* (optional) argument.
|
|
*/
|
|
if (sh_bang++ == 0) {
|
|
p = copy_strings(envc, envp, page, p, 0);
|
|
p = copy_strings(--argc, argv+1, page, p, 0);
|
|
}
|
|
/*
|
|
* Splice in (1) the interpreter's name for argv[0]
|
|
* (2) (optional) argument to interpreter
|
|
* (3) filename of shell script
|
|
*
|
|
* This is done in reverse order, because of how the
|
|
* user environment and arguments are stored.
|
|
*/
|
|
p = copy_strings(1, &filename, page, p, 1);
|
|
argc++;
|
|
if (i_arg) {
|
|
p = copy_strings(1, &i_arg, page, p, 2);
|
|
argc++;
|
|
}
|
|
p = copy_strings(1, &i_name, page, p, 2);
|
|
argc++;
|
|
if (!p) {
|
|
retval = -ENOMEM;
|
|
goto exec_error1;
|
|
}
|
|
/*
|
|
* OK, now restart the process with the interpreter's inode.
|
|
*/
|
|
old_fs = get_fs();
|
|
set_fs(get_ds());
|
|
if (!(inode=namei(interp))) { /* get executables inode */
|
|
set_fs(old_fs);
|
|
retval = -ENOENT;
|
|
goto exec_error1;
|
|
}
|
|
set_fs(old_fs);
|
|
goto restart_interp;
|
|
}
|
|
brelse(bh);
|
|
if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
|
|
ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
|
|
inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
|
|
retval = -ENOEXEC;
|
|
goto exec_error2;
|
|
}
|
|
if (N_TXTOFF(ex) != BLOCK_SIZE) {
|
|
printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
|
|
retval = -ENOEXEC;
|
|
goto exec_error2;
|
|
}
|
|
if (!sh_bang) {
|
|
p = copy_strings(envc,envp,page,p,0);
|
|
p = copy_strings(argc,argv,page,p,0);
|
|
if (!p) {
|
|
retval = -ENOMEM;
|
|
goto exec_error2;
|
|
}
|
|
}
|
|
/* OK, This is the point of no return */
|
|
if (current->executable)
|
|
iput(current->executable);
|
|
current->executable = inode;
|
|
for (i=0 ; i<32 ; i++)
|
|
current->sigaction[i].sa_handler = NULL;
|
|
for (i=0 ; i<NR_OPEN ; i++)
|
|
if ((current->close_on_exec>>i)&1)
|
|
sys_close(i);
|
|
current->close_on_exec = 0;
|
|
free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
|
|
free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
|
|
|
|
/*we should rewrite here*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**/
|
|
if (last_task_used_math == current)
|
|
last_task_used_math = NULL;
|
|
current->used_math = 0;
|
|
p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
|
|
p = (unsigned long) create_tables((char *)p,argc,envc);
|
|
current->brk = ex.a_bss +
|
|
(current->end_data = ex.a_data +
|
|
(current->end_code = ex.a_text));
|
|
current->start_stack = p & 0xfffff000;
|
|
current->euid = e_uid;
|
|
current->egid = e_gid;
|
|
i = ex.a_text+ex.a_data;
|
|
while (i&0xfff)
|
|
put_fs_byte(0,(char *) (i++));
|
|
eip[0] = ex.a_entry; /* eip, magic happens :-) */
|
|
eip[3] = p; /* stack pointer */
|
|
return 0;
|
|
exec_error2:
|
|
iput(inode);
|
|
exec_error1:
|
|
for (i=0 ; i<MAX_ARG_PAGES ; i++)
|
|
free_page(page[i]);
|
|
return(retval);
|
|
}
|
|
|
|
|
|
int sys_sleep(unsigned int seconds)
|
|
{
|
|
sys_signal(SIGALRM,SIG_IGN);
|
|
sys_alarm(seconds);
|
|
if(sys_pause()!=-1)
|
|
{
|
|
/* printk("sleep\n");*/
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*printk("do not sleep\n");*/
|
|
return -1;
|
|
}
|
|
/*just full the sys_call_table[89]*/
|
|
int sys_something()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*find the father inode constantly*/
|
|
long sys_getcwd(char *buf,size_t size)
|
|
{
|
|
return 0;
|
|
} |