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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 #include <sys/types.h> 36 #include <sys/param.h> 37 #include <sys/errno.h> 38 #include <st_pathname.h> 39 #include <sys/promif.h> 40 #include <sys/salib.h> 41 #include <sys/bootdebug.h> 42 43 /* 44 * Pathname utilities. 45 * 46 * In translating file names we copy each argument file 47 * name into a pathname structure where we operate on it. 48 * Each pathname structure can hold MAXPATHLEN characters 49 * including a terminating null, and operations here support 50 * fetching strings from user space, getting the next character from 51 * a pathname, combining two pathnames (used in symbolic 52 * link processing), and peeling off the first component 53 * of a pathname. 54 */ 55 56 #define dprintf if (boothowto & RB_DEBUG) printf 57 58 /* 59 * Setup contents of pathname structure. Warn about missing allocations. 60 * Structure itself is typically automatic 61 * variable in calling routine for convenience. 62 * 63 * NOTE: if buf is NULL, failure occurs. 64 */ 65 int 66 stpn_alloc(struct st_pathname *pnp) 67 { 68 if (pnp->pn_buf == NULL) 69 return (-1); 70 pnp->pn_path = (char *)pnp->pn_buf; 71 pnp->pn_pathlen = 0; 72 return (0); 73 } 74 75 /* 76 * Pull a pathname from user user or kernel space 77 */ 78 int 79 stpn_get(char *str, struct st_pathname *pnp) 80 { 81 if (stpn_alloc(pnp) != 0) 82 return (-1); 83 bcopy(str, pnp->pn_path, strlen(str)); 84 pnp->pn_pathlen = strlen(str); /* don't count null byte */ 85 return (0); 86 } 87 88 /* 89 * Set pathname to argument string. 90 */ 91 int 92 stpn_set(struct st_pathname *pnp, char *path) 93 { 94 pnp->pn_path = pnp->pn_buf; 95 pnp->pn_pathlen = strlen(pnp->pn_path); /* don't count null byte */ 96 bcopy(pnp->pn_path, path, pnp->pn_pathlen); 97 return (0); 98 } 99 100 /* 101 * Combine two argument pathnames by putting 102 * second argument before first in first's buffer, 103 * and freeing second argument. 104 * This isn't very general: it is designed specifically 105 * for symbolic link processing. 106 */ 107 int 108 stpn_combine(struct st_pathname *pnp, struct st_pathname *sympnp) 109 { 110 111 if (pnp->pn_pathlen + sympnp->pn_pathlen >= MAXPATHLEN) 112 return (ENAMETOOLONG); 113 bcopy(pnp->pn_path, pnp->pn_buf + sympnp->pn_pathlen, 114 (uint_t)pnp->pn_pathlen); 115 bcopy(sympnp->pn_path, pnp->pn_buf, (uint_t)sympnp->pn_pathlen); 116 pnp->pn_pathlen += sympnp->pn_pathlen; 117 pnp->pn_buf[pnp->pn_pathlen] = '\0'; 118 pnp->pn_path = pnp->pn_buf; 119 return (0); 120 } 121 122 /* 123 * Get next component off a pathname and leave in 124 * buffer comoponent which should have room for 125 * NFS_MAXNAMLEN (1024) bytes and a null terminator character. 126 * If PEEK is set in flags, just peek at the component, 127 * i.e., don't strip it out of pnp. 128 */ 129 int 130 stpn_getcomponent(struct st_pathname *pnp, char *component, int flags) 131 { 132 char *cp; 133 int l; 134 int n; 135 136 cp = pnp->pn_path; 137 l = pnp->pn_pathlen; 138 n = 1024; 139 while ((l > 0) && (*cp != '/')) { 140 if (--n < 0) 141 return (ENAMETOOLONG); 142 *component++ = *cp++; 143 --l; 144 } 145 if (!(flags & PN_PEEK)) { 146 pnp->pn_path = cp; 147 pnp->pn_pathlen = l; 148 } 149 *component = 0; 150 return (0); 151 } 152 153 /* 154 * skip over consecutive slashes in the pathname 155 */ 156 void 157 stpn_skipslash(struct st_pathname *pnp) 158 { 159 while ((pnp->pn_pathlen != 0) && (*pnp->pn_path == '/')) { 160 pnp->pn_path++; 161 pnp->pn_pathlen--; 162 } 163 } 164 165 /* 166 * free pathname resources. This is a nop - the user of these 167 * routines is responsible for allocating and freeing their memory. 168 */ 169 /*ARGSUSED*/ 170 void 171 stpn_free(struct st_pathname *pnp) 172 { 173 /* nop */ 174 dprintf("pn_free(): you shouldn't be calling pn_free()!\n"); 175 } 176