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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
35 #include <sys/types.h>
36 #include <sys/mntent.h>
37 #include <sys/mnttab.h>
38 #include <sys/param.h>
39 #include <libzonecfg.h>
40 #include "zones_strings.h"
41 #include "instzones_lib.h"
43 #define MNTTAB "/etc/mnttab"
45 #define MNTTAB_HUNK 32
47 static struct mnttab
*mountTable
;
48 static size_t mountTableSize
= 0;
49 static boolean_t createdFlag
= B_FALSE
;
52 * Name : z_createMountTable
53 * Description : Populate the mountTable Array with mnttab entries
56 * 0: The Mount Table was succesfully initialized
57 * -1: There was an error during initialisation
60 z_createMountTable(void)
70 fp
= fopen(MNTTAB
, "r");
72 _z_program_error(ERR_OPEN_READ
, MNTTAB
, errno
,
77 /* Put the entries into the table */
81 while (getmntent(fp
, &ent
) == 0) {
82 if (mountTableSize
% MNTTAB_HUNK
== 0) {
83 mountTable
= _z_realloc(mountTable
,
84 (mountTableSize
+ MNTTAB_HUNK
) * sizeof (ent
));
86 entp
= &mountTable
[mountTableSize
++];
89 * Zero out any fields we're not using.
91 (void) memset(entp
, 0, sizeof (*entp
));
93 if (ent
.mnt_special
!= NULL
)
94 entp
->mnt_special
= _z_strdup(ent
.mnt_special
);
95 if (ent
.mnt_mntopts
!= NULL
)
96 entp
->mnt_mntopts
= _z_strdup(ent
.mnt_mntopts
);
97 entp
->mnt_mountp
= _z_strdup(ent
.mnt_mountp
);
98 entp
->mnt_fstype
= _z_strdup(ent
.mnt_fstype
);
106 * Name : findPathRWStatus
107 * Description : Check whether the given path is an mnttab entry
108 * Arguments : char * - The Path to be verified
110 * -1: The Path is NOT present in the table (mnttab)
111 * 0: The Path is present in the table and is mounted read-only
112 * 1: The Path is present in the table and is mounted read-write
115 findPathRWStatus(const char *a_path
)
119 for (i
= 0; i
< mountTableSize
; i
++) {
120 if (strcmp(a_path
, mountTable
[i
].mnt_mountp
) == 0) {
121 if (hasmntopt(&mountTable
[i
], MNTOPT_RO
) != NULL
) {
134 * Name : z_isPathWritable
135 * Description : Check if the given path is in a writable area
136 * Arguments : char * - The Path to be verified
138 * 0: The Path is under a read-only mount
139 * 1: The Path is under a read-write mount
140 * NOTE : This funcion automatically initialises
141 * the mountPoint table if needed.
144 z_isPathWritable(const char *a_str
)
147 char a_path
[MAXPATHLEN
];
150 if (z_createMountTable() != 0) {
155 (void) strlcpy(a_path
, a_str
, sizeof (a_path
));
156 slen
= strlen(a_path
);
159 * This for loop traverses Path backwards, incrementally removing the
160 * basename of Path and looking for the resultant directory in the
161 * mnttab. Once found, it returns the rw status of that file system.
163 for (i
= slen
; i
> 0; i
--) {
164 if ((a_path
[i
] == '/') || (a_path
[i
] == '\0')) {
166 result
= findPathRWStatus(a_path
);
177 * Name : z_destroyMountTable
178 * Description : Clear the entries in the mount table
183 z_destroyMountTable(void)
191 if (mountTable
== NULL
) {
195 for (i
= 0; i
< mountTableSize
; i
++) {
196 free(mountTable
[i
].mnt_mountp
);
197 free(mountTable
[i
].mnt_fstype
);
198 free(mountTable
[i
].mnt_special
);
199 free(mountTable
[i
].mnt_mntopts
);
200 assert(mountTable
[i
].mnt_time
== NULL
);
206 createdFlag
= B_FALSE
;
210 * Name : z_resolve_lofs
211 * Description : Loop over potential loopback mounts and symlinks in a
212 * given path and resolve them all down to an absolute path.
213 * Arguments : char * - path to resolve. path is in writable storage.
214 * size_t - length of path storage.
218 z_resolve_lofs(char *path
, size_t pathlen
)
222 char tmppath
[MAXPATHLEN
];
223 boolean_t outside_altroot
;
225 if ((len
= resolvepath(path
, tmppath
, sizeof (tmppath
))) == -1)
229 (void) strlcpy(path
, tmppath
, pathlen
);
231 if (z_createMountTable() == -1)
234 altroot
= zonecfg_get_root();
235 arlen
= strlen(altroot
);
236 outside_altroot
= B_FALSE
;
240 /* Search in reverse order to find longest match */
241 for (i
= mountTableSize
; i
> 0; i
--) {
242 mnp
= &mountTable
[i
- 1];
243 if (mnp
->mnt_fstype
== NULL
||
244 mnp
->mnt_mountp
== NULL
||
245 mnp
->mnt_special
== NULL
)
247 len
= strlen(mnp
->mnt_mountp
);
248 if (strncmp(mnp
->mnt_mountp
, path
, len
) == 0 &&
249 (path
[len
] == '/' || path
[len
] == '\0'))
255 /* If it's not a lofs then we're done */
256 if (strcmp(mnp
->mnt_fstype
, MNTTYPE_LOFS
) != 0)
259 if (outside_altroot
) {
261 int olen
= sizeof (MNTOPT_RO
) - 1;
264 * If we run into a read-only mount outside of the
265 * alternate root environment, then the user doesn't
266 * want this path to be made read-write.
268 if (mnp
->mnt_mntopts
!= NULL
&&
269 (cp
= strstr(mnp
->mnt_mntopts
, MNTOPT_RO
)) !=
271 (cp
== mnp
->mnt_mntopts
|| cp
[-1] == ',') &&
272 (cp
[olen
] == '\0' || cp
[olen
] == ',')) {
275 } else if (arlen
> 0 &&
276 (strncmp(mnp
->mnt_special
, altroot
, arlen
) != 0 ||
277 (mnp
->mnt_special
[arlen
] != '\0' &&
278 mnp
->mnt_special
[arlen
] != '/'))) {
279 outside_altroot
= B_TRUE
;
281 /* use temporary buffer because new path might be longer */
282 (void) snprintf(tmppath
, sizeof (tmppath
), "%s%s",
283 mnp
->mnt_special
, path
+ len
);
284 if ((len
= resolvepath(tmppath
, path
, pathlen
)) == -1)