1 /* 2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_subr.c 8.1 (Berkeley) 06/10/93 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/proc.h> 13 #include <sys/malloc.h> 14 15 uiomove(cp, n, uio) 16 register caddr_t cp; 17 register int n; 18 register struct uio *uio; 19 { 20 register struct iovec *iov; 21 u_int cnt; 22 int error = 0; 23 24 #ifdef DIAGNOSTIC 25 if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) 26 panic("uiomove: mode"); 27 if (uio->uio_segflg == UIO_USERSPACE && uio->uio_procp != curproc) 28 panic("uiomove proc"); 29 #endif 30 while (n > 0 && uio->uio_resid) { 31 iov = uio->uio_iov; 32 cnt = iov->iov_len; 33 if (cnt == 0) { 34 uio->uio_iov++; 35 uio->uio_iovcnt--; 36 continue; 37 } 38 if (cnt > n) 39 cnt = n; 40 switch (uio->uio_segflg) { 41 42 case UIO_USERSPACE: 43 case UIO_USERISPACE: 44 if (uio->uio_rw == UIO_READ) 45 error = copyout(cp, iov->iov_base, cnt); 46 else 47 error = copyin(iov->iov_base, cp, cnt); 48 if (error) 49 return (error); 50 break; 51 52 case UIO_SYSSPACE: 53 if (uio->uio_rw == UIO_READ) 54 bcopy((caddr_t)cp, iov->iov_base, cnt); 55 else 56 bcopy(iov->iov_base, (caddr_t)cp, cnt); 57 break; 58 } 59 iov->iov_base += cnt; 60 iov->iov_len -= cnt; 61 uio->uio_resid -= cnt; 62 uio->uio_offset += cnt; 63 cp += cnt; 64 n -= cnt; 65 } 66 return (error); 67 } 68 69 /* 70 * Give next character to user as result of read. 71 */ 72 ureadc(c, uio) 73 register int c; 74 register struct uio *uio; 75 { 76 register struct iovec *iov; 77 78 again: 79 if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 80 panic("ureadc"); 81 iov = uio->uio_iov; 82 if (iov->iov_len == 0) { 83 uio->uio_iovcnt--; 84 uio->uio_iov++; 85 goto again; 86 } 87 switch (uio->uio_segflg) { 88 89 case UIO_USERSPACE: 90 if (subyte(iov->iov_base, c) < 0) 91 return (EFAULT); 92 break; 93 94 case UIO_SYSSPACE: 95 *iov->iov_base = c; 96 break; 97 98 case UIO_USERISPACE: 99 if (suibyte(iov->iov_base, c) < 0) 100 return (EFAULT); 101 break; 102 } 103 iov->iov_base++; 104 iov->iov_len--; 105 uio->uio_resid--; 106 uio->uio_offset++; 107 return (0); 108 } 109 110 #ifdef vax /* unused except by ct.c, other oddities XXX */ 111 /* 112 * Get next character written in by user from uio. 113 */ 114 uwritec(uio) 115 struct uio *uio; 116 { 117 register struct iovec *iov; 118 register int c; 119 120 if (uio->uio_resid <= 0) 121 return (-1); 122 again: 123 if (uio->uio_iovcnt <= 0) 124 panic("uwritec"); 125 iov = uio->uio_iov; 126 if (iov->iov_len == 0) { 127 uio->uio_iov++; 128 if (--uio->uio_iovcnt == 0) 129 return (-1); 130 goto again; 131 } 132 switch (uio->uio_segflg) { 133 134 case UIO_USERSPACE: 135 c = fubyte(iov->iov_base); 136 break; 137 138 case UIO_SYSSPACE: 139 c = *(u_char *) iov->iov_base; 140 break; 141 142 case UIO_USERISPACE: 143 c = fuibyte(iov->iov_base); 144 break; 145 } 146 if (c < 0) 147 return (-1); 148 iov->iov_base++; 149 iov->iov_len--; 150 uio->uio_resid--; 151 uio->uio_offset++; 152 return (c); 153 } 154 #endif /* vax */ 155 156 /* 157 * General routine to allocate a hash table. 158 */ 159 void * 160 hashinit(elements, type, hashmask) 161 int elements, type; 162 u_long *hashmask; 163 { 164 long hashsize; 165 void *hashtbl; 166 167 if (elements <= 0) 168 panic("hashinit: bad cnt"); 169 for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 170 continue; 171 hashsize >>= 1; 172 hashtbl = malloc((u_long)hashsize * sizeof(void *), type, M_WAITOK); 173 bzero(hashtbl, hashsize * sizeof(void *)); 174 *hashmask = hashsize - 1; 175 return (hashtbl); 176 } 177