X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/4147b3f690ea42bd015c9077ae49137621134f19..92438dfc96ed982a3af6a9bf3cdda47a07a002a5:/usr/src/sys/kern/kern_descrip.c diff --git a/usr/src/sys/kern/kern_descrip.c b/usr/src/sys/kern/kern_descrip.c index c3c87f5d0c..188d77e304 100644 --- a/usr/src/sys/kern/kern_descrip.c +++ b/usr/src/sys/kern/kern_descrip.c @@ -1,19 +1,20 @@ -/* kern_descrip.c 5.2 82/07/24 */ +/* kern_descrip.c 5.25 83/06/12 */ #include "../h/param.h" #include "../h/systm.h" #include "../h/dir.h" #include "../h/user.h" +#include "../h/kernel.h" #include "../h/inode.h" #include "../h/proc.h" #include "../h/conf.h" #include "../h/file.h" -#include "../h/inline.h" #include "../h/socket.h" #include "../h/socketvar.h" #include "../h/mount.h" +#include "../h/stat.h" -#include "../h/descrip.h" +#include "../h/ioctl.h" /* * Descriptor management. @@ -21,37 +22,46 @@ /* * TODO: - * getf should be renamed - * ufalloc side effects are gross + * increase NOFILE + * eliminate u.u_error side effects */ /* * System calls on descriptors. */ -dstd() +getdtablesize() { u.u_r.r_val1 = NOFILE; } +getdopt() +{ + +} + +setdopt() +{ + +} + dup() { register struct a { int i; } *uap = (struct a *) u.u_ap; - register struct file *fp; - register int j; + struct file *fp; + int j; if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ fp = getf(uap->i); if (fp == 0) return; - j = ufalloc(); + j = ufalloc(0); if (j < 0) return; - u.u_ofile[j] = fp; - fp->f_count++; + dupit(j, fp, u.u_pofile[uap->i]); } dup2() @@ -72,258 +82,222 @@ dup2() if (uap->i == uap->j) return; if (u.u_ofile[uap->j]) { - closef(u.u_ofile[uap->j], 0); + if (u.u_pofile[uap->j] & UF_MAPPED) + munmapfd(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; */ } - u.u_ofile[uap->j] = fp; - fp->f_count++; + dupit(uap->j, fp, u.u_pofile[uap->i]); } -close() -{ - register struct a { - int i; - } *uap = (struct a *)u.u_ap; +dupit(fd, fp, lockflags) + int fd; register struct file *fp; + register int lockflags; +{ - fp = getf(uap->i); - if (fp == 0) - return; - u.u_ofile[uap->i] = 0; - closef(fp, 0); - /* WHAT IF u.u_error ? */ + u.u_ofile[fd] = fp; + u.u_pofile[fd] = lockflags; + fp->f_count++; +/* THIS DOESN'T BELONG HERE */ + if (lockflags&UF_SHLOCK) + ((struct inode *)fp->f_data)->i_shlockc++; + if (lockflags&UF_EXLOCK) + ((struct inode *)fp->f_data)->i_exlockc++; +/* END DOESN'T BELONG */ } -dtype() +/* + * The file control system call. + */ +fcntl() { - register struct a { - int d; - struct dtype *dtypeb; - } *uap = (struct a *)u.u_ap; register struct file *fp; - struct dtype adtype; + register struct a { + int fdes; + int cmd; + int arg; + } *uap; + register i; + register char *pop; - fp = getf(uap->d); - if (fp == 0) - return; - adtype.dt_type = 0; /* XXX */ - adtype.dt_protocol = 0; /* XXX */ - if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, - sizeof (struct dtype)) < 0) { - u.u_error = EFAULT; + uap = (struct a *)u.u_ap; + fp = getf(uap->fdes); + if (fp == NULL) return; - } -} + pop = &u.u_pofile[uap->fdes]; + switch(uap->cmd) { + case 0: + i = uap->arg; + if (i < 0 || i > NOFILE) { + u.u_error = EINVAL; + return; + } + if ((i = ufalloc(i)) < 0) + return; + dupit(i, fp, *pop); + break; -dwrap() -{ - register struct a { - int d; - struct dtype *dtypeb; - } *uap = (struct a *)u.u_ap; - register struct file *fp; - struct dtype adtype; + case 1: + u.u_r.r_val1 = *pop & 1; + break; - fp = getf(uap->d); - if (fp == 0) - return; - if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, - sizeof (struct dtype)) < 0) { - u.u_error = EFAULT; - return; - } - /* DO WRAP */ -} + case 2: + *pop = (*pop &~ 1) | (uap->arg & 1); + break; -dselect() -{ + case 3: + u.u_r.r_val1 = fp->f_flag+FOPEN; + break; -} + 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; -dnblock() -{ - register struct a { - int d; - int how; - } *uap = (struct a *)u.u_ap; + case 5: + u.u_error = fsetown(fp, uap->arg); + break; + + case 6: + u.u_error = fgetown(fp, &u.u_r.r_val1); + break; - /* XXX */ + default: + u.u_error = EINVAL; + } } -dsignal() +fset(fp, bit, value) + struct file *fp; + int bit, value; { - register struct a { - int d; - int how; - } *uap = (struct a *)u.u_ap; - /* XXX */ + if (value) + fp->f_flag |= bit; + else + fp->f_flag &= ~bit; + return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), + (caddr_t)&value)); } -int nselcoll; -/* - * Select system call. - */ -oselect() +fgetown(fp, valuep) + struct file *fp; + int *valuep; { - register struct uap { - int nfd; - fd_set *rp, *wp; - int timo; - } *ap = (struct uap *)u.u_ap; - fd_set rd, wr; - int nfds = 0, readable = 0, writeable = 0; - time_t t = time; - int s, tsel, ncoll, rem; - - if (ap->nfd > NOFILE) - ap->nfd = NOFILE; - if (ap->nfd < 0) { - u.u_error = EBADF; - return; - } - if (ap->rp && copyin((caddr_t)ap->rp,(caddr_t)&rd,sizeof(fd_set))) - return; - if (ap->wp && copyin((caddr_t)ap->wp,(caddr_t)&wr,sizeof(fd_set))) - return; -retry: - ncoll = nselcoll; - u.u_procp->p_flag |= SSEL; - if (ap->rp) - readable = selscan(ap->nfd, rd, &nfds, FREAD); - if (ap->wp) - writeable = selscan(ap->nfd, wr, &nfds, FWRITE); - if (u.u_error) - goto done; - if (readable || writeable) - goto done; - rem = (ap->timo+999)/1000 - (time - t); - if (ap->timo == 0 || rem <= 0) - goto done; - s = spl6(); - 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; - tsel = tsleep((caddr_t)&selwait, PZERO+1, rem); - splx(s); - switch (tsel) { + int error; - case TS_OK: - goto retry; + switch (fp->f_type) { - case TS_SIG: - u.u_error = EINTR; - return; + case DTYPE_SOCKET: + *valuep = ((struct socket *)fp->f_data)->so_pgrp; + return (0); - case TS_TIME: - break; + default: + error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); + *valuep = -*valuep; + return (error); } -done: - rd.fds_bits[0] = readable; - wr.fds_bits[0] = writeable; - s = sizeof (fd_set); - if (s * NBBY > ap->nfd) - s = (ap->nfd + NBBY - 1) / NBBY; - u.u_r.r_val1 = nfds; - if (ap->rp) - (void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set)); - if (ap->wp) - (void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set)); } -selscan(nfd, fds, nfdp, flag) - int nfd; - fd_set fds; - int *nfdp, flag; -{ +fsetown(fp, value) struct file *fp; - struct inode *ip; - register int bits; - int i, able, res = 0; - - bits = fds.fds_bits[0]; - while (i = ffs(bits)) { - if (i > nfd) - break; - bits &= ~(1<<(i-1)); - fp = u.u_ofile[i-1]; - if (fp == NULL) { - u.u_error = EBADF; - return (0); - } - 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; - } + int value; +{ - } - if (able) { - res |= (1<<(i-1)); - (*nfdp)++; - } + if (fp->f_type == DTYPE_SOCKET) { + ((struct socket *)fp->f_data)->so_pgrp = value; + return (0); } - return (res); + 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)); } -/*ARGSUSED*/ -seltrue(dev, flag) - dev_t dev; - int flag; +fioctl(fp, cmd, value) + struct file *fp; + int cmd; + caddr_t value; { - return (1); + return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); } -selwakeup(p, coll) - register struct proc *p; - int coll; +close() { - int s; + register struct a { + int i; + } *uap = (struct a *)u.u_ap; + register struct file *fp; + register u_char *pf; - if (coll) { - nselcoll++; - wakeup((caddr_t)&selwait); - } - if (p) { - if (p->p_wchan == (caddr_t)&selwait) - setrun(p); - else { - s = spl6(); - if (p->p_flag & SSEL) - p->p_flag &= ~SSEL; - splx(s); - } - } + fp = getf(uap->i); + if (fp == 0) + return; + pf = (u_char *)&u.u_pofile[uap->i]; + if (*pf & UF_MAPPED) + munmapfd(uap->i); + if (*pf & (UF_SHLOCK|UF_EXLOCK)) + unlockf(fp, pf); + closef(fp); + /* WHAT IF u.u_error ? */ + u.u_ofile[uap->i] = NULL; + *pf = 0; } +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; + switch (fp->f_type) { + + case DTYPE_INODE: + u.u_error = ino_stat((struct inode *)fp->f_data, &ub); + break; + + case DTYPE_SOCKET: + u.u_error = soo_stat((struct socket *)fp->f_data, &ub); + break; + + default: + panic("fstat"); + /*NOTREACHED*/ + } + if (u.u_error == 0) + u.u_error = copyout(&ub, uap->sb, sizeof (ub)); +} /* * 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) @@ -388,171 +373,92 @@ 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. + * 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) +closef(fp) register struct file *fp; { - 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 = 0; /* XXX */ - 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; - ilock(ip); - iput(ip); + (*fp->f_ops->fo_close)(fp); fp->f_count = 0; - - switch (mode) { - - case IFCHR: - cfunc = cdevsw[major(dev)].d_close; -#ifdef EFS - /* - * Every close() must call the driver if the - * extended file system is being used -- not - * just the last close. Pass along the file - * pointer for reference later. - */ - if (major(dev) == efs_major) { - (*cfunc)(dev, flag, fp, nouser); - return; - } -#endif - 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); } -#ifdef CAD /* - * chfile -- change all references to the inode named by - * device/inum to the file referred to by fd. - * Used by init to remove all references to the device. + * Apply an advisory lock on a file descriptor. */ -chfile() +flock() { - register struct file *fp; - register struct inode *from; - register struct inode *to; - off_t offset; - dev_t dev; - int rw; - struct a { - int device; /* actually dev_t */ - int inum; /* actually ino_t */ + register struct a { int fd; - } *uap; + int how; + } *uap = (struct a *)u.u_ap; + register struct file *fp; + register u_char *pf; + int cmd; - if (!suser()) { - u.u_error = EPERM; - return; - } - uap = (struct a *) u.u_ap; fp = getf(uap->fd); - if (fp == NULL) { - u.u_error = EBADF; - return; - } - if (fp->f_type == DTYPE_SOCKET) { - u.u_error = EINVAL; + if (fp == NULL) return; - } - for (from = &inode[0]; from < &inode[ninode]; from++) - if (from->i_number == (ino_t)uap->inum - && from->i_dev == (dev_t)uap->device) - break; - if (from >= &inode[ninode]) { - u.u_error = ENXIO; + cmd = uap->how; + pf = (u_char *)&u.u_pofile[uap->fd]; + if (cmd & LOCK_UN) { + unlockf(fp, pf); return; } - offset = fp->f_offset; - to = fp->f_inode; - from->i_count++; - for (fp = &file[0]; fp < &file[nfile]; fp++) { - if (fp->f_count > 0 && fp->f_inode == from) { - fp->f_inode = to; - to->i_count++; - fp->f_offset = offset; - rw |= fp->f_flag & FWRITE; - iput(from); - } - } /* - * This inode is no longer referenced. - * Switch out to the appropriate close - * routine, if required + * No reason to write lock a file we've already + * write locked, similarly with a read lock. */ - dev = (dev_t)from->i_un.i_rdev; - switch(from->i_mode & IFMT) { + if ((*pf & UF_EXLOCK) && (cmd & LOCK_EX) || + (*pf & UF_SHLOCK) && (cmd & LOCK_SH)) + return; + switch (fp->f_type) { - case IFCHR: - (*cdevsw[major(dev)].d_close)(dev, rw); + case DTYPE_INODE: + u.u_error = ino_lock((struct inode *)fp->f_data, pf, cmd); break; - - case IFBLK: - (*bdevsw[major(dev)].d_close)(dev, rw); + + case DTYPE_SOCKET: + u.u_error = soo_lock((struct socket *)fp->f_data, pf, cmd); break; default: + panic("lockf"); + } +} + +unlockf(fp, pf) + register struct file *fp; + register u_char *pf; +{ + + if ((*pf & (UF_SHLOCK|UF_EXLOCK)) == 0) + return; + switch (fp->f_type) { + + case DTYPE_INODE: + ino_unlock((struct inode *)fp->f_data, *pf); + break; + + case DTYPE_SOCKET: + soo_unlock((struct socket *)fp->f_data, *pf); break; + + default: + panic("unlockf"); } - iput(from); + *pf &= ~(UF_SHLOCK|UF_EXLOCK); } -#endif