1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Miscellaneous C routines for copying data around without 29 * descending into assembler. Compilers are pretty good at 30 * scheduling instructions, and humans are pretty hopeless at 31 * writing correct assembler. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/systm.h> 36 #include <sys/errno.h> 37 #include <sys/param.h> 38 39 /* 40 * copyinstr_noerr and copyoutstr_noerr can be implemented completely 41 * in C on machines with shared user and kernel context. 42 */ 43 static int 44 copystr_nofault(const char *src, char *dst, size_t maxlength, 45 size_t *lencopied) 46 { 47 int error = 0; 48 size_t leftover; 49 50 if ((leftover = maxlength) == 0) 51 error = ENAMETOOLONG; 52 else 53 do { 54 leftover--; 55 if ((*dst++ = *src++) == '\0') 56 break; 57 if (leftover == 0) { 58 error = ENAMETOOLONG; 59 break; 60 } 61 /*CONSTCOND*/ 62 } while (1); 63 64 if (lencopied) 65 *lencopied = maxlength - leftover; 66 return (error); 67 } 68 69 70 int 71 copyinstr_noerr(const char *uaddr, char *kaddr, size_t maxlength, 72 size_t *lencopied) 73 { 74 char *ua = (char *)uaddr; 75 76 ASSERT((uintptr_t)kaddr > kernelbase); 77 78 if ((uintptr_t)ua > kernelbase) { 79 /* 80 * force fault at kernelbase 81 */ 82 ua = (char *)kernelbase; 83 } 84 return (copystr_nofault(ua, kaddr, maxlength, lencopied)); 85 } 86 87 int 88 copyoutstr_noerr(const char *kaddr, char *uaddr, size_t maxlength, 89 size_t *lencopied) 90 { 91 char *ua = (char *)uaddr; 92 93 ASSERT((uintptr_t)kaddr > kernelbase); 94 95 if ((uintptr_t)ua > kernelbase) { 96 /* 97 * force fault at kernelbase 98 */ 99 ua = (char *)kernelbase; 100 } 101 return (copystr_nofault(kaddr, ua, maxlength, lencopied)); 102 } 103