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.

402 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>
#include <linux/sched.h> //调度程序头文件。定义了任务结构task_struct,任务0的数据,
//还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语言
#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;
}
//返回从1970年1月1号 开始记时的时间值(s)
int sys_time(long * tloc)
{
int i;
i = CURRENT_TIME;
if (tloc) {
verify_area(tloc,4);
put_fs_long(i,(unsigned long *)tloc); //把时间值存储到用户空间
//段寄存器fs被默认地指向用户数据空间因此此函数可利用fs段寄存器来访问用户空间中的值
}
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)
{
//如果参数值大于代码结尾,并且小于(堆栈-16kb则设置新数据段结尾值
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(void){
return 0;
}
int sys_sleep(unsigned int seconds){
sys_signal(SIGALRM,SIG_IGN);
sys_alarm(seconds);
sys_pause();
return 0;
}
int sys_execve2(){
return 0;
}
/*获取目录的目录项*/
/*fd指目录描述符dirp指目录信息count指目录信息大小*/
int sys_getdents(unsigned int fd,struct linux_dirent *dirp,unsigned int count)
{
struct file *file;
struct m_inode *inode;
struct buffer_head *bh;
struct dir_entry *de;
struct linux_dirent *temp;
char * buf;
int i,len = 0,ret = 0;
if(!count)return -1;
if(fd>=NR_OPEN)return -1; /*fd超过进程最多打开文件数20*/
file=current->filp[fd];
if(!file)return -1;
inode = file->f_inode;
temp = (struct linux_dirent *)malloc(sizeof(struct linux_dirent)); //目录信息
buf = (char*)malloc(sizeof(struct linux_dirent));
bh = bread(inode->i_dev , inode->i_zone[0]); //读取指向的数据块
for (;ret<inode->i_size;ret += sizeof(struct dir_entry)){
if (len >= count-sizeof(struct linux_dirent))
break; /* full */
de = (struct dir_entry *)(bh->b_data + ret);/*de更新为当前目录项*/
if (!de->inode )/*如果节点号为空,就退出*/
continue;
/*用temp保存当前目录项信息*/
temp->d_ino = de->inode;
temp->d_off = 0;
temp->d_reclen = sizeof(struct linux_dirent);
strcpy(temp->d_name,de->name);
/*将数据写回到用户*/
memcpy(buf, temp, sizeof(struct linux_dirent));
for (i=0;i < sizeof(struct linux_dirent);i++){
put_fs_byte(*(buf+i), ((char*)dirp)+len+i); //用来访问用户程序的数据
}
len += sizeof(struct linux_dirent);
}
return len;
}
//参考find_entry
int sys_getcwd(char* buf,size_t size){
struct buffer_head *bh;
struct dir_entry*de,*p_de;
unsigned current_depth = 0;
struct m_inode* current_ino;
struct m_inode* parent_ino;
char* t_buf;
int ret = 0;
t_buf = (char*)malloc(256);
strcpy(t_buf,"");
buf = malloc(size);
if(!buf)return -1;
for(;;){
current_ino = namei(".");
parent_ino = namei("..");
if(current_ino == parent_ino) //找到了根节点
break;
sys_chdir("..");
//read_inode(current_ino); 这是个静态函数
//buf[current_depth++] = read_inode(current_ino);//根据节点号在当前目录查找文件read_inode
bh = bread(parent_ino->i_dev,parent_ino->i_zone[0]);
for(;ret<parent_ino->i_size;ret+=sizeof(struct dir_entry))
{
de = (struct dir_entry*)(bh->b_data + ret);
if(!de->inode)break;
if(de->inode == (current_ino->i_num)){
memcpy(t_buf,de->name,NAME_LEN);
current_depth += NAME_LEN;
break;
}
}
//current_depth++;
}
// int i = current_depth-1;
// for(i;i >= 0;i--){
// printk("/%s",buf[i]);
// }
// printk("%s\n",current_depth==0?"/":"");
// //复制过来
int i;
for(i = 0;t_buf[i];i++){
put_fs_byte(t_buf[i],buf+i);
}
return (int)buf;
}