186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * CDDL HEADER START
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * The contents of this file are subject to the terms of the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Common Development and Distribution License (the "License").
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * You may not use this file except in compliance with the License.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * or http://www.opensolaris.org/os/licensing.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * See the License for the specific language governing permissions
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * and limitations under the License.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * When distributing Covered Code, include this CDDL HEADER in each
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * If applicable, add the following below this CDDL HEADER, with the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * fields enclosed by brackets "[]" replaced with your own identifying
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * information: Portions Copyright [yyyy] [name of copyright owner]
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * CDDL HEADER END
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Use is subject to license terms.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill/*
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved.
2a12f85ad140e332791b4bad1208a734c3f26bf3Jeremy Jones * Copyright (c) 2013 by Delphix. All rights reserved.
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <assert.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <dlfcn.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <errno.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <libzonecfg.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <link.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <string.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <strings.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/list.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/types.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/mkdev.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/mman.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/mnttab.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include "Pcontrol.h"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczstruct path_node {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz struct path_node *pn_next;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char *pn_path;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz};
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicztypedef struct path_node path_node_t;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner/*
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * Parameters of the lofs lookup cache.
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulknerstatic struct stat64 lofs_mstat; /* last stat() of MNTTAB */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulknerstatic struct lofs_mnttab { /* linked list of all lofs mount points */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner struct lofs_mnttab *l_next;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner char *l_special; /* extracted from MNTTAB */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner char *l_mountp; /* ditto */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner} *lofs_mnttab = NULL;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulknerstatic mutex_t lofs_lock = DEFAULTMUTEX; /* protects the lofs cache */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulknerstatic void
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulknerrebuild_lofs_cache(void)
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner{
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner struct mnttab mt;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner struct mnttab mt_find;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner struct lofs_mnttab *lmt;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner struct lofs_mnttab *next;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner FILE *fp;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner assert(MUTEX_HELD(&lofs_lock));
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner /* destroy the old cache */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner for (lmt = lofs_mnttab; lmt != NULL; lmt = next) {
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner next = lmt->l_next;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner free(lmt->l_special);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner free(lmt->l_mountp);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner free(lmt);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner }
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner lofs_mnttab = NULL;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner /* prepare to create the new cache */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner if ((fp = fopen(MNTTAB, "r")) == NULL)
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner return;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner /*
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * We only care about lofs mount points. But we need to
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * ignore lofs mounts where the source path is the same
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * as the target path. (This can happen when a non-global
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * zone has a lofs mount of a global zone filesystem, since
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * the source path can't expose information about global
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * zone paths to the non-global zone.)
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner bzero(&mt_find, sizeof (mt_find));
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner mt_find.mnt_fstype = "lofs";
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner while (getmntany(fp, &mt, &mt_find) == 0 &&
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner (strcmp(mt.mnt_fstype, "lofs") == 0) &&
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner (strcmp(mt.mnt_special, mt.mnt_mountp) != 0)) {
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner if ((lmt = malloc(sizeof (struct lofs_mnttab))) == NULL)
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner break;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner lmt->l_special = strdup(mt.mnt_special);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner lmt->l_mountp = strdup(mt.mnt_mountp);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner lmt->l_next = lofs_mnttab;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner lofs_mnttab = lmt;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner }
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner (void) fclose(fp);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner}
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulknerstatic const char *
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulknerlookup_lofs_mount_point(const char *mountp)
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner{
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner struct lofs_mnttab *lmt;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner assert(MUTEX_HELD(&lofs_lock));
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner for (lmt = lofs_mnttab; lmt != NULL; lmt = lmt->l_next) {
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner if (strcmp(lmt->l_mountp, mountp) == 0)
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner return (lmt->l_special);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner }
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner return (NULL);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner}
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczstatic path_node_t *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczpn_push(path_node_t **pnp, char *path)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz path_node_t *pn;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((pn = calloc(sizeof (path_node_t), 1)) == NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((pn->pn_path = strdup(path)) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz free(pn);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn->pn_next = *pnp;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (*pnp = pn);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczstatic void
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczpn_free(path_node_t **pnp)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz path_node_t *pn;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz while (*pnp != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn = *pnp;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *pnp = pn->pn_next;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz free(pn->pn_path);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz free(pn);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczstatic void
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczpn_free2(path_node_t **pn1, path_node_t **pn2)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free(pn1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free(pn2);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczstatic char *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczpn_pop(path_node_t **pnp, char *path)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz path_node_t *pn;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (*pnp == NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn = *pnp;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *pnp = pn->pn_next;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn->pn_next = NULL;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (path == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free(&pn);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(path, pn->pn_path, PATH_MAX);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free(&pn);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (path);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Libzonecfg.so links against libproc, so libproc can't link against
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * libzonecfg.so. Also, libzonecfg.so is optional and might not be
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * installed. Hence instead of relying on linking to access libzonecfg.so,
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * we'll try dlopening it here. This trick is borrowed from
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * libc`zone_get_id(), see that function for more detailed comments.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczstatic int
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczi_zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz typedef int (*zone_get_zonepath_t)(char *, char *, size_t);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz static zone_get_zonepath_t zone_get_zonepath_fp = NULL;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (zone_get_zonepath_fp == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* There's no harm in doing this multiple times. */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz void *sym = (void *)(-1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (dlhandle != NULL &&
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (sym = dlsym(dlhandle, "zone_get_zonepath")) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz sym = (void *)(-1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) dlclose(dlhandle);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz zone_get_zonepath_fp = (zone_get_zonepath_t)sym;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* If we've successfully loaded it, call the real function */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (zone_get_zonepath_fp != (zone_get_zonepath_t)(-1))
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (zone_get_zonepath_fp(zone_name, zonepath, rp_sz));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (Z_NO_ZONE);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward PilatowiczPbrandname(struct ps_prochandle *P, char *buf, size_t buflen)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz long addr;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((addr = Pgetauxval(P, AT_SUN_BRANDNAME)) == -1)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Pread_string(P, buf, buflen, addr) == -1)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (buf);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Get the zone name from the core file if we have it; look up the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * name based on the zone id if this is a live process.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward PilatowiczPzonename(struct ps_prochandle *P, char *s, size_t n)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
2a12f85ad140e332791b4bad1208a734c3f26bf3Jeremy Jones return (P->ops.pop_zonename(P, s, n, P->data));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward PilatowiczPzoneroot(struct ps_prochandle *P, char *s, size_t n)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char zname[ZONENAME_MAX], zpath[PATH_MAX], tmp[PATH_MAX];
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz int rv;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (P->zoneroot != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, P->zoneroot, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((Pzonename(P, zname, sizeof (zname)) == NULL) ||
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (strcmp(zname, GLOBAL_ZONENAME) == 0)) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((P->zoneroot = strdup("")) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz errno = ENOMEM;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzoneroot defaulting to '%s'\n", GLOBAL_ZONENAME);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, P->zoneroot, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (i_zone_get_zonepath(zname, zpath, sizeof (zpath)) != Z_OK) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((P->zoneroot = strdup("")) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz errno = ENOMEM;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf(
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "Pzoneroot zone not found '%s', defaulting to '%s'\n",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz zname, GLOBAL_ZONENAME);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, P->zoneroot, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(zpath, "/root", sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((rv = resolvepath(zpath, tmp, sizeof (tmp) - 1)) < 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((P->zoneroot = strdup("")) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz errno = ENOMEM;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf(
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "Pzoneroot can't access '%s:%s', defaulting to '%s'\n",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz zname, zpath, GLOBAL_ZONENAME);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, P->zoneroot, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz tmp[rv] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(zpath, tmp, sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((P->zoneroot = strdup(zpath)) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz errno = ENOMEM;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzoneroot found zone root '%s:%s'\n", zname, zpath);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, P->zoneroot, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Plofspath() takes a path, "path", and removes any lofs components from
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * that path. The resultant path (if different from the starting path)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * is placed in "s", which is limited to "n" characters, and the return
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * value is the pointer s. If there are no lofs components in the path
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * the NULL is returned and s is not modified. It's ok for "path" and
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * "s" to be the same pointer. (ie, the results can be stored directly
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * in the input buffer.) The path that is passed in must be an absolute
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * path.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Example:
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * if "path" == "/foo/bar", and "/candy/" is lofs mounted on "/foo/"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * then "/candy/bar/" will be written into "s" and "s" will be returned.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward PilatowiczPlofspath(const char *path, char *s, size_t n)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char tmp[PATH_MAX + 1];
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner struct stat64 statb;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner const char *special;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char *p, *p2;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz int rv;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Plofspath path '%s'\n", path);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* We only deal with absolute paths */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (path[0] != '/')
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Make a copy of the path so that we can muck with it */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(tmp, path, sizeof (tmp) - 1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Use resolvepath() to make sure there are no consecutive or
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * trailing '/'s in the path.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((rv = resolvepath(tmp, tmp, sizeof (tmp) - 1)) >= 0)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz tmp[rv] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner (void) mutex_lock(&lofs_lock);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner /*
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * If /etc/mnttab has been modified since the last time
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner * we looked, then rebuild the lofs lookup cache.
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner */
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner if (stat64(MNTTAB, &statb) == 0 &&
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner (statb.st_mtim.tv_sec != lofs_mstat.st_mtim.tv_sec ||
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner statb.st_mtim.tv_nsec != lofs_mstat.st_mtim.tv_nsec ||
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner statb.st_ctim.tv_sec != lofs_mstat.st_ctim.tv_sec ||
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner statb.st_ctim.tv_nsec != lofs_mstat.st_ctim.tv_nsec)) {
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner lofs_mstat = statb;
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner rebuild_lofs_cache();
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner }
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * So now we're going to search the path for any components that
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * might be lofs mounts. We'll start out search from the full
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * path and then step back through each parent directly till
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * we reach the root. If we find a lofs mount point in the path
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * then we'll replace the initial portion of the path (up
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * to that mount point) with the source of that mount point
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * and then start our search over again.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Here's some of the variables we're going to use:
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * tmp - A pointer to our working copy of the path. Sometimes
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * this path will be divided into two strings by a
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * '\0' (NUL) character. The first string is the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * component we're currently checking and the second
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * string is the path components we've already checked.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * p - A pointer to the last '/' seen in the string.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * p[1] - A pointer to the component of the string we've already
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * checked.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Initially, p will point to the end of our path and p[1] will point
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * to an extra '\0' (NUL) that we'll append to the end of the string.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * (This is why we declared tmp with a size of PATH_MAX + 1).
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz p = &tmp[strlen(tmp)];
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz p[1] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz for (;;) {
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner if ((special = lookup_lofs_mount_point(tmp)) != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char tmp2[PATH_MAX + 1];
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * We found a lofs mount. Update the path that we're
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * checking and start over. This means append the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * portion of the path we've already checked to the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * source of the lofs mount and re-start this entire
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * lofs resolution loop. Use resolvepath() to make
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * sure there are no consecutive or trailing '/'s
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * in the path.
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek *
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek * However, we need to be careful to handle the case of
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek * a lofs mounted file under a lofs mounted file system.
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek * In this case, we just keep going.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner (void) strlcpy(tmp2, special, sizeof (tmp2) - 1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(tmp2, "/", sizeof (tmp2) - 1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(tmp2, &p[1], sizeof (tmp2) - 1);
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek if ((rv = resolvepath(tmp2, tmp2, sizeof (tmp2) - 1)) >=
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek 0) {
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek tmp2[rv] = '\0';
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek (void) strlcpy(tmp, tmp2, sizeof (tmp) - 1);
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek p = &tmp[strlen(tmp)];
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek p[1] = '\0';
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek continue;
b00e809c3e9ef3c14558dfdbbc80115ede90be81Jerry Jelinek }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* No lofs mount found */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((p2 = strrchr(tmp, '/')) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char tmp2[PATH_MAX];
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner (void) mutex_unlock(&lofs_lock);
a7e1d0d300de20869e70883ddfa4a5ca867ce135Roger A. Faulkner
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * We know that tmp was an absolute path, so if we
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * made it here we know that (p == tmp) and that
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * (*p == '\0'). This means that we've managed
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * to check the whole path and so we're done.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz assert(p == tmp);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz assert(p[0] == '\0');
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Restore the leading '/' in the path */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz p[0] = '/';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (strcmp(tmp, path) == 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* The path didn't change */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * It's possible that lofs source path we just
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * obtained contains a symbolic link. Use
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * resolvepath() to clean it up.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(tmp2, tmp, sizeof (tmp2));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((rv = resolvepath(tmp, tmp, sizeof (tmp) - 1)) >= 0)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz tmp[rv] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * It's always possible that our lofs source path is
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * actually another lofs mount. So call ourselves
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * recursively to resolve that path.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) Plofspath(tmp, tmp, PATH_MAX);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Copy out our final resolved lofs source path */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, tmp, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Plofspath path result '%s'\n", s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * So the path we just checked is not a lofs mount. Next we
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * want to check the parent path component for a lofs mount.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * First, restore any '/' that we replaced with a '\0' (NUL).
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * We can determine if we should do this by looking at p[1].
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * If p[1] points to a '\0' (NUL) then we know that p points
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * to the end of the string and there is no '/' to restore.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * if p[1] doesn't point to a '\0' (NUL) then it points to
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * the part of the path that we've already verified so there
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * is a '/' to restore.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (p[1] != '\0')
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz p[0] = '/';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Second, replace the last '/' in the part of the path
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * that we've already checked with a '\0' (NUL) so that
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * when we loop around we check the parent component of the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * path.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz p2[0] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz p = p2;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*NOTREACHED*/
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Pzonepath() - Way too much code to attempt to derive the full path of
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * an object within a zone.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Pzonepath() takes a path and attempts to resolve it relative to the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * root associated with the current process handle. If it fails it will
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * not update the results string. It is safe to specify the same pointer
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * for the file string and the results string.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Doing this resolution is more difficult than it initially sounds.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * We can't simply append the file path to the zone root, because in
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * a root directory, '..' is treated the same as '.'. Also, symbolic
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * links that specify an absolute path need to be interpreted relative
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * to the zone root.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * It seems like perhaps we could do a chroot(<zone root>) followed by a
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * resolvepath(). But we can't do this because chroot requires special
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * privileges and affects the entire process. Perhaps if there was a
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * special version of resolvepath() which took an addition root path
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * we could use that, but this isn't ideal either. The reason is
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * that we want to have special handling for native paths. (A native path
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * is a path that begins with "/native/" or "/.SUNWnative/".) Native
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * paths could be passed explicity to this function or could be embedded
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * in a symlink that is part of the path passed into this function.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * These paths are always lofs mounts of global zone paths, but lofs
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * mounts only exist when a zone is booted. So if we were to try to do
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * a resolvepath() on a native path when the zone wasn't booted the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * resolvepath() would fail even though we know that the components
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * exists in the global zone.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Given all these constraints, we just implement a path walking function
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * that resolves a file path relative to a zone root by manually inspecting
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * each of the path components and verifying its existence. This means that
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * we must have access to the zone and that all the components of the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * path must exist for this operation to succeed.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward PilatowiczPzonepath(struct ps_prochandle *P, const char *path, char *s, size_t n)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char zroot[PATH_MAX], zpath[PATH_MAX], tmp[PATH_MAX], link[PATH_MAX];
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz path_node_t *pn_stack = NULL, *pn_links = NULL, *pn;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz struct stat64 sb;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char *p;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz int i, rv;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath lookup '%s'\n", path);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* First lookup the zone root */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Pzoneroot(P, zroot, sizeof (zroot)) == NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Make a temporary copy of the path specified.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * If it's a relative path then make it into an absolute path.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz tmp[0] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (path[0] != '/')
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(tmp, "/", sizeof (tmp));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(tmp, path, sizeof (tmp));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * If the path that was passed in is the zone root, we're done.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * If the path that was passed in already contains the zone root
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * then strip the zone root out and verify the rest of the path.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (strcmp(tmp, zroot) == 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) Plofspath(zroot, zroot, sizeof (zroot));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath found zone path (1) '%s'\n", zroot);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, zroot, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz i = strlen(zroot);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((strncmp(tmp, zroot, i) == 0) && (tmp[i] == '/'))
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) memmove(tmp, tmp + i, strlen(tmp + i) + 1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* If no path is passed in, then it maps to the zone root */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (strlen(tmp) == 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) Plofspath(zroot, zroot, sizeof (zroot));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath found zone path (2) '%s'\n", zroot);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, zroot, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Push each path component that we plan to verify onto a stack of
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * path components, with parent components at the top of the stack.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * So for example, if we're going to verify the path /foo/bar/bang
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * then our stack will look like:
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * foo (top)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * bar
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * bang (bottom)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz while ((p = strrchr(tmp, '/')) != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *p = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (pn_push(&pn_stack, &p[1]) != NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free(&pn_stack);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* We're going to store the final zone relative path in zpath */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *zpath = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz while (pn_pop(&pn_stack, tmp) != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Drop zero length path components (which come from
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * consecutive '/'s) and '.' path components.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((strlen(tmp) == 0) || (strcmp(tmp, ".") == 0))
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Check the current path component for '..', if found
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * drop any previous path component.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (strcmp(tmp, "..") == 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((p = strrchr(zpath, '/')) != NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *p = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* The path we want to verify now is zpath + / + tmp. */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(zpath, "/", sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(zpath, tmp, sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Check if this is a native object. A native object is an
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * object from the global zone that is running in a branded
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * zone. These objects are lofs mounted into a zone. So if a
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * branded zone is not booted then lofs mounts won't be setup
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * so we won't be able to find these objects. Luckily, we know
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * that they exist in the global zone with the same path sans
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * the initial native component, so we'll just strip out the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * native component here.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((strncmp(zpath, "/native", sizeof ("/native")) == 0) ||
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (strncmp(zpath, "/.SUNWnative",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz sizeof ("/.SUNWnative")) == 0)) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Free any cached symlink paths */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free(&pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Reconstruct the path from our path component stack */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *zpath = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz while (pn_pop(&pn_stack, tmp) != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(zpath, "/", sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(zpath, tmp, sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Verify that the path actually exists */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz rv = resolvepath(zpath, tmp, sizeof (tmp) - 1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (rv < 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath invalid native path '%s'\n",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz zpath);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz tmp[rv] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Return the path */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath found native path '%s'\n", tmp);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) Plofspath(tmp, tmp, sizeof (tmp));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, tmp, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Check if the path points to a symlink. We do this
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * explicitly since any absolute symlink needs to be
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * interpreted relativly to the zone root and not "/".
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(tmp, zroot, sizeof (tmp));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(tmp, zpath, sizeof (tmp));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (lstat64(tmp, &sb) != 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free2(&pn_stack, &pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (!S_ISLNK(sb.st_mode)) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Since the lstat64() above succeeded we know that
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * zpath exists, since this is not a symlink loop
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * around and check the next path component.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Symlink allow for paths with loops. Make sure
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * we're not stuck in a loop.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz for (pn = pn_links; pn != NULL; pn = pn->pn_next) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (strcmp(zpath, pn->pn_path) != 0)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* We have a loop. Fail. */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath symlink loop '%s'\n", zpath);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free2(&pn_stack, &pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Save this symlink path for future loop checks */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (pn_push(&pn_links, zpath) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Out of memory */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free2(&pn_stack, &pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Now follow the contents of the symlink */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz bzero(link, sizeof (link));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (readlink(tmp, link, sizeof (link)) == -1) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free2(&pn_stack, &pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath following symlink '%s' -> '%s'\n",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz zpath, link);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Push each path component of the symlink target onto our
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * path components stack since we need to verify each one.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz while ((p = strrchr(link, '/')) != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *p = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (pn_push(&pn_stack, &p[1]) != NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free2(&pn_stack, &pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* absolute or relative symlink? */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (*link == '\0') {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Absolute symlink, nuke existing zpath. */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *zpath = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Relative symlink. Push the first path component of the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * symlink target onto our stack for verification and then
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * remove the current path component from zpath.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (pn_push(&pn_stack, link) == NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free2(&pn_stack, &pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz p = strrchr(zpath, '/');
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz assert(p != NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *p = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz continue;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz pn_free(&pn_links);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Place the final result in zpath */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(tmp, zroot, sizeof (tmp));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcat(tmp, zpath, sizeof (tmp));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(zpath, tmp, sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) Plofspath(zpath, zpath, sizeof (zpath));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pzonepath found zone path (3) '%s'\n", zpath);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, zpath, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward PilatowiczPfindobj(struct ps_prochandle *P, const char *path, char *s, size_t n)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz int len;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dprintf("Pfindobj '%s'\n", path);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* We only deal with absolute paths */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (path[0] != '/')
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* First try to resolve the path to some zone */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Pzonepath(P, path, s, n) != NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* If that fails resolve any lofs links in the path */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Plofspath(path, s, n) != NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* If that fails then just see if the path exists */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((len = resolvepath(path, s, n)) > 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz s[len] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward PilatowiczPfindmap(struct ps_prochandle *P, map_info_t *mptr, char *s, size_t n)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz file_info_t *fptr = mptr->map_file;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char buf[PATH_MAX];
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz int len;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* If it's already been explicity set return that */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((fptr != NULL) && (fptr->file_rname != NULL)) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, fptr->file_rname, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* If it's the a.out segment, defer to the magical Pexecname() */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((P->map_exec == mptr) ||
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (strcmp(mptr->map_pmap.pr_mapname, "a.out") == 0) ||
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz ((fptr != NULL) && (fptr->file_lname != NULL) &&
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (strcmp(fptr->file_lname, "a.out") == 0))) {
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill if (Pexecname(P, buf, sizeof (buf)) != NULL) {
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill (void) strlcpy(s, buf, n);
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill return (s);
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Try /proc first to get the real object name */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((Pstate(P) != PS_DEAD) && (mptr->map_pmap.pr_mapname[0] != '\0')) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) snprintf(buf, sizeof (buf), "%s/%d/path/%s",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz procfs_path, (int)P->pid, mptr->map_pmap.pr_mapname);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((len = readlink(buf, buf, sizeof (buf))) > 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz buf[len] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) Plofspath(buf, buf, sizeof (buf));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, buf, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * If we couldn't get the name from /proc, take the lname and
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * try to expand it on the current system to a real object path.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz fptr = mptr->map_file;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((fptr != NULL) && (fptr->file_lname != NULL)) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(buf, fptr->file_lname, sizeof (buf));
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Pfindobj(P, buf, buf, sizeof (buf)) == NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strlcpy(s, buf, n);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (s);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}