1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* 31*0Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*0Sstevel@tonic-gate * The Regents of the University of California 33*0Sstevel@tonic-gate * All Rights Reserved 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*0Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*0Sstevel@tonic-gate * contributors. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #include <sys/types.h> 43*0Sstevel@tonic-gate #include <sys/sysmacros.h> 44*0Sstevel@tonic-gate #include <sys/param.h> 45*0Sstevel@tonic-gate #include <sys/systm.h> 46*0Sstevel@tonic-gate #include <sys/uio.h> 47*0Sstevel@tonic-gate #include <sys/errno.h> 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* 50*0Sstevel@tonic-gate * Move "n" bytes at byte address "p"; "rw" indicates the direction 51*0Sstevel@tonic-gate * of the move, and the I/O parameters are provided in "uio", which is 52*0Sstevel@tonic-gate * update to reflect the data which was moved. Returns 0 on success or 53*0Sstevel@tonic-gate * a non-zero errno on failure. 54*0Sstevel@tonic-gate */ 55*0Sstevel@tonic-gate int 56*0Sstevel@tonic-gate uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio) 57*0Sstevel@tonic-gate { 58*0Sstevel@tonic-gate struct iovec *iov; 59*0Sstevel@tonic-gate ulong_t cnt; 60*0Sstevel@tonic-gate int error; 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate while (n && uio->uio_resid) { 63*0Sstevel@tonic-gate iov = uio->uio_iov; 64*0Sstevel@tonic-gate cnt = MIN(iov->iov_len, n); 65*0Sstevel@tonic-gate if (cnt == 0l) { 66*0Sstevel@tonic-gate uio->uio_iov++; 67*0Sstevel@tonic-gate uio->uio_iovcnt--; 68*0Sstevel@tonic-gate continue; 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate switch (uio->uio_segflg) { 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate case UIO_USERSPACE: 73*0Sstevel@tonic-gate case UIO_USERISPACE: 74*0Sstevel@tonic-gate if (rw == UIO_READ) { 75*0Sstevel@tonic-gate error = xcopyout_nta(p, iov->iov_base, cnt, 76*0Sstevel@tonic-gate (uio->uio_extflg & UIO_COPY_CACHED)); 77*0Sstevel@tonic-gate } else { 78*0Sstevel@tonic-gate error = xcopyin_nta(iov->iov_base, p, cnt, 79*0Sstevel@tonic-gate (uio->uio_extflg & UIO_COPY_CACHED)); 80*0Sstevel@tonic-gate } 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate if (error) 83*0Sstevel@tonic-gate return (error); 84*0Sstevel@tonic-gate break; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate case UIO_SYSSPACE: 87*0Sstevel@tonic-gate if (rw == UIO_READ) 88*0Sstevel@tonic-gate error = kcopy_nta(p, iov->iov_base, cnt, 89*0Sstevel@tonic-gate (uio->uio_extflg & UIO_COPY_CACHED)); 90*0Sstevel@tonic-gate else 91*0Sstevel@tonic-gate error = kcopy_nta(iov->iov_base, p, cnt, 92*0Sstevel@tonic-gate (uio->uio_extflg & UIO_COPY_CACHED)); 93*0Sstevel@tonic-gate if (error) 94*0Sstevel@tonic-gate return (error); 95*0Sstevel@tonic-gate break; 96*0Sstevel@tonic-gate } 97*0Sstevel@tonic-gate iov->iov_base += cnt; 98*0Sstevel@tonic-gate iov->iov_len -= cnt; 99*0Sstevel@tonic-gate uio->uio_resid -= cnt; 100*0Sstevel@tonic-gate uio->uio_loffset += cnt; 101*0Sstevel@tonic-gate p = (caddr_t)p + cnt; 102*0Sstevel@tonic-gate n -= cnt; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate return (0); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate /* 108*0Sstevel@tonic-gate * transfer a character value into the address space 109*0Sstevel@tonic-gate * delineated by a uio and update fields within the 110*0Sstevel@tonic-gate * uio for next character. Return 0 for success, EFAULT 111*0Sstevel@tonic-gate * for error. 112*0Sstevel@tonic-gate */ 113*0Sstevel@tonic-gate int 114*0Sstevel@tonic-gate ureadc(int val, struct uio *uiop) 115*0Sstevel@tonic-gate { 116*0Sstevel@tonic-gate struct iovec *iovp; 117*0Sstevel@tonic-gate unsigned char c; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * first determine if uio is valid. uiop should be 121*0Sstevel@tonic-gate * non-NULL and the resid count > 0. 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate if (!(uiop && uiop->uio_resid > 0)) 124*0Sstevel@tonic-gate return (EFAULT); 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate /* 127*0Sstevel@tonic-gate * scan through iovecs until one is found that is non-empty. 128*0Sstevel@tonic-gate * Return EFAULT if none found. 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate while (uiop->uio_iovcnt > 0) { 131*0Sstevel@tonic-gate iovp = uiop->uio_iov; 132*0Sstevel@tonic-gate if (iovp->iov_len <= 0) { 133*0Sstevel@tonic-gate uiop->uio_iovcnt--; 134*0Sstevel@tonic-gate uiop->uio_iov++; 135*0Sstevel@tonic-gate } else 136*0Sstevel@tonic-gate break; 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate if (uiop->uio_iovcnt <= 0) 140*0Sstevel@tonic-gate return (EFAULT); 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * Transfer character to uio space. 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate c = (unsigned char) (val & 0xFF); 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate switch (uiop->uio_segflg) { 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate case UIO_USERISPACE: 151*0Sstevel@tonic-gate case UIO_USERSPACE: 152*0Sstevel@tonic-gate if (copyout(&c, iovp->iov_base, sizeof (unsigned char))) 153*0Sstevel@tonic-gate return (EFAULT); 154*0Sstevel@tonic-gate break; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate case UIO_SYSSPACE: /* can do direct copy since kernel-kernel */ 157*0Sstevel@tonic-gate *iovp->iov_base = c; 158*0Sstevel@tonic-gate break; 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate default: 161*0Sstevel@tonic-gate return (EFAULT); /* invalid segflg value */ 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* 165*0Sstevel@tonic-gate * bump up/down iovec and uio members to reflect transfer. 166*0Sstevel@tonic-gate */ 167*0Sstevel@tonic-gate iovp->iov_base++; 168*0Sstevel@tonic-gate iovp->iov_len--; 169*0Sstevel@tonic-gate uiop->uio_resid--; 170*0Sstevel@tonic-gate uiop->uio_loffset++; 171*0Sstevel@tonic-gate return (0); /* success */ 172*0Sstevel@tonic-gate } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* 175*0Sstevel@tonic-gate * return a character value from the address space 176*0Sstevel@tonic-gate * delineated by a uio and update fields within the 177*0Sstevel@tonic-gate * uio for next character. Return the character for success, 178*0Sstevel@tonic-gate * -1 for error. 179*0Sstevel@tonic-gate */ 180*0Sstevel@tonic-gate int 181*0Sstevel@tonic-gate uwritec(struct uio *uiop) 182*0Sstevel@tonic-gate { 183*0Sstevel@tonic-gate struct iovec *iovp; 184*0Sstevel@tonic-gate unsigned char c; 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate /* 187*0Sstevel@tonic-gate * verify we were passed a valid uio structure. 188*0Sstevel@tonic-gate * (1) non-NULL uiop, (2) positive resid count 189*0Sstevel@tonic-gate * (3) there is an iovec with positive length 190*0Sstevel@tonic-gate */ 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate if (!(uiop && uiop->uio_resid > 0)) 193*0Sstevel@tonic-gate return (-1); 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate while (uiop->uio_iovcnt > 0) { 196*0Sstevel@tonic-gate iovp = uiop->uio_iov; 197*0Sstevel@tonic-gate if (iovp->iov_len <= 0) { 198*0Sstevel@tonic-gate uiop->uio_iovcnt--; 199*0Sstevel@tonic-gate uiop->uio_iov++; 200*0Sstevel@tonic-gate } else 201*0Sstevel@tonic-gate break; 202*0Sstevel@tonic-gate } 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate if (uiop->uio_iovcnt <= 0) 205*0Sstevel@tonic-gate return (-1); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate /* 208*0Sstevel@tonic-gate * Get the character from the uio address space. 209*0Sstevel@tonic-gate */ 210*0Sstevel@tonic-gate switch (uiop->uio_segflg) { 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate case UIO_USERISPACE: 213*0Sstevel@tonic-gate case UIO_USERSPACE: 214*0Sstevel@tonic-gate if (copyin(iovp->iov_base, &c, sizeof (unsigned char))) 215*0Sstevel@tonic-gate return (-1); 216*0Sstevel@tonic-gate break; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate case UIO_SYSSPACE: 219*0Sstevel@tonic-gate c = *iovp->iov_base; 220*0Sstevel@tonic-gate break; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate default: 223*0Sstevel@tonic-gate return (-1); /* invalid segflg */ 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate /* 227*0Sstevel@tonic-gate * Adjust fields of iovec and uio appropriately. 228*0Sstevel@tonic-gate */ 229*0Sstevel@tonic-gate iovp->iov_base++; 230*0Sstevel@tonic-gate iovp->iov_len--; 231*0Sstevel@tonic-gate uiop->uio_resid--; 232*0Sstevel@tonic-gate uiop->uio_loffset++; 233*0Sstevel@tonic-gate return ((int)c & 0xFF); /* success */ 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate /* 237*0Sstevel@tonic-gate * Drop the next n chars out of *uiop. 238*0Sstevel@tonic-gate */ 239*0Sstevel@tonic-gate void 240*0Sstevel@tonic-gate uioskip(uio_t *uiop, size_t n) 241*0Sstevel@tonic-gate { 242*0Sstevel@tonic-gate if (n > uiop->uio_resid) 243*0Sstevel@tonic-gate return; 244*0Sstevel@tonic-gate while (n != 0) { 245*0Sstevel@tonic-gate register iovec_t *iovp = uiop->uio_iov; 246*0Sstevel@tonic-gate register size_t niovb = MIN(iovp->iov_len, n); 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (niovb == 0) { 249*0Sstevel@tonic-gate uiop->uio_iov++; 250*0Sstevel@tonic-gate uiop->uio_iovcnt--; 251*0Sstevel@tonic-gate continue; 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate iovp->iov_base += niovb; 254*0Sstevel@tonic-gate uiop->uio_loffset += niovb; 255*0Sstevel@tonic-gate iovp->iov_len -= niovb; 256*0Sstevel@tonic-gate uiop->uio_resid -= niovb; 257*0Sstevel@tonic-gate n -= niovb; 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * Dup the suio into the duio and diovec of size diov_cnt. If diov 263*0Sstevel@tonic-gate * is too small to dup suio then an error will be returned, else 0. 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate int 266*0Sstevel@tonic-gate uiodup(uio_t *suio, uio_t *duio, iovec_t *diov, int diov_cnt) 267*0Sstevel@tonic-gate { 268*0Sstevel@tonic-gate int ix; 269*0Sstevel@tonic-gate iovec_t *siov = suio->uio_iov; 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate *duio = *suio; 272*0Sstevel@tonic-gate for (ix = 0; ix < suio->uio_iovcnt; ix++) { 273*0Sstevel@tonic-gate diov[ix] = siov[ix]; 274*0Sstevel@tonic-gate if (ix >= diov_cnt) 275*0Sstevel@tonic-gate return (1); 276*0Sstevel@tonic-gate } 277*0Sstevel@tonic-gate duio->uio_iov = diov; 278*0Sstevel@tonic-gate return (0); 279*0Sstevel@tonic-gate } 280