123375Smckusick /*
263176Sbostic * Copyright (c) 1982, 1986, 1991, 1993
363176Sbostic * The Regents of the University of California. All rights reserved.
465771Sbostic * (c) UNIX System Laboratories, Inc.
565771Sbostic * All or some portions of this file are derived from material licensed
665771Sbostic * to the University of California by American Telephone and Telegraph
765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with
865771Sbostic * the permission of UNIX System Laboratories, Inc.
923375Smckusick *
1047540Skarels * %sccs.include.redist.c%
1147540Skarels *
12*68304Scgd * @(#)kern_subr.c 8.4 (Berkeley) 02/14/95
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
21*68304Scgd int
uiomove(cp,n,uio)2237728Smckusick uiomove(cp, n, uio)
2312792Ssam register caddr_t cp;
2412792Ssam register int n;
2512792Ssam register struct uio *uio;
2612792Ssam {
2712792Ssam register struct iovec *iov;
2812792Ssam u_int cnt;
2912792Ssam int error = 0;
3012792Ssam
3148016Smckusick #ifdef DIAGNOSTIC
3237728Smckusick if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
3337728Smckusick panic("uiomove: mode");
3448016Smckusick if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc)
3548016Smckusick panic("uiomove proc");
3648016Smckusick #endif
3712792Ssam while (n > 0 && uio->uio_resid) {
3812792Ssam iov = uio->uio_iov;
3912792Ssam cnt = iov->iov_len;
4012792Ssam if (cnt == 0) {
4112792Ssam uio->uio_iov++;
4212792Ssam uio->uio_iovcnt--;
4312792Ssam continue;
4412792Ssam }
4512792Ssam if (cnt > n)
4612792Ssam cnt = n;
4712792Ssam switch (uio->uio_segflg) {
4812792Ssam
4916704Smckusick case UIO_USERSPACE:
5016704Smckusick case UIO_USERISPACE:
5137728Smckusick if (uio->uio_rw == UIO_READ)
5212792Ssam error = copyout(cp, iov->iov_base, cnt);
5312792Ssam else
5412792Ssam error = copyin(iov->iov_base, cp, cnt);
5512792Ssam if (error)
5612792Ssam return (error);
5712792Ssam break;
5812792Ssam
5916704Smckusick case UIO_SYSSPACE:
6037728Smckusick if (uio->uio_rw == UIO_READ)
6112792Ssam bcopy((caddr_t)cp, iov->iov_base, cnt);
6212792Ssam else
6312792Ssam bcopy(iov->iov_base, (caddr_t)cp, cnt);
6412792Ssam break;
6512792Ssam }
6612792Ssam iov->iov_base += cnt;
6712792Ssam iov->iov_len -= cnt;
6812792Ssam uio->uio_resid -= cnt;
6912792Ssam uio->uio_offset += cnt;
7012792Ssam cp += cnt;
7112792Ssam n -= cnt;
7212792Ssam }
7312792Ssam return (error);
7412792Ssam }
7512792Ssam
7612792Ssam /*
7712792Ssam * Give next character to user as result of read.
7812792Ssam */
79*68304Scgd int
ureadc(c,uio)8012792Ssam ureadc(c, uio)
8112792Ssam register int c;
8212792Ssam register struct uio *uio;
8312792Ssam {
8412792Ssam register struct iovec *iov;
8512792Ssam
86*68304Scgd if (uio->uio_resid <= 0)
87*68304Scgd panic("ureadc: non-positive resid");
8812792Ssam again:
89*68304Scgd if (uio->uio_iovcnt <= 0)
90*68304Scgd panic("ureadc: non-positive iovcnt");
9112792Ssam iov = uio->uio_iov;
92*68304Scgd if (iov->iov_len <= 0) {
9312792Ssam uio->uio_iovcnt--;
9412792Ssam uio->uio_iov++;
9512792Ssam goto again;
9612792Ssam }
9712792Ssam switch (uio->uio_segflg) {
9812792Ssam
9916704Smckusick case UIO_USERSPACE:
10012792Ssam if (subyte(iov->iov_base, c) < 0)
10112792Ssam return (EFAULT);
10212792Ssam break;
10312792Ssam
10416704Smckusick case UIO_SYSSPACE:
10512792Ssam *iov->iov_base = c;
10612792Ssam break;
10712792Ssam
10816704Smckusick case UIO_USERISPACE:
10912792Ssam if (suibyte(iov->iov_base, c) < 0)
11012792Ssam return (EFAULT);
11112792Ssam break;
11212792Ssam }
11312792Ssam iov->iov_base++;
11412792Ssam iov->iov_len--;
11512792Ssam uio->uio_resid--;
11612792Ssam uio->uio_offset++;
11712792Ssam return (0);
11812792Ssam }
11912792Ssam
12052497Storek #ifdef vax /* unused except by ct.c, other oddities XXX */
12112792Ssam /*
12212792Ssam * Get next character written in by user from uio.
12312792Ssam */
124*68304Scgd int
uwritec(uio)12512792Ssam uwritec(uio)
12612792Ssam struct uio *uio;
12712792Ssam {
12812792Ssam register struct iovec *iov;
12912792Ssam register int c;
13012792Ssam
13127235Skarels if (uio->uio_resid <= 0)
13227235Skarels return (-1);
13312792Ssam again:
13427235Skarels if (uio->uio_iovcnt <= 0)
135*68304Scgd panic("uwritec: non-positive iovcnt");
13612792Ssam iov = uio->uio_iov;
13712792Ssam if (iov->iov_len == 0) {
13812792Ssam uio->uio_iov++;
13927235Skarels if (--uio->uio_iovcnt == 0)
14027235Skarels return (-1);
14112792Ssam goto again;
14212792Ssam }
14312792Ssam switch (uio->uio_segflg) {
14412792Ssam
14516704Smckusick case UIO_USERSPACE:
14612792Ssam c = fubyte(iov->iov_base);
14712792Ssam break;
14812792Ssam
14916704Smckusick case UIO_SYSSPACE:
15047540Skarels c = *(u_char *) iov->iov_base;
15112792Ssam break;
15212792Ssam
15316704Smckusick case UIO_USERISPACE:
15412792Ssam c = fuibyte(iov->iov_base);
15512792Ssam break;
15612792Ssam }
15712792Ssam if (c < 0)
15812792Ssam return (-1);
15912792Ssam iov->iov_base++;
16012792Ssam iov->iov_len--;
16112792Ssam uio->uio_resid--;
16212792Ssam uio->uio_offset++;
16347540Skarels return (c);
16412792Ssam }
16552497Storek #endif /* vax */
16655404Smckusick
16755404Smckusick /*
16855404Smckusick * General routine to allocate a hash table.
16955404Smckusick */
17055404Smckusick void *
hashinit(elements,type,hashmask)17155404Smckusick hashinit(elements, type, hashmask)
17255404Smckusick int elements, type;
17355404Smckusick u_long *hashmask;
17455404Smckusick {
17555404Smckusick long hashsize;
17665257Smckusick LIST_HEAD(generic, generic) *hashtbl;
17765257Smckusick int i;
17855404Smckusick
17955404Smckusick if (elements <= 0)
18055404Smckusick panic("hashinit: bad cnt");
18155404Smckusick for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
18255404Smckusick continue;
18355404Smckusick hashsize >>= 1;
18465257Smckusick hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
18565257Smckusick for (i = 0; i < hashsize; i++)
18665257Smckusick LIST_INIT(&hashtbl[i]);
18755404Smckusick *hashmask = hashsize - 1;
18855404Smckusick return (hashtbl);
18955404Smckusick }
190