1*186f7fbfSEdward Pilatowicz /* 2*186f7fbfSEdward Pilatowicz * CDDL HEADER START 3*186f7fbfSEdward Pilatowicz * 4*186f7fbfSEdward Pilatowicz * The contents of this file are subject to the terms of the 5*186f7fbfSEdward Pilatowicz * Common Development and Distribution License (the "License"). 6*186f7fbfSEdward Pilatowicz * You may not use this file except in compliance with the License. 7*186f7fbfSEdward Pilatowicz * 8*186f7fbfSEdward Pilatowicz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*186f7fbfSEdward Pilatowicz * or http://www.opensolaris.org/os/licensing. 10*186f7fbfSEdward Pilatowicz * See the License for the specific language governing permissions 11*186f7fbfSEdward Pilatowicz * and limitations under the License. 12*186f7fbfSEdward Pilatowicz * 13*186f7fbfSEdward Pilatowicz * When distributing Covered Code, include this CDDL HEADER in each 14*186f7fbfSEdward Pilatowicz * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*186f7fbfSEdward Pilatowicz * If applicable, add the following below this CDDL HEADER, with the 16*186f7fbfSEdward Pilatowicz * fields enclosed by brackets "[]" replaced with your own identifying 17*186f7fbfSEdward Pilatowicz * information: Portions Copyright [yyyy] [name of copyright owner] 18*186f7fbfSEdward Pilatowicz * 19*186f7fbfSEdward Pilatowicz * CDDL HEADER END 20*186f7fbfSEdward Pilatowicz */ 21*186f7fbfSEdward Pilatowicz 22*186f7fbfSEdward Pilatowicz /* 23*186f7fbfSEdward Pilatowicz * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*186f7fbfSEdward Pilatowicz * Use is subject to license terms. 25*186f7fbfSEdward Pilatowicz */ 26*186f7fbfSEdward Pilatowicz 27*186f7fbfSEdward Pilatowicz #include <assert.h> 28*186f7fbfSEdward Pilatowicz #include <dlfcn.h> 29*186f7fbfSEdward Pilatowicz #include <errno.h> 30*186f7fbfSEdward Pilatowicz #include <libzonecfg.h> 31*186f7fbfSEdward Pilatowicz #include <link.h> 32*186f7fbfSEdward Pilatowicz #include <string.h> 33*186f7fbfSEdward Pilatowicz #include <strings.h> 34*186f7fbfSEdward Pilatowicz #include <sys/list.h> 35*186f7fbfSEdward Pilatowicz #include <sys/types.h> 36*186f7fbfSEdward Pilatowicz #include <sys/mkdev.h> 37*186f7fbfSEdward Pilatowicz #include <sys/mman.h> 38*186f7fbfSEdward Pilatowicz #include <sys/mnttab.h> 39*186f7fbfSEdward Pilatowicz 40*186f7fbfSEdward Pilatowicz #include "Pcontrol.h" 41*186f7fbfSEdward Pilatowicz 42*186f7fbfSEdward Pilatowicz struct path_node { 43*186f7fbfSEdward Pilatowicz struct path_node *pn_next; 44*186f7fbfSEdward Pilatowicz char *pn_path; 45*186f7fbfSEdward Pilatowicz }; 46*186f7fbfSEdward Pilatowicz typedef struct path_node path_node_t; 47*186f7fbfSEdward Pilatowicz 48*186f7fbfSEdward Pilatowicz static path_node_t * 49*186f7fbfSEdward Pilatowicz pn_push(path_node_t **pnp, char *path) 50*186f7fbfSEdward Pilatowicz { 51*186f7fbfSEdward Pilatowicz path_node_t *pn; 52*186f7fbfSEdward Pilatowicz 53*186f7fbfSEdward Pilatowicz if ((pn = calloc(sizeof (path_node_t), 1)) == NULL) 54*186f7fbfSEdward Pilatowicz return (NULL); 55*186f7fbfSEdward Pilatowicz 56*186f7fbfSEdward Pilatowicz if ((pn->pn_path = strdup(path)) == NULL) { 57*186f7fbfSEdward Pilatowicz free(pn); 58*186f7fbfSEdward Pilatowicz return (NULL); 59*186f7fbfSEdward Pilatowicz } 60*186f7fbfSEdward Pilatowicz pn->pn_next = *pnp; 61*186f7fbfSEdward Pilatowicz return (*pnp = pn); 62*186f7fbfSEdward Pilatowicz } 63*186f7fbfSEdward Pilatowicz 64*186f7fbfSEdward Pilatowicz static void 65*186f7fbfSEdward Pilatowicz pn_free(path_node_t **pnp) 66*186f7fbfSEdward Pilatowicz { 67*186f7fbfSEdward Pilatowicz path_node_t *pn; 68*186f7fbfSEdward Pilatowicz 69*186f7fbfSEdward Pilatowicz while (*pnp != NULL) { 70*186f7fbfSEdward Pilatowicz pn = *pnp; 71*186f7fbfSEdward Pilatowicz *pnp = pn->pn_next; 72*186f7fbfSEdward Pilatowicz free(pn->pn_path); 73*186f7fbfSEdward Pilatowicz free(pn); 74*186f7fbfSEdward Pilatowicz } 75*186f7fbfSEdward Pilatowicz } 76*186f7fbfSEdward Pilatowicz 77*186f7fbfSEdward Pilatowicz static void 78*186f7fbfSEdward Pilatowicz pn_free2(path_node_t **pn1, path_node_t **pn2) 79*186f7fbfSEdward Pilatowicz { 80*186f7fbfSEdward Pilatowicz pn_free(pn1); 81*186f7fbfSEdward Pilatowicz pn_free(pn2); 82*186f7fbfSEdward Pilatowicz } 83*186f7fbfSEdward Pilatowicz 84*186f7fbfSEdward Pilatowicz static char * 85*186f7fbfSEdward Pilatowicz pn_pop(path_node_t **pnp, char *path) 86*186f7fbfSEdward Pilatowicz { 87*186f7fbfSEdward Pilatowicz path_node_t *pn; 88*186f7fbfSEdward Pilatowicz 89*186f7fbfSEdward Pilatowicz if (*pnp == NULL) 90*186f7fbfSEdward Pilatowicz return (NULL); 91*186f7fbfSEdward Pilatowicz 92*186f7fbfSEdward Pilatowicz pn = *pnp; 93*186f7fbfSEdward Pilatowicz *pnp = pn->pn_next; 94*186f7fbfSEdward Pilatowicz pn->pn_next = NULL; 95*186f7fbfSEdward Pilatowicz 96*186f7fbfSEdward Pilatowicz if (path == NULL) { 97*186f7fbfSEdward Pilatowicz pn_free(&pn); 98*186f7fbfSEdward Pilatowicz return (NULL); 99*186f7fbfSEdward Pilatowicz } 100*186f7fbfSEdward Pilatowicz (void) strlcpy(path, pn->pn_path, PATH_MAX); 101*186f7fbfSEdward Pilatowicz pn_free(&pn); 102*186f7fbfSEdward Pilatowicz return (path); 103*186f7fbfSEdward Pilatowicz } 104*186f7fbfSEdward Pilatowicz 105*186f7fbfSEdward Pilatowicz 106*186f7fbfSEdward Pilatowicz /* 107*186f7fbfSEdward Pilatowicz * Libzonecfg.so links against libproc, so libproc can't link against 108*186f7fbfSEdward Pilatowicz * libzonecfg.so. Also, libzonecfg.so is optional and might not be 109*186f7fbfSEdward Pilatowicz * installed. Hence instead of relying on linking to access libzonecfg.so, 110*186f7fbfSEdward Pilatowicz * we'll try dlopening it here. This trick is borrowed from 111*186f7fbfSEdward Pilatowicz * libc`zone_get_id(), see that function for more detailed comments. 112*186f7fbfSEdward Pilatowicz */ 113*186f7fbfSEdward Pilatowicz static int 114*186f7fbfSEdward Pilatowicz i_zone_get_zonepath(char *zone_name, char *zonepath, size_t rp_sz) 115*186f7fbfSEdward Pilatowicz { 116*186f7fbfSEdward Pilatowicz typedef int (*zone_get_zonepath_t)(char *, char *, size_t); 117*186f7fbfSEdward Pilatowicz static zone_get_zonepath_t zone_get_zonepath_fp = NULL; 118*186f7fbfSEdward Pilatowicz 119*186f7fbfSEdward Pilatowicz if (zone_get_zonepath_fp == NULL) { 120*186f7fbfSEdward Pilatowicz /* There's no harm in doing this multiple times. */ 121*186f7fbfSEdward Pilatowicz void *dlhandle = dlopen("libzonecfg.so.1", RTLD_LAZY); 122*186f7fbfSEdward Pilatowicz void *sym = (void *)(-1); 123*186f7fbfSEdward Pilatowicz if (dlhandle != NULL && 124*186f7fbfSEdward Pilatowicz (sym = dlsym(dlhandle, "zone_get_zonepath")) == NULL) { 125*186f7fbfSEdward Pilatowicz sym = (void *)(-1); 126*186f7fbfSEdward Pilatowicz (void) dlclose(dlhandle); 127*186f7fbfSEdward Pilatowicz } 128*186f7fbfSEdward Pilatowicz zone_get_zonepath_fp = (zone_get_zonepath_t)sym; 129*186f7fbfSEdward Pilatowicz } 130*186f7fbfSEdward Pilatowicz 131*186f7fbfSEdward Pilatowicz /* If we've successfully loaded it, call the real function */ 132*186f7fbfSEdward Pilatowicz if (zone_get_zonepath_fp != (zone_get_zonepath_t)(-1)) 133*186f7fbfSEdward Pilatowicz return (zone_get_zonepath_fp(zone_name, zonepath, rp_sz)); 134*186f7fbfSEdward Pilatowicz return (Z_NO_ZONE); 135*186f7fbfSEdward Pilatowicz } 136*186f7fbfSEdward Pilatowicz 137*186f7fbfSEdward Pilatowicz char * 138*186f7fbfSEdward Pilatowicz Pbrandname(struct ps_prochandle *P, char *buf, size_t buflen) 139*186f7fbfSEdward Pilatowicz { 140*186f7fbfSEdward Pilatowicz long addr; 141*186f7fbfSEdward Pilatowicz 142*186f7fbfSEdward Pilatowicz if ((addr = Pgetauxval(P, AT_SUN_BRANDNAME)) == -1) 143*186f7fbfSEdward Pilatowicz return (NULL); 144*186f7fbfSEdward Pilatowicz 145*186f7fbfSEdward Pilatowicz if (Pread_string(P, buf, buflen, addr) == -1) 146*186f7fbfSEdward Pilatowicz return (NULL); 147*186f7fbfSEdward Pilatowicz 148*186f7fbfSEdward Pilatowicz return (buf); 149*186f7fbfSEdward Pilatowicz } 150*186f7fbfSEdward Pilatowicz 151*186f7fbfSEdward Pilatowicz /* 152*186f7fbfSEdward Pilatowicz * Get the zone name from the core file if we have it; look up the 153*186f7fbfSEdward Pilatowicz * name based on the zone id if this is a live process. 154*186f7fbfSEdward Pilatowicz */ 155*186f7fbfSEdward Pilatowicz char * 156*186f7fbfSEdward Pilatowicz Pzonename(struct ps_prochandle *P, char *s, size_t n) 157*186f7fbfSEdward Pilatowicz { 158*186f7fbfSEdward Pilatowicz if (P->state == PS_IDLE) { 159*186f7fbfSEdward Pilatowicz errno = ENODATA; 160*186f7fbfSEdward Pilatowicz return (NULL); 161*186f7fbfSEdward Pilatowicz } 162*186f7fbfSEdward Pilatowicz 163*186f7fbfSEdward Pilatowicz if (P->state == PS_DEAD) { 164*186f7fbfSEdward Pilatowicz if (P->core->core_zonename == NULL) { 165*186f7fbfSEdward Pilatowicz errno = ENODATA; 166*186f7fbfSEdward Pilatowicz return (NULL); 167*186f7fbfSEdward Pilatowicz } 168*186f7fbfSEdward Pilatowicz (void) strlcpy(s, P->core->core_zonename, n); 169*186f7fbfSEdward Pilatowicz } else { 170*186f7fbfSEdward Pilatowicz if (getzonenamebyid(P->status.pr_zoneid, s, n) < 0) 171*186f7fbfSEdward Pilatowicz return (NULL); 172*186f7fbfSEdward Pilatowicz s[n - 1] = '\0'; 173*186f7fbfSEdward Pilatowicz } 174*186f7fbfSEdward Pilatowicz return (s); 175*186f7fbfSEdward Pilatowicz } 176*186f7fbfSEdward Pilatowicz 177*186f7fbfSEdward Pilatowicz char * 178*186f7fbfSEdward Pilatowicz Pzoneroot(struct ps_prochandle *P, char *s, size_t n) 179*186f7fbfSEdward Pilatowicz { 180*186f7fbfSEdward Pilatowicz char zname[ZONENAME_MAX], zpath[PATH_MAX], tmp[PATH_MAX]; 181*186f7fbfSEdward Pilatowicz int rv; 182*186f7fbfSEdward Pilatowicz 183*186f7fbfSEdward Pilatowicz if (P->zoneroot != NULL) { 184*186f7fbfSEdward Pilatowicz (void) strlcpy(s, P->zoneroot, n); 185*186f7fbfSEdward Pilatowicz return (s); 186*186f7fbfSEdward Pilatowicz } 187*186f7fbfSEdward Pilatowicz 188*186f7fbfSEdward Pilatowicz if ((Pzonename(P, zname, sizeof (zname)) == NULL) || 189*186f7fbfSEdward Pilatowicz (strcmp(zname, GLOBAL_ZONENAME) == 0)) { 190*186f7fbfSEdward Pilatowicz if ((P->zoneroot = strdup("")) == NULL) { 191*186f7fbfSEdward Pilatowicz errno = ENOMEM; 192*186f7fbfSEdward Pilatowicz return (NULL); 193*186f7fbfSEdward Pilatowicz } 194*186f7fbfSEdward Pilatowicz dprintf("Pzoneroot defaulting to '%s'\n", GLOBAL_ZONENAME); 195*186f7fbfSEdward Pilatowicz (void) strlcpy(s, P->zoneroot, n); 196*186f7fbfSEdward Pilatowicz return (s); 197*186f7fbfSEdward Pilatowicz } 198*186f7fbfSEdward Pilatowicz 199*186f7fbfSEdward Pilatowicz if (i_zone_get_zonepath(zname, zpath, sizeof (zpath)) != Z_OK) { 200*186f7fbfSEdward Pilatowicz if ((P->zoneroot = strdup("")) == NULL) { 201*186f7fbfSEdward Pilatowicz errno = ENOMEM; 202*186f7fbfSEdward Pilatowicz return (NULL); 203*186f7fbfSEdward Pilatowicz } 204*186f7fbfSEdward Pilatowicz dprintf( 205*186f7fbfSEdward Pilatowicz "Pzoneroot zone not found '%s', defaulting to '%s'\n", 206*186f7fbfSEdward Pilatowicz zname, GLOBAL_ZONENAME); 207*186f7fbfSEdward Pilatowicz (void) strlcpy(s, P->zoneroot, n); 208*186f7fbfSEdward Pilatowicz return (s); 209*186f7fbfSEdward Pilatowicz } 210*186f7fbfSEdward Pilatowicz (void) strlcat(zpath, "/root", sizeof (zpath)); 211*186f7fbfSEdward Pilatowicz 212*186f7fbfSEdward Pilatowicz if ((rv = resolvepath(zpath, tmp, sizeof (tmp) - 1)) < 0) { 213*186f7fbfSEdward Pilatowicz if ((P->zoneroot = strdup("")) == NULL) { 214*186f7fbfSEdward Pilatowicz errno = ENOMEM; 215*186f7fbfSEdward Pilatowicz return (NULL); 216*186f7fbfSEdward Pilatowicz } 217*186f7fbfSEdward Pilatowicz dprintf( 218*186f7fbfSEdward Pilatowicz "Pzoneroot can't access '%s:%s', defaulting to '%s'\n", 219*186f7fbfSEdward Pilatowicz zname, zpath, GLOBAL_ZONENAME); 220*186f7fbfSEdward Pilatowicz (void) strlcpy(s, P->zoneroot, n); 221*186f7fbfSEdward Pilatowicz return (s); 222*186f7fbfSEdward Pilatowicz } 223*186f7fbfSEdward Pilatowicz tmp[rv] = '\0'; 224*186f7fbfSEdward Pilatowicz (void) strlcpy(zpath, tmp, sizeof (zpath)); 225*186f7fbfSEdward Pilatowicz 226*186f7fbfSEdward Pilatowicz if ((P->zoneroot = strdup(zpath)) == NULL) { 227*186f7fbfSEdward Pilatowicz errno = ENOMEM; 228*186f7fbfSEdward Pilatowicz return (NULL); 229*186f7fbfSEdward Pilatowicz } 230*186f7fbfSEdward Pilatowicz dprintf("Pzoneroot found zone root '%s:%s'\n", zname, zpath); 231*186f7fbfSEdward Pilatowicz (void) strlcpy(s, P->zoneroot, n); 232*186f7fbfSEdward Pilatowicz return (s); 233*186f7fbfSEdward Pilatowicz } 234*186f7fbfSEdward Pilatowicz 235*186f7fbfSEdward Pilatowicz /* 236*186f7fbfSEdward Pilatowicz * Plofspath() takes a path, "path", and removes any lofs components from 237*186f7fbfSEdward Pilatowicz * that path. The resultant path (if different from the starting path) 238*186f7fbfSEdward Pilatowicz * is placed in "s", which is limited to "n" characters, and the return 239*186f7fbfSEdward Pilatowicz * value is the pointer s. If there are no lofs components in the path 240*186f7fbfSEdward Pilatowicz * the NULL is returned and s is not modified. It's ok for "path" and 241*186f7fbfSEdward Pilatowicz * "s" to be the same pointer. (ie, the results can be stored directly 242*186f7fbfSEdward Pilatowicz * in the input buffer.) The path that is passed in must be an absolute 243*186f7fbfSEdward Pilatowicz * path. 244*186f7fbfSEdward Pilatowicz * 245*186f7fbfSEdward Pilatowicz * Example: 246*186f7fbfSEdward Pilatowicz * if "path" == "/foo/bar", and "/candy/" is lofs mounted on "/foo/" 247*186f7fbfSEdward Pilatowicz * then "/candy/bar/" will be written into "s" and "s" will be returned. 248*186f7fbfSEdward Pilatowicz */ 249*186f7fbfSEdward Pilatowicz char * 250*186f7fbfSEdward Pilatowicz Plofspath(const char *path, char *s, size_t n) 251*186f7fbfSEdward Pilatowicz { 252*186f7fbfSEdward Pilatowicz char tmp[PATH_MAX + 1]; 253*186f7fbfSEdward Pilatowicz struct mnttab mt, mt_find; 254*186f7fbfSEdward Pilatowicz FILE *fp; 255*186f7fbfSEdward Pilatowicz char *p, *p2; 256*186f7fbfSEdward Pilatowicz int rv; 257*186f7fbfSEdward Pilatowicz 258*186f7fbfSEdward Pilatowicz dprintf("Plofspath path '%s'\n", path); 259*186f7fbfSEdward Pilatowicz 260*186f7fbfSEdward Pilatowicz /* We only deal with absolute paths */ 261*186f7fbfSEdward Pilatowicz if (path[0] != '/') 262*186f7fbfSEdward Pilatowicz return (NULL); 263*186f7fbfSEdward Pilatowicz 264*186f7fbfSEdward Pilatowicz /* Open /etc/mnttab */ 265*186f7fbfSEdward Pilatowicz if ((fp = fopen(MNTTAB, "r")) == NULL) 266*186f7fbfSEdward Pilatowicz return (NULL); 267*186f7fbfSEdward Pilatowicz 268*186f7fbfSEdward Pilatowicz /* Make a copy of the path so that we can muck with it */ 269*186f7fbfSEdward Pilatowicz (void) strlcpy(tmp, path, sizeof (tmp) - 1); 270*186f7fbfSEdward Pilatowicz 271*186f7fbfSEdward Pilatowicz /* 272*186f7fbfSEdward Pilatowicz * Use resolvepath() to make sure there are no consecutive or 273*186f7fbfSEdward Pilatowicz * trailing '/'s in the path. 274*186f7fbfSEdward Pilatowicz */ 275*186f7fbfSEdward Pilatowicz if ((rv = resolvepath(tmp, tmp, sizeof (tmp) - 1)) >= 0) 276*186f7fbfSEdward Pilatowicz tmp[rv] = '\0'; 277*186f7fbfSEdward Pilatowicz 278*186f7fbfSEdward Pilatowicz /* 279*186f7fbfSEdward Pilatowicz * So now we're going to search the path for any components that 280*186f7fbfSEdward Pilatowicz * might be lofs mounts. We'll start out search from the full 281*186f7fbfSEdward Pilatowicz * path and then step back through each parent directly till 282*186f7fbfSEdward Pilatowicz * we reach the root. If we find a lofs mount point in the path 283*186f7fbfSEdward Pilatowicz * then we'll replace the initial portion of the path (up 284*186f7fbfSEdward Pilatowicz * to that mount point) with the source of that mount point 285*186f7fbfSEdward Pilatowicz * and then start our search over again. 286*186f7fbfSEdward Pilatowicz * 287*186f7fbfSEdward Pilatowicz * Here's some of the variables we're going to use: 288*186f7fbfSEdward Pilatowicz * 289*186f7fbfSEdward Pilatowicz * tmp - A pointer to our working copy of the path. Sometimes 290*186f7fbfSEdward Pilatowicz * this path will be divided into two strings by a 291*186f7fbfSEdward Pilatowicz * '\0' (NUL) character. The first string is the 292*186f7fbfSEdward Pilatowicz * component we're currently checking and the second 293*186f7fbfSEdward Pilatowicz * string is the path components we've already checked. 294*186f7fbfSEdward Pilatowicz * 295*186f7fbfSEdward Pilatowicz * p - A pointer to the last '/' seen in the string. 296*186f7fbfSEdward Pilatowicz * 297*186f7fbfSEdward Pilatowicz * p[1] - A pointer to the component of the string we've already 298*186f7fbfSEdward Pilatowicz * checked. 299*186f7fbfSEdward Pilatowicz * 300*186f7fbfSEdward Pilatowicz * Initially, p will point to the end of our path and p[1] will point 301*186f7fbfSEdward Pilatowicz * to an extra '\0' (NUL) that we'll append to the end of the string. 302*186f7fbfSEdward Pilatowicz * (This is why we declared tmp with a size of PATH_MAX + 1). 303*186f7fbfSEdward Pilatowicz */ 304*186f7fbfSEdward Pilatowicz p = &tmp[strlen(tmp)]; 305*186f7fbfSEdward Pilatowicz p[1] = '\0'; 306*186f7fbfSEdward Pilatowicz for (;;) { 307*186f7fbfSEdward Pilatowicz /* Check if tmp is a mount point */ 308*186f7fbfSEdward Pilatowicz rewind(fp); 309*186f7fbfSEdward Pilatowicz bzero(&mt_find, sizeof (mt_find)); 310*186f7fbfSEdward Pilatowicz mt_find.mnt_mountp = tmp; 311*186f7fbfSEdward Pilatowicz rv = getmntany(fp, &mt, &mt_find); 312*186f7fbfSEdward Pilatowicz 313*186f7fbfSEdward Pilatowicz /* We only care about lofs mount points */ 314*186f7fbfSEdward Pilatowicz if ((rv == 0) && (strcmp(mt.mnt_fstype, "lofs") == 0)) { 315*186f7fbfSEdward Pilatowicz char tmp2[PATH_MAX + 1]; 316*186f7fbfSEdward Pilatowicz 317*186f7fbfSEdward Pilatowicz /* 318*186f7fbfSEdward Pilatowicz * We found a lofs mount. Update the path that we're 319*186f7fbfSEdward Pilatowicz * checking and start over. This means append the 320*186f7fbfSEdward Pilatowicz * portion of the path we've already checked to the 321*186f7fbfSEdward Pilatowicz * source of the lofs mount and re-start this entire 322*186f7fbfSEdward Pilatowicz * lofs resolution loop. Use resolvepath() to make 323*186f7fbfSEdward Pilatowicz * sure there are no consecutive or trailing '/'s 324*186f7fbfSEdward Pilatowicz * in the path. 325*186f7fbfSEdward Pilatowicz */ 326*186f7fbfSEdward Pilatowicz (void) strlcpy(tmp2, mt.mnt_special, sizeof (tmp2) - 1); 327*186f7fbfSEdward Pilatowicz (void) strlcat(tmp2, "/", sizeof (tmp2) - 1); 328*186f7fbfSEdward Pilatowicz (void) strlcat(tmp2, &p[1], sizeof (tmp2) - 1); 329*186f7fbfSEdward Pilatowicz (void) strlcpy(tmp, tmp2, sizeof (tmp) - 1); 330*186f7fbfSEdward Pilatowicz if ((rv = resolvepath(tmp, tmp, sizeof (tmp) - 1)) >= 0) 331*186f7fbfSEdward Pilatowicz tmp[rv] = '\0'; 332*186f7fbfSEdward Pilatowicz p = &tmp[strlen(tmp)]; 333*186f7fbfSEdward Pilatowicz p[1] = '\0'; 334*186f7fbfSEdward Pilatowicz continue; 335*186f7fbfSEdward Pilatowicz } 336*186f7fbfSEdward Pilatowicz 337*186f7fbfSEdward Pilatowicz /* No lofs mount found */ 338*186f7fbfSEdward Pilatowicz if ((p2 = strrchr(tmp, '/')) == NULL) { 339*186f7fbfSEdward Pilatowicz char tmp2[PATH_MAX]; 340*186f7fbfSEdward Pilatowicz 341*186f7fbfSEdward Pilatowicz /* 342*186f7fbfSEdward Pilatowicz * We know that tmp was an absolute path, so if we 343*186f7fbfSEdward Pilatowicz * made it here we know that (p == tmp) and that 344*186f7fbfSEdward Pilatowicz * (*p == '\0'). This means that we've managed 345*186f7fbfSEdward Pilatowicz * to check the whole path and so we're done. 346*186f7fbfSEdward Pilatowicz */ 347*186f7fbfSEdward Pilatowicz assert(p == tmp); 348*186f7fbfSEdward Pilatowicz assert(p[0] == '\0'); 349*186f7fbfSEdward Pilatowicz (void) fclose(fp); 350*186f7fbfSEdward Pilatowicz 351*186f7fbfSEdward Pilatowicz /* Restore the leading '/' in the path */ 352*186f7fbfSEdward Pilatowicz p[0] = '/'; 353*186f7fbfSEdward Pilatowicz 354*186f7fbfSEdward Pilatowicz if (strcmp(tmp, path) == 0) { 355*186f7fbfSEdward Pilatowicz /* The path didn't change */ 356*186f7fbfSEdward Pilatowicz return (NULL); 357*186f7fbfSEdward Pilatowicz } 358*186f7fbfSEdward Pilatowicz 359*186f7fbfSEdward Pilatowicz /* 360*186f7fbfSEdward Pilatowicz * It's possible that lofs source path we just 361*186f7fbfSEdward Pilatowicz * obtained contains a symbolic link. Use 362*186f7fbfSEdward Pilatowicz * resolvepath() to clean it up. 363*186f7fbfSEdward Pilatowicz */ 364*186f7fbfSEdward Pilatowicz (void) strlcpy(tmp2, tmp, sizeof (tmp2)); 365*186f7fbfSEdward Pilatowicz if ((rv = resolvepath(tmp, tmp, sizeof (tmp) - 1)) >= 0) 366*186f7fbfSEdward Pilatowicz tmp[rv] = '\0'; 367*186f7fbfSEdward Pilatowicz 368*186f7fbfSEdward Pilatowicz /* 369*186f7fbfSEdward Pilatowicz * It's always possible that our lofs source path is 370*186f7fbfSEdward Pilatowicz * actually another lofs mount. So call ourselves 371*186f7fbfSEdward Pilatowicz * recursively to resolve that path. 372*186f7fbfSEdward Pilatowicz */ 373*186f7fbfSEdward Pilatowicz (void) Plofspath(tmp, tmp, PATH_MAX); 374*186f7fbfSEdward Pilatowicz 375*186f7fbfSEdward Pilatowicz /* Copy out our final resolved lofs source path */ 376*186f7fbfSEdward Pilatowicz (void) strlcpy(s, tmp, n); 377*186f7fbfSEdward Pilatowicz dprintf("Plofspath path result '%s'\n", s); 378*186f7fbfSEdward Pilatowicz return (s); 379*186f7fbfSEdward Pilatowicz } 380*186f7fbfSEdward Pilatowicz 381*186f7fbfSEdward Pilatowicz /* 382*186f7fbfSEdward Pilatowicz * So the path we just checked is not a lofs mount. Next we 383*186f7fbfSEdward Pilatowicz * want to check the parent path component for a lofs mount. 384*186f7fbfSEdward Pilatowicz * 385*186f7fbfSEdward Pilatowicz * First, restore any '/' that we replaced with a '\0' (NUL). 386*186f7fbfSEdward Pilatowicz * We can determine if we should do this by looking at p[1]. 387*186f7fbfSEdward Pilatowicz * If p[1] points to a '\0' (NUL) then we know that p points 388*186f7fbfSEdward Pilatowicz * to the end of the string and there is no '/' to restore. 389*186f7fbfSEdward Pilatowicz * if p[1] doesn't point to a '\0' (NUL) then it points to 390*186f7fbfSEdward Pilatowicz * the part of the path that we've already verified so there 391*186f7fbfSEdward Pilatowicz * is a '/' to restore. 392*186f7fbfSEdward Pilatowicz */ 393*186f7fbfSEdward Pilatowicz if (p[1] != '\0') 394*186f7fbfSEdward Pilatowicz p[0] = '/'; 395*186f7fbfSEdward Pilatowicz 396*186f7fbfSEdward Pilatowicz /* 397*186f7fbfSEdward Pilatowicz * Second, replace the last '/' in the part of the path 398*186f7fbfSEdward Pilatowicz * that we've already checked with a '\0' (NUL) so that 399*186f7fbfSEdward Pilatowicz * when we loop around we check the parent component of the 400*186f7fbfSEdward Pilatowicz * path. 401*186f7fbfSEdward Pilatowicz */ 402*186f7fbfSEdward Pilatowicz p2[0] = '\0'; 403*186f7fbfSEdward Pilatowicz p = p2; 404*186f7fbfSEdward Pilatowicz } 405*186f7fbfSEdward Pilatowicz /*NOTREACHED*/ 406*186f7fbfSEdward Pilatowicz } 407*186f7fbfSEdward Pilatowicz 408*186f7fbfSEdward Pilatowicz /* 409*186f7fbfSEdward Pilatowicz * Pzonepath() - Way too much code to attempt to derive the full path of 410*186f7fbfSEdward Pilatowicz * an object within a zone. 411*186f7fbfSEdward Pilatowicz * 412*186f7fbfSEdward Pilatowicz * Pzonepath() takes a path and attempts to resolve it relative to the 413*186f7fbfSEdward Pilatowicz * root associated with the current process handle. If it fails it will 414*186f7fbfSEdward Pilatowicz * not update the results string. It is safe to specify the same pointer 415*186f7fbfSEdward Pilatowicz * for the file string and the results string. 416*186f7fbfSEdward Pilatowicz * 417*186f7fbfSEdward Pilatowicz * Doing this resolution is more difficult than it initially sounds. 418*186f7fbfSEdward Pilatowicz * We can't simply append the file path to the zone root, because in 419*186f7fbfSEdward Pilatowicz * a root directory, '..' is treated the same as '.'. Also, symbolic 420*186f7fbfSEdward Pilatowicz * links that specify an absolute path need to be interpreted relative 421*186f7fbfSEdward Pilatowicz * to the zone root. 422*186f7fbfSEdward Pilatowicz * 423*186f7fbfSEdward Pilatowicz * It seems like perhaps we could do a chroot(<zone root>) followed by a 424*186f7fbfSEdward Pilatowicz * resolvepath(). But we can't do this because chroot requires special 425*186f7fbfSEdward Pilatowicz * privileges and affects the entire process. Perhaps if there was a 426*186f7fbfSEdward Pilatowicz * special version of resolvepath() which took an addition root path 427*186f7fbfSEdward Pilatowicz * we could use that, but this isn't ideal either. The reason is 428*186f7fbfSEdward Pilatowicz * that we want to have special handling for native paths. (A native path 429*186f7fbfSEdward Pilatowicz * is a path that begins with "/native/" or "/.SUNWnative/".) Native 430*186f7fbfSEdward Pilatowicz * paths could be passed explicity to this function or could be embedded 431*186f7fbfSEdward Pilatowicz * in a symlink that is part of the path passed into this function. 432*186f7fbfSEdward Pilatowicz * These paths are always lofs mounts of global zone paths, but lofs 433*186f7fbfSEdward Pilatowicz * mounts only exist when a zone is booted. So if we were to try to do 434*186f7fbfSEdward Pilatowicz * a resolvepath() on a native path when the zone wasn't booted the 435*186f7fbfSEdward Pilatowicz * resolvepath() would fail even though we know that the components 436*186f7fbfSEdward Pilatowicz * exists in the global zone. 437*186f7fbfSEdward Pilatowicz * 438*186f7fbfSEdward Pilatowicz * Given all these constraints, we just implement a path walking function 439*186f7fbfSEdward Pilatowicz * that resolves a file path relative to a zone root by manually inspecting 440*186f7fbfSEdward Pilatowicz * each of the path components and verifying its existence. This means that 441*186f7fbfSEdward Pilatowicz * we must have access to the zone and that all the components of the 442*186f7fbfSEdward Pilatowicz * path must exist for this operation to succeed. 443*186f7fbfSEdward Pilatowicz */ 444*186f7fbfSEdward Pilatowicz char * 445*186f7fbfSEdward Pilatowicz Pzonepath(struct ps_prochandle *P, const char *path, char *s, size_t n) 446*186f7fbfSEdward Pilatowicz { 447*186f7fbfSEdward Pilatowicz char zroot[PATH_MAX], zpath[PATH_MAX], tmp[PATH_MAX], link[PATH_MAX]; 448*186f7fbfSEdward Pilatowicz path_node_t *pn_stack = NULL, *pn_links = NULL, *pn; 449*186f7fbfSEdward Pilatowicz struct stat64 sb; 450*186f7fbfSEdward Pilatowicz char *p; 451*186f7fbfSEdward Pilatowicz int i, rv; 452*186f7fbfSEdward Pilatowicz 453*186f7fbfSEdward Pilatowicz dprintf("Pzonepath lookup '%s'\n", path); 454*186f7fbfSEdward Pilatowicz 455*186f7fbfSEdward Pilatowicz /* First lookup the zone root */ 456*186f7fbfSEdward Pilatowicz if (Pzoneroot(P, zroot, sizeof (zroot)) == NULL) 457*186f7fbfSEdward Pilatowicz return (NULL); 458*186f7fbfSEdward Pilatowicz 459*186f7fbfSEdward Pilatowicz /* 460*186f7fbfSEdward Pilatowicz * Make a temporary copy of the path specified. 461*186f7fbfSEdward Pilatowicz * If it's a relative path then make it into an absolute path. 462*186f7fbfSEdward Pilatowicz */ 463*186f7fbfSEdward Pilatowicz tmp[0] = '\0'; 464*186f7fbfSEdward Pilatowicz if (path[0] != '/') 465*186f7fbfSEdward Pilatowicz (void) strlcat(tmp, "/", sizeof (tmp)); 466*186f7fbfSEdward Pilatowicz (void) strlcat(tmp, path, sizeof (tmp)); 467*186f7fbfSEdward Pilatowicz 468*186f7fbfSEdward Pilatowicz /* 469*186f7fbfSEdward Pilatowicz * If the path that was passed in is the zone root, we're done. 470*186f7fbfSEdward Pilatowicz * If the path that was passed in already contains the zone root 471*186f7fbfSEdward Pilatowicz * then strip the zone root out and verify the rest of the path. 472*186f7fbfSEdward Pilatowicz */ 473*186f7fbfSEdward Pilatowicz if (strcmp(tmp, zroot) == 0) { 474*186f7fbfSEdward Pilatowicz (void) Plofspath(zroot, zroot, sizeof (zroot)); 475*186f7fbfSEdward Pilatowicz dprintf("Pzonepath found zone path (1) '%s'\n", zroot); 476*186f7fbfSEdward Pilatowicz (void) strlcpy(s, zroot, n); 477*186f7fbfSEdward Pilatowicz return (s); 478*186f7fbfSEdward Pilatowicz } 479*186f7fbfSEdward Pilatowicz i = strlen(zroot); 480*186f7fbfSEdward Pilatowicz if ((strncmp(tmp, zroot, i) == 0) && (tmp[i] == '/')) 481*186f7fbfSEdward Pilatowicz (void) memmove(tmp, tmp + i, strlen(tmp + i) + 1); 482*186f7fbfSEdward Pilatowicz 483*186f7fbfSEdward Pilatowicz /* If no path is passed in, then it maps to the zone root */ 484*186f7fbfSEdward Pilatowicz if (strlen(tmp) == 0) { 485*186f7fbfSEdward Pilatowicz (void) Plofspath(zroot, zroot, sizeof (zroot)); 486*186f7fbfSEdward Pilatowicz dprintf("Pzonepath found zone path (2) '%s'\n", zroot); 487*186f7fbfSEdward Pilatowicz (void) strlcpy(s, zroot, n); 488*186f7fbfSEdward Pilatowicz return (s); 489*186f7fbfSEdward Pilatowicz } 490*186f7fbfSEdward Pilatowicz 491*186f7fbfSEdward Pilatowicz /* 492*186f7fbfSEdward Pilatowicz * Push each path component that we plan to verify onto a stack of 493*186f7fbfSEdward Pilatowicz * path components, with parent components at the top of the stack. 494*186f7fbfSEdward Pilatowicz * So for example, if we're going to verify the path /foo/bar/bang 495*186f7fbfSEdward Pilatowicz * then our stack will look like: 496*186f7fbfSEdward Pilatowicz * foo (top) 497*186f7fbfSEdward Pilatowicz * bar 498*186f7fbfSEdward Pilatowicz * bang (bottom) 499*186f7fbfSEdward Pilatowicz */ 500*186f7fbfSEdward Pilatowicz while ((p = strrchr(tmp, '/')) != NULL) { 501*186f7fbfSEdward Pilatowicz *p = '\0'; 502*186f7fbfSEdward Pilatowicz if (pn_push(&pn_stack, &p[1]) != NULL) 503*186f7fbfSEdward Pilatowicz continue; 504*186f7fbfSEdward Pilatowicz pn_free(&pn_stack); 505*186f7fbfSEdward Pilatowicz return (NULL); 506*186f7fbfSEdward Pilatowicz } 507*186f7fbfSEdward Pilatowicz 508*186f7fbfSEdward Pilatowicz /* We're going to store the final zone relative path in zpath */ 509*186f7fbfSEdward Pilatowicz *zpath = '\0'; 510*186f7fbfSEdward Pilatowicz 511*186f7fbfSEdward Pilatowicz while (pn_pop(&pn_stack, tmp) != NULL) { 512*186f7fbfSEdward Pilatowicz /* 513*186f7fbfSEdward Pilatowicz * Drop zero length path components (which come from 514*186f7fbfSEdward Pilatowicz * consecutive '/'s) and '.' path components. 515*186f7fbfSEdward Pilatowicz */ 516*186f7fbfSEdward Pilatowicz if ((strlen(tmp) == 0) || (strcmp(tmp, ".") == 0)) 517*186f7fbfSEdward Pilatowicz continue; 518*186f7fbfSEdward Pilatowicz 519*186f7fbfSEdward Pilatowicz /* 520*186f7fbfSEdward Pilatowicz * Check the current path component for '..', if found 521*186f7fbfSEdward Pilatowicz * drop any previous path component. 522*186f7fbfSEdward Pilatowicz */ 523*186f7fbfSEdward Pilatowicz if (strcmp(tmp, "..") == 0) { 524*186f7fbfSEdward Pilatowicz if ((p = strrchr(zpath, '/')) != NULL) 525*186f7fbfSEdward Pilatowicz *p = '\0'; 526*186f7fbfSEdward Pilatowicz continue; 527*186f7fbfSEdward Pilatowicz } 528*186f7fbfSEdward Pilatowicz 529*186f7fbfSEdward Pilatowicz /* The path we want to verify now is zpath + / + tmp. */ 530*186f7fbfSEdward Pilatowicz (void) strlcat(zpath, "/", sizeof (zpath)); 531*186f7fbfSEdward Pilatowicz (void) strlcat(zpath, tmp, sizeof (zpath)); 532*186f7fbfSEdward Pilatowicz 533*186f7fbfSEdward Pilatowicz /* 534*186f7fbfSEdward Pilatowicz * Check if this is a native object. A native object is an 535*186f7fbfSEdward Pilatowicz * object from the global zone that is running in a branded 536*186f7fbfSEdward Pilatowicz * zone. These objects are lofs mounted into a zone. So if a 537*186f7fbfSEdward Pilatowicz * branded zone is not booted then lofs mounts won't be setup 538*186f7fbfSEdward Pilatowicz * so we won't be able to find these objects. Luckily, we know 539*186f7fbfSEdward Pilatowicz * that they exist in the global zone with the same path sans 540*186f7fbfSEdward Pilatowicz * the initial native component, so we'll just strip out the 541*186f7fbfSEdward Pilatowicz * native component here. 542*186f7fbfSEdward Pilatowicz */ 543*186f7fbfSEdward Pilatowicz if ((strncmp(zpath, "/native", sizeof ("/native")) == 0) || 544*186f7fbfSEdward Pilatowicz (strncmp(zpath, "/.SUNWnative", 545*186f7fbfSEdward Pilatowicz sizeof ("/.SUNWnative")) == 0)) { 546*186f7fbfSEdward Pilatowicz 547*186f7fbfSEdward Pilatowicz /* Free any cached symlink paths */ 548*186f7fbfSEdward Pilatowicz pn_free(&pn_links); 549*186f7fbfSEdward Pilatowicz 550*186f7fbfSEdward Pilatowicz /* Reconstruct the path from our path component stack */ 551*186f7fbfSEdward Pilatowicz *zpath = '\0'; 552*186f7fbfSEdward Pilatowicz while (pn_pop(&pn_stack, tmp) != NULL) { 553*186f7fbfSEdward Pilatowicz (void) strlcat(zpath, "/", sizeof (zpath)); 554*186f7fbfSEdward Pilatowicz (void) strlcat(zpath, tmp, sizeof (zpath)); 555*186f7fbfSEdward Pilatowicz } 556*186f7fbfSEdward Pilatowicz 557*186f7fbfSEdward Pilatowicz /* Verify that the path actually exists */ 558*186f7fbfSEdward Pilatowicz rv = resolvepath(zpath, tmp, sizeof (tmp) - 1); 559*186f7fbfSEdward Pilatowicz if (rv < 0) { 560*186f7fbfSEdward Pilatowicz dprintf("Pzonepath invalid native path '%s'\n", 561*186f7fbfSEdward Pilatowicz zpath); 562*186f7fbfSEdward Pilatowicz return (NULL); 563*186f7fbfSEdward Pilatowicz } 564*186f7fbfSEdward Pilatowicz tmp[rv] = '\0'; 565*186f7fbfSEdward Pilatowicz 566*186f7fbfSEdward Pilatowicz /* Return the path */ 567*186f7fbfSEdward Pilatowicz dprintf("Pzonepath found native path '%s'\n", tmp); 568*186f7fbfSEdward Pilatowicz (void) Plofspath(tmp, tmp, sizeof (tmp)); 569*186f7fbfSEdward Pilatowicz (void) strlcpy(s, tmp, n); 570*186f7fbfSEdward Pilatowicz return (s); 571*186f7fbfSEdward Pilatowicz } 572*186f7fbfSEdward Pilatowicz 573*186f7fbfSEdward Pilatowicz /* 574*186f7fbfSEdward Pilatowicz * Check if the path points to a symlink. We do this 575*186f7fbfSEdward Pilatowicz * explicitly since any absolute symlink needs to be 576*186f7fbfSEdward Pilatowicz * interpreted relativly to the zone root and not "/". 577*186f7fbfSEdward Pilatowicz */ 578*186f7fbfSEdward Pilatowicz (void) strlcpy(tmp, zroot, sizeof (tmp)); 579*186f7fbfSEdward Pilatowicz (void) strlcat(tmp, zpath, sizeof (tmp)); 580*186f7fbfSEdward Pilatowicz if (lstat64(tmp, &sb) != 0) { 581*186f7fbfSEdward Pilatowicz pn_free2(&pn_stack, &pn_links); 582*186f7fbfSEdward Pilatowicz return (NULL); 583*186f7fbfSEdward Pilatowicz } 584*186f7fbfSEdward Pilatowicz if (!S_ISLNK(sb.st_mode)) { 585*186f7fbfSEdward Pilatowicz /* 586*186f7fbfSEdward Pilatowicz * Since the lstat64() above succeeded we know that 587*186f7fbfSEdward Pilatowicz * zpath exists, since this is not a symlink loop 588*186f7fbfSEdward Pilatowicz * around and check the next path component. 589*186f7fbfSEdward Pilatowicz */ 590*186f7fbfSEdward Pilatowicz continue; 591*186f7fbfSEdward Pilatowicz } 592*186f7fbfSEdward Pilatowicz 593*186f7fbfSEdward Pilatowicz /* 594*186f7fbfSEdward Pilatowicz * Symlink allow for paths with loops. Make sure 595*186f7fbfSEdward Pilatowicz * we're not stuck in a loop. 596*186f7fbfSEdward Pilatowicz */ 597*186f7fbfSEdward Pilatowicz for (pn = pn_links; pn != NULL; pn = pn->pn_next) { 598*186f7fbfSEdward Pilatowicz if (strcmp(zpath, pn->pn_path) != 0) 599*186f7fbfSEdward Pilatowicz continue; 600*186f7fbfSEdward Pilatowicz 601*186f7fbfSEdward Pilatowicz /* We have a loop. Fail. */ 602*186f7fbfSEdward Pilatowicz dprintf("Pzonepath symlink loop '%s'\n", zpath); 603*186f7fbfSEdward Pilatowicz pn_free2(&pn_stack, &pn_links); 604*186f7fbfSEdward Pilatowicz return (NULL); 605*186f7fbfSEdward Pilatowicz } 606*186f7fbfSEdward Pilatowicz 607*186f7fbfSEdward Pilatowicz /* Save this symlink path for future loop checks */ 608*186f7fbfSEdward Pilatowicz if (pn_push(&pn_links, zpath) == NULL) { 609*186f7fbfSEdward Pilatowicz /* Out of memory */ 610*186f7fbfSEdward Pilatowicz pn_free2(&pn_stack, &pn_links); 611*186f7fbfSEdward Pilatowicz return (NULL); 612*186f7fbfSEdward Pilatowicz } 613*186f7fbfSEdward Pilatowicz 614*186f7fbfSEdward Pilatowicz /* Now follow the contents of the symlink */ 615*186f7fbfSEdward Pilatowicz bzero(link, sizeof (link)); 616*186f7fbfSEdward Pilatowicz if (readlink(tmp, link, sizeof (link)) == -1) { 617*186f7fbfSEdward Pilatowicz pn_free2(&pn_stack, &pn_links); 618*186f7fbfSEdward Pilatowicz return (NULL); 619*186f7fbfSEdward Pilatowicz } 620*186f7fbfSEdward Pilatowicz 621*186f7fbfSEdward Pilatowicz dprintf("Pzonepath following symlink '%s' -> '%s'\n", 622*186f7fbfSEdward Pilatowicz zpath, link); 623*186f7fbfSEdward Pilatowicz 624*186f7fbfSEdward Pilatowicz /* 625*186f7fbfSEdward Pilatowicz * Push each path component of the symlink target onto our 626*186f7fbfSEdward Pilatowicz * path components stack since we need to verify each one. 627*186f7fbfSEdward Pilatowicz */ 628*186f7fbfSEdward Pilatowicz while ((p = strrchr(link, '/')) != NULL) { 629*186f7fbfSEdward Pilatowicz *p = '\0'; 630*186f7fbfSEdward Pilatowicz if (pn_push(&pn_stack, &p[1]) != NULL) 631*186f7fbfSEdward Pilatowicz continue; 632*186f7fbfSEdward Pilatowicz pn_free2(&pn_stack, &pn_links); 633*186f7fbfSEdward Pilatowicz return (NULL); 634*186f7fbfSEdward Pilatowicz } 635*186f7fbfSEdward Pilatowicz 636*186f7fbfSEdward Pilatowicz /* absolute or relative symlink? */ 637*186f7fbfSEdward Pilatowicz if (*link == '\0') { 638*186f7fbfSEdward Pilatowicz /* Absolute symlink, nuke existing zpath. */ 639*186f7fbfSEdward Pilatowicz *zpath = '\0'; 640*186f7fbfSEdward Pilatowicz continue; 641*186f7fbfSEdward Pilatowicz } 642*186f7fbfSEdward Pilatowicz 643*186f7fbfSEdward Pilatowicz /* 644*186f7fbfSEdward Pilatowicz * Relative symlink. Push the first path component of the 645*186f7fbfSEdward Pilatowicz * symlink target onto our stack for verification and then 646*186f7fbfSEdward Pilatowicz * remove the current path component from zpath. 647*186f7fbfSEdward Pilatowicz */ 648*186f7fbfSEdward Pilatowicz if (pn_push(&pn_stack, link) == NULL) { 649*186f7fbfSEdward Pilatowicz pn_free2(&pn_stack, &pn_links); 650*186f7fbfSEdward Pilatowicz return (NULL); 651*186f7fbfSEdward Pilatowicz } 652*186f7fbfSEdward Pilatowicz p = strrchr(zpath, '/'); 653*186f7fbfSEdward Pilatowicz assert(p != NULL); 654*186f7fbfSEdward Pilatowicz *p = '\0'; 655*186f7fbfSEdward Pilatowicz continue; 656*186f7fbfSEdward Pilatowicz } 657*186f7fbfSEdward Pilatowicz pn_free(&pn_links); 658*186f7fbfSEdward Pilatowicz 659*186f7fbfSEdward Pilatowicz /* Place the final result in zpath */ 660*186f7fbfSEdward Pilatowicz (void) strlcpy(tmp, zroot, sizeof (tmp)); 661*186f7fbfSEdward Pilatowicz (void) strlcat(tmp, zpath, sizeof (tmp)); 662*186f7fbfSEdward Pilatowicz (void) strlcpy(zpath, tmp, sizeof (zpath)); 663*186f7fbfSEdward Pilatowicz 664*186f7fbfSEdward Pilatowicz (void) Plofspath(zpath, zpath, sizeof (zpath)); 665*186f7fbfSEdward Pilatowicz dprintf("Pzonepath found zone path (3) '%s'\n", zpath); 666*186f7fbfSEdward Pilatowicz 667*186f7fbfSEdward Pilatowicz (void) strlcpy(s, zpath, n); 668*186f7fbfSEdward Pilatowicz return (s); 669*186f7fbfSEdward Pilatowicz } 670*186f7fbfSEdward Pilatowicz 671*186f7fbfSEdward Pilatowicz char * 672*186f7fbfSEdward Pilatowicz Pfindobj(struct ps_prochandle *P, const char *path, char *s, size_t n) 673*186f7fbfSEdward Pilatowicz { 674*186f7fbfSEdward Pilatowicz int len; 675*186f7fbfSEdward Pilatowicz 676*186f7fbfSEdward Pilatowicz dprintf("Pfindobj '%s'\n", path); 677*186f7fbfSEdward Pilatowicz 678*186f7fbfSEdward Pilatowicz /* We only deal with absolute paths */ 679*186f7fbfSEdward Pilatowicz if (path[0] != '/') 680*186f7fbfSEdward Pilatowicz return (NULL); 681*186f7fbfSEdward Pilatowicz 682*186f7fbfSEdward Pilatowicz /* First try to resolve the path to some zone */ 683*186f7fbfSEdward Pilatowicz if (Pzonepath(P, path, s, n) != NULL) 684*186f7fbfSEdward Pilatowicz return (s); 685*186f7fbfSEdward Pilatowicz 686*186f7fbfSEdward Pilatowicz /* If that fails resolve any lofs links in the path */ 687*186f7fbfSEdward Pilatowicz if (Plofspath(path, s, n) != NULL) 688*186f7fbfSEdward Pilatowicz return (s); 689*186f7fbfSEdward Pilatowicz 690*186f7fbfSEdward Pilatowicz /* If that fails then just see if the path exists */ 691*186f7fbfSEdward Pilatowicz if ((len = resolvepath(path, s, n)) > 0) { 692*186f7fbfSEdward Pilatowicz s[len] = '\0'; 693*186f7fbfSEdward Pilatowicz return (s); 694*186f7fbfSEdward Pilatowicz } 695*186f7fbfSEdward Pilatowicz 696*186f7fbfSEdward Pilatowicz return (NULL); 697*186f7fbfSEdward Pilatowicz } 698*186f7fbfSEdward Pilatowicz 699*186f7fbfSEdward Pilatowicz char * 700*186f7fbfSEdward Pilatowicz Pfindmap(struct ps_prochandle *P, map_info_t *mptr, char *s, size_t n) 701*186f7fbfSEdward Pilatowicz { 702*186f7fbfSEdward Pilatowicz file_info_t *fptr = mptr->map_file; 703*186f7fbfSEdward Pilatowicz char buf[PATH_MAX]; 704*186f7fbfSEdward Pilatowicz int len; 705*186f7fbfSEdward Pilatowicz 706*186f7fbfSEdward Pilatowicz /* If it's already been explicity set return that */ 707*186f7fbfSEdward Pilatowicz if ((fptr != NULL) && (fptr->file_rname != NULL)) { 708*186f7fbfSEdward Pilatowicz (void) strlcpy(s, fptr->file_rname, n); 709*186f7fbfSEdward Pilatowicz return (s); 710*186f7fbfSEdward Pilatowicz } 711*186f7fbfSEdward Pilatowicz 712*186f7fbfSEdward Pilatowicz /* If it's the a.out segment, defer to the magical Pexecname() */ 713*186f7fbfSEdward Pilatowicz if ((P->map_exec == mptr) || 714*186f7fbfSEdward Pilatowicz (strcmp(mptr->map_pmap.pr_mapname, "a.out") == 0) || 715*186f7fbfSEdward Pilatowicz ((fptr != NULL) && (fptr->file_lname != NULL) && 716*186f7fbfSEdward Pilatowicz (strcmp(fptr->file_lname, "a.out") == 0))) { 717*186f7fbfSEdward Pilatowicz (void) Pexecname(P, buf, sizeof (buf)); 718*186f7fbfSEdward Pilatowicz (void) strlcpy(s, buf, n); 719*186f7fbfSEdward Pilatowicz return (s); 720*186f7fbfSEdward Pilatowicz } 721*186f7fbfSEdward Pilatowicz 722*186f7fbfSEdward Pilatowicz /* Try /proc first to get the real object name */ 723*186f7fbfSEdward Pilatowicz if ((Pstate(P) != PS_DEAD) && (mptr->map_pmap.pr_mapname[0] != '\0')) { 724*186f7fbfSEdward Pilatowicz (void) snprintf(buf, sizeof (buf), "%s/%d/path/%s", 725*186f7fbfSEdward Pilatowicz procfs_path, (int)P->pid, mptr->map_pmap.pr_mapname); 726*186f7fbfSEdward Pilatowicz if ((len = readlink(buf, buf, sizeof (buf))) > 0) { 727*186f7fbfSEdward Pilatowicz buf[len] = '\0'; 728*186f7fbfSEdward Pilatowicz (void) Plofspath(buf, buf, sizeof (buf)); 729*186f7fbfSEdward Pilatowicz (void) strlcpy(s, buf, n); 730*186f7fbfSEdward Pilatowicz return (s); 731*186f7fbfSEdward Pilatowicz } 732*186f7fbfSEdward Pilatowicz } 733*186f7fbfSEdward Pilatowicz 734*186f7fbfSEdward Pilatowicz /* 735*186f7fbfSEdward Pilatowicz * If we couldn't get the name from /proc, take the lname and 736*186f7fbfSEdward Pilatowicz * try to expand it on the current system to a real object path. 737*186f7fbfSEdward Pilatowicz */ 738*186f7fbfSEdward Pilatowicz fptr = mptr->map_file; 739*186f7fbfSEdward Pilatowicz if ((fptr != NULL) && (fptr->file_lname != NULL)) { 740*186f7fbfSEdward Pilatowicz (void) strlcpy(buf, fptr->file_lname, sizeof (buf)); 741*186f7fbfSEdward Pilatowicz if (Pfindobj(P, buf, buf, sizeof (buf)) == NULL) 742*186f7fbfSEdward Pilatowicz return (NULL); 743*186f7fbfSEdward Pilatowicz (void) strlcpy(s, buf, n); 744*186f7fbfSEdward Pilatowicz return (s); 745*186f7fbfSEdward Pilatowicz } 746*186f7fbfSEdward Pilatowicz 747*186f7fbfSEdward Pilatowicz return (NULL); 748*186f7fbfSEdward Pilatowicz } 749