zones_paths.c revision 12734:76969fc28795
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 */
76char *
77z_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
91void
92z_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
142void
143z_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