From 88a7a62ac37860454424240400aa10e0319144c7 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Fri, 27 May 1983 19:51:31 -0800 Subject: [PATCH] merge of bill's code plus lint (plus, of course, cleanup of bill's bugs) SCCS-vsn: sys/kern/kern_clock.c 4.54 SCCS-vsn: sys/kern/kern_descrip.c 5.24 SCCS-vsn: sys/kern/kern_proc.c 4.64 SCCS-vsn: sys/kern/kern_prot.c 5.17 SCCS-vsn: sys/kern/kern_resource.c 4.22 SCCS-vsn: sys/kern/kern_sig.c 5.17 SCCS-vsn: sys/kern/kern_time.c 5.15 SCCS-vsn: sys/kern/subr_prf.c 4.27 SCCS-vsn: sys/kern/subr_xxx.c 4.22 SCCS-vsn: sys/kern/sys_generic.c 5.36 SCCS-vsn: sys/kern/tty.c 4.41 SCCS-vsn: sys/kern/tty_bk.c 4.9 SCCS-vsn: sys/kern/tty_conf.c 4.3 SCCS-vsn: sys/kern/tty_pty.c 4.31 SCCS-vsn: sys/kern/tty_subr.c 4.20 SCCS-vsn: sys/kern/tty_tb.c 4.8 SCCS-vsn: sys/ufs/ffs/ffs_alloc.c 2.26 SCCS-vsn: sys/ufs/lfs/lfs_alloc.c 2.26 SCCS-vsn: sys/kern/vfs_vnops.c 4.35 SCCS-vsn: sys/kern/vfs_syscalls.c 4.57 SCCS-vsn: sys/ufs/ffs/ffs_vnops.c 4.57 SCCS-vsn: sys/ufs/ffs/ufs_vnops.c 4.57 SCCS-vsn: sys/ufs/lfs/lfs_vnops.c 4.57 SCCS-vsn: sys/ufs/ufs/ufs_vnops.c 4.57 SCCS-vsn: sys/ufs/ffs/ffs_tables.c 2.4 SCCS-vsn: sys/kern/vfs_xxx.c 4.5 SCCS-vsn: sys/kern/uipc_mbuf.c 1.43 SCCS-vsn: sys/kern/uipc_proto.c 4.28 SCCS-vsn: sys/kern/uipc_socket.c 4.75 SCCS-vsn: sys/kern/uipc_socket2.c 4.37 SCCS-vsn: sys/kern/uipc_syscalls.c 4.46 SCCS-vsn: sys/kern/uipc_usrreq.c 1.10 --- usr/src/sys/kern/kern_clock.c | 107 ++-- usr/src/sys/kern/kern_descrip.c | 474 +++++---------- usr/src/sys/kern/kern_proc.c | 992 +------------------------------ usr/src/sys/kern/kern_prot.c | 79 +-- usr/src/sys/kern/kern_resource.c | 85 +-- usr/src/sys/kern/kern_sig.c | 109 +--- usr/src/sys/kern/kern_time.c | 72 +-- usr/src/sys/kern/subr_prf.c | 4 +- usr/src/sys/kern/subr_xxx.c | 4 +- usr/src/sys/kern/sys_generic.c | 560 +++++++---------- usr/src/sys/kern/tty.c | 217 ++++--- usr/src/sys/kern/tty_bk.c | 4 +- usr/src/sys/kern/tty_conf.c | 19 +- usr/src/sys/kern/tty_pty.c | 6 +- usr/src/sys/kern/tty_subr.c | 33 +- usr/src/sys/kern/tty_tb.c | 4 +- usr/src/sys/kern/uipc_mbuf.c | 2 +- usr/src/sys/kern/uipc_proto.c | 4 +- usr/src/sys/kern/uipc_socket.c | 326 +++++----- usr/src/sys/kern/uipc_socket2.c | 119 ++-- usr/src/sys/kern/uipc_syscalls.c | 466 +++++++++------ usr/src/sys/kern/uipc_usrreq.c | 257 +++++++- usr/src/sys/kern/vfs_syscalls.c | 555 ++++++++++------- usr/src/sys/kern/vfs_vnops.c | 28 +- usr/src/sys/kern/vfs_xxx.c | 17 +- usr/src/sys/ufs/ffs/ffs_alloc.c | 12 +- usr/src/sys/ufs/ffs/ffs_tables.c | 15 +- usr/src/sys/ufs/ffs/ffs_vnops.c | 555 ++++++++++------- usr/src/sys/ufs/ffs/ufs_vnops.c | 555 ++++++++++------- usr/src/sys/ufs/lfs/lfs_alloc.c | 12 +- usr/src/sys/ufs/lfs/lfs_vnops.c | 555 ++++++++++------- usr/src/sys/ufs/ufs/ufs_vnops.c | 555 ++++++++++------- 32 files changed, 3073 insertions(+), 3729 deletions(-) diff --git a/usr/src/sys/kern/kern_clock.c b/usr/src/sys/kern/kern_clock.c index fffeb95e9f..875b45a615 100644 --- a/usr/src/sys/kern/kern_clock.c +++ b/usr/src/sys/kern/kern_clock.c @@ -1,4 +1,4 @@ -/* kern_clock.c 4.53 83/05/21 */ +/* kern_clock.c 4.54 83/05/27 */ #include "../machine/reg.h" #include "../machine/psl.h" @@ -43,21 +43,10 @@ extern int phz; /* * TODO: - * * Keep more accurate statistics by simulating good interval timers. - * * Use the time-of-day clock on the VAX to keep more accurate time - * than is possible by repeated use of the interval timer. - * * Allocate more timeout table slots when table overflows. - * * Get all resource allocation to use second timer. + * time of day, system/user timing, timeouts, profiling on separate timers + * allocate more timeout table slots when table overflows. */ -/* bump a timeval by a small number of usec's */ -#define bumptime(tp, usec) \ - (tp)->tv_usec += usec; \ - if ((tp)->tv_usec >= 1000000) { \ - (tp)->tv_usec -= 1000000; \ - (tp)->tv_sec++; \ - } - /* * The hz hardware interval timer. * We update the events relating to real time. @@ -75,17 +64,14 @@ hardclock(pc, ps) hardclock(regs) struct regs regs; { - int ps = regs.r_sr; - caddr_t pc = (caddr_t)regs.r_pc; +#define ps regs.r_sr +#define pc (caddr_t)regs.r_pc #endif register struct callout *p1; register struct proc *p; register int s, cpstate; + int needsoft = 0; -#ifdef sun - if (USERMODE(ps)) /* aston needs ar0 */ - u.u_ar0 = ®s.r_r0; -#endif /* * Update real-time timeout queue. * At front of queue are some number of events which are ``due''. @@ -96,10 +82,15 @@ hardclock(regs) * Decrementing just the first of these serves to decrement the time * to all events. */ - for (p1 = calltodo.c_next; p1 && p1->c_time <= 0; p1 = p1->c_next) - --p1->c_time; - if (p1) - --p1->c_time; + p1 = calltodo.c_next; + while (p1) { + if (--p1->c_time > 0) + break; + needsoft = 1; + if (p1->c_time == 0) + break; + p1 = p1->c_next; + } /* * Charge the time out based on the mode the cpu is in. @@ -108,6 +99,11 @@ hardclock(regs) * one tick. */ if (USERMODE(ps)) { +#ifdef sun + u.u_ar0 = ®s.r_r0; /* aston needs ar0 */ +#endif + if (u.u_prof.pr_scale) + needsoft = 1; /* * CPU was in user state. Increment * user time counter, and process process-virtual time @@ -221,8 +217,13 @@ hardclock(regs) * priority any longer than necessary. */ bumptime(&time, tick); - setsoftclock(); + if (needsoft) + setsoftclock(); } +#ifdef sun +#undef pc +#undef ps +#endif /* * Gather statistics on resource utilization. @@ -232,6 +233,7 @@ hardclock(regs) * or idle state) for the entire last time interval, and * update statistics accordingly. */ +/*ARGSUSED*/ gatherstats(pc, ps) caddr_t pc; int ps; @@ -288,8 +290,8 @@ softclock(pc, ps) #ifdef sun softclock() { - int ps = u.u_ar0[PS]; - caddr_t pc = (caddr_t)u.u_ar0[PC]; +#define pc (caddr_t)u.u_ar0[PC] +#define ps u.u_ar0[PS] #endif for (;;) { @@ -320,19 +322,33 @@ softclock() } /* - * Arrange that (*fun)(arg) is called in tim/hz seconds. + * Bump a timeval by a small number of usec's. + */ +bumptime(tp, usec) + register struct timeval *tp; + int usec; +{ + + tp->tv_usec += usec; + if (tp->tv_usec >= 1000000) { + tp->tv_usec -= 1000000; + tp->tv_sec++; + } +} + +/* + * Arrange that (*fun)(arg) is called in t/hz seconds. */ -timeout(fun, arg, tim) +timeout(fun, arg, t) int (*fun)(); caddr_t arg; - int tim; + register int t; { register struct callout *p1, *p2, *pnew; - register int t; - int s; + register int s = spl7(); - t = tim; - s = spl7(); + if (t == 0) + t = 1; pnew = callfree; if (pnew == NULL) panic("timeout table overflow"); @@ -407,3 +423,26 @@ hzto(tv) splx(s); return (ticks); } + +profil() +{ + register struct a { + short *bufbase; + unsigned bufsize; + unsigned pcoffset; + unsigned pcscale; + } *uap = (struct a *)u.u_ap; + register struct uprof *upp = &u.u_prof; + + upp->pr_base = uap->bufbase; + upp->pr_size = uap->bufsize; + upp->pr_off = uap->pcoffset; + upp->pr_scale = uap->pcscale; +} + +opause() +{ + + for (;;) + sleep((caddr_t)&u, PSLEP); +} diff --git a/usr/src/sys/kern/kern_descrip.c b/usr/src/sys/kern/kern_descrip.c index 5bd7a0a682..81b5652784 100644 --- a/usr/src/sys/kern/kern_descrip.c +++ b/usr/src/sys/kern/kern_descrip.c @@ -1,4 +1,4 @@ -/* kern_descrip.c 5.23 83/01/17 */ +/* kern_descrip.c 5.24 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -13,7 +13,7 @@ #include "../h/socketvar.h" #include "../h/mount.h" -#include "../h/descrip.h" +#include "../h/ioctl.h" /* * Descriptor management. @@ -21,8 +21,8 @@ /* * TODO: - * getf should be renamed - * ufalloc side effects are gross + * increase NOFILE + * eliminate u.u_error side effects */ /* @@ -34,26 +34,6 @@ getdtablesize() u.u_r.r_val1 = NOFILE; } -getdprop() -{ - register struct a { - int d; - struct dtype *dtypeb; - } *uap = (struct a *)u.u_ap; - register struct file *fp; - struct dtype adtype; - - fp = getf(uap->d); - if (fp == 0) - return; - adtype.dt_type = 0; /* XXX */ - adtype.dt_protocol = 0; /* XXX */ - u.u_error = copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, - sizeof (struct dtype)); - if (u.u_error) - return; -} - getdopt() { @@ -77,10 +57,10 @@ dup() fp = getf(uap->i); if (fp == 0) return; - j = ufalloc(); + j = ufalloc(0); if (j < 0) return; - dupit(j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK)); + dupit(j, fp, u.u_pofile[uap->i]); } dup2() @@ -103,13 +83,13 @@ dup2() if (u.u_ofile[uap->j]) { if (u.u_pofile[uap->j] & UF_MAPPED) munmapfd(uap->j); - closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); + closef(u.u_ofile[uap->j], u.u_pofile[uap->j]); if (u.u_error) return; /* u.u_ofile[uap->j] = 0; */ /* u.u_pofile[uap->j] = 0; */ } - dupit(uap->j, fp, u.u_pofile[uap->i] & (UF_SHLOCK|UF_EXLOCK)); + dupit(uap->j, fp, u.u_pofile[uap->i]); } dupit(fd, fp, lockflags) @@ -121,264 +101,167 @@ dupit(fd, fp, lockflags) u.u_ofile[fd] = fp; u.u_pofile[fd] = lockflags; fp->f_count++; +/* THIS DOESN'T BELONG HERE */ if (lockflags&UF_SHLOCK) - fp->f_inode->i_shlockc++; + ((struct inode *)fp->f_data)->i_shlockc++; if (lockflags&UF_EXLOCK) - fp->f_inode->i_exlockc++; + ((struct inode *)fp->f_data)->i_exlockc++; +/* END DOESN'T BELONG */ } -close() +/* + * The file control system call. + */ +fcntl() { - register struct a { - int i; - } *uap = (struct a *)u.u_ap; register struct file *fp; - - fp = getf(uap->i); - if (fp == 0) - return; - if (u.u_pofile[uap->i] & UF_MAPPED) - munmapfd(uap->i); - closef(fp, 0, u.u_pofile[uap->i]); - /* WHAT IF u.u_error ? */ - u.u_ofile[uap->i] = NULL; - u.u_pofile[uap->i] = 0; -} - -wrap() -{ register struct a { - int d; - struct dtype *dtypeb; - } *uap = (struct a *)u.u_ap; - register struct file *fp; - struct dtype adtype; + int fdes; + int cmd; + int arg; + } *uap; + register i; + register char *pop; - fp = getf(uap->d); - if (fp == 0) - return; - u.u_error = copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, - sizeof (struct dtype)); - if (u.u_error) + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if (fp == NULL) return; - /* DO WRAP */ -} - -int unselect(); -int nselcoll; -/* - * Select system call. - */ -select() -{ - register struct uap { - int nd; - long *in; - long *ou; - long *ex; - struct timeval *tv; - } *uap = (struct uap *)u.u_ap; - int ibits[3], obits[3]; - struct timeval atv; - int s, ncoll; - label_t lqsave; - - obits[0] = obits[1] = obits[2] = 0; - if (uap->nd > NOFILE) - uap->nd = NOFILE; /* forgiving, if slightly wrong */ - -#define getbits(name, x) \ - if (uap->name) { \ - u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ - sizeof (ibits[x])); \ - if (u.u_error) \ - goto done; \ - } else \ - ibits[x] = 0; - getbits(in, 0); - getbits(ou, 1); - getbits(ex, 2); -#undef getbits - - if (uap->tv) { - u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, - sizeof (atv)); - if (u.u_error) - goto done; - if (itimerfix(&atv)) { + pop = &u.u_pofile[uap->fdes]; + switch(uap->cmd) { + case 0: + i = uap->arg; + if (i < 0 || i > NOFILE) { u.u_error = EINVAL; - goto done; - } - s = spl7(); timevaladd(&atv, &time); splx(s); - } -retry: - ncoll = nselcoll; - u.u_procp->p_flag |= SSEL; - u.u_r.r_val1 = selscan(ibits, obits); - if (u.u_error || u.u_r.r_val1) - goto done; - s = spl6(); - if (uap->tv && timercmp(&time, &atv, >=)) { - splx(s); - goto done; - } - if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { - u.u_procp->p_flag &= ~SSEL; - splx(s); - goto retry; - } - u.u_procp->p_flag &= ~SSEL; - if (uap->tv) { - lqsave = u.u_qsave; - if (setjmp(&u.u_qsave)) { - untimeout(unselect, (caddr_t)u.u_procp); - u.u_error = EINTR; - splx(s); - goto done; + return; } - timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); - } - sleep((caddr_t)&selwait, PZERO+1); - if (uap->tv) { - u.u_qsave = lqsave; - untimeout(unselect, (caddr_t)u.u_procp); - } - splx(s); - goto retry; -done: -#define putbits(name, x) \ - if (uap->name) { \ - int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ - sizeof (obits[x])); \ - if (error) \ - u.u_error = error; \ - } - putbits(in, 0); - putbits(ou, 1); - putbits(ex, 2); -#undef putbits -} + if ((i = ufalloc(i)) < 0) + return; + dupit(i, fp, *pop); + break; -unselect(p) - register struct proc *p; -{ - register int s = spl6(); + case 1: + u.u_r.r_val1 = *pop & 1; + break; - switch (p->p_stat) { + case 2: + *pop = (*pop &~ 1) | (uap->arg & 1); + break; - case SSLEEP: - setrun(p); + case 3: + u.u_r.r_val1 = fp->f_flag+FOPEN; break; - case SSTOP: - unsleep(p); + case 4: + fp->f_flag &= FCNTLCANT; + fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; + u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); + if (u.u_error) + break; + u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); + if (u.u_error) + (void) fset(fp, FNDELAY, 0); break; + + case 5: + u.u_error = fsetown(fp, uap->arg); + break; + + case 6: + u.u_error = fgetown(fp, &u.u_r.r_val1); + break; + + default: + u.u_error = EINVAL; } - splx(s); } -selscan(ibits, obits) - int *ibits, *obits; -{ - register int which, bits, i; - int flag; +fset(fp, bit, value) struct file *fp; - int able; - struct inode *ip; - int n = 0; + int bit, value; +{ - for (which = 0; which < 3; which++) { - bits = ibits[which]; - obits[which] = 0; - switch (which) { + if (value) + fp->f_flag |= bit; + else + fp->f_flag &= ~bit; + return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), + (caddr_t)&value)); +} - case 0: - flag = FREAD; break; +fgetown(fp, valuep) + struct file *fp; + int *valuep; +{ + int error; - case 1: - flag = FWRITE; break; + switch (fp->f_type) { - case 2: - flag = 0; break; - } - while (i = ffs(bits)) { - bits &= ~(1<<(i-1)); - fp = u.u_ofile[i-1]; - if (fp == NULL) { - u.u_error = EBADF; - break; - } - if (fp->f_type == DTYPE_SOCKET) - able = soselect(fp->f_socket, flag); - else { - ip = fp->f_inode; - switch (ip->i_mode & IFMT) { - - case IFCHR: - able = - (*cdevsw[major(ip->i_rdev)].d_select) - (ip->i_rdev, flag); - break; - - case IFBLK: - case IFREG: - case IFDIR: - able = 1; - break; - } - - } - if (able) { - obits[which] |= (1<<(i-1)); - n++; - } - } + case DTYPE_SOCKET: + *valuep = ((struct socket *)fp->f_data)->so_pgrp; + return (0); + + default: + error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); + *valuep = -*valuep; + return (error); } - return (n); } -/*ARGSUSED*/ -seltrue(dev, flag) - dev_t dev; - int flag; +fsetown(fp, value) + struct file *fp; + int value; { - return (1); + if (fp->f_type == DTYPE_SOCKET) { + ((struct socket *)fp->f_data)->so_pgrp = value; + return (0); + } + if (value > 0) { + struct proc *p = pfind(value); + if (p == 0) + return (EINVAL); + value = p->p_pgrp; + } else + value = -value; + return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); } -selwakeup(p, coll) - register struct proc *p; - int coll; +fioctl(fp, cmd, value) + struct file *fp; + int cmd; + caddr_t value; { - if (coll) { - nselcoll++; - wakeup((caddr_t)&selwait); - } - if (p) { - int s = spl6(); - if (p->p_wchan == (caddr_t)&selwait) - setrun(p); - else if (p->p_flag & SSEL) - p->p_flag &= ~SSEL; - splx(s); - } + return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); } -revoke() +close() { + register struct a { + int i; + } *uap = (struct a *)u.u_ap; + register struct file *fp; - /* XXX */ + fp = getf(uap->i); + if (fp == 0) + return; + if (u.u_pofile[uap->i] & UF_MAPPED) + munmapfd(uap->i); + closef(fp, u.u_pofile[uap->i]); + /* WHAT IF u.u_error ? */ + u.u_ofile[uap->i] = NULL; + u.u_pofile[uap->i] = 0; } /* * Allocate a user file descriptor. */ -ufalloc() +ufalloc(i) + register int i; { - register i; - for (i=0; if_count++; + fp->f_count = 1; + fp->f_data = 0; fp->f_offset = 0; - fp->f_inode = 0; lastf = fp + 1; return (fp); } + /* * Convert a user supplied file descriptor into a pointer * to a file structure. Only task is to check range of the descriptor. - * Critical paths should use the GETF macro, defined in inline.h. + * Critical paths should use the GETF macro. */ struct file * getf(f) @@ -443,94 +337,26 @@ getf(f) /* * Internal form of close. - * Decrement reference count on - * file structure. - * Also make sure the pipe protocol - * does not constipate. - * - * Decrement reference count on the inode following - * removal to the referencing file structure. - * Call device handler on last close. - * Nouser indicates that the user isn't available to present - * errors to. - * - * Handling locking at this level is RIDICULOUS. + * Decrement reference count on file structure. + * If last reference not going away, but no more + * references except in message queues, run a + * garbage collect. This would better be done by + * forcing a gc() to happen sometime soon, rather + * than running one each time. */ -closef(fp, nouser, flags) +closef(fp, flags) register struct file *fp; - int nouser, flags; + int flags; /* XXX */ { - register struct inode *ip; - register struct mount *mp; - int flag, mode; - dev_t dev; - register int (*cfunc)(); if (fp == NULL) return; if (fp->f_count > 1) { fp->f_count--; + if (fp->f_count == fp->f_msgcount) + unp_gc(); return; } - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = soclose(fp->f_socket, nouser); - if (nouser == 0 && u.u_error) - return; - fp->f_socket = 0; - fp->f_count = 0; - return; - } - flag = fp->f_flag; - ip = fp->f_inode; - dev = (dev_t)ip->i_rdev; - mode = ip->i_mode & IFMT; - flags &= UF_SHLOCK|UF_EXLOCK; /* conservative */ - if (flags) - funlocki(ip, flags); - ilock(ip); - iput(ip); + (*fp->f_ops->fo_close)(fp, flags); fp->f_count = 0; - - switch (mode) { - - case IFCHR: - cfunc = cdevsw[major(dev)].d_close; - break; - - case IFBLK: - /* - * We don't want to really close the device if it is mounted - */ - for (mp = mount; mp < &mount[NMOUNT]; mp++) - if (mp->m_bufp != NULL && mp->m_dev == dev) - return; - cfunc = bdevsw[major(dev)].d_close; - break; - - default: - return; - } - for (fp = file; fp < fileNFILE; fp++) { - if (fp->f_type == DTYPE_SOCKET) /* XXX */ - continue; - if (fp->f_count && (ip = fp->f_inode) && - ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) - return; - } - if (mode == IFBLK) { - /* - * On last close of a block device (that isn't mounted) - * we must invalidate any in core blocks - */ - bflush(dev); - binval(dev); - } - (*cfunc)(dev, flag, fp); -} - -opause() -{ - - for (;;) - sleep((caddr_t)&u, PSLEP); } diff --git a/usr/src/sys/kern/kern_proc.c b/usr/src/sys/kern/kern_proc.c index 80ba6aa038..0363ade080 100644 --- a/usr/src/sys/kern/kern_proc.c +++ b/usr/src/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* kern_proc.c 4.63 83/05/21 */ +/* kern_proc.c 4.64 83/05/27 */ #include "../machine/reg.h" #include "../machine/pte.h" @@ -20,830 +20,12 @@ #include "../h/text.h" #include "../h/file.h" #include "../h/quota.h" -#include "../h/descrip.h" #include "../h/uio.h" #include "../h/mbuf.h" #include "../h/nami.h" -gethostid() -{ - - u.u_r.r_val1 = hostid; -} - -sethostid() -{ - struct a { - int hostid; - } *uap = (struct a *)u.u_ap; - - if (suser()) - hostid = uap->hostid; -} - -gethostname() -{ - register struct a { - char *hostname; - int len; - } *uap = (struct a *)u.u_ap; - register u_int len; - - len = uap->len; - if (len > hostnamelen + 1) - len = hostnamelen + 1; - u.u_error = copyout((caddr_t)hostname, (caddr_t)uap->hostname, len); -} - -sethostname() -{ - register struct a { - char *hostname; - u_int len; - } *uap = (struct a *)u.u_ap; - - if (!suser()) - return; - if (uap->len > sizeof (hostname) - 1) { - u.u_error = EINVAL; - return; - } - hostnamelen = uap->len; - u.u_error = copyin((caddr_t)uap->hostname, hostname, uap->len); - hostname[hostnamelen] = 0; -} - -/* - * exec system call, with and without environments. - */ -struct execa { - char *fname; - char **argp; - char **envp; -}; - -execv() -{ - ((struct execa *)u.u_ap)->envp = NULL; - execve(); -} - -execve() -{ - register nc; - register char *cp; - register struct buf *bp; - register struct execa *uap; - int na, ne, ucp, ap, c; - int indir, uid, gid; - char *sharg; - struct inode *ip; - swblk_t bno; - char cfname[MAXCOMLEN + 1]; - char cfarg[SHSIZE]; - int resid; - - if ((ip = namei(uchar, LOOKUP, 1)) == NULL) - return; - bno = 0; - bp = 0; - indir = 0; - uid = u.u_uid; - gid = u.u_gid; - if (ip->i_mode & ISUID) - uid = ip->i_uid; - if (ip->i_mode & ISGID) - gid = ip->i_gid; - - again: - if (access(ip, IEXEC)) - goto bad; - if ((u.u_procp->p_flag&STRC) && access(ip, IREAD)) - goto bad; - if ((ip->i_mode & IFMT) != IFREG || - (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { - u.u_error = EACCES; - goto bad; - } - - /* - * Read in first few bytes of file for segment sizes, ux_mag: - * 407 = plain executable - * 410 = RO text - * 413 = demand paged RO text - * Also an ASCII line beginning with #! is - * the file name of a ``shell'' and arguments may be prepended - * to the argument list if given here. - * - * SHELL NAMES ARE LIMITED IN LENGTH. - * - * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM - * THE ASCII LINE. - */ - u.u_exdata.ux_shell[0] = 0; /* for zero length files */ - u.u_error = rdwri(UIO_READ, ip, (caddr_t)&u.u_exdata, sizeof (u.u_exdata), - 0, 1, &resid); - if (u.u_error) - goto bad; - u.u_count = resid; -#ifndef lint - if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A) && - u.u_exdata.ux_shell[0] != '#') { - u.u_error = ENOEXEC; - goto bad; - } -#endif - switch (u.u_exdata.ux_mag) { - - case 0407: - u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; - u.u_exdata.ux_tsize = 0; - break; - - case 0413: - case 0410: - if (u.u_exdata.ux_tsize == 0) { - u.u_error = ENOEXEC; - goto bad; - } - break; - - default: - if (u.u_exdata.ux_shell[0] != '#' || - u.u_exdata.ux_shell[1] != '!' || - indir) { - u.u_error = ENOEXEC; - goto bad; - } - cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */ - while (cp < &u.u_exdata.ux_shell[SHSIZE]) { - if (*cp == '\t') - *cp = ' '; - else if (*cp == '\n') { - *cp = '\0'; - break; - } - cp++; - } - if (*cp != '\0') { - u.u_error = ENOEXEC; - goto bad; - } - cp = &u.u_exdata.ux_shell[2]; - while (*cp == ' ') - cp++; - u.u_dirp = cp; - while (*cp && *cp != ' ') - cp++; - sharg = NULL; - if (*cp) { - *cp++ = '\0'; - while (*cp == ' ') - cp++; - if (*cp) { - bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE); - sharg = cfarg; - } - } - if (u.u_dent.d_namlen > MAXCOMLEN) - u.u_dent.d_namlen = MAXCOMLEN; - bcopy((caddr_t)u.u_dent.d_name, (caddr_t)cfname, - (unsigned)(u.u_dent.d_namlen + 1)); - cfname[MAXCOMLEN] = 0; - indir = 1; - iput(ip); - ip = namei(schar, LOOKUP, 1); - if (ip == NULL) - return; - goto again; - } - - /* - * Collect arguments on "file" in swap space. - */ - na = 0; - ne = 0; - nc = 0; - uap = (struct execa *)u.u_ap; - if ((bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))))) == 0) { - swkill(u.u_procp, "exece"); - goto bad; - } - if (bno % CLSIZE) - panic("execa rmalloc"); - if (uap->argp) for (;;) { - ap = NULL; - if (indir && (na == 1 || na == 2 && sharg)) - ap = (int)uap->fname; - else if (uap->argp) { - ap = fuword((caddr_t)uap->argp); - uap->argp++; - } - if (ap==NULL && uap->envp) { - uap->argp = NULL; - if ((ap = fuword((caddr_t)uap->envp)) == NULL) - break; - uap->envp++; - ne++; - } - if (ap == NULL) - break; - na++; - if (ap == -1) - u.u_error = EFAULT; - do { - if (nc >= NCARGS-1) - u.u_error = E2BIG; - if (indir && na == 2 && sharg != NULL) - c = *sharg++ & 0377; - else if ((c = fubyte((caddr_t)ap++)) < 0) - u.u_error = EFAULT; - if (u.u_error) { - if (bp) - brelse(bp); - bp = 0; - goto badarg; - } - if (nc % (CLSIZE*NBPG) == 0) { - if (bp) - bdwrite(bp); - bp = getblk(argdev, bno + ctod(nc / NBPG), - CLSIZE*NBPG); - cp = bp->b_un.b_addr; - } - nc++; - *cp++ = c; - } while (c > 0); - } - if (bp) - bdwrite(bp); - bp = 0; - nc = (nc + NBPW-1) & ~(NBPW-1); - if (indir) { - u.u_dent.d_namlen = strlen(cfname); - bcopy((caddr_t)cfname, (caddr_t)u.u_dent.d_name, - (unsigned)(u.u_dent.d_namlen + 1)); - } - getxfile(ip, nc + (na+4)*NBPW, uid, gid); - if (u.u_error) { -badarg: - for (c = 0; c < nc; c += CLSIZE*NBPG) { - bp = baddr(argdev, bno + ctod(c / NBPG), CLSIZE*NBPG); - if (bp) { - bp->b_flags |= B_AGE; /* throw away */ - bp->b_flags &= ~B_DELWRI; /* cancel io */ - brelse(bp); - bp = 0; - } - } - goto bad; - } - - /* - * copy back arglist - */ - ucp = USRSTACK - nc - NBPW; - ap = ucp - na*NBPW - 3*NBPW; - u.u_ar0[SP] = ap; - (void) suword((caddr_t)ap, na-ne); - nc = 0; - for (;;) { - ap += NBPW; - if (na==ne) { - (void) suword((caddr_t)ap, 0); - ap += NBPW; - } - if (--na < 0) - break; - (void) suword((caddr_t)ap, ucp); - do { - if (nc % (CLSIZE*NBPG) == 0) { - if (bp) - brelse(bp); - bp = bread(argdev, bno + ctod(nc / NBPG), - CLSIZE*NBPG); - bp->b_flags |= B_AGE; /* throw away */ - bp->b_flags &= ~B_DELWRI; /* cancel io */ - cp = bp->b_un.b_addr; - } - (void) subyte((caddr_t)ucp++, (c = *cp++)); - nc++; - } while(c&0377); - } - (void) suword((caddr_t)ap, 0); - setregs(); -bad: - if (bp) - brelse(bp); - if (bno) - rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno); - iput(ip); -} - -/* - * Read in and set up memory for executed file. - */ -getxfile(ip, nargc, uid, gid) -register struct inode *ip; -{ - register size_t ts, ds, ss; - int pagi; - - if (u.u_exdata.ux_mag == 0413) - pagi = SPAGI; - else - pagi = 0; - if (u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && - ip->i_count!=1) { - register struct file *fp; - - for (fp = file; fp < fileNFILE; fp++) { - if (fp->f_type == DTYPE_FILE && - fp->f_count > 0 && - fp->f_inode == ip && (fp->f_flag&FWRITE)) { - u.u_error = ETXTBSY; - goto bad; - } - } - } - - /* - * Compute text and data sizes and make sure not too large. - */ - ts = clrnd(btoc(u.u_exdata.ux_tsize)); - ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); - ss = clrnd(SSIZE + btoc(nargc)); - if (chksize(ts, ds, ss)) - goto bad; - - /* - * Make sure enough space to start process. - */ - u.u_cdmap = zdmap; - u.u_csmap = zdmap; - if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) - goto bad; - - /* - * At this point, committed to the new image! - * Release virtual memory resources of old process, and - * initialize the virtual memory of the new process. - * If we resulted from vfork(), instead wakeup our - * parent who will set SVFDONE when he has taken back - * our resources. - */ - if ((u.u_procp->p_flag & SVFORK) == 0) - vrelvm(); - else { - u.u_procp->p_flag &= ~SVFORK; - u.u_procp->p_flag |= SKEEP; - wakeup((caddr_t)u.u_procp); - while ((u.u_procp->p_flag & SVFDONE) == 0) - sleep((caddr_t)u.u_procp, PZERO - 1); - u.u_procp->p_flag &= ~(SVFDONE|SKEEP); - } - u.u_procp->p_flag &= ~(SPAGI|SSEQL|SUANOM|SNUSIG); - u.u_procp->p_flag |= pagi; - u.u_dmap = u.u_cdmap; - u.u_smap = u.u_csmap; - vgetvm(ts, ds, ss); - - if (pagi == 0) - u.u_error = - rdwri(UIO_READ, ip, - (char *)ctob(dptov(u.u_procp, 0)), - (int)u.u_exdata.ux_dsize, - (int)(sizeof(u.u_exdata)+u.u_exdata.ux_tsize), - 0, (int *)0); - xalloc(ip, pagi); - if (pagi && u.u_procp->p_textp) - vinifod((struct fpte *)dptopte(u.u_procp, 0), - PG_FTEXT, u.u_procp->p_textp->x_iptr, - (long)(1 + ts/CLSIZE), (int)btoc(u.u_exdata.ux_dsize)); - -#ifdef vax - /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ -#include "../vax/mtpr.h" /* XXX */ - mtpr(TBIA, 0); -#endif - - if (u.u_error) - swkill(u.u_procp, "i/o error mapping pages"); - /* - * set SUID/SGID protections, if no tracing - */ - if ((u.u_procp->p_flag&STRC)==0) { - u.u_uid = uid; - u.u_procp->p_uid = uid; - u.u_gid = gid; - } else - psignal(u.u_procp, SIGTRAP); - u.u_tsize = ts; - u.u_dsize = ds; - u.u_ssize = ss; -bad: - return; -} - -/* - * Clear registers on exec - */ -setregs() -{ - register int (**rp)(); - register i; - long sigmask; - - for (rp = &u.u_signal[1], sigmask = 1L; rp < &u.u_signal[NSIG]; - sigmask <<= 1, rp++) { - switch (*rp) { - - case SIG_IGN: - case SIG_DFL: - case SIG_HOLD: - continue; - - default: - /* - * Normal or deferring catch; revert to default. - */ - (void) spl6(); - *rp = SIG_DFL; - if ((int)*rp & 1) - u.u_procp->p_siga0 |= sigmask; - else - u.u_procp->p_siga0 &= ~sigmask; - if ((int)*rp & 2) - u.u_procp->p_siga1 |= sigmask; - else - u.u_procp->p_siga1 &= ~sigmask; - (void) spl0(); - continue; - } - } -#ifdef vax -/* - for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) - *rp++ = 0; -*/ - u.u_ar0[PC] = u.u_exdata.ux_entloc+2; -#endif -#ifdef sun - { register struct regs *r = (struct regs *)u.u_ar0; - for (i = 0; i < 8; i++) { - r->r_dreg[i] = 0; - if (&r->r_areg[i] != &r->r_sp) - r->r_areg[i] = 0; - } - r->r_sr = PSL_USERSET; - r->r_pc = u.u_exdata.ux_entloc; - } -#endif - for (i=0; irval & 0377) << 8); -} - -/* - * Release resources. - * Save u. area for parent to look at. - * Enter zombie state. - * Wake up parent and init processes, - * and dispose of children. - */ -exit(rv) -{ - register int i; - register struct proc *p, *q; - register int x; - struct mbuf *m = m_getclr(M_WAIT, MT_ZOMBIE); - -#ifdef PGINPROF - vmsizmon(); -#endif - p = u.u_procp; - p->p_flag &= ~(STRC|SULOCK); - p->p_flag |= SWEXIT; - (void) spl6(); - if ((int)SIG_IGN & 1) - p->p_siga0 = ~0; - else - p->p_siga0 = 0; - if ((int)SIG_IGN & 2) - p->p_siga1 = ~0; - else - p->p_siga1 = 0; - (void) spl0(); - p->p_cpticks = 0; - p->p_pctcpu = 0; - for (i=0; ip_flag & SVFORK) == 0) - vrelvm(); - else { - p->p_flag &= ~SVFORK; - wakeup((caddr_t)p); - while ((p->p_flag & SVFDONE) == 0) - sleep((caddr_t)p, PZERO - 1); - p->p_flag &= ~SVFDONE; - } - for (i = 0; i < NOFILE; i++) { - struct file *f; - int p; - - f = u.u_ofile[i]; - u.u_ofile[i] = NULL; - p = u.u_pofile[i]; - u.u_pofile[i] = 0; - closef(f, 1, p); - } - ilock(u.u_cdir); - iput(u.u_cdir); - if (u.u_rdir) { - ilock(u.u_rdir); - iput(u.u_rdir); - } - u.u_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; - acct(); -#ifdef QUOTA - qclean(); -#endif -#ifdef sun - ctxfree(u.u_procp); -#endif - vrelpt(u.u_procp); - vrelu(u.u_procp, 0); - (void) spl5(); /* hack for mem alloc race XXX */ - multprog--; - p->p_stat = SZOMB; - noproc = 1; - i = PIDHASH(p->p_pid); - x = p - proc; - if (pidhash[i] == x) - pidhash[i] = p->p_idhash; - else { - for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) - if (proc[i].p_idhash == x) { - proc[i].p_idhash = p->p_idhash; - goto done; - } - panic("exit"); - } - if (p->p_pid == 1) - panic("init died"); -done: - p->p_xstat = rv; -if (m == 0) -panic("exit: m_getclr"); - p->p_ru = mtod(m, struct rusage *); - *p->p_ru = u.u_ru; - ruadd(p->p_ru, &u.u_cru); - for (q = proc; q < procNPROC; q++) - if (q->p_pptr == p) { - if (q->p_osptr) - q->p_osptr->p_ysptr = q->p_ysptr; - if (q->p_ysptr) - q->p_ysptr->p_osptr = q->p_osptr; - if (proc[1].p_cptr) - proc[1].p_cptr->p_ysptr = q; - q->p_osptr = proc[1].p_cptr; - q->p_ysptr = NULL; - proc[1].p_cptr = q; - - q->p_pptr = &proc[1]; - q->p_ppid = 1; - wakeup((caddr_t)&proc[1]); - /* - * Traced processes are killed - * since their existence means someone is screwing up. - * Stopped processes are sent a hangup and a continue. - * This is designed to be ``safe'' for setuid - * processes since they must be willing to tolerate - * hangups anyways. - */ - if (q->p_flag&STRC) { - q->p_flag &= ~STRC; - psignal(q, SIGKILL); - } else if (q->p_stat == SSTOP) { - psignal(q, SIGHUP); - psignal(q, SIGCONT); - } - /* - * Protect this process from future - * tty signals, clear TSTP/TTIN/TTOU if pending. - */ - (void) spgrp(q, -1); - } - psignal(p->p_pptr, SIGCHLD); - wakeup((caddr_t)p->p_pptr); - swtch(); -} - -wait() -{ - struct rusage ru, *rup; - - if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { - u.u_error = wait1(0, (struct rusage *)0); - return; - } - rup = (struct rusage *)u.u_ar0[R1]; - u.u_error = wait1(u.u_ar0[R0], &ru); - if (u.u_error) - return; - (void) copyout((caddr_t)&ru, (caddr_t)rup, sizeof (struct rusage)); -} - -#ifndef NOCOMPAT -#include "../h/vtimes.h" - -owait() -{ - struct rusage ru; - struct vtimes *vtp, avt; - - if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) { - u.u_error = wait1(0, (struct rusage *)0); - return; - } - vtp = (struct vtimes *)u.u_ar0[R1]; - u.u_error = wait1(u.u_ar0[R0], &ru); - if (u.u_error) - return; - getvtimes(&ru, &avt); - (void) copyout((caddr_t)&avt, (caddr_t)vtp, sizeof (struct vtimes)); -} -#endif - -/* - * Wait system call. - * Search for a terminated (zombie) child, - * finally lay it to rest, and collect its status. - * Look also for stopped (traced) children, - * and pass back status from them. - */ -wait1(options, ru) - register int options; - struct rusage *ru; -{ - register f; - register struct proc *p, *q; - - f = 0; -loop: - for (p = proc; p < procNPROC; p++) - if (p->p_pptr == u.u_procp) { - f++; - if (p->p_stat == SZOMB) { - u.u_r.r_val1 = p->p_pid; - u.u_r.r_val2 = p->p_xstat; - p->p_xstat = 0; - if (ru) - *ru = *p->p_ru; - ruadd(&u.u_cru, p->p_ru); - (void) m_free(dtom(p->p_ru)); - p->p_ru = 0; - p->p_stat = NULL; - p->p_pid = 0; - p->p_ppid = 0; - if (q = p->p_ysptr) - q->p_osptr = p->p_osptr; - if (q = p->p_osptr) - q->p_ysptr = p->p_ysptr; - if ((q = p->p_pptr)->p_cptr == p) - q->p_cptr = p->p_osptr; - p->p_pptr = 0; - p->p_ysptr = 0; - p->p_osptr = 0; - p->p_cptr = 0; - p->p_sig = 0; - p->p_siga0 = 0; - p->p_siga1 = 0; - p->p_pgrp = 0; - p->p_flag = 0; - p->p_wchan = 0; - p->p_cursig = 0; - return (0); - } - if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 && - (p->p_flag&STRC || options&WUNTRACED)) { - p->p_flag |= SWTED; - u.u_r.r_val1 = p->p_pid; - u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED; - return (0); - } - } - if (f == 0) { - return (ECHILD); - } - if (options&WNOHANG) { - u.u_r.r_val1 = 0; - return (0); - } - if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { - u.u_eosys = RESTARTSYS; - return (0); - } - sleep((caddr_t)u.u_procp, PWAIT); - goto loop; -} - -/* - * fork system call. - */ -fork() -{ - - u.u_cdmap = zdmap; - u.u_csmap = zdmap; - if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { - u.u_r.r_val2 = 0; - return; - } - fork1(0); -} - -fork1(isvfork) -{ - register struct proc *p1, *p2; - register a; - - a = 0; - p2 = NULL; - for (p1 = proc; p1 < procNPROC; p1++) { - if (p1->p_stat==NULL && p2==NULL) - p2 = p1; - else { - if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) - a++; - } - } - /* - * Disallow if - * No processes at all; - * not su and too many procs owned; or - * not su and would take last slot. - */ - if (p2==NULL) - tablefull("proc"); - if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) { - u.u_error = EAGAIN; - if (!isvfork) { - (void) vsexpand(0, &u.u_cdmap, 1); - (void) vsexpand(0, &u.u_csmap, 1); - } - goto out; - } - p1 = u.u_procp; - if (newproc(isvfork)) { - u.u_r.r_val1 = p1->p_pid; - u.u_r.r_val2 = 1; /* child */ - u.u_start = time.tv_sec; - u.u_acflag = AFORK; - return; - } - u.u_r.r_val1 = p2->p_pid; - -out: - u.u_r.r_val2 = 0; -} - spgrp(top, npgrp) -register struct proc *top; + register struct proc *top; { register struct proc *pp, *p; int f = 0; @@ -900,173 +82,3 @@ pfind(pid) return (p); return ((struct proc *)0); } - -/* - * Create a new process-- the internal version of - * sys fork. - * It returns 1 in the new process, 0 in the old. - */ -newproc(isvfork) - int isvfork; -{ - register struct proc *p; - register struct proc *rpp, *rip; - register int n; - register struct file *fp; - - p = NULL; - /* - * First, just locate a slot for a process - * and copy the useful info from this process into it. - * The panic "cannot happen" because fork has already - * checked for the existence of a slot. - */ -retry: - mpid++; - if (mpid >= 30000) { - mpid = 0; - goto retry; - } - for (rpp = proc; rpp < procNPROC; rpp++) { - if (rpp->p_stat == NULL && p==NULL) - p = rpp; - if (rpp->p_pid==mpid || rpp->p_pgrp==mpid) - goto retry; - } - if ((rpp = p) == NULL) - panic("no procs"); - - /* - * Make a proc table entry for the new process. - */ - rip = u.u_procp; -#ifdef QUOTA - rpp->p_quota = rip->p_quota; - rpp->p_quota->q_cnt++; -#endif - rpp->p_stat = SIDL; - timerclear(&rpp->p_realtimer.it_value); - rpp->p_flag = SLOAD | (rip->p_flag & (SPAGI|SNUSIG)); - if (isvfork) { - rpp->p_flag |= SVFORK; - rpp->p_ndx = rip->p_ndx; - } else - rpp->p_ndx = rpp - proc; - rpp->p_uid = rip->p_uid; - rpp->p_pgrp = rip->p_pgrp; - rpp->p_nice = rip->p_nice; - rpp->p_textp = isvfork ? 0 : rip->p_textp; - rpp->p_pid = mpid; - rpp->p_ppid = rip->p_pid; - rpp->p_pptr = rip; - rpp->p_osptr = rip->p_cptr; - if (rip->p_cptr) - rip->p_cptr->p_ysptr = rpp; - rpp->p_ysptr = NULL; - rpp->p_cptr = NULL; - rip->p_cptr = rpp; - rpp->p_time = 0; - rpp->p_cpu = 0; - rpp->p_siga0 = rip->p_siga0; - rpp->p_siga1 = rip->p_siga1; - /* take along any pending signals, like stops? */ - if (isvfork) { - rpp->p_tsize = rpp->p_dsize = rpp->p_ssize = 0; - rpp->p_szpt = clrnd(ctopt(UPAGES)); - forkstat.cntvfork++; - forkstat.sizvfork += rip->p_dsize + rip->p_ssize; - } else { - rpp->p_tsize = rip->p_tsize; - rpp->p_dsize = rip->p_dsize; - rpp->p_ssize = rip->p_ssize; - rpp->p_szpt = rip->p_szpt; - forkstat.cntfork++; - forkstat.sizfork += rip->p_dsize + rip->p_ssize; - } - rpp->p_rssize = 0; - rpp->p_maxrss = rip->p_maxrss; - rpp->p_wchan = 0; - rpp->p_slptime = 0; - rpp->p_pctcpu = 0; - rpp->p_cpticks = 0; - n = PIDHASH(rpp->p_pid); - p->p_idhash = pidhash[n]; - pidhash[n] = rpp - proc; - multprog++; - - /* - * Increase reference counts on shared objects. - */ - for (n = 0; n < NOFILE; n++) { - fp = u.u_ofile[n]; - if (fp == NULL) - continue; - fp->f_count++; - if (u.u_pofile[n]&UF_SHLOCK) - fp->f_inode->i_shlockc++; - if (u.u_pofile[n]&UF_EXLOCK) - fp->f_inode->i_exlockc++; - } - u.u_cdir->i_count++; - if (u.u_rdir) - u.u_rdir->i_count++; - - /* - * Partially simulate the environment - * of the new process so that when it is actually - * created (by copying) it will look right. - * This begins the section where we must prevent the parent - * from being swapped. - */ - rip->p_flag |= SKEEP; - if (procdup(rpp, isvfork)) - return (1); - - /* - * Make child runnable and add to run queue. - */ - (void) spl6(); - rpp->p_stat = SRUN; - setrq(rpp); - (void) spl0(); - - /* - * Cause child to take a non-local goto as soon as it runs. - * On older systems this was done with SSWAP bit in proc - * table; on VAX we use u.u_pcb.pcb_sswap so don't need - * to do rpp->p_flag |= SSWAP. Actually do nothing here. - */ - /* rpp->p_flag |= SSWAP; */ - - /* - * Now can be swapped. - */ - rip->p_flag &= ~SKEEP; - - /* - * If vfork make chain from parent process to child - * (where virtal memory is temporarily). Wait for - * child to finish, steal virtual memory back, - * and wakeup child to let it die. - */ - if (isvfork) { - u.u_procp->p_xlink = rpp; - u.u_procp->p_flag |= SNOVM; - while (rpp->p_flag & SVFORK) - sleep((caddr_t)rpp, PZERO - 1); - if ((rpp->p_flag & SLOAD) == 0) - panic("newproc vfork"); - uaccess(rpp, Vfmap, &vfutl); - u.u_procp->p_xlink = 0; - vpassvm(rpp, u.u_procp, &vfutl, &u, Vfmap); - u.u_procp->p_flag &= ~SNOVM; - rpp->p_ndx = rpp - proc; - rpp->p_flag |= SVFDONE; - wakeup((caddr_t)rpp); - } - - /* - * 0 return means parent. - */ - return (0); -} diff --git a/usr/src/sys/kern/kern_prot.c b/usr/src/sys/kern/kern_prot.c index 7972a77a6d..822e1ab897 100644 --- a/usr/src/sys/kern/kern_prot.c +++ b/usr/src/sys/kern/kern_prot.c @@ -1,4 +1,4 @@ -/* kern_prot.c 5.16 83/03/31 */ +/* kern_prot.c 5.17 83/05/27 */ /* * System calls related to processes and protection @@ -138,30 +138,6 @@ setreuid() u.u_uid = euid; } -#ifndef NOCOMPAT -osetuid() -{ - register uid; - register struct a { - int uid; - } *uap; - - uap = (struct a *)u.u_ap; - uid = uap->uid; - if (u.u_ruid == uid || u.u_uid == uid || suser()) { -#ifdef QUOTA - if (u.u_quota->q_uid != uid) { - qclean(); - qstart(getquota(uid, 0, 0)); - } -#endif - u.u_uid = uid; - u.u_procp->p_uid = uid; - u.u_ruid = uid; - } -} -#endif - setregid() { register struct a { @@ -189,24 +165,6 @@ setregid() u.u_gid = egid; } -#ifndef NOCOMPAT -osetgid() -{ - register gid; - register struct a { - int gid; - } *uap; - - uap = (struct a *)u.u_ap; - gid = uap->gid; - if (u.u_rgid == gid || u.u_gid == gid || suser()) { - leavegroup(u.u_rgid); - (void) entergroup(gid); - u.u_gid = gid; - u.u_rgid = gid; - } -} - setgroups() { register struct a { @@ -229,41 +187,6 @@ setgroups() *gp = NOGROUP; } -/* - * Pid of zero implies current process. - * Pgrp -1 is getpgrp system call returning - * current process group. - */ -osetpgrp() -{ - register struct proc *p; - register struct a { - int pid; - int pgrp; - } *uap; - - uap = (struct a *)u.u_ap; - if (uap->pid == 0) - p = u.u_procp; - else { - p = pfind(uap->pid); - if (p == 0) { - u.u_error = ESRCH; - return; - } - } - if (uap->pgrp <= 0) { - u.u_r.r_val1 = p->p_pgrp; - return; - } - if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) { - u.u_error = EPERM; - return; - } - p->p_pgrp = uap->pgrp; -} -/* END DEFUNCT */ - /* * Group utility functions. */ diff --git a/usr/src/sys/kern/kern_resource.c b/usr/src/sys/kern/kern_resource.c index 9db1664a3e..2adca5f1cc 100644 --- a/usr/src/sys/kern/kern_resource.c +++ b/usr/src/sys/kern/kern_resource.c @@ -1,4 +1,4 @@ -/* kern_resource.c 4.21 83/05/23 */ +/* kern_resource.c 4.22 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -236,86 +236,3 @@ ruadd(ru, ru2) for (i = &ru->ru_last - &ru->ru_first; i > 0; i--) *ip++ += *ip2++; } - -#ifndef NOCOMPAT -onice() -{ - register struct a { - int niceness; - } *uap = (struct a *)u.u_ap; - register struct proc *p = u.u_procp; - - donice(p, (p->p_nice-NZERO)+uap->niceness); -} - -#include "../h/times.h" - -otimes() -{ - register struct a { - struct tms *tmsb; - } *uap = (struct a *)u.u_ap; - struct tms atms; - - atms.tms_utime = scale60(&u.u_ru.ru_utime); - atms.tms_stime = scale60(&u.u_ru.ru_stime); - atms.tms_cutime = scale60(&u.u_cru.ru_utime); - atms.tms_cstime = scale60(&u.u_cru.ru_stime); - u.u_error = copyout((caddr_t)&atms, (caddr_t)uap->tmsb, sizeof (atms)); -} - -scale60(tvp) - register struct timeval *tvp; -{ - - return (tvp->tv_sec * 60 + tvp->tv_usec / 16667); -} - -#include "../h/vtimes.h" - -ovtimes() -{ - register struct a { - struct vtimes *par; - struct vtimes *chi; - } *uap = (struct a *)u.u_ap; - struct vtimes avt; - - if (uap->par) { - getvtimes(&u.u_ru, &avt); - u.u_error = copyout((caddr_t)&avt, (caddr_t)uap->par, - sizeof (avt)); - if (u.u_error) - return; - } - if (uap->chi) { - getvtimes(&u.u_cru, &avt); - u.u_error = copyout((caddr_t)&avt, (caddr_t)uap->chi, - sizeof (avt)); - if (u.u_error) - return; - } -} - -getvtimes(aru, avt) - register struct rusage *aru; - register struct vtimes *avt; -{ - - avt->vm_utime = scale60(&aru->ru_utime); - avt->vm_stime = scale60(&aru->ru_stime); - avt->vm_idsrss = ((aru->ru_idrss+aru->ru_isrss) / hz) * 60; - avt->vm_ixrss = aru->ru_ixrss / hz * 60; - avt->vm_maxrss = aru->ru_maxrss; - avt->vm_majflt = aru->ru_majflt; - avt->vm_minflt = aru->ru_minflt; - avt->vm_nswap = aru->ru_nswap; - avt->vm_inblk = aru->ru_inblock; - avt->vm_oublk = aru->ru_oublock; -} - -ovlimit() -{ - - u.u_error = EACCES; -} diff --git a/usr/src/sys/kern/kern_sig.c b/usr/src/sys/kern/kern_sig.c index f3449c7cf7..5639cc8d79 100644 --- a/usr/src/sys/kern/kern_sig.c +++ b/usr/src/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* kern_sig.c 5.16 83/05/21 */ +/* kern_sig.c 5.17 83/05/27 */ #include "../machine/reg.h" #include "../machine/pte.h" @@ -57,7 +57,6 @@ kill() } #endif -/* TEMPORARY */ killpg() { register struct a { @@ -65,22 +64,10 @@ killpg() int signo; } *uap = (struct a *)u.u_ap; - u.u_error = okill1(1, uap->signo, uap->pgrp); + u.u_error = kill1(1, uap->signo, uap->pgrp); } -/* BEGIN DEFUNCT */ -okill() -{ - register struct a { - int pid; - int signo; - } *uap = (struct a *)u.u_ap; - - u.u_error = okill1(uap->signo < 0, - uap->signo < 0 ? -uap->signo : uap->signo, uap->pid); -} - -okill1(ispgrp, signo, who) +kill1(ispgrp, signo, who) int ispgrp, signo, who; { register struct proc *p; @@ -121,70 +108,7 @@ okill1(ispgrp, signo, who) f++; psignal(p, signo); } - return (f == 0? ESRCH : 0); -} - -ossig() -{ - register int (*f)(); - struct a { - int signo; - int (*fun)(); - } *uap; - register struct proc *p = u.u_procp; - register a; - long sigmask; - - uap = (struct a *)u.u_ap; - a = uap->signo & SIGNUMMASK; - f = uap->fun; - if (a<=0 || a>=NSIG || a==SIGKILL || a==SIGSTOP || - a==SIGCONT && (f == SIG_IGN || f == SIG_HOLD)) { - u.u_error = EINVAL; - return; - } - if ((uap->signo &~ SIGNUMMASK) || (f != SIG_DFL && f != SIG_IGN && - SIGISDEFER(f))) - u.u_procp->p_flag |= SNUSIG; - /* - * Don't clobber registers if we are to simulate - * a ret+rti. - */ - if ((uap->signo&SIGDORTI) == 0) - u.u_r.r_val1 = (int)u.u_signal[a]; - /* - * Change setting atomically. - */ - (void) spl6(); - sigmask = 1L << (a-1); - if (f == SIG_IGN) - p->p_sig &= ~sigmask; /* never to be seen again */ - u.u_signal[a] = f; - if (f != SIG_DFL && f != SIG_IGN && f != SIG_HOLD) - f = SIG_CATCH; - if ((int)f & 1) - p->p_siga0 |= sigmask; - else - p->p_siga0 &= ~sigmask; - if ((int)f & 2) - p->p_siga1 |= sigmask; - else - p->p_siga1 &= ~sigmask; - (void) spl0(); - /* - * Now handle options. - */ - if (uap->signo & SIGDOPAUSE) { - /* - * Simulate a PDP11 style wait instrution which - * atomically lowers priority, enables interrupts - * and hangs. - */ - opause(); - /*NOTREACHED*/ - } - if (uap->signo & SIGDORTI) - u.u_eosys = SIMULATERTI; + return (f == 0 ? ESRCH : 0); } /* @@ -617,14 +541,9 @@ psig() */ if (SIGISDEFER(action)) { (void) spl6(); - if ((int)SIG_HOLD & 1) - rp->p_siga0 |= sigmask; - else - rp->p_siga0 &= ~sigmask; - if ((int)SIG_HOLD & 2) - rp->p_siga1 |= sigmask; - else - rp->p_siga1 &= ~sigmask; + /* SIG_HOLD known to be 3 */ + rp->p_siga0 |= sigmask; + rp->p_siga1 |= sigmask; u.u_signal[n] = SIG_HOLD; (void) spl0(); action = SIGUNDEFER(action); @@ -653,9 +572,6 @@ psig() exit(n); } -#ifdef unneeded -int corestop = 0; -#endif /* * Create a core image on the file "core" * If you are looking for protection glitches, @@ -671,17 +587,6 @@ core() register struct inode *ip; extern schar(); -#ifdef unneeded - if (corestop) { - int i; - for (i = 0; i < 10; i++) - if (u.u_comm[i]) - putchar(u.u_comm[i], 0); - printf(", uid %d\n", u.u_uid); - if (corestop&2) - asm("halt"); - } -#endif if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) return (0); if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= diff --git a/usr/src/sys/kern/kern_time.c b/usr/src/sys/kern/kern_time.c index 28607a7974..067821c919 100644 --- a/usr/src/sys/kern/kern_time.c +++ b/usr/src/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* kern_time.c 5.14 82/12/30 */ +/* kern_time.c 5.15 83/05/27 */ #include "../machine/reg.h" @@ -298,73 +298,3 @@ timevalfix(t1) t1->tv_usec -= 1000000; } } - -#ifndef NOCOMPAT -otime() -{ - - u.u_r.r_time = time.tv_sec; -} - -ostime() -{ - register struct a { - int time; - } *uap = (struct a *)u.u_ap; - struct timeval tv; - - tv.tv_sec = uap->time; - tv.tv_usec = 0; - setthetime(&tv); -} - -/* from old timeb.h */ -struct timeb { - time_t time; - u_short millitm; - short timezone; - short dstflag; -}; - -oftime() -{ - register struct a { - struct timeb *tp; - } *uap; - struct timeb tb; - - uap = (struct a *)u.u_ap; - (void) spl7(); - tb.time = time.tv_sec; - tb.millitm = time.tv_usec / 1000; - (void) spl0(); - tb.timezone = tz.tz_minuteswest; - tb.dstflag = tz.tz_dsttime; - u.u_error = copyout((caddr_t)&tb, (caddr_t)uap->tp, sizeof (tb)); -} - -oalarm() -{ - register struct a { - int deltat; - } *uap = (struct a *)u.u_ap; - register struct proc *p = u.u_procp; - int s = spl7(); - - untimeout(realitexpire, (caddr_t)p); - timerclear(&p->p_realtimer.it_interval); - u.u_r.r_val1 = 0; - if (timerisset(&p->p_realtimer.it_value) && - timercmp(&p->p_realtimer.it_value, &time, >)) - u.u_r.r_val1 = p->p_realtimer.it_value.tv_sec - time.tv_sec; - if (uap->deltat == 0) { - timerclear(&p->p_realtimer.it_value); - splx(s); - return; - } - p->p_realtimer.it_value = time; - p->p_realtimer.it_value.tv_sec += uap->deltat; - timeout(realitexpire, (caddr_t)p, hzto(&p->p_realtimer.it_value)); - splx(s); -} -#endif diff --git a/usr/src/sys/kern/subr_prf.c b/usr/src/sys/kern/subr_prf.c index 751962383b..ac4f2b3fa4 100644 --- a/usr/src/sys/kern/subr_prf.c +++ b/usr/src/sys/kern/subr_prf.c @@ -1,4 +1,4 @@ -/* subr_prf.c 4.26 83/05/18 */ +/* subr_prf.c 4.27 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -202,6 +202,7 @@ tablefull(tab) printf("%s: table is full\n", tab); } +#ifdef vax /* * Hard error is the preface to plaintive error messages * about failing disk transfers. @@ -214,6 +215,7 @@ harderr(bp, cp) printf("%s%d%c: hard error sn%d ", cp, dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); } +#endif /* * Print a character on console or users terminal. diff --git a/usr/src/sys/kern/subr_xxx.c b/usr/src/sys/kern/subr_xxx.c index 86efb60103..7137d22efe 100644 --- a/usr/src/sys/kern/subr_xxx.c +++ b/usr/src/sys/kern/subr_xxx.c @@ -1,4 +1,4 @@ -/* subr_xxx.c 4.21 82/12/17 */ +/* subr_xxx.c 4.22 83/05/27 */ #include "../machine/pte.h" @@ -103,7 +103,7 @@ ffs(mask) { register int i; - for(i=1; i>= 1; diff --git a/usr/src/sys/kern/sys_generic.c b/usr/src/sys/kern/sys_generic.c index f051d7efa2..56ff7b8836 100644 --- a/usr/src/sys/kern/sys_generic.c +++ b/usr/src/sys/kern/sys_generic.c @@ -1,22 +1,15 @@ -/* sys_generic.c 5.35 83/05/21 */ +/* sys_generic.c 5.36 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/ioctl.h" -#include "../h/tty.h" #include "../h/file.h" -#include "../h/inode.h" -#include "../h/buf.h" #include "../h/proc.h" -#include "../h/conf.h" -#include "../h/socket.h" -#include "../h/socketvar.h" -#include "../h/fs.h" -#include "../h/descrip.h" #include "../h/uio.h" -#include "../h/cmap.h" +#include "../h/kernel.h" +#include "../h/stat.h" /* * Read system call. @@ -113,7 +106,6 @@ rwuio(uio, rw) }; register struct file *fp; register struct iovec *iov; - register struct inode *ip; int i, count; GETF(fp, ((struct a *)u.u_ap)->fdes); @@ -136,318 +128,18 @@ rwuio(uio, rw) } } count = uio->uio_resid; + uio->uio_offset = fp->f_offset; if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { if (uio->uio_resid == count) u.u_eosys = RESTARTSYS; - } else if (fp->f_type == DTYPE_SOCKET) { - int sosend(), soreceive(); - u.u_error = - (*(rw==UIO_READ?soreceive:sosend)) - (fp->f_socket, (struct sockaddr *)0, uio, 0); - } else { - ip = fp->f_inode; - uio->uio_offset = fp->f_offset; - if ((ip->i_mode&IFMT) == IFREG) { - ILOCK(ip); - if (fp->f_flag&FAPPEND && rw == UIO_WRITE) - uio->uio_offset = fp->f_offset = ip->i_size; - u.u_error = rwip(ip, uio, rw); - IUNLOCK(ip); - } else - u.u_error = rwip(ip, uio, rw); - fp->f_offset += count - uio->uio_resid; - } - u.u_r.r_val1 = count - uio->uio_resid; -} - -rdwri(rw, ip, base, len, offset, segflg, aresid) - struct inode *ip; - caddr_t base; - int len, offset, segflg; - int *aresid; - enum uio_rw rw; -{ - struct uio auio; - struct iovec aiov; - int error; - - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - aiov.iov_base = base; - aiov.iov_len = len; - auio.uio_resid = len; - auio.uio_offset = offset; - auio.uio_segflg = segflg; - error = rwip(ip, &auio, rw); - if (aresid) - *aresid = auio.uio_resid; - else - if (auio.uio_resid) - error = EIO; - return (error); -} - -rwip(ip, uio, rw) - register struct inode *ip; - register struct uio *uio; - enum uio_rw rw; -{ - dev_t dev = (dev_t)ip->i_rdev; - struct buf *bp; - struct fs *fs; - daddr_t lbn, bn; - register int n, on, type; - int size; - long bsize; - extern int mem_no; - int error = 0; - - if (rw != UIO_READ && rw != UIO_WRITE) - panic("rwip"); - if (rw == UIO_READ && uio->uio_resid == 0) - return (0); - if (uio->uio_offset < 0 && - ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev))) - return (EINVAL); - if (rw == UIO_READ) - ip->i_flag |= IACC; - type = ip->i_mode&IFMT; - if (type == IFCHR) { - if (rw == UIO_READ) - u.u_error = (*cdevsw[major(dev)].d_read)(dev, uio); - else { - ip->i_flag |= IUPD|ICHG; - u.u_error = (*cdevsw[major(dev)].d_write)(dev, uio); - } - return (u.u_error); - } - if (uio->uio_resid == 0) - return (0); - if (rw == UIO_WRITE && type == IFREG && - uio->uio_offset + uio->uio_resid > - u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { - psignal(u.u_procp, SIGXFSZ); - return (EMFILE); - } - if (type != IFBLK) { - dev = ip->i_dev; - fs = ip->i_fs; - bsize = fs->fs_bsize; } else - bsize = BLKDEV_IOSIZE; - do { - lbn = uio->uio_offset / bsize; - on = uio->uio_offset % bsize; - n = MIN((unsigned)(bsize - on), uio->uio_resid); - if (type != IFBLK) { - if (rw == UIO_READ) { - int diff = ip->i_size - uio->uio_offset; - if (diff <= 0) - return (0); - if (diff < n) - n = diff; - } - bn = fsbtodb(fs, - bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n))); - if (u.u_error || rw == UIO_WRITE && (long)bn<0) - return (u.u_error); - if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size && - (type == IFDIR || type == IFREG || type == IFLNK)) - ip->i_size = uio->uio_offset + n; - size = blksize(fs, ip, lbn); - } else { - bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); - rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); - rasize = size = bsize; - } - if (rw == UIO_READ) { - if ((long)bn<0) { - bp = geteblk(size); - clrbuf(bp); - } else if (ip->i_lastr + 1 == lbn) - bp = breada(dev, bn, size, rablock, rasize); - else - bp = bread(dev, bn, size); - ip->i_lastr = lbn; - } else { - int i, count; - extern struct cmap *mfind(); - - count = howmany(size, DEV_BSIZE); - for (i = 0; i < count; i += CLSIZE) - if (mfind(dev, bn + i)) - munhash(dev, bn + i); - if (n == bsize) - bp = getblk(dev, bn, size); - else - bp = bread(dev, bn, size); - } - n = MIN(n, size - bp->b_resid); - if (bp->b_flags & B_ERROR) { - error = EIO; - brelse(bp); - goto bad; - } - u.u_error = - uiomove(bp->b_un.b_addr+on, n, rw, uio); - if (rw == UIO_READ) { - if (n + on == bsize || uio->uio_offset == ip->i_size) - bp->b_flags |= B_AGE; - brelse(bp); - } else { - if ((ip->i_mode&IFMT) == IFDIR) - bwrite(bp); - else if (n + on == bsize) { - bp->b_flags |= B_AGE; - bawrite(bp); - } else - bdwrite(bp); - ip->i_flag |= IUPD|ICHG; - if (u.u_ruid != 0) - ip->i_mode &= ~(ISUID|ISGID); - } - } while (u.u_error == 0 && uio->uio_resid > 0 && n != 0); -bad: - return (error); -} - -uiomove(cp, n, rw, uio) - register caddr_t cp; - register int n; - enum uio_rw rw; - register struct uio *uio; -{ - register struct iovec *iov; - u_int cnt; - int error = 0; - - while (n > 0 && uio->uio_resid) { - iov = uio->uio_iov; - cnt = iov->iov_len; - if (cnt == 0) { - uio->uio_iov++; - uio->uio_iovcnt--; - continue; - } - if (cnt > n) - cnt = n; - switch (uio->uio_segflg) { - - case 0: - case 2: - if (rw == UIO_READ) - error = copyout(cp, iov->iov_base, cnt); - else - error = copyin(iov->iov_base, cp, cnt); - if (error) - return (error); - break; - - case 1: - if (rw == UIO_READ) - bcopy((caddr_t)cp, iov->iov_base, cnt); - else - bcopy(iov->iov_base, (caddr_t)cp, cnt); - break; - } - iov->iov_base += cnt; - iov->iov_len -= cnt; - uio->uio_resid -= cnt; - uio->uio_offset += cnt; - cp += cnt; - n -= cnt; - } - return (error); -} - -/* - * Give next character to user as result of read. - */ -ureadc(c, uio) - register int c; - register struct uio *uio; -{ - register struct iovec *iov; - -again: - if (uio->uio_iovcnt == 0) - panic("ureadc"); - iov = uio->uio_iov; - if (iov->iov_len <= 0 || uio->uio_resid <= 0) { - uio->uio_iovcnt--; - uio->uio_iov++; - goto again; - } - switch (uio->uio_segflg) { - - case 0: - if (subyte(iov->iov_base, c) < 0) - return (EFAULT); - break; - - case 1: - *iov->iov_base = c; - break; - - case 2: - if (suibyte(iov->iov_base, c) < 0) - return (EFAULT); - break; - } - iov->iov_base++; - iov->iov_len--; - uio->uio_resid--; - uio->uio_offset++; - return (0); -} - -#ifdef notdef -/* - * Get next character written in by user from uio. - */ -uwritec(uio) - struct uio *uio; -{ - register struct iovec *iov; - register int c; - -again: - if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0) - panic("uwritec"); - iov = uio->uio_iov; - if (iov->iov_len == 0) { - uio->uio_iovcnt--; - uio->uio_iov++; - goto again; - } - switch (uio->uio_segflg) { - - case 0: - c = fubyte(iov->iov_base); - break; - - case 1: - c = *iov->iov_base & 0377; - break; - - case 2: - c = fuibyte(iov->iov_base); - break; - } - if (c < 0) - return (-1); - iov->iov_base++; - iov->iov_len--; - uio->uio_resid--; - uio->uio_offset++; - return (c & 0377); + u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio); + u.u_r.r_val1 = count - uio->uio_resid; + fp->f_offset += u.u_r.r_val1; } -#endif /* * Ioctl system call - * Check legality, execute common code, - * and switch out to individual device routine. */ ioctl() { @@ -470,7 +162,7 @@ ioctl() } com = uap->cmd; -#ifndef NOCOMPAT +#if defined(vax) && !defined(NOCOMPAT) /* * Map old style ioctl's into new for the * sake of backwards compatibility (sigh). @@ -519,33 +211,25 @@ ioctl() else if (com&IOC_VOID) *(caddr_t *)data = uap->cmarg; - if (fp->f_type == DTYPE_SOCKET) - u.u_error = soioctl(fp->f_socket, com, data); - else { - register struct inode *ip = fp->f_inode; - int fmt = ip->i_mode & IFMT; - dev_t dev; - - if (fmt != IFCHR) { - if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) { - *(off_t *)data = ip->i_size - fp->f_offset; - goto returndata; - } - if (com != FIONBIO && com != FIOASYNC) - u.u_error = ENOTTY; - return; - } - dev = ip->i_rdev; - u.u_r.r_val1 = 0; - if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { - u.u_eosys = RESTARTSYS; - return; - } - u.u_error = - (*cdevsw[major(dev)].d_ioctl)(dev, com, data, fp->f_flag); - } + switch (com) { + + case FIONBIO: + u.u_error = fset(fp, FNDELAY, *(int *)data); + return; + + case FIOASYNC: + u.u_error = fset(fp, FASYNC, *(int *)data); + return; + + case FIOSETOWN: + u.u_error = fsetown(fp, *(int *)data); + return; -returndata: + case FIOGETOWN: + u.u_error = fgetown(fp, (int *)data); + return; + } + u.u_error = (*fp->f_ops->fo_ioctl)(fp, com, data); /* * Copy any data to user, size was * already set and checked above. @@ -554,29 +238,197 @@ returndata: u.u_error = copyout(data, uap->cmarg, (u_int)size); } +int unselect(); +int nselcoll; /* - * Do nothing specific version of line - * discipline specific ioctl command. + * Select system call. */ +select() +{ + register struct uap { + int nd; + long *in, *ou, *ex; + struct timeval *tv; + } *uap = (struct uap *)u.u_ap; + int ibits[3], obits[3]; + struct timeval atv; + int s, ncoll; + label_t lqsave; + + obits[0] = obits[1] = obits[2] = 0; + if (uap->nd > NOFILE) + uap->nd = NOFILE; /* forgiving, if slightly wrong */ + +#define getbits(name, x) \ + if (uap->name) { \ + u.u_error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ + sizeof (ibits[x])); \ + if (u.u_error) \ + goto done; \ + } else \ + ibits[x] = 0; + getbits(in, 0); + getbits(ou, 1); + getbits(ex, 2); +#undef getbits + + if (uap->tv) { + u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv, + sizeof (atv)); + if (u.u_error) + goto done; + if (itimerfix(&atv)) { + u.u_error = EINVAL; + goto done; + } + s = spl7(); timevaladd(&atv, &time); splx(s); + } +retry: + ncoll = nselcoll; + u.u_procp->p_flag |= SSEL; + u.u_r.r_val1 = selscan(ibits, obits); + if (u.u_error || u.u_r.r_val1) + goto done; + s = spl6(); + if (uap->tv && timercmp(&time, &atv, >=)) { + splx(s); + goto done; + } + if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { + u.u_procp->p_flag &= ~SSEL; + splx(s); + goto retry; + } + u.u_procp->p_flag &= ~SSEL; + if (uap->tv) { + lqsave = u.u_qsave; + if (setjmp(&u.u_qsave)) { + untimeout(unselect, (caddr_t)u.u_procp); + u.u_error = EINTR; + splx(s); + goto done; + } + timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); + } + sleep((caddr_t)&selwait, PZERO+1); + if (uap->tv) { + u.u_qsave = lqsave; + untimeout(unselect, (caddr_t)u.u_procp); + } + splx(s); + goto retry; +done: +#define putbits(name, x) \ + if (uap->name) { \ + int error = copyout((caddr_t)&obits[x], (caddr_t)uap->name, \ + sizeof (obits[x])); \ + if (error) \ + u.u_error = error; \ + } + putbits(in, 0); + putbits(ou, 1); + putbits(ex, 2); +#undef putbits +} + +unselect(p) + register struct proc *p; +{ + register int s = spl6(); + + switch (p->p_stat) { + + case SSLEEP: + setrun(p); + break; + + case SSTOP: + unsleep(p); + break; + } + splx(s); +} + +selscan(ibits, obits) + int *ibits, *obits; +{ + register int which, bits, i; + int flag; + struct file *fp; + int n = 0; + + for (which = 0; which < 3; which++) { + bits = ibits[which]; + obits[which] = 0; + switch (which) { + + case 0: + flag = FREAD; break; + + case 1: + flag = FWRITE; break; + + case 2: + flag = 0; break; + } + while (i = ffs(bits)) { + bits &= ~(1<<(i-1)); + fp = u.u_ofile[i-1]; + if (fp == NULL) { + u.u_error = EBADF; + break; + } + if ((*fp->f_ops->fo_select)(fp, flag)) { + obits[which] |= (1<<(i-1)); + n++; + } + } + } + return (n); +} + /*ARGSUSED*/ -nullioctl(tp, cmd, data, flags) - struct tty *tp; - char *data; - int flags; +seltrue(dev, flag) + dev_t dev; + int flag; { -#ifdef lint - tp = tp; data = data; flags = flags; -#endif - return (-1); + return (1); } -ostty() +selwakeup(p, coll) + register struct proc *p; + int coll; { + if (coll) { + nselcoll++; + wakeup((caddr_t)&selwait); + } + if (p) { + int s = spl6(); + if (p->p_wchan == (caddr_t)&selwait) + setrun(p); + else if (p->p_flag & SSEL) + p->p_flag &= ~SSEL; + splx(s); + } } -ogtty() +fstat() { + register struct file *fp; + register struct a { + int fdes; + struct stat *sb; + } *uap; + struct stat ub; + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if (fp == 0) + return; + u.u_error = (*fp->f_ops->fo_stat)(fp, &ub); + if (u.u_error == 0) + u.u_error = copyout(&ub, uap->sb, sizeof (ub)); } diff --git a/usr/src/sys/kern/tty.c b/usr/src/sys/kern/tty.c index 9b6d093a9d..c2f74f3e0e 100644 --- a/usr/src/sys/kern/tty.c +++ b/usr/src/sys/kern/tty.c @@ -1,4 +1,4 @@ -/* tty.c 4.40 83/02/10 */ +/* tty.c 4.41 83/05/27 */ #include "../machine/reg.h" @@ -112,26 +112,32 @@ ttychars(tp) /* * Wait for output to drain, then flush input waiting. */ -wflushtty(tp) +ttywflush(tp) register struct tty *tp; { - int s; - s = spl5(); + ttywait(tp); + ttyflush(tp, FREAD); +} + +ttywait(tp) + register struct tty *tp; +{ + register int s = spl5(); + while (tp->t_outq.c_cc && tp->t_state&TS_CARR_ON && tp->t_oproc) { /* kludge for pty */ (*tp->t_oproc)(tp); tp->t_state |= TS_ASLEEP; sleep((caddr_t)&tp->t_outq, TTOPRI); } - flushtty(tp, FREAD); splx(s); } /* * Flush all TTY queues */ -flushtty(tp, rw) +ttyflush(tp, rw) register struct tty *tp; { register s; @@ -170,7 +176,7 @@ ttyblock(tp) x = tp->t_rawq.c_cc + tp->t_canq.c_cc; if (tp->t_rawq.c_cc > TTYHOG) { - flushtty(tp, FREAD|FWRITE); + ttyflush(tp, FREAD|FWRITE); tp->t_state &= ~TS_TBLOCK; } if (x >= TTYHOG/2 && putc(tp->t_stopc, &tp->t_outq) == 0) { @@ -224,6 +230,7 @@ ttioctl(tp, com, data, flag) int dev = tp->t_dev; extern int nldisp; int s; + register int newflags; /* * If the ioctl involves modification, @@ -300,64 +307,9 @@ ttioctl(tp, com, data, flag) tp->t_state &= ~TS_XCLUDE; break; - case TIOCSET: - case TIOCBIS: { - u_long newflags = *(u_long *)data; - - s = spl5(); - if (tp->t_flags&RAW || newflags&RAW) - wflushtty(tp); - else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) - if (newflags&CBREAK) { - struct clist tq; - - catq(&tp->t_rawq, &tp->t_canq); - tq = tp->t_rawq; - tp->t_rawq = tp->t_canq; - tp->t_canq = tq; - } else { - tp->t_flags |= PENDIN; - ttwakeup(tp); - } - if (com == TIOCSET) - tp->t_flags = newflags; - else - tp->t_flags |= newflags; - if (tp->t_flags&RAW) { - tp->t_state &= ~TS_TTSTOP; - ttstart(tp); - } - splx(s); - break; - } - - case TIOCBIC: { - u_long newflags = *(long *)data; - - if (tp->t_flags&RAW) - wflushtty(tp); - else if ((tp->t_flags&CBREAK) != (CBREAK&~newflags)) - if (newflags&CBREAK) { - tp->t_flags |= PENDIN; - ttwakeup(tp); - } else { - struct clist tq; - - catq(&tp->t_rawq, &tp->t_canq); - tq = tp->t_rawq; - tp->t_rawq = tp->t_canq; - tp->t_canq = tq; - } - if (tp->t_flags&RAW) { - tp->t_state &= ~TS_TTSTOP; - ttstart(tp); - } - splx(s); - break; - } case TIOCGET: - *(long *)data = tp->t_flags; + *(int *)data = tp->t_flags; break; case TIOCCGET: @@ -380,7 +332,7 @@ ttioctl(tp, com, data, flag) flags = FREAD|FWRITE; else flags &= FREAD|FWRITE; - flushtty(tp, flags); + ttyflush(tp, flags); break; } @@ -417,12 +369,118 @@ ttioctl(tp, com, data, flag) (*linesw[tp->t_line].l_rint)(*(char *)data, tp); break; + case TIOCSET: + case TIOCBIS: + case TIOCBIC: + newflags = *(int *)data; + if (com == TIOCBIS) + newflags |= tp->t_flags; + else if (com == TIOCBIC) + newflags = tp->t_flags &~ newflags; + goto setin; + + case TIOCSETP: + case TIOCSETN: { + register struct sgttyb *sg = (struct sgttyb *)data; + + tp->t_erase = sg->sg_erase; + tp->t_kill = sg->sg_kill; + tp->t_ispeed = sg->sg_ispeed; + tp->t_ospeed = sg->sg_ospeed; + newflags = (tp->t_flags&0xffff0000) | (sg->sg_flags&0xffff); +setin: + s = spl5(); + if (tp->t_flags&RAW || newflags&RAW || com == TIOCSETP) { + ttywait(tp); + ttyflush(tp, FREAD); + } else if ((tp->t_flags&CBREAK) != (newflags&CBREAK)) { + if (newflags&CBREAK) { + struct clist tq; + + catq(&tp->t_rawq, &tp->t_canq); + tq = tp->t_rawq; + tp->t_rawq = tp->t_canq; + tp->t_canq = tq; + } else { + tp->t_flags |= PENDIN; + ttwakeup(tp); + } + } + tp->t_flags = newflags; + if (tp->t_flags&RAW) { + tp->t_state &= ~TS_TTSTOP; + ttstart(tp); + } + splx(s); + break; + } + + /* send current parameters to user */ + case TIOCGETP: { + register struct sgttyb *sg = (struct sgttyb *)data; + + sg->sg_ispeed = tp->t_ispeed; + sg->sg_ospeed = tp->t_ospeed; + sg->sg_erase = tp->t_erase; + sg->sg_kill = tp->t_kill; + sg->sg_flags = tp->t_flags; + break; + } + + case FIONBIO: + if (*(int *)data) + tp->t_state |= TS_NBIO; + else + tp->t_state &= ~TS_NBIO; + break; + + case FIOASYNC: + if (*(int *)data) + tp->t_state |= TS_ASYNC; + else + tp->t_state &= ~TS_ASYNC; + break; + + /* set/get local special characters */ + case TIOCSLTC: + bcopy(data, (caddr_t)&tp->t_suspc, sizeof (struct ltchars)); + break; + + case TIOCGLTC: + bcopy((caddr_t)&tp->t_suspc, data, sizeof (struct ltchars)); + break; + + /* + * Modify local mode word. + */ + case TIOCLBIS: + tp->t_flags |= *(int *)data << 16; + break; + + case TIOCLBIC: + tp->t_flags &= ~(*(int *)data << 16); + break; + + case TIOCLSET: + tp->t_flags &= 0xffff; + tp->t_flags |= *(int *)data << 16; + break; + + case TIOCLGET: + *(int *)data = tp->t_flags >> 16; + break; + + /* should allow SPGRP and GPGRP only if tty open for reading */ + case TIOCSPGRP: + tp->t_pgrp = *(int *)data; + break; + + case TIOCGPGRP: + *(int *)data = tp->t_pgrp; + break; + default: -#ifndef NOCOMPAT - return (ottioctl(tp, com, data, flag)); -#else return (-1); -#endif } return (0); } @@ -498,7 +556,7 @@ ttyopen(dev, tp) tp->t_state &= ~TS_WOPEN; tp->t_state |= TS_ISOPEN; if (tp->t_line != NTTYDISC) - wflushtty(tp); + ttywflush(tp); return (0); } @@ -510,12 +568,12 @@ ttyclose(tp) { if (tp->t_line) { - wflushtty(tp); + ttywflush(tp); tp->t_line = 0; return; } tp->t_pgrp = 0; - wflushtty(tp); + ttywflush(tp); tp->t_state = 0; } @@ -573,7 +631,7 @@ ttyinput(c, tp) * in input q w/o interpretation. */ if (tp->t_rawq.c_cc > TTYHOG) - flushtty(tp, FREAD|FWRITE); + ttyflush(tp, FREAD|FWRITE); else { if (putc(c, &tp->t_rawq) >= 0) ttwakeup(tp); @@ -614,7 +672,7 @@ ttyinput(c, tp) if (tp->t_flags&FLUSHO) tp->t_flags &= ~FLUSHO; else { - flushtty(tp, FWRITE); + ttyflush(tp, FWRITE); ttyecho(c, tp); if (tp->t_rawq.c_cc + tp->t_canq.c_cc) ttyretype(tp); @@ -624,7 +682,7 @@ ttyinput(c, tp) } if (c == tp->t_suspc) { if ((tp->t_flags&NOFLSH) == 0) - flushtty(tp, FREAD); + ttyflush(tp, FREAD); ttyecho(c, tp); gsignal(tp->t_pgrp, SIGTSTP); goto endcase; @@ -652,7 +710,7 @@ ttyinput(c, tp) */ if (c == tp->t_intrc || c == tp->t_quitc) { if ((tp->t_flags&NOFLSH) == 0) - flushtty(tp, FREAD|FWRITE); + ttyflush(tp, FREAD|FWRITE); ttyecho(c, tp); gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT); goto endcase; @@ -898,7 +956,7 @@ ttyoutput(c, tp) case NEWLINE: ctype = (tp->t_flags >> 8) & 03; if (ctype == 1) { /* tty 37 */ - if (*colp) + if (*colp > 0) c = max(((unsigned)*colp>>4) + 3, (unsigned)6); } else if (ctype == 2) /* vt05 */ c = 6; @@ -1153,7 +1211,7 @@ loop: if (cc > OBUFSIZ) cc = OBUFSIZ; cp = obuf; - error = uiomove(cp, (unsigned)cc, UIO_WRITE, uio); + error = uiomove(cp, cc, UIO_WRITE, uio); if (error) break; if (tp->t_outq.c_cc > hiwat) @@ -1194,7 +1252,8 @@ loop: if (tp->t_flags & (RAW|LITOUT)) ce = cc; else { - ce = cc - scanc(cc, cp, partab, 077); + ce = cc - scanc((unsigned)cc, (caddr_t)cp, + (caddr_t)partab, 077); /* * If ce is zero, then we're processing * a special character through ttyoutput. @@ -1460,6 +1519,8 @@ ttwakeup(tp) tp->t_state &= ~TS_RCOLL; tp->t_rsel = 0; } + if (tp->t_state & TS_ASYNC) + gsignal(tp->t_pgrp, SIGIO); wakeup((caddr_t)&tp->t_rawq); } diff --git a/usr/src/sys/kern/tty_bk.c b/usr/src/sys/kern/tty_bk.c index d79ad52fd0..911b3dbc03 100644 --- a/usr/src/sys/kern/tty_bk.c +++ b/usr/src/sys/kern/tty_bk.c @@ -1,4 +1,4 @@ -/* tty_bk.c 4.8 82/12/05 */ +/* tty_bk.c 4.9 83/05/27 */ #include "bk.h" @@ -44,7 +44,7 @@ bkopen(dev, tp) if (tp->t_line == NETLDISC) return (EBUSY); /* sometimes the network opens /dev/tty */ bp = geteblk(1024); - flushtty(tp, FREAD|FWRITE); + ttyflush(tp, FREAD|FWRITE); tp->t_bufp = bp; tp->t_cp = (char *)bp->b_un.b_addr; tp->t_inbuf = 0; diff --git a/usr/src/sys/kern/tty_conf.c b/usr/src/sys/kern/tty_conf.c index d4d09439dd..76dfecd9b7 100644 --- a/usr/src/sys/kern/tty_conf.c +++ b/usr/src/sys/kern/tty_conf.c @@ -1,4 +1,4 @@ -/* tty_conf.c 4.2 82/10/17 */ +/* tty_conf.c 4.3 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -52,3 +52,20 @@ struct linesw linesw[] = }; int nldisp = sizeof (linesw) / sizeof (linesw[0]); + +/* + * Do nothing specific version of line + * discipline specific ioctl command. + */ +/*ARGSUSED*/ +nullioctl(tp, cmd, data, flags) + struct tty *tp; + char *data; + int flags; +{ + +#ifdef lint + tp = tp; data = data; flags = flags; +#endif + return (-1); +} diff --git a/usr/src/sys/kern/tty_pty.c b/usr/src/sys/kern/tty_pty.c index f7b84f0c83..0bbb7e22a0 100644 --- a/usr/src/sys/kern/tty_pty.c +++ b/usr/src/sys/kern/tty_pty.c @@ -1,4 +1,4 @@ -/* tty_pty.c 4.30 83/05/21 */ +/* tty_pty.c 4.31 83/05/27 */ /* * Pseudo-teletype Driver @@ -208,7 +208,7 @@ ptcclose(dev) if (tp->t_state & TS_ISOPEN) gsignal(tp->t_pgrp, SIGHUP); tp->t_state &= ~TS_CARR_ON; /* virtual carrier gone */ - flushtty(tp, FREAD|FWRITE); + ttyflush(tp, FREAD|FWRITE); tp->t_oproc = 0; /* mark closed */ } @@ -414,7 +414,7 @@ ptyioctl(dev, cmd, data, flag) pti->pt_flags |= PF_REMOTE; else pti->pt_flags &= ~PF_REMOTE; - flushtty(tp, FREAD|FWRITE); + ttyflush(tp, FREAD|FWRITE); return (0); case FIONBIO: diff --git a/usr/src/sys/kern/tty_subr.c b/usr/src/sys/kern/tty_subr.c index c7be434109..edd9a2ba56 100644 --- a/usr/src/sys/kern/tty_subr.c +++ b/usr/src/sys/kern/tty_subr.c @@ -1,4 +1,4 @@ -/* tty_subr.c 4.19 83/02/06 */ +/* tty_subr.c 4.20 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -13,7 +13,7 @@ char cwaiting; * Character list get/put */ getc(p) -register struct clist *p; + register struct clist *p; { register struct cblock *bp; register int c, s; @@ -54,6 +54,7 @@ register struct clist *p; return(c); } +#ifdef notdef /* * copy clist to buffer. * return number of bytes moved. @@ -109,6 +110,7 @@ q_to_b(q, cp, cc) splx(s); return(cp-acp); } +#endif /* * Return count of contiguous characters @@ -156,13 +158,12 @@ out: * Flush cc bytes from q. */ ndflush(q, cc) -register struct clist *q; -register cc; + register struct clist *q; + register cc; { -register struct cblock *bp; -char *end; -int rem; -register s; + register struct cblock *bp; + char *end; + int rem, s; s = spl5(); if (q->c_cc <= 0) { @@ -212,7 +213,7 @@ out: putc(c, p) -register struct clist *p; + register struct clist *p; { register struct cblock *bp; register char *cp; @@ -254,9 +255,9 @@ register struct clist *p; * return number of bytes not transfered. */ b_to_q(cp, cc, q) -register char *cp; -struct clist *q; -register int cc; + register char *cp; + struct clist *q; + register int cc; { register char *cq; register struct cblock *bp; @@ -308,8 +309,8 @@ out: */ char * nextc(p, cp) -register struct clist *p; -register char *cp; + register struct clist *p; + register char *cp; { if (p->c_cc && ++cp != p->c_cl) { @@ -324,7 +325,7 @@ register char *cp; * Remove the last character in the list and return it. */ unputc(p) -register struct clist *p; + register struct clist *p; { register struct cblock *bp; register int c, s; @@ -368,7 +369,7 @@ register struct clist *p; * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. */ catq(from, to) -struct clist *from, *to; + struct clist *from, *to; { register c; diff --git a/usr/src/sys/kern/tty_tb.c b/usr/src/sys/kern/tty_tb.c index 90dae83df8..49cfcda10c 100644 --- a/usr/src/sys/kern/tty_tb.c +++ b/usr/src/sys/kern/tty_tb.c @@ -1,4 +1,4 @@ -/* tty_tb.c 4.7 82/12/05 */ +/* tty_tb.c 4.8 83/05/27 */ #include "tb.h" #if NTB > 0 @@ -48,7 +48,7 @@ tbopen(dev, tp) if (tp->t_line == TABLDISC || tp->t_line == NTABLDISC) { return (EBUSY); - wflushtty(tp); + ttywflush(tp); tp->t_cp = (char *) &tp->t_un.T_CTLQ; /* overlay control queue */ tp->t_inbuf = 0; tbp = (struct tbposition *) &tp->t_rocount; diff --git a/usr/src/sys/kern/uipc_mbuf.c b/usr/src/sys/kern/uipc_mbuf.c index d7b1ffe286..11f5f9b982 100644 --- a/usr/src/sys/kern/uipc_mbuf.c +++ b/usr/src/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* uipc_mbuf.c 1.42 82/12/17 */ +/* uipc_mbuf.c 1.43 83/05/27 */ #include "../machine/pte.h" diff --git a/usr/src/sys/kern/uipc_proto.c b/usr/src/sys/kern/uipc_proto.c index d7f56847d8..70fb6811e0 100644 --- a/usr/src/sys/kern/uipc_proto.c +++ b/usr/src/sys/kern/uipc_proto.c @@ -1,4 +1,4 @@ -/* uipc_proto.c 4.27 82/11/02 */ +/* uipc_proto.c 4.28 83/05/27 */ #include "../h/param.h" #include "../h/socket.h" @@ -19,7 +19,7 @@ struct protosw unixsw[] = { uipc_usrreq, 0, 0, 0, 0, }, -{ SOCK_DGRAM, PF_UNIX, 0, PR_ATOMIC|PR_ADDR, +{ SOCK_DGRAM, PF_UNIX, 0, PR_ATOMIC|PR_ADDR|PR_RIGHTS, 0, 0, 0, 0, uipc_usrreq, 0, 0, 0, 0, diff --git a/usr/src/sys/kern/uipc_socket.c b/usr/src/sys/kern/uipc_socket.c index b1117daade..2e1ef2294f 100644 --- a/usr/src/sys/kern/uipc_socket.c +++ b/usr/src/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* uipc_socket.c 4.74 83/05/18 */ +/* uipc_socket.c 4.75 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -9,6 +9,7 @@ #include "../h/inode.h" #include "../h/buf.h" #include "../h/mbuf.h" +#include "../h/un.h" #include "../h/protosw.h" #include "../h/socket.h" #include "../h/socketvar.h" @@ -16,6 +17,7 @@ #include "../h/ioctl.h" #include "../h/uio.h" #include "../net/route.h" +#include "../netinet/in.h" #include "../net/if.h" /* @@ -24,17 +26,24 @@ * sys_socket.c or from a system process, and * implement the semantics of socket operations by * switching out to the protocol specific routines. + * + * TODO: + * sostat + * test socketpair + * PR_RIGHTS + * clean up select, async + * out-of-band is a kludge */ - /*ARGSUSED*/ socreate(dom, aso, type, proto) struct socket **aso; - int type, proto; + register int type; + int proto; { register struct protosw *prp; register struct socket *so; - struct mbuf *m; - int error; + register struct mbuf *m; + register int error; if (proto) prp = pffindproto(dom, proto); @@ -48,14 +57,15 @@ socreate(dom, aso, type, proto) if (m == 0) return (ENOBUFS); so = mtod(m, struct socket *); - so->so_options = SO_LINGER; + so->so_options = 0; so->so_state = 0; so->so_type = type; if (u.u_uid == 0) so->so_state = SS_PRIV; so->so_proto = prp; - error = (*prp->pr_usrreq)(so, PRU_ATTACH, - (struct mbuf *)0, (struct mbuf *)0); + error = + (*prp->pr_usrreq)(so, PRU_ATTACH, + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); if (error) { so->so_state |= SS_NOFDREF; sofree(so); @@ -73,20 +83,21 @@ sobind(so, nam) int error; error = - (*so->so_proto->pr_usrreq)(so, PRU_BIND, (struct mbuf *)0, nam); + (*so->so_proto->pr_usrreq)(so, PRU_BIND, + (struct mbuf *)0, nam, (struct mbuf *)0); splx(s); return (error); } solisten(so, backlog) - struct socket *so; + register struct socket *so; int backlog; { - int s = splnet(); - int error; + int s = splnet(), error; - error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, - (struct mbuf *)0, (struct mbuf *)0); + error = + (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); if (error) { splx(s); return (error); @@ -98,15 +109,13 @@ solisten(so, backlog) } if (backlog < 0) backlog = 0; -#define SOMAXCONN 5 so->so_qlimit = MIN(backlog, SOMAXCONN); - so->so_options |= SO_NEWFDONCONN; splx(s); return (0); } sofree(so) - struct socket *so; + register struct socket *so; { if (so->so_head) { @@ -117,7 +126,7 @@ sofree(so) if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) return; sbrelease(&so->so_snd); - sbrelease(&so->so_rcv); + sorflush(so); (void) m_free(dtom(so)); } @@ -126,9 +135,8 @@ sofree(so) * Initiate disconnect if connected. * Free socket when disconnect complete. */ -soclose(so, exiting) +soclose(so) register struct socket *so; - int exiting; { int s = splnet(); /* conservative */ int error; @@ -141,36 +149,27 @@ soclose(so, exiting) } if (so->so_pcb == 0) goto discard; - if (exiting) - so->so_options |= SO_KEEPALIVE; if (so->so_state & SS_ISCONNECTED) { if ((so->so_state & SS_ISDISCONNECTING) == 0) { error = sodisconnect(so, (struct mbuf *)0); - if (error) { - if (exiting) - goto drop; - splx(s); - return (error); - } + if (error) + goto drop; } if (so->so_options & SO_LINGER) { if ((so->so_state & SS_ISDISCONNECTING) && - (so->so_state & SS_NBIO) && - exiting == 0) - return (EINPROGRESS); - /* should use tsleep here, for at most linger */ + (so->so_state & SS_NBIO)) + goto drop; while (so->so_state & SS_ISCONNECTED) sleep((caddr_t)&so->so_timeo, PZERO+1); } } drop: if (so->so_pcb) { - error = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, - (struct mbuf *)0, (struct mbuf *)0); - if (exiting == 0 && error) { - splx(s); - return (error); - } + int error2 = + (*so->so_proto->pr_usrreq)(so, PRU_DETACH, + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); + if (error == 0) + error = error2; } discard: if (so->so_state & SS_NOFDREF) @@ -178,7 +177,7 @@ discard: so->so_state |= SS_NOFDREF; sofree(so); splx(s); - return (0); + return (error); } /* @@ -187,27 +186,14 @@ discard: soabort(so) struct socket *so; { - int error; - error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, - (struct mbuf *)0, (struct mbuf *)0); - return (error); -} - -/*ARGSUSED*/ -sostat(so, ub) - struct socket *so; - struct stat *ub; -{ - struct stat sb; - - bzero((caddr_t)&sb, sizeof (sb)); /* XXX */ - (void) copyout((caddr_t)&sb, (caddr_t)ub, sizeof (sb));/* XXX */ - return (0); /* XXX */ + return ( + (*so->so_proto->pr_usrreq)(so, PRU_ABORT, + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); } soaccept(so, nam) - struct socket *so; + register struct socket *so; struct mbuf *nam; { int s = splnet(); @@ -217,13 +203,13 @@ soaccept(so, nam) panic("soaccept: !NOFDREF"); so->so_state &= ~SS_NOFDREF; error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, - (struct mbuf *)0, nam); + (struct mbuf *)0, nam, (struct mbuf *)0); splx(s); return (error); } soconnect(so, nam) - struct socket *so; + register struct socket *so; struct mbuf *nam; { int s = splnet(); @@ -234,14 +220,30 @@ soconnect(so, nam) goto bad; } error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT, - (struct mbuf *)0, nam); + (struct mbuf *)0, nam, (struct mbuf *)0); bad: splx(s); return (error); } +#ifdef notdef +soconnect2(so1, so2) + register struct socket *so1; + struct socket *so2; +{ + int s = splnet(); + int error; + + error = + (*so1->so_proto->pr_usrreq)(so, PRU_CONNECT2, + (struct mbuf *)0, (struct mbuf *)so2, (struct mbuf *)0); + splx(s); + return (error); +} +#endif + sodisconnect(so, nam) - struct socket *so; + register struct socket *so; struct mbuf *nam; { int s = splnet(); @@ -256,7 +258,7 @@ sodisconnect(so, nam) goto bad; } error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, - (struct mbuf *)0, nam); + (struct mbuf *)0, nam, (struct mbuf *)0); bad: splx(s); return (error); @@ -270,22 +272,23 @@ bad: * If must go all at once and not enough room now, then * inform user that this would block and do nothing. */ -sosend(so, nam, uio, flags) +sosend(so, nam, uio, flags, rights) register struct socket *so; struct mbuf *nam; - struct uio *uio; + register struct uio *uio; int flags; + struct mbuf *rights; { struct mbuf *top = 0; register struct mbuf *m, **mp = ⊤ - register int len; - int error = 0, space, s, dontroute; + register int space; + int len, error = 0, s, dontroute; if (sosendallatonce(so) && uio->uio_resid > so->so_snd.sb_hiwat) return (EMSGSIZE); - dontroute = (flags & SOF_DONTROUTE) && - (so->so_options & SO_DONTROUTE) == 0 && - (so->so_proto->pr_flags & PR_ATOMIC); + dontroute = + (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 && + (so->so_proto->pr_flags & PR_ATOMIC); restart: sblock(&so->so_snd); #define snderr(errno) { error = errno; splx(s); goto release; } @@ -313,8 +316,8 @@ again: if (dontroute) so->so_options |= SO_DONTROUTE; error = (*so->so_proto->pr_usrreq)(so, - (flags & SOF_OOB) ? PRU_SENDOOB : PRU_SEND, - top, (caddr_t)nam); + (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND, + top, (caddr_t)nam, rights); if (dontroute) so->so_options &= ~SO_DONTROUTE; top = 0; @@ -328,7 +331,7 @@ again: splx(s); goto release; } - if (flags & SOF_OOB) + if (flags & MSG_OOB) space = 1024; else { space = sbspace(&so->so_snd); @@ -373,7 +376,7 @@ nopages: m->m_len = len; *mp = m; mp = &m->m_next; - if (flags & SOF_OOB) + if (flags & MSG_OOB) space -= len; else space = sbspace(&so->so_snd); @@ -387,22 +390,28 @@ release: return (error); } -soreceive(so, aname, uio, flags) +soreceive(so, aname, uio, flags, rightsp) register struct socket *so; struct mbuf **aname; - struct uio *uio; + register struct uio *uio; int flags; + struct mbuf **rightsp; { register struct mbuf *m, *n; - int len; - int eor, s, error = 0, moff, tomark; - - if (flags & SOF_OOB) { + register int len, error = 0, s, eor, tomark; + struct protosw *pr = so->so_proto; + int moff; + + if (rightsp) + *rightsp = 0; + if (aname) + *aname = 0; + if (flags & MSG_OOB) { m = m_get(M_WAIT, MT_DATA); - if (m == NULL) + if (m == 0) return (ENOBUFS); - error = (*so->so_proto->pr_usrreq)(so, PRU_RCVOOB, - m, (struct mbuf *)0); + error = (*pr->pr_usrreq)(so, PRU_RCVOOB, + m, (struct mbuf *)0, (struct mbuf *)0); if (error) goto bad; do { @@ -449,13 +458,13 @@ restart: m = so->so_rcv.sb_mb; if (m == 0) panic("receive"); - if (so->so_proto->pr_flags & PR_ADDR) { - if ((flags & SOF_PREVIEW) == 0) { + if (pr->pr_flags & PR_ADDR) { + if ((flags & MSG_PEEK) == 0) { so->so_rcv.sb_cc -= m->m_len; so->so_rcv.sb_mbcnt -= MSIZE; } if (aname) { - if (flags & SOF_PREVIEW) { + if (flags & MSG_PEEK) { *aname = m_copy(m, 0, m->m_len); if (*aname == NULL) panic("receive 2"); @@ -464,13 +473,33 @@ restart: m = m->m_next; (*aname)->m_next = 0; } else - if (flags & SOF_PREVIEW) + if (flags & MSG_PEEK) m = m->m_next; else m = m_free(m); + if (m == 0) + panic("receive 2a"); + if (rightsp) { + if (m->m_len) + *rightsp = m_copy(m, 0, m->m_len); + else { + *rightsp = m_get(M_DONTWAIT, MT_SONAME); + if (*rightsp) + (*rightsp)->m_len = 0; + } + if (*rightsp == NULL) + panic("receive 2b"); + } + if (flags & MSG_PEEK) + m = m->m_next; + else { + so->so_rcv.sb_cc -= m->m_len; + so->so_rcv.sb_mbcnt -= MSIZE; + m = m_free(m); + } if (m == 0) panic("receive 3"); - if ((flags & SOF_PREVIEW) == 0) + if ((flags & MSG_PEEK) == 0) so->so_rcv.sb_mb = m; } eor = 0; @@ -491,7 +520,7 @@ restart: s = splnet(); if (len == m->m_len) { eor = (int)m->m_act; - if (flags & SOF_PREVIEW) + if (flags & MSG_PEEK) m = m->m_next; else { sbfree(&so->so_rcv, m); @@ -501,7 +530,7 @@ restart: } moff = 0; } else { - if (flags & SOF_PREVIEW) + if (flags & MSG_PEEK) moff += len; else { m->m_off += len; @@ -509,7 +538,7 @@ restart: so->so_rcv.sb_cc -= len; } } - if ((flags & SOF_PREVIEW) == 0 && so->so_oobmark) { + if ((flags & MSG_PEEK) == 0 && so->so_oobmark) { so->so_oobmark -= len; if (so->so_oobmark == 0) { so->so_state |= SS_RCVATMARK; @@ -522,7 +551,7 @@ restart: break; } } while (m && error == 0 && !eor); - if (flags & SOF_PREVIEW) + if (flags & MSG_PEEK) goto release; if ((so->so_proto->pr_flags & PR_ATOMIC) && eor == 0) do { @@ -536,35 +565,55 @@ restart: } while (eor == 0); if ((so->so_proto->pr_flags & PR_WANTRCVD) && so->so_pcb) (*so->so_proto->pr_usrreq)(so, PRU_RCVD, - (struct mbuf *)0, (struct mbuf *)0); + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0); release: sbunlock(&so->so_rcv); + if (error == 0 && rightsp && + *rightsp && so->so_proto->pr_family == AF_UNIX) + error = unp_externalize(*rightsp); splx(s); return (error); } soshutdown(so, how) - struct socket *so; - int how; + register struct socket *so; + register int how; { + register struct protosw *pr = so->so_proto; how++; - if (how & FREAD) { - int s = splimp(); - socantrcvmore(so); - sbflush(&so->so_rcv); - splx(s); - } + if (how & FREAD) + sorflush(so); if (how & FWRITE) - return ((*so->so_proto->pr_usrreq)(so, PRU_SHUTDOWN, - (struct mbuf *)0, (struct mbuf *)0)); + return ((*pr->pr_usrreq)(so, PRU_SHUTDOWN, + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)); return (0); } +sorflush(so) + register struct socket *so; +{ + register struct sockbuf *sb = &so->so_rcv; + register struct protosw *pr = so->so_proto; + register int s; + struct sockbuf asb; + + sblock(sb); + s = splimp(); + socantrcvmore(so); + sbunlock(sb); + asb = *sb; + bzero((caddr_t)sb, sizeof (*sb)); + splx(s); + if (pr->pr_family == AF_UNIX && (pr->pr_flags & PR_RIGHTS)) + unp_scan(asb.sb_mb, unp_discard); + sbrelease(&asb); +} + sosetopt(so, level, optname, m) - struct socket *so; + register struct socket *so; int level, optname; - struct mbuf *m; + register struct mbuf *m; { if (level != SOL_SOCKET) @@ -598,9 +647,9 @@ sosetopt(so, level, optname, m) } sogetopt(so, level, optname, m) - struct socket *so; + register struct socket *so; int level, optname; - struct mbuf *m; + register struct mbuf *m; { if (level != SOL_SOCKET) @@ -628,7 +677,7 @@ sogetopt(so, level, optname, m) } sohasoutofband(so) - struct socket *so; + register struct socket *so; { if (so->so_pgrp == 0) @@ -642,68 +691,3 @@ sohasoutofband(so) psignal(p, SIGURG); } } - -/*ARGSUSED*/ -soioctl(so, cmd, data) - register struct socket *so; - int cmd; - register char *data; -{ - - switch (cmd) { - - case FIONBIO: - if (*(int *)data) - so->so_state |= SS_NBIO; - else - so->so_state &= ~SS_NBIO; - break; - - case FIOASYNC: - if (*(int *)data) - so->so_state |= SS_ASYNC; - else - so->so_state &= ~SS_ASYNC; - break; - - case SIOCSPGRP: - so->so_pgrp = *(int *)data; - break; - - case SIOCGPGRP: - *(int *)data = so->so_pgrp; - break; - - case SIOCATMARK: - *(int *)data = (so->so_state&SS_RCVATMARK) != 0; - break; - - /* routing table update calls */ - case SIOCADDRT: - case SIOCDELRT: - if (!suser()) - return (u.u_error); - return (rtrequest(cmd, (struct rtentry *)data)); - - /* interface parameter requests */ - case SIOCSIFADDR: - case SIOCSIFFLAGS: - case SIOCSIFDSTADDR: - if (!suser()) - return (u.u_error); - return (ifrequest(cmd, data)); - - case SIOCGIFADDR: - case SIOCGIFFLAGS: - case SIOCGIFDSTADDR: - return (ifrequest(cmd, data)); - - case SIOCGIFCONF: - return (ifconf(cmd, data)); - - /* type/protocol specific ioctls */ - default: - return (ENOTTY); /* XXX */ - } - return (0); -} diff --git a/usr/src/sys/kern/uipc_socket2.c b/usr/src/sys/kern/uipc_socket2.c index 19ea2a8ac2..716be26d51 100644 --- a/usr/src/sys/kern/uipc_socket2.c +++ b/usr/src/sys/kern/uipc_socket2.c @@ -1,4 +1,4 @@ -/* uipc_socket2.c 4.36 83/05/01 */ +/* uipc_socket2.c 4.37 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -31,24 +31,24 @@ * only, bypassing the in-progress calls when setting up a ``connection'' * takes no time. * - * From the passive side, a socket is created with SO_ACCEPTCONN - * creating two queues of sockets: so_q0 for connections in progress + * From the passive side, a socket is created with + * two queues of sockets: so_q0 for connections in progress * and so_q for connections already made and awaiting user acceptance. * As a protocol is preparing incoming connections, it creates a socket * structure queued on so_q0 by calling sonewconn(). When the connection * is established, soisconnected() is called, and transfers the * socket structure to so_q, making it available to accept(). * - * If a SO_ACCEPTCONN socket is closed with sockets on either + * If a socket is closed with sockets on either * so_q0 or so_q, these sockets are dropped. * - * If and when higher level protocols are implemented in + * If higher level protocols are implemented in * the kernel, the wakeups done here will sometimes - * be implemented as software-interrupt process scheduling. + * cause software-interrupt process scheduling. */ soisconnecting(so) - struct socket *so; + register struct socket *so; { so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING); @@ -57,7 +57,7 @@ soisconnecting(so) } soisconnected(so) - struct socket *so; + register struct socket *so; { register struct socket *head = so->so_head; @@ -65,8 +65,8 @@ soisconnected(so) if (soqremque(so, 0) == 0) panic("soisconnected"); soqinsque(head, so, 1); - wakeup((caddr_t)&head->so_timeo); sorwakeup(head); + wakeup((caddr_t)&head->so_timeo); } so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING); so->so_state |= SS_ISCONNECTED; @@ -76,7 +76,7 @@ soisconnected(so) } soisdisconnecting(so) - struct socket *so; + register struct socket *so; { so->so_state &= ~SS_ISCONNECTING; @@ -87,7 +87,7 @@ soisdisconnecting(so) } soisdisconnected(so) - struct socket *so; + register struct socket *so; { so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING); @@ -109,7 +109,7 @@ sonewconn(head) register struct socket *head; { register struct socket *so; - struct mbuf *m; + register struct mbuf *m; if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) goto bad; @@ -125,8 +125,8 @@ sonewconn(head) so->so_timeo = head->so_timeo; so->so_pgrp = head->so_pgrp; soqinsque(head, so, 0); - if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, (struct mbuf *)0, - (struct mbuf *)0)) { + if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, + (struct mbuf *)0, (struct mbuf *)0, (struct mbuf *)0)) { (void) soqremque(so, 0); (void) m_free(m); goto bad; @@ -211,38 +211,6 @@ socantrcvmore(so) * Socket select/wakeup routines. */ -/* - * Interface routine to select() system - * call for sockets. - */ -soselect(so, rw) - register struct socket *so; - int rw; -{ - int s = splnet(); - - switch (rw) { - - case FREAD: - if (soreadable(so)) { - splx(s); - return (1); - } - sbselqueue(&so->so_rcv); - break; - - case FWRITE: - if (sowriteable(so)) { - splx(s); - return (1); - } - sbselqueue(&so->so_snd); - break; - } - splx(s); - return (0); -} - /* * Queue a process for a select on a socket buffer. */ @@ -272,7 +240,7 @@ sbwait(sb) * Wakeup processes waiting on a socket buffer. */ sbwakeup(sb) - struct sockbuf *sb; + register struct sockbuf *sb; { if (sb->sb_sel) { @@ -325,7 +293,7 @@ sbwakeup(sb) */ soreserve(so, sndcc, rcvcc) - struct socket *so; + register struct socket *so; int sndcc, rcvcc; { @@ -349,8 +317,8 @@ sbreserve(sb, cc) /* someday maybe this routine will fail... */ sb->sb_hiwat = cc; - /* the 2 implies names can be no more than 1 mbuf each */ - sb->sb_mbmax = cc*2; + /* * 2 implies names can be no more than 1 mbuf each */ + sb->sb_mbmax = cc<<1; return (1); } @@ -414,15 +382,17 @@ sbappend(sb, m) * Return 0 if no space in sockbuf or if * can't get mbuf to stuff address in. */ -sbappendaddr(sb, asa, m0) +sbappendaddr(sb, asa, m0, rights0) struct sockbuf *sb; struct sockaddr *asa; - struct mbuf *m0; + struct mbuf *m0, *rights0; { - struct sockaddr *msa; register struct mbuf *m; register int len = sizeof (struct sockaddr); + register struct mbuf *rights; + if (rights0) + len += rights0->m_len; m = m0; if (m == 0) panic("sbappendaddr"); @@ -437,45 +407,34 @@ sbappendaddr(sb, asa, m0) if (len > sbspace(sb)) return (0); m = m_get(M_DONTWAIT, MT_SONAME); - if (m == 0) + if (m == NULL) return (0); m->m_len = sizeof (struct sockaddr); - msa = mtod(m, struct sockaddr *); - *msa = *asa; m->m_act = (struct mbuf *)1; + *mtod(m, struct sockaddr *) = *asa; + if (rights0 == 0 || rights0->m_len == 0) { + rights = m_get(M_DONTWAIT, MT_SONAME); + if (rights) + rights->m_len = 0; + } else + rights = m_copy(rights0, 0, rights0->m_len); + if (rights == 0) { + m_freem(m); + return (0); + } + rights->m_act = (struct mbuf *)1; + m->m_next = rights; + rights->m_next = m0; sbappend(sb, m); - sbappend(sb, m0); return (1); } -#ifdef notdef -SBCHECK(sb, str) - struct sockbuf *sb; - char *str; -{ - register int cnt = sb->sb_cc; - register int mbcnt = sb->sb_mbcnt; - register struct mbuf *m; - - for (m = sb->sb_mb; m; m = m->m_next) { - cnt -= m->m_len; - mbcnt -= MSIZE; - if (m->m_off > MMAXOFF) - mbcnt -= CLBYTES; - } - if (cnt || mbcnt) { - printf("cnt %d mbcnt %d\n", cnt, mbcnt); - panic(str); - } -} -#endif - /* * Free all mbufs on a sockbuf mbuf chain. * Check that resource allocations return to 0. */ sbflush(sb) - struct sockbuf *sb; + register struct sockbuf *sb; { if (sb->sb_flags & SB_LOCK) diff --git a/usr/src/sys/kern/uipc_syscalls.c b/usr/src/sys/kern/uipc_syscalls.c index 3a3c851372..9e0e60cc03 100644 --- a/usr/src/sys/kern/uipc_syscalls.c +++ b/usr/src/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* uipc_syscalls.c 4.45 83/03/23 */ +/* uipc_syscalls.c 4.46 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,13 +12,15 @@ #include "../h/protosw.h" #include "../h/socket.h" #include "../h/socketvar.h" -#include "../h/descrip.h" #include "../h/uio.h" /* * System call interface to the socket abstraction. */ +struct file *getsock(); +extern struct fileops socketops; + socket() { register struct a { @@ -33,10 +35,11 @@ socket() return; fp->f_flag = FREAD|FWRITE; fp->f_type = DTYPE_SOCKET; + fp->f_ops = &socketops; u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol); if (u.u_error) goto bad; - fp->f_socket = so; + fp->f_data = (caddr_t)so; return; bad: u.u_ofile[u.u_r.r_val1] = 0; @@ -53,17 +56,13 @@ bind() register struct file *fp; struct mbuf *nam; - fp = getf(uap->s); + fp = getsock(uap->s); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - u.u_error = sockname(&nam, uap->name, uap->namelen); + u.u_error = sockargs(&nam, uap->name, uap->namelen); if (u.u_error) return; - u.u_error = sobind(fp->f_socket, nam); + u.u_error = sobind((struct socket *)fp->f_data, nam); m_freem(nam); } @@ -75,14 +74,10 @@ listen() } *uap = (struct a *)u.u_ap; register struct file *fp; - fp = getf(uap->s); + fp = getsock(uap->s); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - u.u_error = solisten(fp->f_socket, uap->backlog); + u.u_error = solisten((struct socket *)fp->f_data, uap->backlog); } accept() @@ -109,15 +104,11 @@ accept() return; } noname: - fp = getf(uap->s); + fp = getsock(uap->s); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } s = splnet(); - so = fp->f_socket; + so = (struct socket *)fp->f_data; if ((so->so_options & SO_ACCEPTCONN) == 0) { u.u_error = EINVAL; splx(s); @@ -140,16 +131,7 @@ noname: splx(s); return; } - if ((so->so_options & SO_NEWFDONCONN) == 0) { - struct socket *nso = so->so_q; - (void) soqremque(nso, 1); - u.u_error = soclose(so, 1); - fp->f_socket = nso; - nso->so_q = 0; - so = nso; - goto ret; - } - if (ufalloc() < 0) { + if (ufalloc(0) < 0) { splx(s); return; } @@ -166,8 +148,8 @@ noname: } fp->f_type = DTYPE_SOCKET; fp->f_flag = FREAD|FWRITE; - fp->f_socket = so; -ret: + fp->f_ops = &socketops; + fp->f_data = (caddr_t)so; nam = m_get(M_WAIT, MT_SONAME); (void) soaccept(so, nam); if (uap->name) { @@ -195,15 +177,11 @@ connect() struct mbuf *nam; int s; - fp = getf(uap->s); + fp = getsock(uap->s); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - so = fp->f_socket; - u.u_error = sockname(&nam, uap->name, uap->namelen); + so = (struct socket *)fp->f_data; + u.u_error = sockargs(&nam, uap->name, uap->namelen); if (u.u_error) return; u.u_error = soconnect(so, nam); @@ -213,13 +191,18 @@ connect() if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { u.u_error = EINPROGRESS; - splx(s); - goto bad; + goto bad2; + } + if (setjmp(&u.u_qsave)) { + if (u.u_error == 0) + u.u_error = EINTR; + goto bad2; } while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) sleep((caddr_t)&so->so_timeo, PZERO+1); u.u_error = so->so_error; so->so_error = 0; +bad2: splx(s); bad: m_freem(nam); @@ -241,35 +224,18 @@ sendto() caddr_t to; int tolen; } *uap = (struct a *)u.u_ap; - register struct file *fp; - struct uio auio; + struct msghdr msg; struct iovec aiov; - struct mbuf *to; - fp = getf(uap->s); - if (fp == 0) - return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; + msg.msg_name = uap->to; + msg.msg_namelen = uap->tolen; + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; - auio.uio_resid = uap->len; - auio.uio_segflg = 0; - auio.uio_offset = 0; /* XXX */ - if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { - u.u_error = EFAULT; - return; - } - u.u_error = sockname(&to, uap->to, uap->tolen); - if (u.u_error) - return; - u.u_error = sosend(fp->f_socket, to, &auio, uap->flags); - u.u_r.r_val1 = uap->len - auio.uio_resid; - m_freem(to); + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + sendit(uap->s, &msg, uap->flags); } send() @@ -280,32 +246,107 @@ send() int len; int flags; } *uap = (struct a *)u.u_ap; - register struct file *fp; - struct uio auio; + struct msghdr msg; struct iovec aiov; - fp = getf(uap->s); - if (fp == 0) - return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; - auio.uio_resid = uap->len; - auio.uio_segflg = 0; - auio.uio_offset = 0; /* XXX */ - if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { - u.u_error = EFAULT; + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + sendit(uap->s, &msg, uap->flags); +} + +sendmsg() +{ + register struct a { + int s; + caddr_t msg; + int flags; + } *uap = (struct a *)u.u_ap; + struct msghdr msg; + struct iovec aiov[MSG_MAXIOVLEN]; + + u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); + if (u.u_error) + return; + if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { + u.u_error = EMSGSIZE; return; } + u.u_error = + copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, + (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); if (u.u_error) return; - u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags); - u.u_r.r_val1 = uap->len - auio.uio_resid; + msg.msg_iov = aiov; +#ifdef notdef +printf("sendmsg name %x namelen %d iov %x iovlen %d accrights %x &len %d\n", +msg.msg_name, msg.msg_namelen, msg.msg_iov, msg.msg_iovlen, +msg.msg_accrights, msg.msg_accrightslen); +#endif + sendit(uap->s, &msg, uap->flags); +} + +sendit(s, mp, flags) + int s; + register struct msghdr *mp; + int flags; +{ + register struct file *fp; + struct uio auio; + register struct iovec *iov; + register int i; + struct mbuf *to, *rights; + int len; + + fp = getsock(s); + if (fp == 0) + return; + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = 0; + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++) { + if (iov->iov_len < 0) { + u.u_error = EINVAL; + return; + } + if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) { + u.u_error = EFAULT; + return; + } + auio.uio_resid += iov->iov_len; + iov++; + } + if (mp->msg_name) { + u.u_error = + sockargs(&to, mp->msg_name, mp->msg_namelen); + if (u.u_error) + return; + } else + to = 0; + if (mp->msg_accrights) { + u.u_error = + sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen); + if (u.u_error) + goto bad; + } else + rights = 0; + len = auio.uio_resid; + u.u_error = + sosend((struct socket *)fp->f_data, to, &auio, flags, rights); + u.u_r.r_val1 = len - auio.uio_resid; + if (rights) + m_freem(rights); +bad: + if (to) + m_freem(to); } recvfrom() @@ -318,56 +359,23 @@ recvfrom() caddr_t from; int *fromlenaddr; } *uap = (struct a *)u.u_ap; - register struct file *fp; - struct uio auio; + struct msghdr msg; struct iovec aiov; - struct mbuf *from; - int fromlen; + int len; - u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen, - sizeof (fromlen)); + u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len, + sizeof (len)); if (u.u_error) return; - fp = getf(uap->s); - if (fp == 0) - return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; + msg.msg_name = uap->from; + msg.msg_namelen = len; + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; - auio.uio_resid = uap->len; - auio.uio_segflg = 0; - auio.uio_offset = 0; /* XXX */ - if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { - u.u_error = EFAULT; - return; - } - from = 0; - u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags); - if (u.u_error) - goto bad; - if (from == 0) - fromlen = 0; - else { - if (fromlen > from->m_len) - fromlen = from->m_len; - u.u_error = copyout(mtod(from, caddr_t), uap->from, - (u_int)fromlen); - if (u.u_error) - goto bad; - } - u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr, - sizeof (fromlen)); - if (u.u_error) - goto bad; - u.u_r.r_val1 = uap->len - auio.uio_resid; -bad: - if (from) - m_freem(from); + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + recvit(uap->s, &msg, uap->flags, (caddr_t)uap->fromlenaddr, (caddr_t)0); } recv() @@ -378,43 +386,121 @@ recv() int len; int flags; } *uap = (struct a *)u.u_ap; - register struct file *fp; - struct uio auio; + struct msghdr msg; struct iovec aiov; - fp = getf(uap->s); - if (fp == 0) - return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = &aiov; + msg.msg_iovlen = 1; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; - auio.uio_resid = uap->len; - auio.uio_segflg = 0; - auio.uio_offset = 0; /* XXX */ - if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { - u.u_error = EFAULT; - return; - } - u.u_error = - soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags); - u.u_r.r_val1 = uap->len - auio.uio_resid; + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + recvit(uap->s, &msg, uap->flags, (caddr_t)0, (caddr_t)0); } -sendmsg() +recvmsg() { + register struct a { + int s; + struct msghdr *msg; + int flags; + } *uap = (struct a *)u.u_ap; + struct msghdr msg; + struct iovec aiov[MSG_MAXIOVLEN]; - u.u_error = EINVAL; + u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg)); + if (u.u_error) + return; + if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) { + u.u_error = EMSGSIZE; + return; + } + u.u_error = + copyin((caddr_t)msg.msg_iov, (caddr_t)aiov, + (unsigned)(msg.msg_iovlen * sizeof (aiov[0]))); + if (u.u_error) + return; + msg.msg_iov = aiov; + if (msg.msg_accrights) + if (useracc((caddr_t)msg.msg_accrights, + (unsigned)msg.msg_accrightslen, B_WRITE) == 0) { + u.u_error = EFAULT; + return; + } + recvit(uap->s, &msg, uap->flags, + (caddr_t)&uap->msg->msg_namelen, + (caddr_t)&uap->msg->msg_accrightslen); } -recvmsg() +recvit(s, mp, flags, namelenp, rightslenp) + int s; + register struct msghdr *mp; + int flags; + caddr_t namelenp, rightslenp; { - - u.u_error = EINVAL; + register struct file *fp; + struct uio auio; + register struct iovec *iov; + register int i; + struct mbuf *from, *rights; + int len; + + fp = getsock(s); + if (fp == 0) + return; + auio.uio_iov = mp->msg_iov; + auio.uio_iovcnt = mp->msg_iovlen; + auio.uio_segflg = 0; + auio.uio_offset = 0; /* XXX */ + auio.uio_resid = 0; + iov = mp->msg_iov; + for (i = 0; i < mp->msg_iovlen; i++) { + if (iov->iov_len < 0) { + u.u_error = EINVAL; + return; + } + if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) { + u.u_error = EFAULT; + return; + } + auio.uio_resid += iov->iov_len; + iov++; + } + len = auio.uio_resid; + u.u_error = + soreceive((struct socket *)fp->f_data, &from, &auio, + flags, &rights); + u.u_r.r_val1 = len - auio.uio_resid; + if (mp->msg_name) { + len = mp->msg_namelen; + if (len <= 0 || from == 0) + len = 0; + else { + if (len > from->m_len) + len = from->m_len; + (void) copyout((caddr_t)mtod(from, caddr_t), + (caddr_t)mp->msg_name, (unsigned)len); + } + (void) copyout((caddr_t)&len, namelenp, sizeof (int)); + } + if (mp->msg_accrights) { + len = mp->msg_accrightslen; + if (len <= 0 || rights == 0) + len = 0; + else { + if (len > rights->m_len) + len = rights->m_len; + (void) copyout((caddr_t)mtod(rights, caddr_t), + (caddr_t)mp->msg_accrights, (unsigned)len); + } + (void) copyout((caddr_t)&len, rightslenp, sizeof (int)); + } + if (rights) + m_freem(rights); + if (from) + m_freem(from); } shutdown() @@ -425,14 +511,10 @@ shutdown() } *uap = (struct a *)u.u_ap; struct file *fp; - fp = getf(uap->s); + fp = getsock(uap->s); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } - u.u_error = soshutdown(fp->f_socket, uap->how); + u.u_error = soshutdown((struct socket *)fp->f_data, uap->how); } setsockopt() @@ -447,13 +529,9 @@ setsockopt() struct file *fp; struct mbuf *m = NULL; - fp = getf(uap->s); + fp = getsock(uap->s); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } if (uap->valsize > MLEN) { u.u_error = EINVAL; return; @@ -464,13 +542,14 @@ setsockopt() u.u_error = ENOBUFS; return; } - u.u_error = copyin(uap->val, mtod(m, caddr_t), - (u_int)uap->valsize); + u.u_error = + copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); if (u.u_error) goto bad; m->m_len = uap->valsize; } - u.u_error = sosetopt(fp->f_socket, uap->level, uap->name, m); + u.u_error = + sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m); bad: if (m != NULL) (void) m_free(m); @@ -489,13 +568,9 @@ getsockopt() struct mbuf *m = NULL; int valsize; - fp = getf(uap->s); + fp = getsock(uap->s); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } if (uap->val) { u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, sizeof (valsize)); @@ -507,7 +582,8 @@ getsockopt() return; } } - u.u_error = sogetopt(fp->f_socket, uap->level, uap->name, m); + u.u_error = + sogetopt((struct socket *)fp->f_data, uap->level, uap->name, m); if (u.u_error) goto bad; if (uap->val) { @@ -530,12 +606,10 @@ pipe() struct socket *rso, *wso; int r; - u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, - (struct socketopt *)0); + u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0); if (u.u_error) return; - u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, - (struct socketopt *)0); + u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0); if (u.u_error) goto free; rf = falloc(); @@ -544,13 +618,15 @@ pipe() r = u.u_r.r_val1; rf->f_flag = FREAD; rf->f_type = DTYPE_SOCKET; - rf->f_socket = rso; + rf->f_ops = &socketops; + rf->f_data = (caddr_t)rso; wf = falloc(); if (wf == NULL) goto free3; wf->f_flag = FWRITE; wf->f_type = DTYPE_SOCKET; - wf->f_socket = wso; + wf->f_ops = &socketops; + wf->f_data = (caddr_t)wso; u.u_r.r_val2 = u.u_r.r_val1; u.u_r.r_val1 = r; if (piconnect(wso, rso) == 0) @@ -585,17 +661,13 @@ getsockname() struct mbuf *m; int len; - fp = getf(uap->fdes); + fp = getsock(uap->fdes); if (fp == 0) return; - if (fp->f_type != DTYPE_SOCKET) { - u.u_error = ENOTSOCK; - return; - } u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len)); if (u.u_error) return; - so = fp->f_socket; + so = (struct socket *)fp->f_data; m = m_getclr(M_WAIT, MT_SONAME); if (m == NULL) { u.u_error = ENOBUFS; @@ -614,7 +686,7 @@ bad: m_freem(m); } -sockname(aname, name, namelen) +sockargs(aname, name, namelen) struct mbuf **aname; caddr_t name; int namelen; @@ -635,3 +707,19 @@ sockname(aname, name, namelen) *aname = m; return (error); } + +struct file * +getsock(fdes) + int fdes; +{ + register struct file *fp; + + fp = getf(fdes); + if (fp == NULL) + return (0); + if (fp->f_type != DTYPE_SOCKET) { + u.u_error = ENOTSOCK; + return (0); + } + return (fp); +} diff --git a/usr/src/sys/kern/uipc_usrreq.c b/usr/src/sys/kern/uipc_usrreq.c index 957a3e7d74..633a882d91 100644 --- a/usr/src/sys/kern/uipc_usrreq.c +++ b/usr/src/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* uipc_usrreq.c 1.9 83/04/03 */ +/* uipc_usrreq.c 1.10 83/05/27 */ #include "../h/param.h" #include "../h/dir.h" @@ -11,23 +11,35 @@ #include "../h/un.h" #include "../h/inode.h" #include "../h/nami.h" +#include "../h/file.h" /* * Unix communications domain. + * + * TODO: + * SEQPACKET, RDM + * change for names in file system + * need a proper out-of-band */ /*ARGSUSED*/ -uipc_usrreq(so, req, m, nam) +uipc_usrreq(so, req, m, nam, rights) struct socket *so; int req; - struct mbuf *m, *nam; + struct mbuf *m, *nam, *rights; { struct unpcb *unp = sotounpcb(so); register struct socket *so2; int error = 0; - if (unp == 0 && req != PRU_ATTACH) - return (EINVAL); /* XXX */ + if (req != PRU_SEND && rights && rights->m_len) { + error = EOPNOTSUPP; + goto release; + } + if (unp == 0 && req != PRU_ATTACH) { + error = EINVAL; + goto release; + } switch (req) { case PRU_ATTACH: @@ -55,6 +67,12 @@ uipc_usrreq(so, req, m, nam) error = unp_connect(so, nam); break; +#ifdef notdef + case PRU_CONNECT2: + error = unp_connect2(so, (struct mbuf *)0, (struct socket *)nam); + break; + +#endif case PRU_DISCONNECT: unp_disconnect(unp); break; @@ -121,9 +139,18 @@ uipc_usrreq(so, req, m, nam) } so2 = unp->unp_conn->unp_socket; /* BEGIN XXX */ - if (sbspace(&so2->so_rcv) > 0) + if (rights) { + error = unp_internalize(rights); + if (error) + break; + } + if (sbspace(&so2->so_rcv) > 0) { (void) sbappendaddr(&so2->so_rcv, - mtod(nam, struct sockaddr *), m); + mtod(nam, struct sockaddr *), m, + rights); + sbwakeup(&so2->so_rcv); + m = 0; + } /* END XXX */ if (nam) unp_disconnect(unp); @@ -132,6 +159,10 @@ uipc_usrreq(so, req, m, nam) case SOCK_STREAM: #define rcv (&so2->so_rcv) #define snd (&so->so_snd) + if (rights && rights->m_len) { + error = EOPNOTSUPP; + break; + } if (unp->unp_conn == 0) panic("uipc 3"); so2 = unp->unp_conn->unp_socket; @@ -153,6 +184,7 @@ uipc_usrreq(so, req, m, nam) default: panic("uipc 4"); } + m = 0; break; case PRU_ABORT: @@ -184,9 +216,13 @@ uipc_usrreq(so, req, m, nam) default: panic("piusrreq"); } +release: + if (m) + m_freem(m); return (error); } +/* SHOULD BE PIPSIZ and 0 */ int unp_sendspace = 1024*2; int unp_recvspace = 1024*2; @@ -237,7 +273,10 @@ unp_bind(unp, nam) int error; u.u_dirp = soun->sun_path; - soun->sun_path[sizeof(soun->sun_path)-1] = 0; + if (nam->m_len == MLEN) + return (EINVAL); + *(mtod(nam, caddr_t) + nam->m_len) = 0; +/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ ip = namei(schar, CREATE, 1); if (ip) { iput(ip); @@ -264,14 +303,14 @@ unp_connect(so, nam) struct mbuf *nam; { register struct sockaddr_un *soun = mtod(nam, struct sockaddr_un *); - struct unpcb *unp = sotounpcb(so); register struct inode *ip; int error; - struct socket *so2; - struct unpcb *unp2; + register struct socket *so2; u.u_dirp = soun->sun_path; - soun->sun_path[sizeof(soun->sun_path)-1] = 0; + if (nam->m_len + (nam->m_off - MMINOFF) == MLEN) + return (EMSGSIZE); + *(mtod(nam, caddr_t) + nam->m_len) = 0; ip = namei(schar, LOOKUP, 1); if (ip == 0) { error = u.u_error; @@ -287,41 +326,48 @@ unp_connect(so, nam) error = ECONNREFUSED; goto bad; } - if (so2->so_type != so->so_type) { - error = EPROTOTYPE; - goto bad; - } + error = unp_connect2(so, nam, so2); +bad: + iput(ip); + return (error); +} + +unp_connect2(so, sonam, so2) + register struct socket *so; + struct mbuf *sonam; + register struct socket *so2; +{ + register struct unpcb *unp = sotounpcb(so); + register struct unpcb *unp2; + + if (so2->so_type != so->so_type) + return (EPROTOTYPE); switch (so->so_type) { case SOCK_DGRAM: - unp->unp_conn = sotounpcb(so2); unp2 = sotounpcb(so2); + unp->unp_conn = unp2; unp->unp_nextref = unp2->unp_refs; unp2->unp_refs = unp; break; case SOCK_STREAM: if ((so2->so_options&SO_ACCEPTCONN) == 0 || - (so2 = sonewconn(so2)) == 0) { - error = ECONNREFUSED; - goto bad; - } + (so2 = sonewconn(so2)) == 0) + return (ECONNREFUSED); unp2 = sotounpcb(so2); unp->unp_conn = unp2; unp2->unp_conn = unp; - unp2->unp_remaddr = m_copy(nam, 0, (int)M_COPYALL); + if (sonam) + unp2->unp_remaddr = m_copy(sonam, 0, (int)M_COPYALL); break; default: - panic("uipc connip"); + panic("unp_connect2"); } soisconnected(so2); soisconnected(so); - iput(ip); return (0); -bad: - iput(ip); - return (error); } unp_disconnect(unp) @@ -359,12 +405,14 @@ unp_disconnect(unp) } } +#ifdef notdef unp_abort(unp) struct unpcb *unp; { unp_detach(unp); } +#endif /*ARGSUSED*/ unp_usrclosed(unp) @@ -382,7 +430,162 @@ unp_drop(unp, errno) unp_disconnect(unp); } +#ifdef notdef unp_drain() { } +#endif + +unp_externalize(rights) + struct mbuf *rights; +{ + int newfds = rights->m_len / sizeof (int); + register int i; + register struct file **rp = mtod(rights, struct file **); + register struct file *fp; + int f; + + if (newfds > ufavail()) { + for (i = 0; i < newfds; i++) { + fp = *rp; + unp_discard(fp); + *rp++ = 0; + } + return (EMSGSIZE); + } + for (i = 0; i < newfds; i++) { + f = ufalloc(0); + if (f < 0) + panic("unp_externalize"); + fp = *rp; + u.u_ofile[f] = fp; + fp->f_msgcount--; + *(int *)rp = f; + } + return (0); +} + +unp_internalize(rights) + struct mbuf *rights; +{ + register struct file **rp; + int oldfds = rights->m_len / sizeof (int); + register int i; + register struct file *fp; + + rp = mtod(rights, struct file **); + for (i = 0; i < oldfds; i++) { + if (getf(*(int *)rp++) == 0) + return (EBADF); + rp = mtod(rights, struct file **); + for (i = 0; i < oldfds; i++) + fp = getf(*(int *)rp); + *rp++ = fp; + fp->f_count++; + fp->f_msgcount++; + } + return (0); +} + +int unp_defer, unp_gcing; +int unp_mark(); + +unp_gc() +{ + register struct file *fp; + register struct socket *so; + + if (unp_gcing) + return; + unp_gcing = 1; +restart: + unp_defer = 0; + for (fp = file; fp < fileNFILE; fp++) + fp->f_flag &= ~(FMARK|FDEFER); + do { + for (fp = file; fp < fileNFILE; fp++) { + if (fp->f_count == 0) + continue; + if (fp->f_flag & FDEFER) { + fp->f_flag &= ~FDEFER; + unp_defer--; + } else { + if (fp->f_flag & FMARK) + continue; + if (fp->f_count == fp->f_msgcount) + continue; + fp->f_flag |= FMARK; + } + if (fp->f_type != DTYPE_SOCKET) + continue; + so = (struct socket *)fp->f_data; + if (so->so_proto->pr_family != AF_UNIX || + (so->so_proto->pr_flags&PR_ADDR) == 0) + continue; + if (so->so_rcv.sb_flags & SB_LOCK) { + sbwait(&so->so_rcv); + goto restart; + } + unp_scan(so->so_rcv.sb_mb, unp_mark); + } + } while (unp_defer); + for (fp = file; fp < fileNFILE; fp++) { + if (fp->f_count == 0) + continue; + if (fp->f_count == fp->f_msgcount && (fp->f_flag&FMARK)==0) { + if (fp->f_type != DTYPE_SOCKET) + panic("unp_gc"); + (void) soshutdown((struct socket *)fp->f_data, 0); + } + } + unp_gcing = 0; +} + +unp_scan(m, op) + register struct mbuf *m; + int (*op)(); +{ + register struct file **rp; + register int i; + int qfds; + + while (m) { + m = m->m_next; + if (m == 0) + goto bad; + if (m->m_len) { + qfds = m->m_len / sizeof (struct file *); + rp = mtod(m, struct file **); + for (i = 0; i < qfds; i++) + (*op)(*rp++); + } + do { + m = m->m_next; + if (m == 0) + goto bad; + } while (m->m_act == 0); + m = m->m_next; + } + return; +bad: + panic("unp_gcscan"); +} + +unp_mark(fp) + struct file *fp; +{ + + if (fp->f_flag & FMARK) + return; + unp_defer++; + fp->f_flag |= (FMARK|FDEFER); +} + +unp_discard(fp) + struct file *fp; +{ + + fp->f_msgcount--; + closef(fp, 0); +} diff --git a/usr/src/sys/kern/vfs_syscalls.c b/usr/src/sys/kern/vfs_syscalls.c index 7d71b2da91..fecc16593d 100644 --- a/usr/src/sys/kern/vfs_syscalls.c +++ b/usr/src/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* vfs_syscalls.c 4.56 83/05/21 */ +/* vfs_syscalls.c 4.57 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,11 +12,14 @@ #include "../h/buf.h" #include "../h/proc.h" #include "../h/quota.h" -#include "../h/descrip.h" #include "../h/uio.h" #include "../h/socket.h" #include "../h/socketvar.h" #include "../h/nami.h" +#include "../h/mount.h" + +extern struct fileops inodeops; +struct file *getinode(); /* * Change current working directory (``.''). @@ -72,76 +75,74 @@ bad: */ open() { - register struct inode *ip; - register struct a { + struct a { char *fname; - int flags; int mode; - } *uap; - int checkpermissions = 1, flags; + int crtmode; + } *uap = (struct a *) u.u_ap; - uap = (struct a *)u.u_ap; - flags = uap->flags + 1; - if ((flags&FTRUNCATE) && (flags&FWRITE) == 0) { - u.u_error = EINVAL; - return; - } - if (flags&FCREATE) { - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->mode&07777&(~ISVTX)); - checkpermissions = 0; - flags &= ~FTRUNCATE; - } - } else - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - open1(ip, flags, checkpermissions); + copen(uap->mode-FOPEN, uap->crtmode); } -#ifndef NOCOMPAT /* * Creat system call. */ -ocreat() +creat() { - register struct inode *ip; - register struct a { + struct a { char *fname; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->fmode&07777&(~ISVTX)); - if (ip == NULL) - return; - open1(ip, FWRITE, 0); - } else - open1(ip, FWRITE|FTRUNCATE, 1); + copen(FWRITE|FCREAT|FTRUNC, uap->fmode); } -#endif /* * Common code for open and creat. - * Check permissions (if we haven't done so already), - * allocate an open file structure, and call - * the device open routine, if any. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. */ -open1(ip, mode, checkpermissions) - register struct inode *ip; - register mode; +copen(mode, arg) + register int mode; + int arg; { + register struct inode *ip; register struct file *fp; - int i, flags; + int i; - if (checkpermissions) { +#ifdef notdef + if ((mode&(FREAD|FWRITE)) == 0) { + u.u_error = EINVAL; + return; + } +#endif + if (mode&FCREAT) { + ip = namei(uchar, CREATE, 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, LOOKUP, 1); + if (ip == NULL) + return; + } + if ((ip->i_mode & IFMT) == IFSOCK) { + u.u_error = EOPNOTSUPP; + goto bad; + } + if ((mode&FCREAT) == 0) { if (mode&FREAD) if (access(ip, IREAD)) goto bad; @@ -154,36 +155,31 @@ open1(ip, mode, checkpermissions) } } } - - /* - * Check locking on inode. Release "inode lock" - * while doing so in case we block inside flocki. - */ - flags = 0; - if (mode&(FSHLOCK|FEXLOCK)) { - iunlock(ip); - flags = flocki(ip, 0, mode); - ilock(ip); - if (u.u_error) - goto bad; - } - if (mode&FTRUNCATE) + fp = falloc(); + if (fp == NULL) + goto bad; + if (mode&FTRUNC) itrunc(ip, (u_long)0); iunlock(ip); - if ((fp = falloc()) == NULL) - goto out; - fp->f_flag = mode & FMODES; - fp->f_type = DTYPE_FILE; + fp->f_flag = mode&FMASK; + fp->f_type = DTYPE_INODE; + fp->f_ops = &inodeops; + fp->f_data = (caddr_t)ip; i = u.u_r.r_val1; - fp->f_inode = ip; - u.u_error = openi(ip, mode); - if (u.u_error == 0) { - u.u_pofile[i] = flags; +#ifdef notdef + if (setjmp(&u.u_qsave)) { + if (u.u_error == 0) + u.u_error = EINTR; + u.u_ofile[i] = NULL; + closef(fp); return; } +#endif + u.u_error = openi(ip, mode); + if (u.u_error == 0) + return; u.u_ofile[i] = NULL; fp->f_count--; -out: irele(ip); return; bad: @@ -203,25 +199,30 @@ mknod() } *uap; uap = (struct a *)u.u_ap; - if (suser()) { - ip = namei(uchar, CREATE, 0); - if (ip != NULL) { - u.u_error = EEXIST; - goto out; - } + if (!suser()) + return; + ip = namei(uchar, CREATE, 0); + if (ip != NULL) { + u.u_error = EEXIST; + goto out; } if (u.u_error) return; ip = maknode(uap->fmode); if (ip == NULL) return; - if (uap->dev) { - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - ip->i_rdev = uap->dev; - ip->i_flag |= IACC|IUPD|ICHG; + switch (ip->i_mode & IFMT) { + + case IFCHR: + case IFBLK: + if (uap->dev) { + /* + * Want to be able to use this to make badblock + * inodes, so don't truncate the dev number. + */ + ip->i_rdev = uap->dev; + ip->i_flag |= IACC|IUPD|ICHG; + } } out: @@ -367,17 +368,13 @@ lseek() } *uap; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = ESPIPE; - return; - } - if (uap->sbase == FSEEK_RELATIVE) + if (uap->sbase == L_INCR) uap->off += fp->f_offset; - else if (uap->sbase == FSEEK_EOF) - uap->off += fp->f_inode->i_size; + else if (uap->sbase == L_XTND) + uap->off += ((struct inode *)fp->f_data)->i_size; fp->f_offset = uap->off; u.u_r.r_off = uap->off; } @@ -401,11 +398,11 @@ saccess() u.u_gid = u.u_rgid; ip = namei(uchar, LOOKUP, 1); if (ip != NULL) { - if ((uap->fmode&FACCESS_READ) && access(ip, IREAD)) + if ((uap->fmode&R_OK) && access(ip, IREAD)) goto done; - if ((uap->fmode&FACCESS_WRITE) && access(ip, IWRITE)) + if ((uap->fmode&W_OK) && access(ip, IWRITE)) goto done; - if ((uap->fmode&FACCESS_EXECUTE) && access(ip, IEXEC)) + if ((uap->fmode&X_OK) && access(ip, IEXEC)) goto done; done: iput(ip); @@ -414,103 +411,41 @@ done: u.u_gid = svgid; } -/* - * the fstat system call. - */ -fstat() -{ - register struct file *fp; - register struct a { - int fd; - struct stat *sb; - } *uap; - - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); - if (fp == NULL) - return; - if (fp->f_type == DTYPE_SOCKET) - u.u_error = sostat(fp->f_socket, uap->sb); - else - stat1(fp->f_inode, uap->sb); -} - /* * Stat system call. This version follows links. */ stat() { - register struct inode *ip; - register struct a { - char *fname; - struct stat *sb; - } *uap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - stat1(ip, uap->sb); - iput(ip); + stat1(1); } /* * Lstat system call. This version does not follow links. */ lstat() +{ + + stat1(0); +} + +stat1(follow) + int follow; { register struct inode *ip; register struct a { char *fname; - struct stat *sb; + struct stat *ub; } *uap; + struct stat sb; uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 0); + ip = namei(uchar, LOOKUP, follow); if (ip == NULL) return; - stat1(ip, uap->sb); + (void) statinode(ip, &sb); iput(ip); -} - -/* - * The basic routine for fstat and stat: - * get the inode and pass appropriate parts back. - */ -stat1(ip, ub) - register struct inode *ip; - struct stat *ub; -{ - struct stat ds; - - IUPDAT(ip, &time, &time, 0); - /* - * Copy from inode table - */ - ds.st_dev = ip->i_dev; - ds.st_ino = ip->i_number; - ds.st_mode = ip->i_mode; - ds.st_nlink = ip->i_nlink; - ds.st_uid = ip->i_uid; - ds.st_gid = ip->i_gid; - ds.st_rdev = (dev_t)ip->i_rdev; - ds.st_size = ip->i_size; - ds.st_atime = ip->i_atime; - ds.st_spare1 = 0; - ds.st_mtime = ip->i_mtime; - ds.st_spare2 = 0; - ds.st_ctime = ip->i_ctime; - ds.st_spare3 = 0; - /* this doesn't belong here */ - if ((ip->i_mode&IFMT) == IFBLK) - ds.st_blksize = BLKDEV_IOSIZE; - else if ((ip->i_mode&IFMT) == IFCHR) - ds.st_blksize = MAXBSIZE; - else - ds.st_blksize = ip->i_fs->fs_bsize; - ds.st_blocks = ip->i_blocks; - ds.st_spare4[0] = ds.st_spare4[1] = 0; - u.u_error = copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)); + u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); } /* @@ -570,14 +505,10 @@ fchmod() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (u.u_uid != ip->i_uid && !suser()) return; ilock(ip); @@ -593,7 +524,6 @@ chmod1(ip, mode) register struct inode *ip; register int mode; { - register int *gp; ip->i_mode &= ~07777; if (u.u_uid) { @@ -640,14 +570,10 @@ fchown() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (!suser()) return; ilock(ip); @@ -756,29 +682,24 @@ sync() */ flock() { - struct a { + register struct a { int fd; int how; - } *uap; + } *uap = (struct a *)u.u_ap; register struct file *fp; register int cmd, flags; - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { /* XXX */ - u.u_error = EINVAL; - return; - } cmd = uap->how; flags = u.u_pofile[uap->fd] & (UF_SHLOCK|UF_EXLOCK); - if (cmd&FUNLOCK) { + if (cmd&LOCK_UN) { if (flags == 0) { u.u_error = EINVAL; return; } - funlocki(fp->f_inode, flags); + funlocki((struct inode *)fp->f_data, flags); u.u_pofile[uap->fd] &= ~(UF_SHLOCK|UF_EXLOCK); return; } @@ -786,10 +707,11 @@ flock() * No reason to write lock a file we've already * write locked, similarly with a read lock. */ - if ((flags&UF_EXLOCK) && (cmd&FEXLOCK) || - (flags&UF_SHLOCK) && (cmd&FSHLOCK)) + if ((flags&UF_EXLOCK) && (cmd&LOCK_EX) || + (flags&UF_SHLOCK) && (cmd&LOCK_SH)) return; - u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); + u.u_pofile[uap->fd] = + flocki((struct inode *)fp->f_data, u.u_pofile[uap->fd], cmd); } /* @@ -829,18 +751,14 @@ ftruncate() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } if ((fp->f_flag&FWRITE) == 0) { u.u_error = EINVAL; return; } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); itrunc(ip, uap->length); iunlock(ip); @@ -857,14 +775,10 @@ fsync() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); syncip(ip); iunlock(ip); @@ -1198,3 +1112,220 @@ maknode(mode) } return (ip); } + +/* + * A virgin directory (no blushing please). + */ +struct dirtemplate mastertemplate = { + 0, 12, 1, ".", + 0, DIRBLKSIZ - 12, 2, ".." +}; + +/* + * Mkdir system call + */ +mkdir() +{ + struct a { + char *name; + int dmode; + } *uap; + register struct inode *ip, *dp; + struct dirtemplate dirtemplate; + + uap = (struct a *)u.u_ap; + ip = namei(uchar, CREATE, 0); + if (u.u_error) + return; + if (ip != NULL) { + iput(ip); + u.u_error = EEXIST; + return; + } + dp = u.u_pdir; + uap->dmode &= 0777; + uap->dmode |= IFDIR; + /* + * Must simulate part of maknode here + * in order to acquire the inode, but + * not have it entered in the parent + * directory. The entry is made later + * after writing "." and ".." entries out. + */ + ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); + if (ip == NULL) { + iput(dp); + return; + } +#ifdef QUOTA + if (ip->i_dquot != NODQUOT) + panic("mkdir: dquot"); +#endif + ip->i_flag |= IACC|IUPD|ICHG; + ip->i_mode = uap->dmode & ~u.u_cmask; + ip->i_nlink = 2; + ip->i_uid = u.u_uid; + ip->i_gid = dp->i_gid; +#ifdef QUOTA + ip->i_dquot = inoquota(ip); +#endif + iupdat(ip, &time, &time, 1); + + /* + * Bump link count in parent directory + * to reflect work done below. Should + * be done before reference is created + * so reparation is possible if we crash. + */ + dp->i_nlink++; + dp->i_flag |= ICHG; + iupdat(dp, &time, &time, 1); + + /* + * Initialize directory with "." + * and ".." from static template. + */ + dirtemplate = mastertemplate; + dirtemplate.dot_ino = ip->i_number; + dirtemplate.dotdot_ino = dp->i_number; + u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, + sizeof (dirtemplate), (off_t)0, 1, (int *)0); + if (u.u_error) { + dp->i_nlink--; + dp->i_flag |= ICHG; + goto bad; + } + /* + * Directory all set up, now + * install the entry for it in + * the parent directory. + */ + u.u_error = direnter(ip); + dp = NULL; + if (u.u_error) { + u.u_dirp = uap->name; + dp = namei(uchar, LOOKUP, 0); + if (dp) { + dp->i_nlink--; + dp->i_flag |= ICHG; + } + } +bad: + /* + * No need to do an explicit itrunc here, + * irele will do this for us because we set + * the link count to 0. + */ + if (u.u_error) { + ip->i_nlink = 0; + ip->i_flag |= ICHG; + } + if (dp) + iput(dp); + iput(ip); +} + +/* + * Rmdir system call. + */ +rmdir() +{ + struct a { + char *name; + }; + register struct inode *ip, *dp; + + ip = namei(uchar, DELETE | LOCKPARENT, 0); + if (ip == NULL) + return; + dp = u.u_pdir; + /* + * No rmdir "." please. + */ + if (dp == ip) { + irele(dp); + iput(ip); + u.u_error = EINVAL; + return; + } + if ((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto out; + } + /* + * Don't remove a mounted on directory. + */ + if (ip->i_dev != dp->i_dev) { + u.u_error = EBUSY; + goto out; + } + /* + * Verify the directory is empty (and valid). + * (Rmdir ".." won't be valid since + * ".." will contain a reference to + * the current directory and thus be + * non-empty.) + */ + if (ip->i_nlink != 2 || !dirempty(ip)) { + u.u_error = ENOTEMPTY; + goto out; + } + /* + * Delete reference to directory before purging + * inode. If we crash in between, the directory + * will be reattached to lost+found, + */ + if (dirremove() == 0) + goto out; + dp->i_nlink--; + dp->i_flag |= ICHG; + iput(dp); + dp = NULL; + /* + * Truncate inode. The only stuff left + * in the directory is "." and "..". The + * "." reference is inconsequential since + * we're quashing it. The ".." reference + * has already been adjusted above. We've + * removed the "." reference and the reference + * in the parent directory, but there may be + * other hard links so decrement by 2 and + * worry about them later. + */ + ip->i_nlink -= 2; + itrunc(ip, (u_long)0); +out: + if (dp) + iput(dp); + iput(ip); +} + +struct file * +getinode(fdes) + int fdes; +{ + register struct file *fp; + + fp = getf(fdes); + if (fp == 0) + return (0); + if (fp->f_type != DTYPE_INODE) { + u.u_error = EINVAL; + return (0); + } + return (fp); +} + +/* + * mode mask for creation of files + */ +umask() +{ + register struct a { + int mask; + } *uap; + + uap = (struct a *)u.u_ap; + u.u_r.r_val1 = u.u_cmask; + u.u_cmask = uap->mask & 07777; +} diff --git a/usr/src/sys/kern/vfs_vnops.c b/usr/src/sys/kern/vfs_vnops.c index 39e00a703b..dd8c07d00f 100644 --- a/usr/src/sys/kern/vfs_vnops.c +++ b/usr/src/sys/kern/vfs_vnops.c @@ -1,4 +1,4 @@ -/* vfs_vnops.c 4.34 83/03/31 */ +/* vfs_vnops.c 4.35 83/05/27 */ #include "../machine/reg.h" @@ -17,32 +17,6 @@ #include "../h/proc.h" #include "../h/nami.h" -/* - * Openi called to allow handler - * of special files to initialize and - * validate before actual IO. - */ -openi(ip, mode) - register struct inode *ip; -{ - dev_t dev = (dev_t)ip->i_rdev; - register u_int maj = major(dev); - - switch (ip->i_mode&IFMT) { - - case IFCHR: - if (maj >= nchrdev) - return (ENXIO); - return ((*cdevsw[maj].d_open)(dev, mode)); - - case IFBLK: - if (maj >= nblkdev) - return (ENXIO); - return ((*bdevsw[maj].d_open)(dev, mode)); - } - return (0); -} - /* * Check mode permission on inode pointer. * Mode is READ, WRITE or EXEC. diff --git a/usr/src/sys/kern/vfs_xxx.c b/usr/src/sys/kern/vfs_xxx.c index 21b271f904..46e70ea330 100644 --- a/usr/src/sys/kern/vfs_xxx.c +++ b/usr/src/sys/kern/vfs_xxx.c @@ -1,4 +1,4 @@ -/* vfs_xxx.c 4.4 82/12/28 */ +/* vfs_xxx.c 4.5 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -38,7 +38,6 @@ uchar() #ifndef NOCOMPAT #include "../h/file.h" #include "../h/nami.h" -#include "../h/descrip.h" #include "../h/kernel.h" /* @@ -67,19 +66,13 @@ ofstat() register struct a { int fd; struct ostat *sb; - } *uap; + } *uap = (struct a *)u.u_ap; + extern struct file *getinode(); - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - struct ostat ub; - - bzero((caddr_t)&ub, sizeof (ub)); - (void) copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); - } else - ostat1(fp->f_inode, uap->sb); + ostat1((struct inode *)fp->f_data, uap->sb); } /* diff --git a/usr/src/sys/ufs/ffs/ffs_alloc.c b/usr/src/sys/ufs/ffs/ffs_alloc.c index 202225c577..441a0d8125 100644 --- a/usr/src/sys/ufs/ffs/ffs_alloc.c +++ b/usr/src/sys/ufs/ffs/ffs_alloc.c @@ -1,4 +1,4 @@ -/* ffs_alloc.c 2.25 83/05/21 */ +/* ffs_alloc.c 2.26 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -887,13 +887,15 @@ mapsearch(fs, cgp, bpref, allocsiz) else start = cgp->cg_frotor / NBBY; len = howmany(fs->fs_fpg, NBBY) - start; - loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], - 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); + loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[start], + (caddr_t)fragtbl[fs->fs_frag], + (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) { len = start + 1; start = 0; - loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], - 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); + loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[start], + (caddr_t)fragtbl[fs->fs_frag], + (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) return (-1); } diff --git a/usr/src/sys/ufs/ffs/ffs_tables.c b/usr/src/sys/ufs/ffs/ffs_tables.c index f24149cc2f..8adc5d4fdd 100644 --- a/usr/src/sys/ufs/ffs/ffs_tables.c +++ b/usr/src/sys/ufs/ffs/ffs_tables.c @@ -1,9 +1,9 @@ -/* ffs_tables.c 2.3 82/07/15 */ +/* ffs_tables.c 2.4 83/05/27 */ #include "../h/param.h" /* - * bit patterns for identifying fragments in the block map + * Bit patterns for identifying fragments in the block map * used as ((map & around) == inside) */ int around[9] = { @@ -14,7 +14,7 @@ int inside[9] = { }; /* - * given a block map bit pattern, the frag tables tell whether a + * Given a block map bit pattern, the frag tables tell whether a * particular size fragment is available. * * used as: @@ -25,8 +25,7 @@ int inside[9] = { * These tables are used by the scanc instruction on the VAX to * quickly find an appropriate fragment. */ - -unsigned char fragtbl124[256] = { +u_char fragtbl124[256] = { 0x00, 0x16, 0x16, 0x2a, 0x16, 0x16, 0x26, 0x4e, 0x16, 0x16, 0x16, 0x3e, 0x2a, 0x3e, 0x4e, 0x8a, 0x16, 0x16, 0x16, 0x3e, 0x16, 0x16, 0x36, 0x5e, @@ -61,7 +60,7 @@ unsigned char fragtbl124[256] = { 0x9e, 0x9e, 0x9e, 0xbe, 0xaa, 0xbe, 0xce, 0x8a, }; -unsigned char fragtbl8[256] = { +u_char fragtbl8[256] = { 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x04, 0x01, 0x01, 0x01, 0x03, 0x02, 0x03, 0x04, 0x08, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x03, 0x05, @@ -97,8 +96,8 @@ unsigned char fragtbl8[256] = { }; /* - * the actual fragtbl array + * The actual fragtbl array. */ -unsigned char *fragtbl[MAXFRAG + 1] = { +u_char *fragtbl[MAXFRAG + 1] = { 0, fragtbl124, fragtbl124, 0, fragtbl124, 0, 0, 0, fragtbl8, }; diff --git a/usr/src/sys/ufs/ffs/ffs_vnops.c b/usr/src/sys/ufs/ffs/ffs_vnops.c index cf56cad51d..55ddf6717e 100644 --- a/usr/src/sys/ufs/ffs/ffs_vnops.c +++ b/usr/src/sys/ufs/ffs/ffs_vnops.c @@ -1,4 +1,4 @@ -/* ffs_vnops.c 4.56 83/05/21 */ +/* ffs_vnops.c 4.57 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,11 +12,14 @@ #include "../h/buf.h" #include "../h/proc.h" #include "../h/quota.h" -#include "../h/descrip.h" #include "../h/uio.h" #include "../h/socket.h" #include "../h/socketvar.h" #include "../h/nami.h" +#include "../h/mount.h" + +extern struct fileops inodeops; +struct file *getinode(); /* * Change current working directory (``.''). @@ -72,76 +75,74 @@ bad: */ open() { - register struct inode *ip; - register struct a { + struct a { char *fname; - int flags; int mode; - } *uap; - int checkpermissions = 1, flags; + int crtmode; + } *uap = (struct a *) u.u_ap; - uap = (struct a *)u.u_ap; - flags = uap->flags + 1; - if ((flags&FTRUNCATE) && (flags&FWRITE) == 0) { - u.u_error = EINVAL; - return; - } - if (flags&FCREATE) { - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->mode&07777&(~ISVTX)); - checkpermissions = 0; - flags &= ~FTRUNCATE; - } - } else - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - open1(ip, flags, checkpermissions); + copen(uap->mode-FOPEN, uap->crtmode); } -#ifndef NOCOMPAT /* * Creat system call. */ -ocreat() +creat() { - register struct inode *ip; - register struct a { + struct a { char *fname; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->fmode&07777&(~ISVTX)); - if (ip == NULL) - return; - open1(ip, FWRITE, 0); - } else - open1(ip, FWRITE|FTRUNCATE, 1); + copen(FWRITE|FCREAT|FTRUNC, uap->fmode); } -#endif /* * Common code for open and creat. - * Check permissions (if we haven't done so already), - * allocate an open file structure, and call - * the device open routine, if any. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. */ -open1(ip, mode, checkpermissions) - register struct inode *ip; - register mode; +copen(mode, arg) + register int mode; + int arg; { + register struct inode *ip; register struct file *fp; - int i, flags; + int i; - if (checkpermissions) { +#ifdef notdef + if ((mode&(FREAD|FWRITE)) == 0) { + u.u_error = EINVAL; + return; + } +#endif + if (mode&FCREAT) { + ip = namei(uchar, CREATE, 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, LOOKUP, 1); + if (ip == NULL) + return; + } + if ((ip->i_mode & IFMT) == IFSOCK) { + u.u_error = EOPNOTSUPP; + goto bad; + } + if ((mode&FCREAT) == 0) { if (mode&FREAD) if (access(ip, IREAD)) goto bad; @@ -154,36 +155,31 @@ open1(ip, mode, checkpermissions) } } } - - /* - * Check locking on inode. Release "inode lock" - * while doing so in case we block inside flocki. - */ - flags = 0; - if (mode&(FSHLOCK|FEXLOCK)) { - iunlock(ip); - flags = flocki(ip, 0, mode); - ilock(ip); - if (u.u_error) - goto bad; - } - if (mode&FTRUNCATE) + fp = falloc(); + if (fp == NULL) + goto bad; + if (mode&FTRUNC) itrunc(ip, (u_long)0); iunlock(ip); - if ((fp = falloc()) == NULL) - goto out; - fp->f_flag = mode & FMODES; - fp->f_type = DTYPE_FILE; + fp->f_flag = mode&FMASK; + fp->f_type = DTYPE_INODE; + fp->f_ops = &inodeops; + fp->f_data = (caddr_t)ip; i = u.u_r.r_val1; - fp->f_inode = ip; - u.u_error = openi(ip, mode); - if (u.u_error == 0) { - u.u_pofile[i] = flags; +#ifdef notdef + if (setjmp(&u.u_qsave)) { + if (u.u_error == 0) + u.u_error = EINTR; + u.u_ofile[i] = NULL; + closef(fp); return; } +#endif + u.u_error = openi(ip, mode); + if (u.u_error == 0) + return; u.u_ofile[i] = NULL; fp->f_count--; -out: irele(ip); return; bad: @@ -203,25 +199,30 @@ mknod() } *uap; uap = (struct a *)u.u_ap; - if (suser()) { - ip = namei(uchar, CREATE, 0); - if (ip != NULL) { - u.u_error = EEXIST; - goto out; - } + if (!suser()) + return; + ip = namei(uchar, CREATE, 0); + if (ip != NULL) { + u.u_error = EEXIST; + goto out; } if (u.u_error) return; ip = maknode(uap->fmode); if (ip == NULL) return; - if (uap->dev) { - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - ip->i_rdev = uap->dev; - ip->i_flag |= IACC|IUPD|ICHG; + switch (ip->i_mode & IFMT) { + + case IFCHR: + case IFBLK: + if (uap->dev) { + /* + * Want to be able to use this to make badblock + * inodes, so don't truncate the dev number. + */ + ip->i_rdev = uap->dev; + ip->i_flag |= IACC|IUPD|ICHG; + } } out: @@ -367,17 +368,13 @@ lseek() } *uap; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = ESPIPE; - return; - } - if (uap->sbase == FSEEK_RELATIVE) + if (uap->sbase == L_INCR) uap->off += fp->f_offset; - else if (uap->sbase == FSEEK_EOF) - uap->off += fp->f_inode->i_size; + else if (uap->sbase == L_XTND) + uap->off += ((struct inode *)fp->f_data)->i_size; fp->f_offset = uap->off; u.u_r.r_off = uap->off; } @@ -401,11 +398,11 @@ saccess() u.u_gid = u.u_rgid; ip = namei(uchar, LOOKUP, 1); if (ip != NULL) { - if ((uap->fmode&FACCESS_READ) && access(ip, IREAD)) + if ((uap->fmode&R_OK) && access(ip, IREAD)) goto done; - if ((uap->fmode&FACCESS_WRITE) && access(ip, IWRITE)) + if ((uap->fmode&W_OK) && access(ip, IWRITE)) goto done; - if ((uap->fmode&FACCESS_EXECUTE) && access(ip, IEXEC)) + if ((uap->fmode&X_OK) && access(ip, IEXEC)) goto done; done: iput(ip); @@ -414,103 +411,41 @@ done: u.u_gid = svgid; } -/* - * the fstat system call. - */ -fstat() -{ - register struct file *fp; - register struct a { - int fd; - struct stat *sb; - } *uap; - - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); - if (fp == NULL) - return; - if (fp->f_type == DTYPE_SOCKET) - u.u_error = sostat(fp->f_socket, uap->sb); - else - stat1(fp->f_inode, uap->sb); -} - /* * Stat system call. This version follows links. */ stat() { - register struct inode *ip; - register struct a { - char *fname; - struct stat *sb; - } *uap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - stat1(ip, uap->sb); - iput(ip); + stat1(1); } /* * Lstat system call. This version does not follow links. */ lstat() +{ + + stat1(0); +} + +stat1(follow) + int follow; { register struct inode *ip; register struct a { char *fname; - struct stat *sb; + struct stat *ub; } *uap; + struct stat sb; uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 0); + ip = namei(uchar, LOOKUP, follow); if (ip == NULL) return; - stat1(ip, uap->sb); + (void) statinode(ip, &sb); iput(ip); -} - -/* - * The basic routine for fstat and stat: - * get the inode and pass appropriate parts back. - */ -stat1(ip, ub) - register struct inode *ip; - struct stat *ub; -{ - struct stat ds; - - IUPDAT(ip, &time, &time, 0); - /* - * Copy from inode table - */ - ds.st_dev = ip->i_dev; - ds.st_ino = ip->i_number; - ds.st_mode = ip->i_mode; - ds.st_nlink = ip->i_nlink; - ds.st_uid = ip->i_uid; - ds.st_gid = ip->i_gid; - ds.st_rdev = (dev_t)ip->i_rdev; - ds.st_size = ip->i_size; - ds.st_atime = ip->i_atime; - ds.st_spare1 = 0; - ds.st_mtime = ip->i_mtime; - ds.st_spare2 = 0; - ds.st_ctime = ip->i_ctime; - ds.st_spare3 = 0; - /* this doesn't belong here */ - if ((ip->i_mode&IFMT) == IFBLK) - ds.st_blksize = BLKDEV_IOSIZE; - else if ((ip->i_mode&IFMT) == IFCHR) - ds.st_blksize = MAXBSIZE; - else - ds.st_blksize = ip->i_fs->fs_bsize; - ds.st_blocks = ip->i_blocks; - ds.st_spare4[0] = ds.st_spare4[1] = 0; - u.u_error = copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)); + u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); } /* @@ -570,14 +505,10 @@ fchmod() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (u.u_uid != ip->i_uid && !suser()) return; ilock(ip); @@ -593,7 +524,6 @@ chmod1(ip, mode) register struct inode *ip; register int mode; { - register int *gp; ip->i_mode &= ~07777; if (u.u_uid) { @@ -640,14 +570,10 @@ fchown() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (!suser()) return; ilock(ip); @@ -756,29 +682,24 @@ sync() */ flock() { - struct a { + register struct a { int fd; int how; - } *uap; + } *uap = (struct a *)u.u_ap; register struct file *fp; register int cmd, flags; - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { /* XXX */ - u.u_error = EINVAL; - return; - } cmd = uap->how; flags = u.u_pofile[uap->fd] & (UF_SHLOCK|UF_EXLOCK); - if (cmd&FUNLOCK) { + if (cmd&LOCK_UN) { if (flags == 0) { u.u_error = EINVAL; return; } - funlocki(fp->f_inode, flags); + funlocki((struct inode *)fp->f_data, flags); u.u_pofile[uap->fd] &= ~(UF_SHLOCK|UF_EXLOCK); return; } @@ -786,10 +707,11 @@ flock() * No reason to write lock a file we've already * write locked, similarly with a read lock. */ - if ((flags&UF_EXLOCK) && (cmd&FEXLOCK) || - (flags&UF_SHLOCK) && (cmd&FSHLOCK)) + if ((flags&UF_EXLOCK) && (cmd&LOCK_EX) || + (flags&UF_SHLOCK) && (cmd&LOCK_SH)) return; - u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); + u.u_pofile[uap->fd] = + flocki((struct inode *)fp->f_data, u.u_pofile[uap->fd], cmd); } /* @@ -829,18 +751,14 @@ ftruncate() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } if ((fp->f_flag&FWRITE) == 0) { u.u_error = EINVAL; return; } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); itrunc(ip, uap->length); iunlock(ip); @@ -857,14 +775,10 @@ fsync() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); syncip(ip); iunlock(ip); @@ -1198,3 +1112,220 @@ maknode(mode) } return (ip); } + +/* + * A virgin directory (no blushing please). + */ +struct dirtemplate mastertemplate = { + 0, 12, 1, ".", + 0, DIRBLKSIZ - 12, 2, ".." +}; + +/* + * Mkdir system call + */ +mkdir() +{ + struct a { + char *name; + int dmode; + } *uap; + register struct inode *ip, *dp; + struct dirtemplate dirtemplate; + + uap = (struct a *)u.u_ap; + ip = namei(uchar, CREATE, 0); + if (u.u_error) + return; + if (ip != NULL) { + iput(ip); + u.u_error = EEXIST; + return; + } + dp = u.u_pdir; + uap->dmode &= 0777; + uap->dmode |= IFDIR; + /* + * Must simulate part of maknode here + * in order to acquire the inode, but + * not have it entered in the parent + * directory. The entry is made later + * after writing "." and ".." entries out. + */ + ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); + if (ip == NULL) { + iput(dp); + return; + } +#ifdef QUOTA + if (ip->i_dquot != NODQUOT) + panic("mkdir: dquot"); +#endif + ip->i_flag |= IACC|IUPD|ICHG; + ip->i_mode = uap->dmode & ~u.u_cmask; + ip->i_nlink = 2; + ip->i_uid = u.u_uid; + ip->i_gid = dp->i_gid; +#ifdef QUOTA + ip->i_dquot = inoquota(ip); +#endif + iupdat(ip, &time, &time, 1); + + /* + * Bump link count in parent directory + * to reflect work done below. Should + * be done before reference is created + * so reparation is possible if we crash. + */ + dp->i_nlink++; + dp->i_flag |= ICHG; + iupdat(dp, &time, &time, 1); + + /* + * Initialize directory with "." + * and ".." from static template. + */ + dirtemplate = mastertemplate; + dirtemplate.dot_ino = ip->i_number; + dirtemplate.dotdot_ino = dp->i_number; + u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, + sizeof (dirtemplate), (off_t)0, 1, (int *)0); + if (u.u_error) { + dp->i_nlink--; + dp->i_flag |= ICHG; + goto bad; + } + /* + * Directory all set up, now + * install the entry for it in + * the parent directory. + */ + u.u_error = direnter(ip); + dp = NULL; + if (u.u_error) { + u.u_dirp = uap->name; + dp = namei(uchar, LOOKUP, 0); + if (dp) { + dp->i_nlink--; + dp->i_flag |= ICHG; + } + } +bad: + /* + * No need to do an explicit itrunc here, + * irele will do this for us because we set + * the link count to 0. + */ + if (u.u_error) { + ip->i_nlink = 0; + ip->i_flag |= ICHG; + } + if (dp) + iput(dp); + iput(ip); +} + +/* + * Rmdir system call. + */ +rmdir() +{ + struct a { + char *name; + }; + register struct inode *ip, *dp; + + ip = namei(uchar, DELETE | LOCKPARENT, 0); + if (ip == NULL) + return; + dp = u.u_pdir; + /* + * No rmdir "." please. + */ + if (dp == ip) { + irele(dp); + iput(ip); + u.u_error = EINVAL; + return; + } + if ((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto out; + } + /* + * Don't remove a mounted on directory. + */ + if (ip->i_dev != dp->i_dev) { + u.u_error = EBUSY; + goto out; + } + /* + * Verify the directory is empty (and valid). + * (Rmdir ".." won't be valid since + * ".." will contain a reference to + * the current directory and thus be + * non-empty.) + */ + if (ip->i_nlink != 2 || !dirempty(ip)) { + u.u_error = ENOTEMPTY; + goto out; + } + /* + * Delete reference to directory before purging + * inode. If we crash in between, the directory + * will be reattached to lost+found, + */ + if (dirremove() == 0) + goto out; + dp->i_nlink--; + dp->i_flag |= ICHG; + iput(dp); + dp = NULL; + /* + * Truncate inode. The only stuff left + * in the directory is "." and "..". The + * "." reference is inconsequential since + * we're quashing it. The ".." reference + * has already been adjusted above. We've + * removed the "." reference and the reference + * in the parent directory, but there may be + * other hard links so decrement by 2 and + * worry about them later. + */ + ip->i_nlink -= 2; + itrunc(ip, (u_long)0); +out: + if (dp) + iput(dp); + iput(ip); +} + +struct file * +getinode(fdes) + int fdes; +{ + register struct file *fp; + + fp = getf(fdes); + if (fp == 0) + return (0); + if (fp->f_type != DTYPE_INODE) { + u.u_error = EINVAL; + return (0); + } + return (fp); +} + +/* + * mode mask for creation of files + */ +umask() +{ + register struct a { + int mask; + } *uap; + + uap = (struct a *)u.u_ap; + u.u_r.r_val1 = u.u_cmask; + u.u_cmask = uap->mask & 07777; +} diff --git a/usr/src/sys/ufs/ffs/ufs_vnops.c b/usr/src/sys/ufs/ffs/ufs_vnops.c index b6bbad2974..a3fdf59fe9 100644 --- a/usr/src/sys/ufs/ffs/ufs_vnops.c +++ b/usr/src/sys/ufs/ffs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* ufs_vnops.c 4.56 83/05/21 */ +/* ufs_vnops.c 4.57 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,11 +12,14 @@ #include "../h/buf.h" #include "../h/proc.h" #include "../h/quota.h" -#include "../h/descrip.h" #include "../h/uio.h" #include "../h/socket.h" #include "../h/socketvar.h" #include "../h/nami.h" +#include "../h/mount.h" + +extern struct fileops inodeops; +struct file *getinode(); /* * Change current working directory (``.''). @@ -72,76 +75,74 @@ bad: */ open() { - register struct inode *ip; - register struct a { + struct a { char *fname; - int flags; int mode; - } *uap; - int checkpermissions = 1, flags; + int crtmode; + } *uap = (struct a *) u.u_ap; - uap = (struct a *)u.u_ap; - flags = uap->flags + 1; - if ((flags&FTRUNCATE) && (flags&FWRITE) == 0) { - u.u_error = EINVAL; - return; - } - if (flags&FCREATE) { - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->mode&07777&(~ISVTX)); - checkpermissions = 0; - flags &= ~FTRUNCATE; - } - } else - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - open1(ip, flags, checkpermissions); + copen(uap->mode-FOPEN, uap->crtmode); } -#ifndef NOCOMPAT /* * Creat system call. */ -ocreat() +creat() { - register struct inode *ip; - register struct a { + struct a { char *fname; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->fmode&07777&(~ISVTX)); - if (ip == NULL) - return; - open1(ip, FWRITE, 0); - } else - open1(ip, FWRITE|FTRUNCATE, 1); + copen(FWRITE|FCREAT|FTRUNC, uap->fmode); } -#endif /* * Common code for open and creat. - * Check permissions (if we haven't done so already), - * allocate an open file structure, and call - * the device open routine, if any. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. */ -open1(ip, mode, checkpermissions) - register struct inode *ip; - register mode; +copen(mode, arg) + register int mode; + int arg; { + register struct inode *ip; register struct file *fp; - int i, flags; + int i; - if (checkpermissions) { +#ifdef notdef + if ((mode&(FREAD|FWRITE)) == 0) { + u.u_error = EINVAL; + return; + } +#endif + if (mode&FCREAT) { + ip = namei(uchar, CREATE, 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, LOOKUP, 1); + if (ip == NULL) + return; + } + if ((ip->i_mode & IFMT) == IFSOCK) { + u.u_error = EOPNOTSUPP; + goto bad; + } + if ((mode&FCREAT) == 0) { if (mode&FREAD) if (access(ip, IREAD)) goto bad; @@ -154,36 +155,31 @@ open1(ip, mode, checkpermissions) } } } - - /* - * Check locking on inode. Release "inode lock" - * while doing so in case we block inside flocki. - */ - flags = 0; - if (mode&(FSHLOCK|FEXLOCK)) { - iunlock(ip); - flags = flocki(ip, 0, mode); - ilock(ip); - if (u.u_error) - goto bad; - } - if (mode&FTRUNCATE) + fp = falloc(); + if (fp == NULL) + goto bad; + if (mode&FTRUNC) itrunc(ip, (u_long)0); iunlock(ip); - if ((fp = falloc()) == NULL) - goto out; - fp->f_flag = mode & FMODES; - fp->f_type = DTYPE_FILE; + fp->f_flag = mode&FMASK; + fp->f_type = DTYPE_INODE; + fp->f_ops = &inodeops; + fp->f_data = (caddr_t)ip; i = u.u_r.r_val1; - fp->f_inode = ip; - u.u_error = openi(ip, mode); - if (u.u_error == 0) { - u.u_pofile[i] = flags; +#ifdef notdef + if (setjmp(&u.u_qsave)) { + if (u.u_error == 0) + u.u_error = EINTR; + u.u_ofile[i] = NULL; + closef(fp); return; } +#endif + u.u_error = openi(ip, mode); + if (u.u_error == 0) + return; u.u_ofile[i] = NULL; fp->f_count--; -out: irele(ip); return; bad: @@ -203,25 +199,30 @@ mknod() } *uap; uap = (struct a *)u.u_ap; - if (suser()) { - ip = namei(uchar, CREATE, 0); - if (ip != NULL) { - u.u_error = EEXIST; - goto out; - } + if (!suser()) + return; + ip = namei(uchar, CREATE, 0); + if (ip != NULL) { + u.u_error = EEXIST; + goto out; } if (u.u_error) return; ip = maknode(uap->fmode); if (ip == NULL) return; - if (uap->dev) { - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - ip->i_rdev = uap->dev; - ip->i_flag |= IACC|IUPD|ICHG; + switch (ip->i_mode & IFMT) { + + case IFCHR: + case IFBLK: + if (uap->dev) { + /* + * Want to be able to use this to make badblock + * inodes, so don't truncate the dev number. + */ + ip->i_rdev = uap->dev; + ip->i_flag |= IACC|IUPD|ICHG; + } } out: @@ -367,17 +368,13 @@ lseek() } *uap; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = ESPIPE; - return; - } - if (uap->sbase == FSEEK_RELATIVE) + if (uap->sbase == L_INCR) uap->off += fp->f_offset; - else if (uap->sbase == FSEEK_EOF) - uap->off += fp->f_inode->i_size; + else if (uap->sbase == L_XTND) + uap->off += ((struct inode *)fp->f_data)->i_size; fp->f_offset = uap->off; u.u_r.r_off = uap->off; } @@ -401,11 +398,11 @@ saccess() u.u_gid = u.u_rgid; ip = namei(uchar, LOOKUP, 1); if (ip != NULL) { - if ((uap->fmode&FACCESS_READ) && access(ip, IREAD)) + if ((uap->fmode&R_OK) && access(ip, IREAD)) goto done; - if ((uap->fmode&FACCESS_WRITE) && access(ip, IWRITE)) + if ((uap->fmode&W_OK) && access(ip, IWRITE)) goto done; - if ((uap->fmode&FACCESS_EXECUTE) && access(ip, IEXEC)) + if ((uap->fmode&X_OK) && access(ip, IEXEC)) goto done; done: iput(ip); @@ -414,103 +411,41 @@ done: u.u_gid = svgid; } -/* - * the fstat system call. - */ -fstat() -{ - register struct file *fp; - register struct a { - int fd; - struct stat *sb; - } *uap; - - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); - if (fp == NULL) - return; - if (fp->f_type == DTYPE_SOCKET) - u.u_error = sostat(fp->f_socket, uap->sb); - else - stat1(fp->f_inode, uap->sb); -} - /* * Stat system call. This version follows links. */ stat() { - register struct inode *ip; - register struct a { - char *fname; - struct stat *sb; - } *uap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - stat1(ip, uap->sb); - iput(ip); + stat1(1); } /* * Lstat system call. This version does not follow links. */ lstat() +{ + + stat1(0); +} + +stat1(follow) + int follow; { register struct inode *ip; register struct a { char *fname; - struct stat *sb; + struct stat *ub; } *uap; + struct stat sb; uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 0); + ip = namei(uchar, LOOKUP, follow); if (ip == NULL) return; - stat1(ip, uap->sb); + (void) statinode(ip, &sb); iput(ip); -} - -/* - * The basic routine for fstat and stat: - * get the inode and pass appropriate parts back. - */ -stat1(ip, ub) - register struct inode *ip; - struct stat *ub; -{ - struct stat ds; - - IUPDAT(ip, &time, &time, 0); - /* - * Copy from inode table - */ - ds.st_dev = ip->i_dev; - ds.st_ino = ip->i_number; - ds.st_mode = ip->i_mode; - ds.st_nlink = ip->i_nlink; - ds.st_uid = ip->i_uid; - ds.st_gid = ip->i_gid; - ds.st_rdev = (dev_t)ip->i_rdev; - ds.st_size = ip->i_size; - ds.st_atime = ip->i_atime; - ds.st_spare1 = 0; - ds.st_mtime = ip->i_mtime; - ds.st_spare2 = 0; - ds.st_ctime = ip->i_ctime; - ds.st_spare3 = 0; - /* this doesn't belong here */ - if ((ip->i_mode&IFMT) == IFBLK) - ds.st_blksize = BLKDEV_IOSIZE; - else if ((ip->i_mode&IFMT) == IFCHR) - ds.st_blksize = MAXBSIZE; - else - ds.st_blksize = ip->i_fs->fs_bsize; - ds.st_blocks = ip->i_blocks; - ds.st_spare4[0] = ds.st_spare4[1] = 0; - u.u_error = copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)); + u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); } /* @@ -570,14 +505,10 @@ fchmod() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (u.u_uid != ip->i_uid && !suser()) return; ilock(ip); @@ -593,7 +524,6 @@ chmod1(ip, mode) register struct inode *ip; register int mode; { - register int *gp; ip->i_mode &= ~07777; if (u.u_uid) { @@ -640,14 +570,10 @@ fchown() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (!suser()) return; ilock(ip); @@ -756,29 +682,24 @@ sync() */ flock() { - struct a { + register struct a { int fd; int how; - } *uap; + } *uap = (struct a *)u.u_ap; register struct file *fp; register int cmd, flags; - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { /* XXX */ - u.u_error = EINVAL; - return; - } cmd = uap->how; flags = u.u_pofile[uap->fd] & (UF_SHLOCK|UF_EXLOCK); - if (cmd&FUNLOCK) { + if (cmd&LOCK_UN) { if (flags == 0) { u.u_error = EINVAL; return; } - funlocki(fp->f_inode, flags); + funlocki((struct inode *)fp->f_data, flags); u.u_pofile[uap->fd] &= ~(UF_SHLOCK|UF_EXLOCK); return; } @@ -786,10 +707,11 @@ flock() * No reason to write lock a file we've already * write locked, similarly with a read lock. */ - if ((flags&UF_EXLOCK) && (cmd&FEXLOCK) || - (flags&UF_SHLOCK) && (cmd&FSHLOCK)) + if ((flags&UF_EXLOCK) && (cmd&LOCK_EX) || + (flags&UF_SHLOCK) && (cmd&LOCK_SH)) return; - u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); + u.u_pofile[uap->fd] = + flocki((struct inode *)fp->f_data, u.u_pofile[uap->fd], cmd); } /* @@ -829,18 +751,14 @@ ftruncate() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } if ((fp->f_flag&FWRITE) == 0) { u.u_error = EINVAL; return; } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); itrunc(ip, uap->length); iunlock(ip); @@ -857,14 +775,10 @@ fsync() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); syncip(ip); iunlock(ip); @@ -1198,3 +1112,220 @@ maknode(mode) } return (ip); } + +/* + * A virgin directory (no blushing please). + */ +struct dirtemplate mastertemplate = { + 0, 12, 1, ".", + 0, DIRBLKSIZ - 12, 2, ".." +}; + +/* + * Mkdir system call + */ +mkdir() +{ + struct a { + char *name; + int dmode; + } *uap; + register struct inode *ip, *dp; + struct dirtemplate dirtemplate; + + uap = (struct a *)u.u_ap; + ip = namei(uchar, CREATE, 0); + if (u.u_error) + return; + if (ip != NULL) { + iput(ip); + u.u_error = EEXIST; + return; + } + dp = u.u_pdir; + uap->dmode &= 0777; + uap->dmode |= IFDIR; + /* + * Must simulate part of maknode here + * in order to acquire the inode, but + * not have it entered in the parent + * directory. The entry is made later + * after writing "." and ".." entries out. + */ + ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); + if (ip == NULL) { + iput(dp); + return; + } +#ifdef QUOTA + if (ip->i_dquot != NODQUOT) + panic("mkdir: dquot"); +#endif + ip->i_flag |= IACC|IUPD|ICHG; + ip->i_mode = uap->dmode & ~u.u_cmask; + ip->i_nlink = 2; + ip->i_uid = u.u_uid; + ip->i_gid = dp->i_gid; +#ifdef QUOTA + ip->i_dquot = inoquota(ip); +#endif + iupdat(ip, &time, &time, 1); + + /* + * Bump link count in parent directory + * to reflect work done below. Should + * be done before reference is created + * so reparation is possible if we crash. + */ + dp->i_nlink++; + dp->i_flag |= ICHG; + iupdat(dp, &time, &time, 1); + + /* + * Initialize directory with "." + * and ".." from static template. + */ + dirtemplate = mastertemplate; + dirtemplate.dot_ino = ip->i_number; + dirtemplate.dotdot_ino = dp->i_number; + u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, + sizeof (dirtemplate), (off_t)0, 1, (int *)0); + if (u.u_error) { + dp->i_nlink--; + dp->i_flag |= ICHG; + goto bad; + } + /* + * Directory all set up, now + * install the entry for it in + * the parent directory. + */ + u.u_error = direnter(ip); + dp = NULL; + if (u.u_error) { + u.u_dirp = uap->name; + dp = namei(uchar, LOOKUP, 0); + if (dp) { + dp->i_nlink--; + dp->i_flag |= ICHG; + } + } +bad: + /* + * No need to do an explicit itrunc here, + * irele will do this for us because we set + * the link count to 0. + */ + if (u.u_error) { + ip->i_nlink = 0; + ip->i_flag |= ICHG; + } + if (dp) + iput(dp); + iput(ip); +} + +/* + * Rmdir system call. + */ +rmdir() +{ + struct a { + char *name; + }; + register struct inode *ip, *dp; + + ip = namei(uchar, DELETE | LOCKPARENT, 0); + if (ip == NULL) + return; + dp = u.u_pdir; + /* + * No rmdir "." please. + */ + if (dp == ip) { + irele(dp); + iput(ip); + u.u_error = EINVAL; + return; + } + if ((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto out; + } + /* + * Don't remove a mounted on directory. + */ + if (ip->i_dev != dp->i_dev) { + u.u_error = EBUSY; + goto out; + } + /* + * Verify the directory is empty (and valid). + * (Rmdir ".." won't be valid since + * ".." will contain a reference to + * the current directory and thus be + * non-empty.) + */ + if (ip->i_nlink != 2 || !dirempty(ip)) { + u.u_error = ENOTEMPTY; + goto out; + } + /* + * Delete reference to directory before purging + * inode. If we crash in between, the directory + * will be reattached to lost+found, + */ + if (dirremove() == 0) + goto out; + dp->i_nlink--; + dp->i_flag |= ICHG; + iput(dp); + dp = NULL; + /* + * Truncate inode. The only stuff left + * in the directory is "." and "..". The + * "." reference is inconsequential since + * we're quashing it. The ".." reference + * has already been adjusted above. We've + * removed the "." reference and the reference + * in the parent directory, but there may be + * other hard links so decrement by 2 and + * worry about them later. + */ + ip->i_nlink -= 2; + itrunc(ip, (u_long)0); +out: + if (dp) + iput(dp); + iput(ip); +} + +struct file * +getinode(fdes) + int fdes; +{ + register struct file *fp; + + fp = getf(fdes); + if (fp == 0) + return (0); + if (fp->f_type != DTYPE_INODE) { + u.u_error = EINVAL; + return (0); + } + return (fp); +} + +/* + * mode mask for creation of files + */ +umask() +{ + register struct a { + int mask; + } *uap; + + uap = (struct a *)u.u_ap; + u.u_r.r_val1 = u.u_cmask; + u.u_cmask = uap->mask & 07777; +} diff --git a/usr/src/sys/ufs/lfs/lfs_alloc.c b/usr/src/sys/ufs/lfs/lfs_alloc.c index c126871655..a1936280c9 100644 --- a/usr/src/sys/ufs/lfs/lfs_alloc.c +++ b/usr/src/sys/ufs/lfs/lfs_alloc.c @@ -1,4 +1,4 @@ -/* lfs_alloc.c 2.25 83/05/21 */ +/* lfs_alloc.c 2.26 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -887,13 +887,15 @@ mapsearch(fs, cgp, bpref, allocsiz) else start = cgp->cg_frotor / NBBY; len = howmany(fs->fs_fpg, NBBY) - start; - loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], - 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); + loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[start], + (caddr_t)fragtbl[fs->fs_frag], + (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) { len = start + 1; start = 0; - loc = scanc(len, &cgp->cg_free[start], fragtbl[fs->fs_frag], - 1 << (allocsiz - 1 + (fs->fs_frag % NBBY))); + loc = scanc((unsigned)len, (caddr_t)&cgp->cg_free[start], + (caddr_t)fragtbl[fs->fs_frag], + (int)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY)))); if (loc == 0) return (-1); } diff --git a/usr/src/sys/ufs/lfs/lfs_vnops.c b/usr/src/sys/ufs/lfs/lfs_vnops.c index 7ec51dc781..b5e8dce5e9 100644 --- a/usr/src/sys/ufs/lfs/lfs_vnops.c +++ b/usr/src/sys/ufs/lfs/lfs_vnops.c @@ -1,4 +1,4 @@ -/* lfs_vnops.c 4.56 83/05/21 */ +/* lfs_vnops.c 4.57 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,11 +12,14 @@ #include "../h/buf.h" #include "../h/proc.h" #include "../h/quota.h" -#include "../h/descrip.h" #include "../h/uio.h" #include "../h/socket.h" #include "../h/socketvar.h" #include "../h/nami.h" +#include "../h/mount.h" + +extern struct fileops inodeops; +struct file *getinode(); /* * Change current working directory (``.''). @@ -72,76 +75,74 @@ bad: */ open() { - register struct inode *ip; - register struct a { + struct a { char *fname; - int flags; int mode; - } *uap; - int checkpermissions = 1, flags; + int crtmode; + } *uap = (struct a *) u.u_ap; - uap = (struct a *)u.u_ap; - flags = uap->flags + 1; - if ((flags&FTRUNCATE) && (flags&FWRITE) == 0) { - u.u_error = EINVAL; - return; - } - if (flags&FCREATE) { - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->mode&07777&(~ISVTX)); - checkpermissions = 0; - flags &= ~FTRUNCATE; - } - } else - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - open1(ip, flags, checkpermissions); + copen(uap->mode-FOPEN, uap->crtmode); } -#ifndef NOCOMPAT /* * Creat system call. */ -ocreat() +creat() { - register struct inode *ip; - register struct a { + struct a { char *fname; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->fmode&07777&(~ISVTX)); - if (ip == NULL) - return; - open1(ip, FWRITE, 0); - } else - open1(ip, FWRITE|FTRUNCATE, 1); + copen(FWRITE|FCREAT|FTRUNC, uap->fmode); } -#endif /* * Common code for open and creat. - * Check permissions (if we haven't done so already), - * allocate an open file structure, and call - * the device open routine, if any. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. */ -open1(ip, mode, checkpermissions) - register struct inode *ip; - register mode; +copen(mode, arg) + register int mode; + int arg; { + register struct inode *ip; register struct file *fp; - int i, flags; + int i; - if (checkpermissions) { +#ifdef notdef + if ((mode&(FREAD|FWRITE)) == 0) { + u.u_error = EINVAL; + return; + } +#endif + if (mode&FCREAT) { + ip = namei(uchar, CREATE, 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, LOOKUP, 1); + if (ip == NULL) + return; + } + if ((ip->i_mode & IFMT) == IFSOCK) { + u.u_error = EOPNOTSUPP; + goto bad; + } + if ((mode&FCREAT) == 0) { if (mode&FREAD) if (access(ip, IREAD)) goto bad; @@ -154,36 +155,31 @@ open1(ip, mode, checkpermissions) } } } - - /* - * Check locking on inode. Release "inode lock" - * while doing so in case we block inside flocki. - */ - flags = 0; - if (mode&(FSHLOCK|FEXLOCK)) { - iunlock(ip); - flags = flocki(ip, 0, mode); - ilock(ip); - if (u.u_error) - goto bad; - } - if (mode&FTRUNCATE) + fp = falloc(); + if (fp == NULL) + goto bad; + if (mode&FTRUNC) itrunc(ip, (u_long)0); iunlock(ip); - if ((fp = falloc()) == NULL) - goto out; - fp->f_flag = mode & FMODES; - fp->f_type = DTYPE_FILE; + fp->f_flag = mode&FMASK; + fp->f_type = DTYPE_INODE; + fp->f_ops = &inodeops; + fp->f_data = (caddr_t)ip; i = u.u_r.r_val1; - fp->f_inode = ip; - u.u_error = openi(ip, mode); - if (u.u_error == 0) { - u.u_pofile[i] = flags; +#ifdef notdef + if (setjmp(&u.u_qsave)) { + if (u.u_error == 0) + u.u_error = EINTR; + u.u_ofile[i] = NULL; + closef(fp); return; } +#endif + u.u_error = openi(ip, mode); + if (u.u_error == 0) + return; u.u_ofile[i] = NULL; fp->f_count--; -out: irele(ip); return; bad: @@ -203,25 +199,30 @@ mknod() } *uap; uap = (struct a *)u.u_ap; - if (suser()) { - ip = namei(uchar, CREATE, 0); - if (ip != NULL) { - u.u_error = EEXIST; - goto out; - } + if (!suser()) + return; + ip = namei(uchar, CREATE, 0); + if (ip != NULL) { + u.u_error = EEXIST; + goto out; } if (u.u_error) return; ip = maknode(uap->fmode); if (ip == NULL) return; - if (uap->dev) { - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - ip->i_rdev = uap->dev; - ip->i_flag |= IACC|IUPD|ICHG; + switch (ip->i_mode & IFMT) { + + case IFCHR: + case IFBLK: + if (uap->dev) { + /* + * Want to be able to use this to make badblock + * inodes, so don't truncate the dev number. + */ + ip->i_rdev = uap->dev; + ip->i_flag |= IACC|IUPD|ICHG; + } } out: @@ -367,17 +368,13 @@ lseek() } *uap; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = ESPIPE; - return; - } - if (uap->sbase == FSEEK_RELATIVE) + if (uap->sbase == L_INCR) uap->off += fp->f_offset; - else if (uap->sbase == FSEEK_EOF) - uap->off += fp->f_inode->i_size; + else if (uap->sbase == L_XTND) + uap->off += ((struct inode *)fp->f_data)->i_size; fp->f_offset = uap->off; u.u_r.r_off = uap->off; } @@ -401,11 +398,11 @@ saccess() u.u_gid = u.u_rgid; ip = namei(uchar, LOOKUP, 1); if (ip != NULL) { - if ((uap->fmode&FACCESS_READ) && access(ip, IREAD)) + if ((uap->fmode&R_OK) && access(ip, IREAD)) goto done; - if ((uap->fmode&FACCESS_WRITE) && access(ip, IWRITE)) + if ((uap->fmode&W_OK) && access(ip, IWRITE)) goto done; - if ((uap->fmode&FACCESS_EXECUTE) && access(ip, IEXEC)) + if ((uap->fmode&X_OK) && access(ip, IEXEC)) goto done; done: iput(ip); @@ -414,103 +411,41 @@ done: u.u_gid = svgid; } -/* - * the fstat system call. - */ -fstat() -{ - register struct file *fp; - register struct a { - int fd; - struct stat *sb; - } *uap; - - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); - if (fp == NULL) - return; - if (fp->f_type == DTYPE_SOCKET) - u.u_error = sostat(fp->f_socket, uap->sb); - else - stat1(fp->f_inode, uap->sb); -} - /* * Stat system call. This version follows links. */ stat() { - register struct inode *ip; - register struct a { - char *fname; - struct stat *sb; - } *uap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - stat1(ip, uap->sb); - iput(ip); + stat1(1); } /* * Lstat system call. This version does not follow links. */ lstat() +{ + + stat1(0); +} + +stat1(follow) + int follow; { register struct inode *ip; register struct a { char *fname; - struct stat *sb; + struct stat *ub; } *uap; + struct stat sb; uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 0); + ip = namei(uchar, LOOKUP, follow); if (ip == NULL) return; - stat1(ip, uap->sb); + (void) statinode(ip, &sb); iput(ip); -} - -/* - * The basic routine for fstat and stat: - * get the inode and pass appropriate parts back. - */ -stat1(ip, ub) - register struct inode *ip; - struct stat *ub; -{ - struct stat ds; - - IUPDAT(ip, &time, &time, 0); - /* - * Copy from inode table - */ - ds.st_dev = ip->i_dev; - ds.st_ino = ip->i_number; - ds.st_mode = ip->i_mode; - ds.st_nlink = ip->i_nlink; - ds.st_uid = ip->i_uid; - ds.st_gid = ip->i_gid; - ds.st_rdev = (dev_t)ip->i_rdev; - ds.st_size = ip->i_size; - ds.st_atime = ip->i_atime; - ds.st_spare1 = 0; - ds.st_mtime = ip->i_mtime; - ds.st_spare2 = 0; - ds.st_ctime = ip->i_ctime; - ds.st_spare3 = 0; - /* this doesn't belong here */ - if ((ip->i_mode&IFMT) == IFBLK) - ds.st_blksize = BLKDEV_IOSIZE; - else if ((ip->i_mode&IFMT) == IFCHR) - ds.st_blksize = MAXBSIZE; - else - ds.st_blksize = ip->i_fs->fs_bsize; - ds.st_blocks = ip->i_blocks; - ds.st_spare4[0] = ds.st_spare4[1] = 0; - u.u_error = copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)); + u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); } /* @@ -570,14 +505,10 @@ fchmod() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (u.u_uid != ip->i_uid && !suser()) return; ilock(ip); @@ -593,7 +524,6 @@ chmod1(ip, mode) register struct inode *ip; register int mode; { - register int *gp; ip->i_mode &= ~07777; if (u.u_uid) { @@ -640,14 +570,10 @@ fchown() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (!suser()) return; ilock(ip); @@ -756,29 +682,24 @@ sync() */ flock() { - struct a { + register struct a { int fd; int how; - } *uap; + } *uap = (struct a *)u.u_ap; register struct file *fp; register int cmd, flags; - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { /* XXX */ - u.u_error = EINVAL; - return; - } cmd = uap->how; flags = u.u_pofile[uap->fd] & (UF_SHLOCK|UF_EXLOCK); - if (cmd&FUNLOCK) { + if (cmd&LOCK_UN) { if (flags == 0) { u.u_error = EINVAL; return; } - funlocki(fp->f_inode, flags); + funlocki((struct inode *)fp->f_data, flags); u.u_pofile[uap->fd] &= ~(UF_SHLOCK|UF_EXLOCK); return; } @@ -786,10 +707,11 @@ flock() * No reason to write lock a file we've already * write locked, similarly with a read lock. */ - if ((flags&UF_EXLOCK) && (cmd&FEXLOCK) || - (flags&UF_SHLOCK) && (cmd&FSHLOCK)) + if ((flags&UF_EXLOCK) && (cmd&LOCK_EX) || + (flags&UF_SHLOCK) && (cmd&LOCK_SH)) return; - u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); + u.u_pofile[uap->fd] = + flocki((struct inode *)fp->f_data, u.u_pofile[uap->fd], cmd); } /* @@ -829,18 +751,14 @@ ftruncate() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } if ((fp->f_flag&FWRITE) == 0) { u.u_error = EINVAL; return; } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); itrunc(ip, uap->length); iunlock(ip); @@ -857,14 +775,10 @@ fsync() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); syncip(ip); iunlock(ip); @@ -1198,3 +1112,220 @@ maknode(mode) } return (ip); } + +/* + * A virgin directory (no blushing please). + */ +struct dirtemplate mastertemplate = { + 0, 12, 1, ".", + 0, DIRBLKSIZ - 12, 2, ".." +}; + +/* + * Mkdir system call + */ +mkdir() +{ + struct a { + char *name; + int dmode; + } *uap; + register struct inode *ip, *dp; + struct dirtemplate dirtemplate; + + uap = (struct a *)u.u_ap; + ip = namei(uchar, CREATE, 0); + if (u.u_error) + return; + if (ip != NULL) { + iput(ip); + u.u_error = EEXIST; + return; + } + dp = u.u_pdir; + uap->dmode &= 0777; + uap->dmode |= IFDIR; + /* + * Must simulate part of maknode here + * in order to acquire the inode, but + * not have it entered in the parent + * directory. The entry is made later + * after writing "." and ".." entries out. + */ + ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); + if (ip == NULL) { + iput(dp); + return; + } +#ifdef QUOTA + if (ip->i_dquot != NODQUOT) + panic("mkdir: dquot"); +#endif + ip->i_flag |= IACC|IUPD|ICHG; + ip->i_mode = uap->dmode & ~u.u_cmask; + ip->i_nlink = 2; + ip->i_uid = u.u_uid; + ip->i_gid = dp->i_gid; +#ifdef QUOTA + ip->i_dquot = inoquota(ip); +#endif + iupdat(ip, &time, &time, 1); + + /* + * Bump link count in parent directory + * to reflect work done below. Should + * be done before reference is created + * so reparation is possible if we crash. + */ + dp->i_nlink++; + dp->i_flag |= ICHG; + iupdat(dp, &time, &time, 1); + + /* + * Initialize directory with "." + * and ".." from static template. + */ + dirtemplate = mastertemplate; + dirtemplate.dot_ino = ip->i_number; + dirtemplate.dotdot_ino = dp->i_number; + u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, + sizeof (dirtemplate), (off_t)0, 1, (int *)0); + if (u.u_error) { + dp->i_nlink--; + dp->i_flag |= ICHG; + goto bad; + } + /* + * Directory all set up, now + * install the entry for it in + * the parent directory. + */ + u.u_error = direnter(ip); + dp = NULL; + if (u.u_error) { + u.u_dirp = uap->name; + dp = namei(uchar, LOOKUP, 0); + if (dp) { + dp->i_nlink--; + dp->i_flag |= ICHG; + } + } +bad: + /* + * No need to do an explicit itrunc here, + * irele will do this for us because we set + * the link count to 0. + */ + if (u.u_error) { + ip->i_nlink = 0; + ip->i_flag |= ICHG; + } + if (dp) + iput(dp); + iput(ip); +} + +/* + * Rmdir system call. + */ +rmdir() +{ + struct a { + char *name; + }; + register struct inode *ip, *dp; + + ip = namei(uchar, DELETE | LOCKPARENT, 0); + if (ip == NULL) + return; + dp = u.u_pdir; + /* + * No rmdir "." please. + */ + if (dp == ip) { + irele(dp); + iput(ip); + u.u_error = EINVAL; + return; + } + if ((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto out; + } + /* + * Don't remove a mounted on directory. + */ + if (ip->i_dev != dp->i_dev) { + u.u_error = EBUSY; + goto out; + } + /* + * Verify the directory is empty (and valid). + * (Rmdir ".." won't be valid since + * ".." will contain a reference to + * the current directory and thus be + * non-empty.) + */ + if (ip->i_nlink != 2 || !dirempty(ip)) { + u.u_error = ENOTEMPTY; + goto out; + } + /* + * Delete reference to directory before purging + * inode. If we crash in between, the directory + * will be reattached to lost+found, + */ + if (dirremove() == 0) + goto out; + dp->i_nlink--; + dp->i_flag |= ICHG; + iput(dp); + dp = NULL; + /* + * Truncate inode. The only stuff left + * in the directory is "." and "..". The + * "." reference is inconsequential since + * we're quashing it. The ".." reference + * has already been adjusted above. We've + * removed the "." reference and the reference + * in the parent directory, but there may be + * other hard links so decrement by 2 and + * worry about them later. + */ + ip->i_nlink -= 2; + itrunc(ip, (u_long)0); +out: + if (dp) + iput(dp); + iput(ip); +} + +struct file * +getinode(fdes) + int fdes; +{ + register struct file *fp; + + fp = getf(fdes); + if (fp == 0) + return (0); + if (fp->f_type != DTYPE_INODE) { + u.u_error = EINVAL; + return (0); + } + return (fp); +} + +/* + * mode mask for creation of files + */ +umask() +{ + register struct a { + int mask; + } *uap; + + uap = (struct a *)u.u_ap; + u.u_r.r_val1 = u.u_cmask; + u.u_cmask = uap->mask & 07777; +} diff --git a/usr/src/sys/ufs/ufs/ufs_vnops.c b/usr/src/sys/ufs/ufs/ufs_vnops.c index b6bbad2974..a3fdf59fe9 100644 --- a/usr/src/sys/ufs/ufs/ufs_vnops.c +++ b/usr/src/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* ufs_vnops.c 4.56 83/05/21 */ +/* ufs_vnops.c 4.57 83/05/27 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,11 +12,14 @@ #include "../h/buf.h" #include "../h/proc.h" #include "../h/quota.h" -#include "../h/descrip.h" #include "../h/uio.h" #include "../h/socket.h" #include "../h/socketvar.h" #include "../h/nami.h" +#include "../h/mount.h" + +extern struct fileops inodeops; +struct file *getinode(); /* * Change current working directory (``.''). @@ -72,76 +75,74 @@ bad: */ open() { - register struct inode *ip; - register struct a { + struct a { char *fname; - int flags; int mode; - } *uap; - int checkpermissions = 1, flags; + int crtmode; + } *uap = (struct a *) u.u_ap; - uap = (struct a *)u.u_ap; - flags = uap->flags + 1; - if ((flags&FTRUNCATE) && (flags&FWRITE) == 0) { - u.u_error = EINVAL; - return; - } - if (flags&FCREATE) { - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->mode&07777&(~ISVTX)); - checkpermissions = 0; - flags &= ~FTRUNCATE; - } - } else - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - open1(ip, flags, checkpermissions); + copen(uap->mode-FOPEN, uap->crtmode); } -#ifndef NOCOMPAT /* * Creat system call. */ -ocreat() +creat() { - register struct inode *ip; - register struct a { + struct a { char *fname; int fmode; - } *uap; + } *uap = (struct a *)u.u_ap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, CREATE, 1); - if (ip == NULL) { - if (u.u_error) - return; - ip = maknode(uap->fmode&07777&(~ISVTX)); - if (ip == NULL) - return; - open1(ip, FWRITE, 0); - } else - open1(ip, FWRITE|FTRUNCATE, 1); + copen(FWRITE|FCREAT|FTRUNC, uap->fmode); } -#endif /* * Common code for open and creat. - * Check permissions (if we haven't done so already), - * allocate an open file structure, and call - * the device open routine, if any. + * Check permissions, allocate an open file structure, + * and call the device open routine if any. */ -open1(ip, mode, checkpermissions) - register struct inode *ip; - register mode; +copen(mode, arg) + register int mode; + int arg; { + register struct inode *ip; register struct file *fp; - int i, flags; + int i; - if (checkpermissions) { +#ifdef notdef + if ((mode&(FREAD|FWRITE)) == 0) { + u.u_error = EINVAL; + return; + } +#endif + if (mode&FCREAT) { + ip = namei(uchar, CREATE, 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, LOOKUP, 1); + if (ip == NULL) + return; + } + if ((ip->i_mode & IFMT) == IFSOCK) { + u.u_error = EOPNOTSUPP; + goto bad; + } + if ((mode&FCREAT) == 0) { if (mode&FREAD) if (access(ip, IREAD)) goto bad; @@ -154,36 +155,31 @@ open1(ip, mode, checkpermissions) } } } - - /* - * Check locking on inode. Release "inode lock" - * while doing so in case we block inside flocki. - */ - flags = 0; - if (mode&(FSHLOCK|FEXLOCK)) { - iunlock(ip); - flags = flocki(ip, 0, mode); - ilock(ip); - if (u.u_error) - goto bad; - } - if (mode&FTRUNCATE) + fp = falloc(); + if (fp == NULL) + goto bad; + if (mode&FTRUNC) itrunc(ip, (u_long)0); iunlock(ip); - if ((fp = falloc()) == NULL) - goto out; - fp->f_flag = mode & FMODES; - fp->f_type = DTYPE_FILE; + fp->f_flag = mode&FMASK; + fp->f_type = DTYPE_INODE; + fp->f_ops = &inodeops; + fp->f_data = (caddr_t)ip; i = u.u_r.r_val1; - fp->f_inode = ip; - u.u_error = openi(ip, mode); - if (u.u_error == 0) { - u.u_pofile[i] = flags; +#ifdef notdef + if (setjmp(&u.u_qsave)) { + if (u.u_error == 0) + u.u_error = EINTR; + u.u_ofile[i] = NULL; + closef(fp); return; } +#endif + u.u_error = openi(ip, mode); + if (u.u_error == 0) + return; u.u_ofile[i] = NULL; fp->f_count--; -out: irele(ip); return; bad: @@ -203,25 +199,30 @@ mknod() } *uap; uap = (struct a *)u.u_ap; - if (suser()) { - ip = namei(uchar, CREATE, 0); - if (ip != NULL) { - u.u_error = EEXIST; - goto out; - } + if (!suser()) + return; + ip = namei(uchar, CREATE, 0); + if (ip != NULL) { + u.u_error = EEXIST; + goto out; } if (u.u_error) return; ip = maknode(uap->fmode); if (ip == NULL) return; - if (uap->dev) { - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - ip->i_rdev = uap->dev; - ip->i_flag |= IACC|IUPD|ICHG; + switch (ip->i_mode & IFMT) { + + case IFCHR: + case IFBLK: + if (uap->dev) { + /* + * Want to be able to use this to make badblock + * inodes, so don't truncate the dev number. + */ + ip->i_rdev = uap->dev; + ip->i_flag |= IACC|IUPD|ICHG; + } } out: @@ -367,17 +368,13 @@ lseek() } *uap; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = ESPIPE; - return; - } - if (uap->sbase == FSEEK_RELATIVE) + if (uap->sbase == L_INCR) uap->off += fp->f_offset; - else if (uap->sbase == FSEEK_EOF) - uap->off += fp->f_inode->i_size; + else if (uap->sbase == L_XTND) + uap->off += ((struct inode *)fp->f_data)->i_size; fp->f_offset = uap->off; u.u_r.r_off = uap->off; } @@ -401,11 +398,11 @@ saccess() u.u_gid = u.u_rgid; ip = namei(uchar, LOOKUP, 1); if (ip != NULL) { - if ((uap->fmode&FACCESS_READ) && access(ip, IREAD)) + if ((uap->fmode&R_OK) && access(ip, IREAD)) goto done; - if ((uap->fmode&FACCESS_WRITE) && access(ip, IWRITE)) + if ((uap->fmode&W_OK) && access(ip, IWRITE)) goto done; - if ((uap->fmode&FACCESS_EXECUTE) && access(ip, IEXEC)) + if ((uap->fmode&X_OK) && access(ip, IEXEC)) goto done; done: iput(ip); @@ -414,103 +411,41 @@ done: u.u_gid = svgid; } -/* - * the fstat system call. - */ -fstat() -{ - register struct file *fp; - register struct a { - int fd; - struct stat *sb; - } *uap; - - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); - if (fp == NULL) - return; - if (fp->f_type == DTYPE_SOCKET) - u.u_error = sostat(fp->f_socket, uap->sb); - else - stat1(fp->f_inode, uap->sb); -} - /* * Stat system call. This version follows links. */ stat() { - register struct inode *ip; - register struct a { - char *fname; - struct stat *sb; - } *uap; - uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 1); - if (ip == NULL) - return; - stat1(ip, uap->sb); - iput(ip); + stat1(1); } /* * Lstat system call. This version does not follow links. */ lstat() +{ + + stat1(0); +} + +stat1(follow) + int follow; { register struct inode *ip; register struct a { char *fname; - struct stat *sb; + struct stat *ub; } *uap; + struct stat sb; uap = (struct a *)u.u_ap; - ip = namei(uchar, LOOKUP, 0); + ip = namei(uchar, LOOKUP, follow); if (ip == NULL) return; - stat1(ip, uap->sb); + (void) statinode(ip, &sb); iput(ip); -} - -/* - * The basic routine for fstat and stat: - * get the inode and pass appropriate parts back. - */ -stat1(ip, ub) - register struct inode *ip; - struct stat *ub; -{ - struct stat ds; - - IUPDAT(ip, &time, &time, 0); - /* - * Copy from inode table - */ - ds.st_dev = ip->i_dev; - ds.st_ino = ip->i_number; - ds.st_mode = ip->i_mode; - ds.st_nlink = ip->i_nlink; - ds.st_uid = ip->i_uid; - ds.st_gid = ip->i_gid; - ds.st_rdev = (dev_t)ip->i_rdev; - ds.st_size = ip->i_size; - ds.st_atime = ip->i_atime; - ds.st_spare1 = 0; - ds.st_mtime = ip->i_mtime; - ds.st_spare2 = 0; - ds.st_ctime = ip->i_ctime; - ds.st_spare3 = 0; - /* this doesn't belong here */ - if ((ip->i_mode&IFMT) == IFBLK) - ds.st_blksize = BLKDEV_IOSIZE; - else if ((ip->i_mode&IFMT) == IFCHR) - ds.st_blksize = MAXBSIZE; - else - ds.st_blksize = ip->i_fs->fs_bsize; - ds.st_blocks = ip->i_blocks; - ds.st_spare4[0] = ds.st_spare4[1] = 0; - u.u_error = copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)); + u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); } /* @@ -570,14 +505,10 @@ fchmod() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (u.u_uid != ip->i_uid && !suser()) return; ilock(ip); @@ -593,7 +524,6 @@ chmod1(ip, mode) register struct inode *ip; register int mode; { - register int *gp; ip->i_mode &= ~07777; if (u.u_uid) { @@ -640,14 +570,10 @@ fchown() register struct file *fp; uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; if (!suser()) return; ilock(ip); @@ -756,29 +682,24 @@ sync() */ flock() { - struct a { + register struct a { int fd; int how; - } *uap; + } *uap = (struct a *)u.u_ap; register struct file *fp; register int cmd, flags; - uap = (struct a *)u.u_ap; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { /* XXX */ - u.u_error = EINVAL; - return; - } cmd = uap->how; flags = u.u_pofile[uap->fd] & (UF_SHLOCK|UF_EXLOCK); - if (cmd&FUNLOCK) { + if (cmd&LOCK_UN) { if (flags == 0) { u.u_error = EINVAL; return; } - funlocki(fp->f_inode, flags); + funlocki((struct inode *)fp->f_data, flags); u.u_pofile[uap->fd] &= ~(UF_SHLOCK|UF_EXLOCK); return; } @@ -786,10 +707,11 @@ flock() * No reason to write lock a file we've already * write locked, similarly with a read lock. */ - if ((flags&UF_EXLOCK) && (cmd&FEXLOCK) || - (flags&UF_SHLOCK) && (cmd&FSHLOCK)) + if ((flags&UF_EXLOCK) && (cmd&LOCK_EX) || + (flags&UF_SHLOCK) && (cmd&LOCK_SH)) return; - u.u_pofile[uap->fd] = flocki(fp->f_inode, u.u_pofile[uap->fd], cmd); + u.u_pofile[uap->fd] = + flocki((struct inode *)fp->f_data, u.u_pofile[uap->fd], cmd); } /* @@ -829,18 +751,14 @@ ftruncate() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } if ((fp->f_flag&FWRITE) == 0) { u.u_error = EINVAL; return; } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); itrunc(ip, uap->length); iunlock(ip); @@ -857,14 +775,10 @@ fsync() struct inode *ip; struct file *fp; - fp = getf(uap->fd); + fp = getinode(uap->fd); if (fp == NULL) return; - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; - return; - } - ip = fp->f_inode; + ip = (struct inode *)fp->f_data; ilock(ip); syncip(ip); iunlock(ip); @@ -1198,3 +1112,220 @@ maknode(mode) } return (ip); } + +/* + * A virgin directory (no blushing please). + */ +struct dirtemplate mastertemplate = { + 0, 12, 1, ".", + 0, DIRBLKSIZ - 12, 2, ".." +}; + +/* + * Mkdir system call + */ +mkdir() +{ + struct a { + char *name; + int dmode; + } *uap; + register struct inode *ip, *dp; + struct dirtemplate dirtemplate; + + uap = (struct a *)u.u_ap; + ip = namei(uchar, CREATE, 0); + if (u.u_error) + return; + if (ip != NULL) { + iput(ip); + u.u_error = EEXIST; + return; + } + dp = u.u_pdir; + uap->dmode &= 0777; + uap->dmode |= IFDIR; + /* + * Must simulate part of maknode here + * in order to acquire the inode, but + * not have it entered in the parent + * directory. The entry is made later + * after writing "." and ".." entries out. + */ + ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode); + if (ip == NULL) { + iput(dp); + return; + } +#ifdef QUOTA + if (ip->i_dquot != NODQUOT) + panic("mkdir: dquot"); +#endif + ip->i_flag |= IACC|IUPD|ICHG; + ip->i_mode = uap->dmode & ~u.u_cmask; + ip->i_nlink = 2; + ip->i_uid = u.u_uid; + ip->i_gid = dp->i_gid; +#ifdef QUOTA + ip->i_dquot = inoquota(ip); +#endif + iupdat(ip, &time, &time, 1); + + /* + * Bump link count in parent directory + * to reflect work done below. Should + * be done before reference is created + * so reparation is possible if we crash. + */ + dp->i_nlink++; + dp->i_flag |= ICHG; + iupdat(dp, &time, &time, 1); + + /* + * Initialize directory with "." + * and ".." from static template. + */ + dirtemplate = mastertemplate; + dirtemplate.dot_ino = ip->i_number; + dirtemplate.dotdot_ino = dp->i_number; + u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate, + sizeof (dirtemplate), (off_t)0, 1, (int *)0); + if (u.u_error) { + dp->i_nlink--; + dp->i_flag |= ICHG; + goto bad; + } + /* + * Directory all set up, now + * install the entry for it in + * the parent directory. + */ + u.u_error = direnter(ip); + dp = NULL; + if (u.u_error) { + u.u_dirp = uap->name; + dp = namei(uchar, LOOKUP, 0); + if (dp) { + dp->i_nlink--; + dp->i_flag |= ICHG; + } + } +bad: + /* + * No need to do an explicit itrunc here, + * irele will do this for us because we set + * the link count to 0. + */ + if (u.u_error) { + ip->i_nlink = 0; + ip->i_flag |= ICHG; + } + if (dp) + iput(dp); + iput(ip); +} + +/* + * Rmdir system call. + */ +rmdir() +{ + struct a { + char *name; + }; + register struct inode *ip, *dp; + + ip = namei(uchar, DELETE | LOCKPARENT, 0); + if (ip == NULL) + return; + dp = u.u_pdir; + /* + * No rmdir "." please. + */ + if (dp == ip) { + irele(dp); + iput(ip); + u.u_error = EINVAL; + return; + } + if ((ip->i_mode&IFMT) != IFDIR) { + u.u_error = ENOTDIR; + goto out; + } + /* + * Don't remove a mounted on directory. + */ + if (ip->i_dev != dp->i_dev) { + u.u_error = EBUSY; + goto out; + } + /* + * Verify the directory is empty (and valid). + * (Rmdir ".." won't be valid since + * ".." will contain a reference to + * the current directory and thus be + * non-empty.) + */ + if (ip->i_nlink != 2 || !dirempty(ip)) { + u.u_error = ENOTEMPTY; + goto out; + } + /* + * Delete reference to directory before purging + * inode. If we crash in between, the directory + * will be reattached to lost+found, + */ + if (dirremove() == 0) + goto out; + dp->i_nlink--; + dp->i_flag |= ICHG; + iput(dp); + dp = NULL; + /* + * Truncate inode. The only stuff left + * in the directory is "." and "..". The + * "." reference is inconsequential since + * we're quashing it. The ".." reference + * has already been adjusted above. We've + * removed the "." reference and the reference + * in the parent directory, but there may be + * other hard links so decrement by 2 and + * worry about them later. + */ + ip->i_nlink -= 2; + itrunc(ip, (u_long)0); +out: + if (dp) + iput(dp); + iput(ip); +} + +struct file * +getinode(fdes) + int fdes; +{ + register struct file *fp; + + fp = getf(fdes); + if (fp == 0) + return (0); + if (fp->f_type != DTYPE_INODE) { + u.u_error = EINVAL; + return (0); + } + return (fp); +} + +/* + * mode mask for creation of files + */ +umask() +{ + register struct a { + int mask; + } *uap; + + uap = (struct a *)u.u_ap; + u.u_r.r_val1 = u.u_cmask; + u.u_cmask = uap->mask & 07777; +} -- 2.20.1