123375Smckusick /* 263176Sbostic * Copyright (c) 1982, 1986, 1991, 1993 363176Sbostic * The Regents of the University of California. All rights reserved. 4*65771Sbostic * (c) UNIX System Laboratories, Inc. 5*65771Sbostic * All or some portions of this file are derived from material licensed 6*65771Sbostic * to the University of California by American Telephone and Telegraph 7*65771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8*65771Sbostic * the permission of UNIX System Laboratories, Inc. 923375Smckusick * 1047540Skarels * %sccs.include.redist.c% 1147540Skarels * 12*65771Sbostic * @(#)kern_subr.c 8.3 (Berkeley) 01/21/94 1323375Smckusick */ 1412792Ssam 1556517Sbostic #include <sys/param.h> 1656517Sbostic #include <sys/systm.h> 1756517Sbostic #include <sys/proc.h> 1856517Sbostic #include <sys/malloc.h> 1965257Smckusick #include <sys/queue.h> 2012792Ssam 2137728Smckusick uiomove(cp, n, uio) 2212792Ssam register caddr_t cp; 2312792Ssam register int n; 2412792Ssam register struct uio *uio; 2512792Ssam { 2612792Ssam register struct iovec *iov; 2712792Ssam u_int cnt; 2812792Ssam int error = 0; 2912792Ssam 3048016Smckusick #ifdef DIAGNOSTIC 3137728Smckusick if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) 3237728Smckusick panic("uiomove: mode"); 3348016Smckusick if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 3448016Smckusick panic("uiomove proc"); 3548016Smckusick #endif 3612792Ssam while (n > 0 && uio->uio_resid) { 3712792Ssam iov = uio->uio_iov; 3812792Ssam cnt = iov->iov_len; 3912792Ssam if (cnt == 0) { 4012792Ssam uio->uio_iov++; 4112792Ssam uio->uio_iovcnt--; 4212792Ssam continue; 4312792Ssam } 4412792Ssam if (cnt > n) 4512792Ssam cnt = n; 4612792Ssam switch (uio->uio_segflg) { 4712792Ssam 4816704Smckusick case UIO_USERSPACE: 4916704Smckusick case UIO_USERISPACE: 5037728Smckusick if (uio->uio_rw == UIO_READ) 5112792Ssam error = copyout(cp, iov->iov_base, cnt); 5212792Ssam else 5312792Ssam error = copyin(iov->iov_base, cp, cnt); 5412792Ssam if (error) 5512792Ssam return (error); 5612792Ssam break; 5712792Ssam 5816704Smckusick case UIO_SYSSPACE: 5937728Smckusick if (uio->uio_rw == UIO_READ) 6012792Ssam bcopy((caddr_t)cp, iov->iov_base, cnt); 6112792Ssam else 6212792Ssam bcopy(iov->iov_base, (caddr_t)cp, cnt); 6312792Ssam break; 6412792Ssam } 6512792Ssam iov->iov_base += cnt; 6612792Ssam iov->iov_len -= cnt; 6712792Ssam uio->uio_resid -= cnt; 6812792Ssam uio->uio_offset += cnt; 6912792Ssam cp += cnt; 7012792Ssam n -= cnt; 7112792Ssam } 7212792Ssam return (error); 7312792Ssam } 7412792Ssam 7512792Ssam /* 7612792Ssam * Give next character to user as result of read. 7712792Ssam */ 7812792Ssam ureadc(c, uio) 7912792Ssam register int c; 8012792Ssam register struct uio *uio; 8112792Ssam { 8212792Ssam register struct iovec *iov; 8312792Ssam 8412792Ssam again: 8557729Smckusick if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 8612792Ssam panic("ureadc"); 8712792Ssam iov = uio->uio_iov; 8857729Smckusick if (iov->iov_len == 0) { 8912792Ssam uio->uio_iovcnt--; 9012792Ssam uio->uio_iov++; 9112792Ssam goto again; 9212792Ssam } 9312792Ssam switch (uio->uio_segflg) { 9412792Ssam 9516704Smckusick case UIO_USERSPACE: 9612792Ssam if (subyte(iov->iov_base, c) < 0) 9712792Ssam return (EFAULT); 9812792Ssam break; 9912792Ssam 10016704Smckusick case UIO_SYSSPACE: 10112792Ssam *iov->iov_base = c; 10212792Ssam break; 10312792Ssam 10416704Smckusick case UIO_USERISPACE: 10512792Ssam if (suibyte(iov->iov_base, c) < 0) 10612792Ssam return (EFAULT); 10712792Ssam break; 10812792Ssam } 10912792Ssam iov->iov_base++; 11012792Ssam iov->iov_len--; 11112792Ssam uio->uio_resid--; 11212792Ssam uio->uio_offset++; 11312792Ssam return (0); 11412792Ssam } 11512792Ssam 11652497Storek #ifdef vax /* unused except by ct.c, other oddities XXX */ 11712792Ssam /* 11812792Ssam * Get next character written in by user from uio. 11912792Ssam */ 12012792Ssam uwritec(uio) 12112792Ssam struct uio *uio; 12212792Ssam { 12312792Ssam register struct iovec *iov; 12412792Ssam register int c; 12512792Ssam 12627235Skarels if (uio->uio_resid <= 0) 12727235Skarels return (-1); 12812792Ssam again: 12927235Skarels if (uio->uio_iovcnt <= 0) 13012792Ssam panic("uwritec"); 13112792Ssam iov = uio->uio_iov; 13212792Ssam if (iov->iov_len == 0) { 13312792Ssam uio->uio_iov++; 13427235Skarels if (--uio->uio_iovcnt == 0) 13527235Skarels return (-1); 13612792Ssam goto again; 13712792Ssam } 13812792Ssam switch (uio->uio_segflg) { 13912792Ssam 14016704Smckusick case UIO_USERSPACE: 14112792Ssam c = fubyte(iov->iov_base); 14212792Ssam break; 14312792Ssam 14416704Smckusick case UIO_SYSSPACE: 14547540Skarels c = *(u_char *) iov->iov_base; 14612792Ssam break; 14712792Ssam 14816704Smckusick case UIO_USERISPACE: 14912792Ssam c = fuibyte(iov->iov_base); 15012792Ssam break; 15112792Ssam } 15212792Ssam if (c < 0) 15312792Ssam return (-1); 15412792Ssam iov->iov_base++; 15512792Ssam iov->iov_len--; 15612792Ssam uio->uio_resid--; 15712792Ssam uio->uio_offset++; 15847540Skarels return (c); 15912792Ssam } 16052497Storek #endif /* vax */ 16155404Smckusick 16255404Smckusick /* 16355404Smckusick * General routine to allocate a hash table. 16455404Smckusick */ 16555404Smckusick void * 16655404Smckusick hashinit(elements, type, hashmask) 16755404Smckusick int elements, type; 16855404Smckusick u_long *hashmask; 16955404Smckusick { 17055404Smckusick long hashsize; 17165257Smckusick LIST_HEAD(generic, generic) *hashtbl; 17265257Smckusick int i; 17355404Smckusick 17455404Smckusick if (elements <= 0) 17555404Smckusick panic("hashinit: bad cnt"); 17655404Smckusick for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 17755404Smckusick continue; 17855404Smckusick hashsize >>= 1; 17965257Smckusick hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 18065257Smckusick for (i = 0; i < hashsize; i++) 18165257Smckusick LIST_INIT(&hashtbl[i]); 18255404Smckusick *hashmask = hashsize - 1; 18355404Smckusick return (hashtbl); 18455404Smckusick } 185