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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 
27 
28 /*
29  * System includes
30  */
31 
32 #include <stdio.h>
33 #include <limits.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <libgen.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <fcntl.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <signal.h>
43 #include <assert.h>
44 #include <locale.h>
45 #include <libintl.h>
46 
47 /*
48  * local includes
49  */
50 
51 #include "instzones_lib.h"
52 #include "zones_strings.h"
53 
54 #define	isdot(x)	((x[0] == '.') && (!x[1] || (x[1] == '/')))
55 #define	isdotdot(x)	((x[0] == '.') && (x[1] == '.') && \
56 		    (!x[2] || (x[2] == '/')))
57 
58 /*
59  * *****************************************************************************
60  * global external (public) functions
61  * *****************************************************************************
62  */
63 
64 /*
65  * Name:	z_make_zone_root
66  * Description:	Given its zonepath, generate a string representing the
67  *              mountpoint of where the root path for a nonglobal zone is
68  *              mounted.  The zone is mounted using 'zoneadm', which mounts
69  *              the zone's filesystems wrt <zonepath>/lu/a
70  * Arguments:	zone_path - non-NULL pointer to string representing zonepath
71  * Returns:	char *	- pointer to string representing zonepath of zone
72  *		NULL	- if zone_path is NULL.
73  * Notes:	The string returned is in static storage and should not be
74  *              free()ed by the caller.
75  */
76 char *
z_make_zone_root(char * zone_path)77 z_make_zone_root(char *zone_path)
78 {
79 	static char	zone_root_buf[MAXPATHLEN];
80 
81 	if (zone_path == NULL)
82 		return (NULL);
83 
84 	(void) snprintf(zone_root_buf, MAXPATHLEN, "%s%slu/a", zone_path,
85 	    (zone_path[0] != '\0' &&
86 	    zone_path[strlen(zone_path) - 1] == '/') ? "" : "/");
87 
88 	return (zone_root_buf);
89 }
90 
91 void
z_path_canonize(char * a_file)92 z_path_canonize(char *a_file)
93 {
94 	char	*pt;
95 	char	*last;
96 	int	level;
97 
98 	/* remove references such as "./" and "../" and "//" */
99 	for (pt = a_file; *pt; /* void */) {
100 		if (isdot(pt)) {
101 			(void) strcpy(pt, pt[1] ? pt+2 : pt+1);
102 		} else if (isdotdot(pt)) {
103 			level = 0;
104 			last = pt;
105 			do {
106 				level++;
107 				last += 2;
108 				if (*last) {
109 					last++;
110 				}
111 			} while (isdotdot(last));
112 			--pt; /* point to previous '/' */
113 			while (level--) {
114 				if (pt <= a_file) {
115 					return;
116 				}
117 				while ((*--pt != '/') && (pt > a_file))
118 					;
119 			}
120 			if (*pt == '/') {
121 				pt++;
122 			}
123 			(void) strcpy(pt, last);
124 		} else {
125 			while (*pt && (*pt != '/')) {
126 				pt++;
127 			}
128 			if (*pt == '/') {
129 				while (pt[1] == '/') {
130 					(void) strcpy(pt, pt+1);
131 				}
132 				pt++;
133 			}
134 		}
135 	}
136 
137 	if ((--pt > a_file) && (*pt == '/')) {
138 		*pt = '\0';
139 	}
140 }
141 
142 void
z_canoninplace(char * src)143 z_canoninplace(char *src)
144 {
145 	char *dst;
146 	char *src_start;
147 
148 	/* keep a ptr to the beginning of the src string */
149 	src_start = src;
150 
151 	dst = src;
152 	while (*src) {
153 		if (*src == '/') {
154 			*dst++ = '/';
155 			while (*src == '/')
156 				src++;
157 		} else
158 			*dst++ = *src++;
159 	}
160 
161 	/*
162 	 * remove any trailing slashes, unless the whole string is just "/".
163 	 * If the whole string is "/" (i.e. if the last '/' cahr in dst
164 	 * in the beginning of the original string), just terminate it
165 	 * and return "/".
166 	 */
167 	if ((*(dst - 1) == '/') && ((dst - 1) != src_start))
168 		dst--;
169 	*dst = '\0';
170 }
171