xref: /illumos-gate/usr/src/stand/lib/fs/nfs/pathname.c (revision 71269a2275bf5a143dad6461eee2710a344e7261)
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 /* 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
36 
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/errno.h>
40 #include <pathname.h>
41 #include <sys/promif.h>
42 #include <sys/salib.h>
43 #include <sys/bootdebug.h>
44 
45 /*
46  * Pathname utilities.
47  *
48  * In translating file names we copy each argument file
49  * name into a pathname structure where we operate on it.
50  * Each pathname structure can hold MAXPATHLEN characters
51  * including a terminating null, and operations here support
52  * fetching strings from user space, getting the next character from
53  * a pathname, combining two pathnames (used in symbolic
54  * link processing), and peeling off the first component
55  * of a pathname.
56  */
57 
58 #define	dprintf	if (boothowto & RB_DEBUG) printf
59 
60 /*
61  * Setup contents of pathname structure. Warn about missing allocations.
62  * Structure itself is typically automatic
63  * variable in calling routine for convenience.
64  *
65  * NOTE: if buf is NULL, failure occurs.
66  */
67 int
68 pn_alloc(struct pathname *pnp)
69 {
70 	if (pnp->pn_buf == NULL)
71 		return (-1);
72 	pnp->pn_path = (char *)pnp->pn_buf;
73 	pnp->pn_pathlen = 0;
74 	return (0);
75 }
76 
77 /*
78  * Pull a pathname from user user or kernel space
79  */
80 int
81 pn_get(char *str, struct pathname *pnp)
82 {
83 	if (pn_alloc(pnp) != 0)
84 		return (-1);
85 	bcopy(str, pnp->pn_path, strlen(str));
86 	pnp->pn_pathlen = strlen(str);		/* don't count null byte */
87 	return (0);
88 }
89 
90 /*
91  * Set pathname to argument string.
92  */
93 int
94 pn_set(struct pathname *pnp, char *path)
95 {
96 	pnp->pn_path = pnp->pn_buf;
97 	pnp->pn_pathlen = strlen(pnp->pn_path); /* don't count null byte */
98 	bcopy(pnp->pn_path, path, pnp->pn_pathlen);
99 	return (0);
100 }
101 
102 /*
103  * Combine two argument pathnames by putting
104  * second argument before first in first's buffer,
105  * and freeing second argument.
106  * This isn't very general: it is designed specifically
107  * for symbolic link processing.
108  */
109 int
110 pn_combine(struct pathname *pnp, struct pathname *sympnp)
111 {
112 
113 	if (pnp->pn_pathlen + sympnp->pn_pathlen >= MAXPATHLEN)
114 		return (ENAMETOOLONG);
115 	bcopy(pnp->pn_path, pnp->pn_buf + sympnp->pn_pathlen,
116 	    (uint_t)pnp->pn_pathlen);
117 	bcopy(sympnp->pn_path, pnp->pn_buf, (uint_t)sympnp->pn_pathlen);
118 	pnp->pn_pathlen += sympnp->pn_pathlen;
119 	pnp->pn_buf[pnp->pn_pathlen] = '\0';
120 	pnp->pn_path = pnp->pn_buf;
121 	return (0);
122 }
123 
124 /*
125  * Get next component off a pathname and leave in
126  * buffer comoponent which should have room for
127  * NFS_MAXNAMLEN (1024) bytes and a null terminator character.
128  * If PEEK is set in flags, just peek at the component,
129  * i.e., don't strip it out of pnp.
130  */
131 int
132 pn_getcomponent(struct pathname *pnp, char *component, int flags)
133 {
134 	char *cp;
135 	int l;
136 	int n;
137 
138 	cp = pnp->pn_path;
139 	l = pnp->pn_pathlen;
140 	n = 1024;
141 	while ((l > 0) && (*cp != '/')) {
142 		if (--n < 0)
143 			return (ENAMETOOLONG);
144 		*component++ = *cp++;
145 		--l;
146 	}
147 	if (!(flags & PN_PEEK)) {
148 		pnp->pn_path = cp;
149 		pnp->pn_pathlen = l;
150 	}
151 	*component = 0;
152 	return (0);
153 }
154 
155 /*
156  * skip over consecutive slashes in the pathname
157  */
158 void
159 pn_skipslash(struct pathname *pnp)
160 {
161 	while ((pnp->pn_pathlen != 0) && (*pnp->pn_path == '/')) {
162 		pnp->pn_path++;
163 		pnp->pn_pathlen--;
164 	}
165 }
166 
167 /*
168  * free pathname resources. This is a nop - the user of these
169  * routines is responsible for allocating and freeing their memory.
170  */
171 /*ARGSUSED*/
172 void
173 pn_free(struct pathname *pnp)
174 {
175 	/* nop */
176 	dprintf("pn_free(): you shouldn't be calling pn_free()!\n");
177 }
178