zones_lofs.c revision 9781:ccf49524d5dc
1168054Sflz/* 2168054Sflz * CDDL HEADER START 3168266Sgabor * 4168266Sgabor * The contents of this file are subject to the terms of the 5168266Sgabor * Common Development and Distribution License (the "License"). 6168266Sgabor * You may not use this file except in compliance with the License. 7168266Sgabor * 8168266Sgabor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168266Sgabor * or http://www.opensolaris.org/os/licensing. 10168266Sgabor * See the License for the specific language governing permissions 11168054Sflz * and limitations under the License. 12168054Sflz * 13168064Sflz * When distributing Covered Code, include this CDDL HEADER in each 14168064Sflz * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168064Sflz * If applicable, add the following below this CDDL HEADER, with the 16168064Sflz * fields enclosed by brackets "[]" replaced with your own identifying 17168064Sflz * information: Portions Copyright [yyyy] [name of copyright owner] 18168064Sflz * 19168064Sflz * CDDL HEADER END 20168064Sflz */ 21168064Sflz 22168064Sflz/* 23168064Sflz * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24168064Sflz * Use is subject to license terms. 25168064Sflz */ 26168064Sflz 27168054Sflz 28168054Sflz#include <stdio.h> 29168064Sflz#include <stdlib.h> 30168054Sflz#include <string.h> 31168064Sflz#include <unistd.h> 32171129Sobrien#include <libintl.h> 33168939Stmclaugh#include <errno.h> 34168131Sbmah#include <assert.h> 35168113Smarcus#include <sys/types.h> 36180225Smarcel#include <sys/mntent.h> 37168123Snetchild#include <sys/mnttab.h> 38168939Stmclaugh#include <sys/param.h> 39168064Sflz#include <libzonecfg.h> 40168054Sflz#include "zones_strings.h" 41168054Sflz#include "instzones_lib.h" 42168054Sflz 43168054Sflz#define MNTTAB "/etc/mnttab" 44168261Sache 45168077Sflz#define MNTTAB_HUNK 32 46168077Sflz 47168126Salestatic struct mnttab *mountTable; 48168069Sgargastatic size_t mountTableSize = 0; 49168472Snovelstatic boolean_t createdFlag = B_FALSE; 50179877Samdmi3 51168274Ssem/* 52169073Saraujo * Name : z_createMountTable 53168667Sstefan * Description : Populate the mountTable Array with mnttab entries 54209039Sashish * Arguments : void 55203044Savilla * Returns : int 56193190Savl * 0: The Mount Table was succesfully initialized 57168274Ssem * -1: There was an error during initialisation 58210573Sbapt */ 59188692Sbeatint 60170471Sbeechz_createMountTable(void) 61168113Smarcus{ 62218631Smiwi FILE *fp; 63173254Sbrix struct mnttab ent; 64168098Skrion struct mnttab *entp; 65168123Snetchild 66170601Schinsan if (createdFlag) { 67168082Sgarga return (0); 68168116Sclsung } 69168937Scperciva 70222995Screes fp = fopen(MNTTAB, "r"); 71225632Scs if (fp == NULL) { 72213988Sculot _z_program_error(ERR_OPEN_READ, MNTTAB, errno, 73168177Sgabor strerror(errno)); 74168354Sdanfe return (-1); 75168072Sehaupt } 76206034Sdecke 77168108Srafan /* Put the entries into the table */ 78168186Smat mountTable = NULL; 79218631Smiwi mountTableSize = 0; 80168210Sitetcu createdFlag = B_TRUE; 81225853Seadler while (getmntent(fp, &ent) == 0) { 82168068Serwin if (mountTableSize % MNTTAB_HUNK == 0) { 83168072Sehaupt mountTable = _z_realloc(mountTable, 84168113Smarcus (mountTableSize + MNTTAB_HUNK) * sizeof (ent)); 85168059Sgabor } 86168542Smiwi entp = &mountTable[mountTableSize++]; 87168098Skrion 88216282Sflo /* 89206495Sfluffy * Zero out any fields we're not using. 90168054Sflz */ 91168059Sgabor (void) memset(entp, 0, sizeof (*entp)); 92176595Sgahr 93168054Sflz if (ent.mnt_special != NULL) 94210773Sglarkin entp->mnt_special = _z_strdup(ent.mnt_special); 95210773Sglarkin if (ent.mnt_mntopts != NULL) 96172158Sjkim entp->mnt_mntopts = _z_strdup(ent.mnt_mntopts); 97172158Sjkim entp->mnt_mountp = _z_strdup(ent.mnt_mountp); 98168256Sijliao entp->mnt_fstype = _z_strdup(ent.mnt_fstype); 99168209Sitetcu } 100206184Sjacula 101176768Sjadawin (void) fclose(fp); 102228752Sjgh return (0); 103172158Sjkim} 104222797Sjlaffaye 105168076Sjmelo/* 106168123Snetchild * Name : findPathRWStatus 107168054Sflz * Description : Check whether the given path is an mnttab entry 108168055Spav * Arguments : char * - The Path to be verified 109182814Sjpaetzel * Returns : int 110210169Sjsa * -1: The Path is NOT present in the table (mnttab) 111168055Spav * 0: The Path is present in the table and is mounted read-only 112168536Skevlo * 1: The Path is present in the table and is mounted read-write 113168177Sgabor */ 114168098Skrionstatic int 115218631SmiwifindPathRWStatus(const char *a_path) 116168055Spav{ 117168161Sphilip int i; 118168054Sflz 119168208Sitetcu for (i = 0; i < mountTableSize; i++) { 120168295Sleeym if (strcmp(a_path, mountTable[i].mnt_mountp) == 0) { 121168295Sleeym if (hasmntopt(&mountTable[i], MNTOPT_RO) != NULL) { 122172158Sjkim return (0); 123175205Sedwin } else { 124168939Stmclaugh return (1); 125176979Slippe } 126218631Smiwi } 127168068Serwin } 128168337Slwhsu 129175205Sedwin return (-1); 130168177Sgabor} 131199480Smandree 132199479Smandree 133168113Smarcus/* 134168918Sbrueffer * Name : z_isPathWritable 135220095Smartymac * Description : Check if the given path is in a writable area 136168186Smat * Arguments : char * - The Path to be verified 137168055Spav * Returns : int 138168098Skrion * 0: The Path is under a read-only mount 139168359Smm * 1: The Path is under a read-write mount 140168100Smnag * NOTE : This funcion automatically initialises 141218631Smiwi * the mountPoint table if needed. 142169036Snemoliu */ 143168123Snetchildint 144168177Sgaborz_isPathWritable(const char *a_str) 145168134Snork{ 146168084Sehaupt int i, result, slen; 147168542Smiwi char a_path[MAXPATHLEN]; 148171129Sobrien 149171129Sobrien if (!createdFlag) { 150169253Sfjoe if (z_createMountTable() != 0) { 151168939Stmclaugh return (1); 152168054Sflz } 153219614Spawel } 154190977Spgj 155168098Skrion (void) strlcpy(a_path, a_str, sizeof (a_path)); 156180729Spgollucci slen = strlen(a_path); 157168108Srafan 158226351Srakuco /* 159206489Srene * This for loop traverses Path backwards, incrementally removing the 160227417Srm * basename of Path and looking for the resultant directory in the 161180983Srnoland * mnttab. Once found, it returns the rw status of that file system. 162203046Sromain */ 163206532Ssahil for (i = slen; i > 0; i--) { 164168098Skrion if ((a_path[i] == '/') || (a_path[i] == '\0')) { 165219730Ssbz a_path[i] = '\0'; 166227731Sscheidell result = findPathRWStatus(a_path); 167168098Skrion if (result != -1) { 168168098Skrion return (result); 169168055Spav } 170168068Serwin } 171191885Sskreuzer } 172168939Stmclaugh 173168290Ssem return (1); 174168667Sstefan} 175223090Sstephen 176213001Ssunpoet/* 177218631Smiwi * Name : z_destroyMountTable 178212219Sswills * Description : Clear the entries in the mount table 179172276Stabthorpe * Arguments : void 180168125Stdb * Returns : void 181170675Stimur */ 182192568Stotavoid 183169018Straszz_destroyMountTable(void) 184168225Strhodes{ 185168186Smat int i; 186168061Sahze 187231128Suqs if (!createdFlag) { 188168069Sgarga return; 189216401Swen } 190180728Swxs 191168935Stmclaugh if (mountTable == NULL) { 192195800Syzlin return; 193224071Szi } 194172158Sjkim 195168054Sflz for (i = 0; i < mountTableSize; i++) { 196168054Sflz free(mountTable[i].mnt_mountp); 197168064Sflz free(mountTable[i].mnt_fstype); 198168064Sflz free(mountTable[i].mnt_special); 199168054Sflz free(mountTable[i].mnt_mntopts); 200168055Spav assert(mountTable[i].mnt_time == NULL); 201168055Spav } 202168055Spav 203168055Spav free(mountTable); 204168055Spav mountTable = NULL; 205182814Sjpaetzel mountTableSize = 0; 206182814Sjpaetzel createdFlag = B_FALSE; 207168055Spav} 208168057Sahze 209168055Spav/* 210176979Slippe * Name : z_resolve_lofs 211180729Spgollucci * Description : Loop over potential loopback mounts and symlinks in a 212176979Slippe * given path and resolve them all down to an absolute path. 213168919Sbrueffer * Arguments : char * - path to resolve. path is in writable storage. 214168667Sstefan * size_t - length of path storage. 215168667Sstefan * Returns : void 216171129Sobrien */ 217171129Sobrienvoid 218226351Srakucoz_resolve_lofs(char *path, size_t pathlen) 219226351Srakuco{ 220225848Seadler int len, arlen, i; 221222817Sjlaffaye const char *altroot; 222222817Sjlaffaye char tmppath[MAXPATHLEN]; 223206034Sdecke boolean_t outside_altroot; 224231128Suqs 225206034Sdecke if ((len = resolvepath(path, tmppath, sizeof (tmppath))) == -1) 226188837Sbeech return; 227188837Sbeech 228188837Sbeech tmppath[len] = '\0'; 229168939Stmclaugh (void) strlcpy(path, tmppath, pathlen); 230168939Stmclaugh 231168939Stmclaugh if (z_createMountTable() == -1) 232218631Smiwi return; 233218631Smiwi 234168125Stdb altroot = zonecfg_get_root(); 235168208Sitetcu arlen = strlen(altroot); 236168125Stdb outside_altroot = B_FALSE; 237168337Slwhsu for (;;) { 238172275Stabthorpe struct mnttab *mnp; 239168337Slwhsu 240228752Sjgh /* Search in reverse order to find longest match */ 241228752Sjgh for (i = mountTableSize; i > 0; i--) { 242169036Snemoliu mnp = &mountTable[i - 1]; 243168108Srafan if (mnp->mnt_fstype == NULL || 244168108Srafan mnp->mnt_mountp == NULL || 245168186Smat mnp->mnt_special == NULL) 246168186Smat continue; 247168938Scperciva len = strlen(mnp->mnt_mountp); 248168068Serwin if (strncmp(mnp->mnt_mountp, path, len) == 0 && 249175205Sedwin (path[len] == '/' || path[len] == '\0')) 250175205Sedwin break; 251168068Serwin } 252168072Sehaupt if (i <= 0) 253220182Smartymac break; 254168072Sehaupt 255168274Ssem /* If it's not a lofs then we're done */ 256168225Strhodes if (strcmp(mnp->mnt_fstype, MNTTYPE_LOFS) != 0) 257168225Strhodes break; 258173254Sbrix 259168068Serwin if (outside_altroot) { 260168059Sgabor char *cp; 261168068Serwin int olen = sizeof (MNTOPT_RO) - 1; 262168068Serwin 263168068Serwin /* 264168059Sgabor * If we run into a read-only mount outside of the 265168354Sdanfe * alternate root environment, then the user doesn't 266216282Sflo * want this path to be made read-write. 267168098Skrion */ 268169251Sfjoe if (mnp->mnt_mntopts != NULL && 269168098Skrion (cp = strstr(mnp->mnt_mntopts, MNTOPT_RO)) != 270168054Sflz NULL && 271168054Sflz (cp == mnp->mnt_mntopts || cp[-1] == ',') && 272168054Sflz (cp[olen] == '\0' || cp[olen] == ',')) { 273203046Sromain break; 274168054Sflz } 275176979Slippe } else if (arlen > 0 && 276190977Spgj (strncmp(mnp->mnt_special, altroot, arlen) != 0 || 277223090Sstephen (mnp->mnt_special[arlen] != '\0' && 278227731Sscheidell mnp->mnt_special[arlen] != '/'))) { 279176979Slippe outside_altroot = B_TRUE; 280168069Sgarga } 281168069Sgarga /* use temporary buffer because new path might be longer */ 282199479Smandree (void) snprintf(tmppath, sizeof (tmppath), "%s%s", 283168359Smm mnp->mnt_special, path + len); 284180983Srnoland if ((len = resolvepath(tmppath, path, pathlen)) == -1) 285168069Sgarga break; 286180728Swxs path[len] = '\0'; 287168935Stmclaugh } 288168069Sgarga} 289193190Savl