SysIII/usr/src/uts/vax/os/sys2.c
#include "sys/param.h"
#include "sys/systm.h"
#include "sys/dir.h"
#include "sys/user.h"
#include "sys/file.h"
#include "sys/inode.h"
#include "sys/sysinfo.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;
{
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 = (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_rval1 = uap->count-u.u_count;
u.u_ioch += u.u_rval1;
if (mode == FREAD)
sysinfo.readch += u.u_rval1;
else
sysinfo.writech += u.u_rval1;
}
/*
* 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_rval1;
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;
else if (uap->sbase != 0) {
u.u_error = EINVAL;
psignal(u.u_procp, SIGSYS);
return;
}
if (uap->off < 0) {
u.u_error = EINVAL;
return;
}
fp->f_offset = uap->off;
u.u_roff = 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_nlink >= MAXLINK) {
u.u_error = EMLINK;
goto out;
}
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 = (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;
}