1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland 28*5c51f124SMoriah Waterland #include <stdio.h> 29*5c51f124SMoriah Waterland #include <stdlib.h> 30*5c51f124SMoriah Waterland #include <string.h> 31*5c51f124SMoriah Waterland #include <unistd.h> 32*5c51f124SMoriah Waterland #include <libintl.h> 33*5c51f124SMoriah Waterland #include <errno.h> 34*5c51f124SMoriah Waterland #include <assert.h> 35*5c51f124SMoriah Waterland #include <sys/types.h> 36*5c51f124SMoriah Waterland #include <sys/mntent.h> 37*5c51f124SMoriah Waterland #include <sys/mnttab.h> 38*5c51f124SMoriah Waterland #include <sys/param.h> 39*5c51f124SMoriah Waterland #include <libzonecfg.h> 40*5c51f124SMoriah Waterland #include "zones_strings.h" 41*5c51f124SMoriah Waterland #include "instzones_lib.h" 42*5c51f124SMoriah Waterland 43*5c51f124SMoriah Waterland #define MNTTAB "/etc/mnttab" 44*5c51f124SMoriah Waterland 45*5c51f124SMoriah Waterland #define MNTTAB_HUNK 32 46*5c51f124SMoriah Waterland 47*5c51f124SMoriah Waterland static struct mnttab *mountTable; 48*5c51f124SMoriah Waterland static size_t mountTableSize = 0; 49*5c51f124SMoriah Waterland static boolean_t createdFlag = B_FALSE; 50*5c51f124SMoriah Waterland 51*5c51f124SMoriah Waterland /* 52*5c51f124SMoriah Waterland * Name : z_createMountTable 53*5c51f124SMoriah Waterland * Description : Populate the mountTable Array with mnttab entries 54*5c51f124SMoriah Waterland * Arguments : void 55*5c51f124SMoriah Waterland * Returns : int 56*5c51f124SMoriah Waterland * 0: The Mount Table was succesfully initialized 57*5c51f124SMoriah Waterland * -1: There was an error during initialisation 58*5c51f124SMoriah Waterland */ 59*5c51f124SMoriah Waterland int 60*5c51f124SMoriah Waterland z_createMountTable(void) 61*5c51f124SMoriah Waterland { 62*5c51f124SMoriah Waterland FILE *fp; 63*5c51f124SMoriah Waterland struct mnttab ent; 64*5c51f124SMoriah Waterland struct mnttab *entp; 65*5c51f124SMoriah Waterland 66*5c51f124SMoriah Waterland if (createdFlag) { 67*5c51f124SMoriah Waterland return (0); 68*5c51f124SMoriah Waterland } 69*5c51f124SMoriah Waterland 70*5c51f124SMoriah Waterland fp = fopen(MNTTAB, "r"); 71*5c51f124SMoriah Waterland if (fp == NULL) { 72*5c51f124SMoriah Waterland _z_program_error(ERR_OPEN_READ, MNTTAB, errno, 73*5c51f124SMoriah Waterland strerror(errno)); 74*5c51f124SMoriah Waterland return (-1); 75*5c51f124SMoriah Waterland } 76*5c51f124SMoriah Waterland 77*5c51f124SMoriah Waterland /* Put the entries into the table */ 78*5c51f124SMoriah Waterland mountTable = NULL; 79*5c51f124SMoriah Waterland mountTableSize = 0; 80*5c51f124SMoriah Waterland createdFlag = B_TRUE; 81*5c51f124SMoriah Waterland while (getmntent(fp, &ent) == 0) { 82*5c51f124SMoriah Waterland if (mountTableSize % MNTTAB_HUNK == 0) { 83*5c51f124SMoriah Waterland mountTable = _z_realloc(mountTable, 84*5c51f124SMoriah Waterland (mountTableSize + MNTTAB_HUNK) * sizeof (ent)); 85*5c51f124SMoriah Waterland } 86*5c51f124SMoriah Waterland entp = &mountTable[mountTableSize++]; 87*5c51f124SMoriah Waterland 88*5c51f124SMoriah Waterland /* 89*5c51f124SMoriah Waterland * Zero out any fields we're not using. 90*5c51f124SMoriah Waterland */ 91*5c51f124SMoriah Waterland (void) memset(entp, 0, sizeof (*entp)); 92*5c51f124SMoriah Waterland 93*5c51f124SMoriah Waterland if (ent.mnt_special != NULL) 94*5c51f124SMoriah Waterland entp->mnt_special = _z_strdup(ent.mnt_special); 95*5c51f124SMoriah Waterland if (ent.mnt_mntopts != NULL) 96*5c51f124SMoriah Waterland entp->mnt_mntopts = _z_strdup(ent.mnt_mntopts); 97*5c51f124SMoriah Waterland entp->mnt_mountp = _z_strdup(ent.mnt_mountp); 98*5c51f124SMoriah Waterland entp->mnt_fstype = _z_strdup(ent.mnt_fstype); 99*5c51f124SMoriah Waterland } 100*5c51f124SMoriah Waterland 101*5c51f124SMoriah Waterland (void) fclose(fp); 102*5c51f124SMoriah Waterland return (0); 103*5c51f124SMoriah Waterland } 104*5c51f124SMoriah Waterland 105*5c51f124SMoriah Waterland /* 106*5c51f124SMoriah Waterland * Name : findPathRWStatus 107*5c51f124SMoriah Waterland * Description : Check whether the given path is an mnttab entry 108*5c51f124SMoriah Waterland * Arguments : char * - The Path to be verified 109*5c51f124SMoriah Waterland * Returns : int 110*5c51f124SMoriah Waterland * -1: The Path is NOT present in the table (mnttab) 111*5c51f124SMoriah Waterland * 0: The Path is present in the table and is mounted read-only 112*5c51f124SMoriah Waterland * 1: The Path is present in the table and is mounted read-write 113*5c51f124SMoriah Waterland */ 114*5c51f124SMoriah Waterland static int 115*5c51f124SMoriah Waterland findPathRWStatus(const char *a_path) 116*5c51f124SMoriah Waterland { 117*5c51f124SMoriah Waterland int i; 118*5c51f124SMoriah Waterland 119*5c51f124SMoriah Waterland for (i = 0; i < mountTableSize; i++) { 120*5c51f124SMoriah Waterland if (strcmp(a_path, mountTable[i].mnt_mountp) == 0) { 121*5c51f124SMoriah Waterland if (hasmntopt(&mountTable[i], MNTOPT_RO) != NULL) { 122*5c51f124SMoriah Waterland return (0); 123*5c51f124SMoriah Waterland } else { 124*5c51f124SMoriah Waterland return (1); 125*5c51f124SMoriah Waterland } 126*5c51f124SMoriah Waterland } 127*5c51f124SMoriah Waterland } 128*5c51f124SMoriah Waterland 129*5c51f124SMoriah Waterland return (-1); 130*5c51f124SMoriah Waterland } 131*5c51f124SMoriah Waterland 132*5c51f124SMoriah Waterland 133*5c51f124SMoriah Waterland /* 134*5c51f124SMoriah Waterland * Name : z_isPathWritable 135*5c51f124SMoriah Waterland * Description : Check if the given path is in a writable area 136*5c51f124SMoriah Waterland * Arguments : char * - The Path to be verified 137*5c51f124SMoriah Waterland * Returns : int 138*5c51f124SMoriah Waterland * 0: The Path is under a read-only mount 139*5c51f124SMoriah Waterland * 1: The Path is under a read-write mount 140*5c51f124SMoriah Waterland * NOTE : This funcion automatically initialises 141*5c51f124SMoriah Waterland * the mountPoint table if needed. 142*5c51f124SMoriah Waterland */ 143*5c51f124SMoriah Waterland int 144*5c51f124SMoriah Waterland z_isPathWritable(const char *a_str) 145*5c51f124SMoriah Waterland { 146*5c51f124SMoriah Waterland int i, result, slen; 147*5c51f124SMoriah Waterland char a_path[MAXPATHLEN]; 148*5c51f124SMoriah Waterland 149*5c51f124SMoriah Waterland if (!createdFlag) { 150*5c51f124SMoriah Waterland if (z_createMountTable() != 0) { 151*5c51f124SMoriah Waterland return (1); 152*5c51f124SMoriah Waterland } 153*5c51f124SMoriah Waterland } 154*5c51f124SMoriah Waterland 155*5c51f124SMoriah Waterland (void) strlcpy(a_path, a_str, sizeof (a_path)); 156*5c51f124SMoriah Waterland slen = strlen(a_path); 157*5c51f124SMoriah Waterland 158*5c51f124SMoriah Waterland /* 159*5c51f124SMoriah Waterland * This for loop traverses Path backwards, incrementally removing the 160*5c51f124SMoriah Waterland * basename of Path and looking for the resultant directory in the 161*5c51f124SMoriah Waterland * mnttab. Once found, it returns the rw status of that file system. 162*5c51f124SMoriah Waterland */ 163*5c51f124SMoriah Waterland for (i = slen; i > 0; i--) { 164*5c51f124SMoriah Waterland if ((a_path[i] == '/') || (a_path[i] == '\0')) { 165*5c51f124SMoriah Waterland a_path[i] = '\0'; 166*5c51f124SMoriah Waterland result = findPathRWStatus(a_path); 167*5c51f124SMoriah Waterland if (result != -1) { 168*5c51f124SMoriah Waterland return (result); 169*5c51f124SMoriah Waterland } 170*5c51f124SMoriah Waterland } 171*5c51f124SMoriah Waterland } 172*5c51f124SMoriah Waterland 173*5c51f124SMoriah Waterland return (1); 174*5c51f124SMoriah Waterland } 175*5c51f124SMoriah Waterland 176*5c51f124SMoriah Waterland /* 177*5c51f124SMoriah Waterland * Name : z_destroyMountTable 178*5c51f124SMoriah Waterland * Description : Clear the entries in the mount table 179*5c51f124SMoriah Waterland * Arguments : void 180*5c51f124SMoriah Waterland * Returns : void 181*5c51f124SMoriah Waterland */ 182*5c51f124SMoriah Waterland void 183*5c51f124SMoriah Waterland z_destroyMountTable(void) 184*5c51f124SMoriah Waterland { 185*5c51f124SMoriah Waterland int i; 186*5c51f124SMoriah Waterland 187*5c51f124SMoriah Waterland if (!createdFlag) { 188*5c51f124SMoriah Waterland return; 189*5c51f124SMoriah Waterland } 190*5c51f124SMoriah Waterland 191*5c51f124SMoriah Waterland if (mountTable == NULL) { 192*5c51f124SMoriah Waterland return; 193*5c51f124SMoriah Waterland } 194*5c51f124SMoriah Waterland 195*5c51f124SMoriah Waterland for (i = 0; i < mountTableSize; i++) { 196*5c51f124SMoriah Waterland free(mountTable[i].mnt_mountp); 197*5c51f124SMoriah Waterland free(mountTable[i].mnt_fstype); 198*5c51f124SMoriah Waterland free(mountTable[i].mnt_special); 199*5c51f124SMoriah Waterland free(mountTable[i].mnt_mntopts); 200*5c51f124SMoriah Waterland assert(mountTable[i].mnt_time == NULL); 201*5c51f124SMoriah Waterland } 202*5c51f124SMoriah Waterland 203*5c51f124SMoriah Waterland free(mountTable); 204*5c51f124SMoriah Waterland mountTable = NULL; 205*5c51f124SMoriah Waterland mountTableSize = 0; 206*5c51f124SMoriah Waterland createdFlag = B_FALSE; 207*5c51f124SMoriah Waterland } 208*5c51f124SMoriah Waterland 209*5c51f124SMoriah Waterland /* 210*5c51f124SMoriah Waterland * Name : z_resolve_lofs 211*5c51f124SMoriah Waterland * Description : Loop over potential loopback mounts and symlinks in a 212*5c51f124SMoriah Waterland * given path and resolve them all down to an absolute path. 213*5c51f124SMoriah Waterland * Arguments : char * - path to resolve. path is in writable storage. 214*5c51f124SMoriah Waterland * size_t - length of path storage. 215*5c51f124SMoriah Waterland * Returns : void 216*5c51f124SMoriah Waterland */ 217*5c51f124SMoriah Waterland void 218*5c51f124SMoriah Waterland z_resolve_lofs(char *path, size_t pathlen) 219*5c51f124SMoriah Waterland { 220*5c51f124SMoriah Waterland int len, arlen, i; 221*5c51f124SMoriah Waterland const char *altroot; 222*5c51f124SMoriah Waterland char tmppath[MAXPATHLEN]; 223*5c51f124SMoriah Waterland boolean_t outside_altroot; 224*5c51f124SMoriah Waterland 225*5c51f124SMoriah Waterland if ((len = resolvepath(path, tmppath, sizeof (tmppath))) == -1) 226*5c51f124SMoriah Waterland return; 227*5c51f124SMoriah Waterland 228*5c51f124SMoriah Waterland tmppath[len] = '\0'; 229*5c51f124SMoriah Waterland (void) strlcpy(path, tmppath, pathlen); 230*5c51f124SMoriah Waterland 231*5c51f124SMoriah Waterland if (z_createMountTable() == -1) 232*5c51f124SMoriah Waterland return; 233*5c51f124SMoriah Waterland 234*5c51f124SMoriah Waterland altroot = zonecfg_get_root(); 235*5c51f124SMoriah Waterland arlen = strlen(altroot); 236*5c51f124SMoriah Waterland outside_altroot = B_FALSE; 237*5c51f124SMoriah Waterland for (;;) { 238*5c51f124SMoriah Waterland struct mnttab *mnp; 239*5c51f124SMoriah Waterland 240*5c51f124SMoriah Waterland /* Search in reverse order to find longest match */ 241*5c51f124SMoriah Waterland for (i = mountTableSize; i > 0; i--) { 242*5c51f124SMoriah Waterland mnp = &mountTable[i - 1]; 243*5c51f124SMoriah Waterland if (mnp->mnt_fstype == NULL || 244*5c51f124SMoriah Waterland mnp->mnt_mountp == NULL || 245*5c51f124SMoriah Waterland mnp->mnt_special == NULL) 246*5c51f124SMoriah Waterland continue; 247*5c51f124SMoriah Waterland len = strlen(mnp->mnt_mountp); 248*5c51f124SMoriah Waterland if (strncmp(mnp->mnt_mountp, path, len) == 0 && 249*5c51f124SMoriah Waterland (path[len] == '/' || path[len] == '\0')) 250*5c51f124SMoriah Waterland break; 251*5c51f124SMoriah Waterland } 252*5c51f124SMoriah Waterland if (i <= 0) 253*5c51f124SMoriah Waterland break; 254*5c51f124SMoriah Waterland 255*5c51f124SMoriah Waterland /* If it's not a lofs then we're done */ 256*5c51f124SMoriah Waterland if (strcmp(mnp->mnt_fstype, MNTTYPE_LOFS) != 0) 257*5c51f124SMoriah Waterland break; 258*5c51f124SMoriah Waterland 259*5c51f124SMoriah Waterland if (outside_altroot) { 260*5c51f124SMoriah Waterland char *cp; 261*5c51f124SMoriah Waterland int olen = sizeof (MNTOPT_RO) - 1; 262*5c51f124SMoriah Waterland 263*5c51f124SMoriah Waterland /* 264*5c51f124SMoriah Waterland * If we run into a read-only mount outside of the 265*5c51f124SMoriah Waterland * alternate root environment, then the user doesn't 266*5c51f124SMoriah Waterland * want this path to be made read-write. 267*5c51f124SMoriah Waterland */ 268*5c51f124SMoriah Waterland if (mnp->mnt_mntopts != NULL && 269*5c51f124SMoriah Waterland (cp = strstr(mnp->mnt_mntopts, MNTOPT_RO)) != 270*5c51f124SMoriah Waterland NULL && 271*5c51f124SMoriah Waterland (cp == mnp->mnt_mntopts || cp[-1] == ',') && 272*5c51f124SMoriah Waterland (cp[olen] == '\0' || cp[olen] == ',')) { 273*5c51f124SMoriah Waterland break; 274*5c51f124SMoriah Waterland } 275*5c51f124SMoriah Waterland } else if (arlen > 0 && 276*5c51f124SMoriah Waterland (strncmp(mnp->mnt_special, altroot, arlen) != 0 || 277*5c51f124SMoriah Waterland (mnp->mnt_special[arlen] != '\0' && 278*5c51f124SMoriah Waterland mnp->mnt_special[arlen] != '/'))) { 279*5c51f124SMoriah Waterland outside_altroot = B_TRUE; 280*5c51f124SMoriah Waterland } 281*5c51f124SMoriah Waterland /* use temporary buffer because new path might be longer */ 282*5c51f124SMoriah Waterland (void) snprintf(tmppath, sizeof (tmppath), "%s%s", 283*5c51f124SMoriah Waterland mnp->mnt_special, path + len); 284*5c51f124SMoriah Waterland if ((len = resolvepath(tmppath, path, pathlen)) == -1) 285*5c51f124SMoriah Waterland break; 286*5c51f124SMoriah Waterland path[len] = '\0'; 287*5c51f124SMoriah Waterland } 288*5c51f124SMoriah Waterland } 289