368 lines
6.1 KiB
C
368 lines
6.1 KiB
C
/******************************************************************************
|
|
*******************************************************************************
|
|
|
|
W E G A - Quelle
|
|
|
|
KERN 3.2 Modul: sys2.c
|
|
|
|
|
|
Bearbeiter: O. Lehmann
|
|
Datum: 18.05.08
|
|
Version: 1.0
|
|
|
|
*******************************************************************************
|
|
******************************************************************************/
|
|
|
|
char sys2wstr[] = "@[$]sys2.c Rev : 4.1 08/27/83 11:59:09";
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/sysinfo.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/file.h>
|
|
#include <sys/inode.h>
|
|
#include <sys/dir.h>
|
|
#include <sys/mmu.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/conf.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/s.out.h>
|
|
#include <sys/user.h>
|
|
|
|
/*
|
|
* read system call
|
|
*/
|
|
read()
|
|
{
|
|
rdwr(FREAD);
|
|
}
|
|
|
|
/*
|
|
* write system call
|
|
*/
|
|
write()
|
|
{
|
|
rdwr(FWRITE);
|
|
}
|
|
|
|
/*
|
|
* common code for read and write calls:
|
|
* check permissions, set base, count, and offset,
|
|
* and switch out to readi or writei code.
|
|
*/
|
|
rdwr(mode)
|
|
register mode;
|
|
{
|
|
int foo,foo2;
|
|
register struct file *fp;
|
|
register struct inode *ip;
|
|
register struct a {
|
|
int fdes;
|
|
char *cbuf;
|
|
unsigned count;
|
|
} *uap;
|
|
int type;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
fp = getf(uap->fdes);
|
|
if (fp == NULL)
|
|
return;
|
|
if ((fp->f_flag&mode) == 0) {
|
|
u.u_error = EBADF;
|
|
return;
|
|
}
|
|
u.u_base.left = (caddr_t)uap->cbuf;
|
|
u.u_count = uap->count;
|
|
u.u_segflg = 0;
|
|
u.u_fmode = fp->f_flag;
|
|
ip = fp->f_inode;
|
|
type = ip->i_mode&IFMT;
|
|
if (type==IFREG || type==IFDIR) {
|
|
plock(ip);
|
|
if ((u.u_fmode&FAPPEND) && (mode == FWRITE))
|
|
fp->f_offset = ip->i_size;
|
|
} else if (type == IFIFO) {
|
|
plock(ip);
|
|
fp->f_offset = 0;
|
|
}
|
|
u.u_offset = fp->f_offset;
|
|
if (mode == FREAD)
|
|
readi(ip);
|
|
else
|
|
writei(ip);
|
|
if (type==IFREG || type==IFDIR || type==IFIFO)
|
|
prele(ip);
|
|
fp->f_offset += uap->count-u.u_count;
|
|
u.u_r.r_val1 = uap->count-u.u_count;
|
|
u.u_ioch += u.u_r.r_val1;
|
|
if (mode == FREAD)
|
|
sysinfo.readch += u.u_r.r_val1;
|
|
else
|
|
sysinfo.writech += u.u_r.r_val1;
|
|
}
|
|
|
|
/*
|
|
* open system call
|
|
*/
|
|
open()
|
|
{
|
|
register struct a {
|
|
char *fname;
|
|
int mode;
|
|
int crtmode;
|
|
} *uap;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
copen(uap->mode-FOPEN, uap->crtmode);
|
|
}
|
|
|
|
/*
|
|
* creat system call
|
|
*/
|
|
creat()
|
|
{
|
|
register struct a {
|
|
char *fname;
|
|
int fmode;
|
|
} *uap;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
copen(FWRITE|FCREAT|FTRUNC, uap->fmode);
|
|
}
|
|
|
|
/*
|
|
* common code for open and creat.
|
|
* Check permissions, allocate an open file structure,
|
|
* and call the device open routine if any.
|
|
*/
|
|
copen(mode, arg)
|
|
register mode;
|
|
{
|
|
register struct inode *ip;
|
|
register struct file *fp;
|
|
int i;
|
|
|
|
if ((mode&(FREAD|FWRITE)) == 0) {
|
|
u.u_error = EINVAL;
|
|
return;
|
|
}
|
|
if (mode&FCREAT) {
|
|
ip = namei(uchar, 1);
|
|
if (ip == NULL) {
|
|
if (u.u_error)
|
|
return;
|
|
ip = maknode(arg&07777&(~ISVTX));
|
|
if (ip == NULL)
|
|
return;
|
|
mode &= ~FTRUNC;
|
|
} else {
|
|
if (mode&FEXCL) {
|
|
u.u_error = EEXIST;
|
|
iput(ip);
|
|
return;
|
|
}
|
|
mode &= ~FCREAT;
|
|
}
|
|
} else {
|
|
ip = namei(uchar, 0);
|
|
if (ip == NULL)
|
|
return;
|
|
}
|
|
if (!(mode&FCREAT)) {
|
|
if (mode&FREAD)
|
|
access(ip, IREAD);
|
|
if (mode&(FWRITE|FTRUNC)) {
|
|
access(ip, IWRITE);
|
|
if ((ip->i_mode&IFMT) == IFDIR)
|
|
u.u_error = EISDIR;
|
|
}
|
|
}
|
|
if (u.u_error || (fp = falloc()) == NULL) {
|
|
iput(ip);
|
|
return;
|
|
}
|
|
if (mode&FTRUNC)
|
|
itrunc(ip);
|
|
prele(ip);
|
|
fp->f_flag = mode&FMASK;
|
|
fp->f_inode = ip;
|
|
i = u.u_r.r_val1;
|
|
if (setjmp(u.u_qsav)) { /* catch half-opens */
|
|
if (u.u_error == 0)
|
|
u.u_error = EINTR;
|
|
u.u_ofile[i] = NULL;
|
|
closef(fp);
|
|
} else {
|
|
openi(ip, mode);
|
|
if (u.u_error == 0)
|
|
return;
|
|
u.u_ofile[i] = NULL;
|
|
fp->f_count--;
|
|
iput(ip);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* close system call
|
|
*/
|
|
close()
|
|
{
|
|
register struct file *fp;
|
|
register struct a {
|
|
int fdes;
|
|
} *uap;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
fp = getf(uap->fdes);
|
|
if (fp == NULL)
|
|
return;
|
|
u.u_ofile[uap->fdes] = NULL;
|
|
closef(fp);
|
|
}
|
|
|
|
/*
|
|
* seek system call
|
|
*/
|
|
seek()
|
|
{
|
|
register struct file *fp;
|
|
register struct inode *ip;
|
|
register struct a {
|
|
int fdes;
|
|
off_t off;
|
|
int sbase;
|
|
} *uap;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
fp = getf(uap->fdes);
|
|
if (fp == NULL)
|
|
return;
|
|
ip = fp->f_inode;
|
|
if ((ip->i_mode&IFMT)==IFIFO) {
|
|
u.u_error = ESPIPE;
|
|
return;
|
|
}
|
|
if (uap->sbase == 1)
|
|
uap->off += fp->f_offset;
|
|
else if (uap->sbase == 2)
|
|
uap->off += fp->f_inode->i_size;
|
|
fp->f_offset = uap->off;
|
|
u.u_r.r_off = uap->off;
|
|
}
|
|
|
|
/*
|
|
* link system call
|
|
*/
|
|
link()
|
|
{
|
|
register struct inode *ip, *xp;
|
|
register struct a {
|
|
char *target;
|
|
char *linkname;
|
|
} *uap;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
ip = namei(uchar, 0);
|
|
if (ip == NULL)
|
|
return;
|
|
if ((ip->i_mode&IFMT)==IFDIR && !suser())
|
|
goto out;
|
|
/*
|
|
* Unlock to avoid possibly hanging the namei.
|
|
* Sadly, this means races. (Suppose someone
|
|
* deletes the file in the meantime?)
|
|
* Nor can it be locked again later
|
|
* because then there will be deadly
|
|
* embraces.
|
|
*/
|
|
prele(ip);
|
|
u.u_dirp.l = (caddr_t)uap->linkname;
|
|
xp = namei(uchar, 1);
|
|
if (xp != NULL) {
|
|
u.u_error = EEXIST;
|
|
iput(xp);
|
|
goto out;
|
|
}
|
|
if (u.u_error)
|
|
goto out;
|
|
if (u.u_pdir->i_dev != ip->i_dev) {
|
|
iput(u.u_pdir);
|
|
u.u_error = EXDEV;
|
|
goto out;
|
|
}
|
|
wdir(ip);
|
|
if (u.u_error==0) {
|
|
ip->i_nlink++;
|
|
ip->i_flag |= ICHG;
|
|
}
|
|
|
|
out:
|
|
iput(ip);
|
|
}
|
|
|
|
/*
|
|
* mknod system call
|
|
*/
|
|
mknod()
|
|
{
|
|
register struct inode *ip;
|
|
register struct a {
|
|
char *fname;
|
|
int fmode;
|
|
dev_t dev;
|
|
} *uap;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
if ((uap->fmode&IFMT) != IFIFO && !suser())
|
|
return;
|
|
ip = namei(uchar, 1);
|
|
if (ip != NULL) {
|
|
u.u_error = EEXIST;
|
|
goto out;
|
|
}
|
|
if (u.u_error)
|
|
return;
|
|
ip = maknode(uap->fmode);
|
|
if (ip == NULL)
|
|
return;
|
|
switch(ip->i_mode&IFMT) {
|
|
case IFCHR:
|
|
case IFBLK:
|
|
ip->i_rdev = (dev_t)uap->dev;
|
|
ip->i_flag |= ICHG;
|
|
}
|
|
|
|
out:
|
|
iput(ip);
|
|
}
|
|
|
|
/*
|
|
* access system call
|
|
*/
|
|
saccess()
|
|
{
|
|
register svuid, svgid;
|
|
register struct inode *ip;
|
|
register struct a {
|
|
char *fname;
|
|
int fmode;
|
|
} *uap;
|
|
|
|
uap = (struct a *)u.u_ap;
|
|
svuid = u.u_uid;
|
|
svgid = u.u_gid;
|
|
u.u_uid = u.u_ruid;
|
|
u.u_gid = u.u_rgid;
|
|
ip = namei(uchar, 0);
|
|
if (ip != NULL) {
|
|
if (uap->fmode&(IREAD>>6))
|
|
access(ip, IREAD);
|
|
if (uap->fmode&(IWRITE>>6))
|
|
access(ip, IWRITE);
|
|
if (uap->fmode&(IEXEC>>6))
|
|
access(ip, IEXEC);
|
|
iput(ip);
|
|
}
|
|
u.u_uid = svuid;
|
|
u.u_gid = svgid;
|
|
}
|