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.

410 lines
8.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* linux/kernel/sys.c
*
* (C) 1991 Linus Torvalds
*/
#include <errno.h>
#define __LIBRARY__
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/kernel.h>
#include <asm/segment.h>
#include <sys/times.h>
#include <sys/utsname.h>
#include <fcntl.h>
int sys_ftime()
{
return -ENOSYS;
}
int sys_break()
{
return -ENOSYS;
}
int sys_ptrace()
{
return -ENOSYS;
}
int sys_stty()
{
return -ENOSYS;
}
int sys_gtty()
{
return -ENOSYS;
}
int sys_rename()
{
return -ENOSYS;
}
int sys_prof()
{
return -ENOSYS;
}
int sys_setregid(int rgid, int egid)
{
if (rgid>0) {
if ((current->gid == rgid) ||
suser())
current->gid = rgid;
else
return(-EPERM);
}
if (egid>0) {
if ((current->gid == egid) ||
(current->egid == egid) ||
suser()) {
current->egid = egid;
current->sgid = egid;
} else
return(-EPERM);
}
return 0;
}
int sys_setgid(int gid)
{
/* return(sys_setregid(gid, gid)); */
if (suser())
current->gid = current->egid = current->sgid = gid;
else if ((gid == current->gid) || (gid == current->sgid))
current->egid = gid;
else
return -EPERM;
return 0;
}
int sys_acct()
{
return -ENOSYS;
}
int sys_phys()
{
return -ENOSYS;
}
int sys_lock()
{
return -ENOSYS;
}
int sys_mpx()
{
return -ENOSYS;
}
int sys_ulimit()
{
return -ENOSYS;
}
int sys_time(long * tloc)
{
int i;
i = CURRENT_TIME;
if (tloc) {
verify_area(tloc,4);
put_fs_long(i,(unsigned long *)tloc);
}
return i;
}
/*
* Unprivileged users may change the real user id to the effective uid
* or vice versa.
*/
int sys_setreuid(int ruid, int euid)
{
int old_ruid = current->uid;
if (ruid>0) {
if ((current->euid==ruid) ||
(old_ruid == ruid) ||
suser())
current->uid = ruid;
else
return(-EPERM);
}
if (euid>0) {
if ((old_ruid == euid) ||
(current->euid == euid) ||
suser()) {
current->euid = euid;
current->suid = euid;
} else {
current->uid = old_ruid;
return(-EPERM);
}
}
return 0;
}
int sys_setuid(int uid)
{
/* return(sys_setreuid(uid, uid)); */
if (suser())
current->uid = current->euid = current->suid = uid;
else if ((uid == current->uid) || (uid == current->suid))
current->euid = uid;
else
return -EPERM;
return(0);
}
int sys_stime(long * tptr)
{
if (!suser())
return -EPERM;
startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
return 0;
}
int sys_times(struct tms * tbuf)
{
if (tbuf) {
verify_area(tbuf,sizeof *tbuf);
put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
}
return jiffies;
}
int sys_brk(unsigned long end_data_seg)
{
if (end_data_seg >= current->end_code &&
end_data_seg < current->start_stack - 16384)
current->brk = end_data_seg;
return current->brk;
}
/*
* This needs some heave checking ...
* I just haven't get the stomach for it. I also don't fully
* understand sessions/pgrp etc. Let somebody who does explain it.
*/
int sys_setpgid(int pid, int pgid)
{
int i;
if (!pid)
pid = current->pid;
if (!pgid)
pgid = current->pid;
for (i=0 ; i<NR_TASKS ; i++)
if (task[i] && task[i]->pid==pid) {
if (task[i]->leader)
return -EPERM;
if (task[i]->session != current->session)
return -EPERM;
task[i]->pgrp = pgid;
return 0;
}
return -ESRCH;
}
int sys_getpgrp(void)
{
return current->pgrp;
}
int sys_setsid(void)
{
if (current->leader && !suser())
return -EPERM;
current->leader = 1;
current->session = current->pgrp = current->pid;
current->tty = -1;
return current->pgrp;
}
int sys_getgroups()
{
return -ENOSYS;
}
int sys_setgroups()
{
return -ENOSYS;
}
int sys_uname(struct utsname * name)
{
static struct utsname thisname = {
"linux .0","nodename","release ","version ","machine "
};
int i;
if (!name) return -ERROR;
verify_area(name,sizeof *name);
for(i=0;i<sizeof *name;i++)
put_fs_byte(((char *) &thisname)[i],i+(char *) name);
return 0;
}
int sys_sethostname()
{
return -ENOSYS;
}
int sys_getrlimit()
{
return -ENOSYS;
}
int sys_setrlimit()
{
return -ENOSYS;
}
int sys_getrusage()
{
return -ENOSYS;
}
int sys_gettimeofday()
{
return -ENOSYS;
}
int sys_settimeofday()
{
return -ENOSYS;
}
int sys_umask(int mask)
{
int old = current->umask;
current->umask = mask & 0777;
return (old);
}
int sys_pipe2(int * pipefd,int flags)
{
sys_pipe(pipefd);
return 0;
}
int sys_sleep(unsigned int seconds){
sys_signal(SIGALRM , SIG_IGN);//收到SIGALRM信号则忽略啥也不干
sys_alarm(seconds);//设定一个时长为seconds秒的闹钟
/*
系统调用pause函数来暂停当前进程当前进程进入睡眠状态。
直到接收到信号且信号函数成功返回pause函数才会返回而且返回值为-1。
*/
sys_pause();
return 0;
}
#define NAME_MAX 14
/////////////////////////sys_getdents//////////////////////////
struct linux_dirent { //专为输出的目录项结构
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[NAME_MAX+1];
};
int sys_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
{
//初始化
struct file *file; //文件结构
struct m_inode *inode; //索引节点结构inode
struct buffer_head *bufhd; //缓冲块头结构
struct dir_entry *d_entry; //目录项结构(内存)
int linux_dirent_size = sizeof(struct linux_dirent);
int dir_entry_size = sizeof(struct dir_entry);
int l = 0;//l为已读linux_dirent总字节数
int d = 0;//d为已读页表项的总字节数
int i;
//检查参数合法性
if(fd >= NR_OPEN) return -1; //目录的文件描述符错误
if(count < linux_dirent_size) return -1;//写入的字节数不足一个linux_dirent
file = current->filp[fd];
if(!file) return -1; //没读到目录文件
//读目录
inode = file->f_inode; //目录的索引节点
struct linux_dirent *dirp_tmp; //专为输出的目录项结构,为dirp的赋值而开
dirp_tmp = (struct dirent *)malloc(linux_dirent_size);
char * buf; //为dirp的赋值而开大小为一个linux_dirent
buf = (char*)malloc(linux_dirent_size);
bufhd = bread(inode->i_dev , inode->i_zone[0]);//读出目录索引节点中的第一个数据块的内容
for( ; d < inode->i_size ; d += dir_entry_size)
{
//printk("***\n");
if (l >= count - linux_dirent_size) break;//dirp已经满了返回读取的字节数 //buggy
//bufhd->b_data 是char*类型的指针(char为一字节),因此+d可以到这个目录项
d_entry = (struct dir_entry *)(bufhd->b_data + d);
//printk("&&&\n");
//读到了目录的最后一项则返回0
if(!d_entry->inode) continue;
//将目录项信息从dir_entry转移到dirp_tmp //d_entry(dir_entry)----->dirp_tmp(linux_dirent)
dirp_tmp->d_ino = d_entry->inode;
dirp_tmp->d_off = 0;
dirp_tmp->d_reclen = linux_dirent_size;
strcpy(dirp_tmp->d_name,d_entry->name);
//将dirp_tmp的信息转化成char类型并存到buf //dirp_tmp(linux_dirent)--->buf(char)
memcpy(buf,dirp_tmp,linux_dirent_size);
//利用put_fs_byte将buf(在核心数据段)逐字节存入dirp(在用户数据段段基址在fs即fs:[addr])
for(i=0 ; i < linux_dirent_size ; i++){ //buf(char)--->dirp数组(linux_dirent)
put_fs_byte(*(buf+i), ((char*)dirp)+l+i);
}
l += linux_dirent_size;
}
return l;
}
char * sys_getcwd(char * buf, size_t size){
}
int sys_execve2(){};
long sys_mmap(void *start, size_t len, int prot, int flags,
int fd, off_t off){}
int sys_munmap(void * start, size_t len){}
int sys_clone(int (*fn)(void *), void *child_stack, int flags, void *arg){}