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