123375Smckusick /* 263176Sbostic * Copyright (c) 1982, 1986, 1991, 1993 363176Sbostic * The Regents of the University of California. All rights reserved. 423375Smckusick * 547540Skarels * %sccs.include.redist.c% 647540Skarels * 7*65257Smckusick * @(#)kern_subr.c 8.2 (Berkeley) 12/30/93 823375Smckusick */ 912792Ssam 1056517Sbostic #include <sys/param.h> 1156517Sbostic #include <sys/systm.h> 1256517Sbostic #include <sys/proc.h> 1356517Sbostic #include <sys/malloc.h> 14*65257Smckusick #include <sys/queue.h> 1512792Ssam 1637728Smckusick uiomove(cp, n, uio) 1712792Ssam register caddr_t cp; 1812792Ssam register int n; 1912792Ssam register struct uio *uio; 2012792Ssam { 2112792Ssam register struct iovec *iov; 2212792Ssam u_int cnt; 2312792Ssam int error = 0; 2412792Ssam 2548016Smckusick #ifdef DIAGNOSTIC 2637728Smckusick if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) 2737728Smckusick panic("uiomove: mode"); 2848016Smckusick if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 2948016Smckusick panic("uiomove proc"); 3048016Smckusick #endif 3112792Ssam while (n > 0 && uio->uio_resid) { 3212792Ssam iov = uio->uio_iov; 3312792Ssam cnt = iov->iov_len; 3412792Ssam if (cnt == 0) { 3512792Ssam uio->uio_iov++; 3612792Ssam uio->uio_iovcnt--; 3712792Ssam continue; 3812792Ssam } 3912792Ssam if (cnt > n) 4012792Ssam cnt = n; 4112792Ssam switch (uio->uio_segflg) { 4212792Ssam 4316704Smckusick case UIO_USERSPACE: 4416704Smckusick case UIO_USERISPACE: 4537728Smckusick if (uio->uio_rw == UIO_READ) 4612792Ssam error = copyout(cp, iov->iov_base, cnt); 4712792Ssam else 4812792Ssam error = copyin(iov->iov_base, cp, cnt); 4912792Ssam if (error) 5012792Ssam return (error); 5112792Ssam break; 5212792Ssam 5316704Smckusick case UIO_SYSSPACE: 5437728Smckusick if (uio->uio_rw == UIO_READ) 5512792Ssam bcopy((caddr_t)cp, iov->iov_base, cnt); 5612792Ssam else 5712792Ssam bcopy(iov->iov_base, (caddr_t)cp, cnt); 5812792Ssam break; 5912792Ssam } 6012792Ssam iov->iov_base += cnt; 6112792Ssam iov->iov_len -= cnt; 6212792Ssam uio->uio_resid -= cnt; 6312792Ssam uio->uio_offset += cnt; 6412792Ssam cp += cnt; 6512792Ssam n -= cnt; 6612792Ssam } 6712792Ssam return (error); 6812792Ssam } 6912792Ssam 7012792Ssam /* 7112792Ssam * Give next character to user as result of read. 7212792Ssam */ 7312792Ssam ureadc(c, uio) 7412792Ssam register int c; 7512792Ssam register struct uio *uio; 7612792Ssam { 7712792Ssam register struct iovec *iov; 7812792Ssam 7912792Ssam again: 8057729Smckusick if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 8112792Ssam panic("ureadc"); 8212792Ssam iov = uio->uio_iov; 8357729Smckusick if (iov->iov_len == 0) { 8412792Ssam uio->uio_iovcnt--; 8512792Ssam uio->uio_iov++; 8612792Ssam goto again; 8712792Ssam } 8812792Ssam switch (uio->uio_segflg) { 8912792Ssam 9016704Smckusick case UIO_USERSPACE: 9112792Ssam if (subyte(iov->iov_base, c) < 0) 9212792Ssam return (EFAULT); 9312792Ssam break; 9412792Ssam 9516704Smckusick case UIO_SYSSPACE: 9612792Ssam *iov->iov_base = c; 9712792Ssam break; 9812792Ssam 9916704Smckusick case UIO_USERISPACE: 10012792Ssam if (suibyte(iov->iov_base, c) < 0) 10112792Ssam return (EFAULT); 10212792Ssam break; 10312792Ssam } 10412792Ssam iov->iov_base++; 10512792Ssam iov->iov_len--; 10612792Ssam uio->uio_resid--; 10712792Ssam uio->uio_offset++; 10812792Ssam return (0); 10912792Ssam } 11012792Ssam 11152497Storek #ifdef vax /* unused except by ct.c, other oddities XXX */ 11212792Ssam /* 11312792Ssam * Get next character written in by user from uio. 11412792Ssam */ 11512792Ssam uwritec(uio) 11612792Ssam struct uio *uio; 11712792Ssam { 11812792Ssam register struct iovec *iov; 11912792Ssam register int c; 12012792Ssam 12127235Skarels if (uio->uio_resid <= 0) 12227235Skarels return (-1); 12312792Ssam again: 12427235Skarels if (uio->uio_iovcnt <= 0) 12512792Ssam panic("uwritec"); 12612792Ssam iov = uio->uio_iov; 12712792Ssam if (iov->iov_len == 0) { 12812792Ssam uio->uio_iov++; 12927235Skarels if (--uio->uio_iovcnt == 0) 13027235Skarels return (-1); 13112792Ssam goto again; 13212792Ssam } 13312792Ssam switch (uio->uio_segflg) { 13412792Ssam 13516704Smckusick case UIO_USERSPACE: 13612792Ssam c = fubyte(iov->iov_base); 13712792Ssam break; 13812792Ssam 13916704Smckusick case UIO_SYSSPACE: 14047540Skarels c = *(u_char *) iov->iov_base; 14112792Ssam break; 14212792Ssam 14316704Smckusick case UIO_USERISPACE: 14412792Ssam c = fuibyte(iov->iov_base); 14512792Ssam break; 14612792Ssam } 14712792Ssam if (c < 0) 14812792Ssam return (-1); 14912792Ssam iov->iov_base++; 15012792Ssam iov->iov_len--; 15112792Ssam uio->uio_resid--; 15212792Ssam uio->uio_offset++; 15347540Skarels return (c); 15412792Ssam } 15552497Storek #endif /* vax */ 15655404Smckusick 15755404Smckusick /* 15855404Smckusick * General routine to allocate a hash table. 15955404Smckusick */ 16055404Smckusick void * 16155404Smckusick hashinit(elements, type, hashmask) 16255404Smckusick int elements, type; 16355404Smckusick u_long *hashmask; 16455404Smckusick { 16555404Smckusick long hashsize; 166*65257Smckusick LIST_HEAD(generic, generic) *hashtbl; 167*65257Smckusick int i; 16855404Smckusick 16955404Smckusick if (elements <= 0) 17055404Smckusick panic("hashinit: bad cnt"); 17155404Smckusick for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 17255404Smckusick continue; 17355404Smckusick hashsize >>= 1; 174*65257Smckusick hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 175*65257Smckusick for (i = 0; i < hashsize; i++) 176*65257Smckusick LIST_INIT(&hashtbl[i]); 17755404Smckusick *hashmask = hashsize - 1; 17855404Smckusick return (hashtbl); 17955404Smckusick } 180