1*6185db85Sdougm /* 2*6185db85Sdougm * CDDL HEADER START 3*6185db85Sdougm * 4*6185db85Sdougm * The contents of this file are subject to the terms of the 5*6185db85Sdougm * Common Development and Distribution License, Version 1.0 only 6*6185db85Sdougm * (the "License"). You may not use this file except in compliance 7*6185db85Sdougm * with the License. 8*6185db85Sdougm * 9*6185db85Sdougm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*6185db85Sdougm * or http://www.opensolaris.org/os/licensing. 11*6185db85Sdougm * See the License for the specific language governing permissions 12*6185db85Sdougm * and limitations under the License. 13*6185db85Sdougm * 14*6185db85Sdougm * When distributing Covered Code, include this CDDL HEADER in each 15*6185db85Sdougm * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*6185db85Sdougm * If applicable, add the following below this CDDL HEADER, with the 17*6185db85Sdougm * fields enclosed by brackets "[]" replaced with your own identifying 18*6185db85Sdougm * information: Portions Copyright [yyyy] [name of copyright owner] 19*6185db85Sdougm * 20*6185db85Sdougm * CDDL HEADER END 21*6185db85Sdougm */ 22*6185db85Sdougm /* 23*6185db85Sdougm * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*6185db85Sdougm * Use is subject to license terms. 25*6185db85Sdougm */ 26*6185db85Sdougm 27*6185db85Sdougm /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*6185db85Sdougm /* All Rights Reserved */ 29*6185db85Sdougm 30*6185db85Sdougm /* 31*6185db85Sdougm * University Copyright- Copyright (c) 1982, 1986, 1988 32*6185db85Sdougm * The Regents of the University of California 33*6185db85Sdougm * All Rights Reserved 34*6185db85Sdougm * 35*6185db85Sdougm * University Acknowledgment- Portions of this document are derived from 36*6185db85Sdougm * software developed by the University of California, Berkeley, and its 37*6185db85Sdougm * contributors. 38*6185db85Sdougm */ 39*6185db85Sdougm 40*6185db85Sdougm #pragma ident "%Z%%M% %I% %E% SMI" 41*6185db85Sdougm 42*6185db85Sdougm /* 43*6185db85Sdougm * Subdirectory detection: needed by exportfs and rpc.mountd. 44*6185db85Sdougm * The above programs call issubdir() frequently, so we make 45*6185db85Sdougm * it fast by caching the results of stat(). 46*6185db85Sdougm */ 47*6185db85Sdougm #include <sys/types.h> 48*6185db85Sdougm #include <sys/param.h> 49*6185db85Sdougm #include <sys/stat.h> 50*6185db85Sdougm #include <string.h> 51*6185db85Sdougm 52*6185db85Sdougm #define MAXSTATS MAXPATHLEN/2 /* maximum number of stat()'s to save */ 53*6185db85Sdougm 54*6185db85Sdougm #define inoeq(ino1, ino2) ((ino1) == (ino2)) 55*6185db85Sdougm #define deveq(dev1, dev2) ((dev1) == (dev2)) 56*6185db85Sdougm 57*6185db85Sdougm /* 58*6185db85Sdougm * dir1 is a subdirectory of dir2 within the same filesystem if 59*6185db85Sdougm * (a) dir1 is identical to dir2 60*6185db85Sdougm * (b) dir1's parent is dir2 61*6185db85Sdougm */ 62*6185db85Sdougm int 63*6185db85Sdougm issubdir(dir1, dir2) 64*6185db85Sdougm char *dir1; 65*6185db85Sdougm char *dir2; 66*6185db85Sdougm { 67*6185db85Sdougm struct stat st; 68*6185db85Sdougm struct stat parent_st; 69*6185db85Sdougm char *p; 70*6185db85Sdougm int index; 71*6185db85Sdougm 72*6185db85Sdougm static dev_t child_dev; 73*6185db85Sdougm static dev_t child_rdev; 74*6185db85Sdougm static ino_t child_ino[MAXSTATS]; 75*6185db85Sdougm static int valid; 76*6185db85Sdougm static char childdir[MAXPATHLEN]; 77*6185db85Sdougm static char child_fstype[_ST_FSTYPSZ]; 78*6185db85Sdougm 79*6185db85Sdougm /* 80*6185db85Sdougm * Get parent directory info 81*6185db85Sdougm */ 82*6185db85Sdougm if (stat(dir2, &parent_st) < 0) { 83*6185db85Sdougm return (0); 84*6185db85Sdougm } 85*6185db85Sdougm 86*6185db85Sdougm if (strcmp(childdir, dir1) != 0) { 87*6185db85Sdougm /* 88*6185db85Sdougm * Not in cache: get child directory info 89*6185db85Sdougm */ 90*6185db85Sdougm p = strcpy(childdir, dir1) + strlen(dir1); 91*6185db85Sdougm index = 0; 92*6185db85Sdougm valid = 0; 93*6185db85Sdougm for (;;) { 94*6185db85Sdougm if (stat(childdir, &st) < 0) { 95*6185db85Sdougm childdir[0] = 0; /* invalidate cache */ 96*6185db85Sdougm return (0); 97*6185db85Sdougm } 98*6185db85Sdougm if (index == 0) { 99*6185db85Sdougm child_dev = st.st_dev; 100*6185db85Sdougm child_rdev = st.st_rdev; 101*6185db85Sdougm (void) strncpy(child_fstype, st.st_fstype, 102*6185db85Sdougm sizeof (child_fstype)); 103*6185db85Sdougm } 104*6185db85Sdougm if (index > 0 && 105*6185db85Sdougm (child_dev != st.st_dev || 106*6185db85Sdougm inoeq(child_ino[index - 1], st.st_ino))) { 107*6185db85Sdougm /* 108*6185db85Sdougm * Hit root: done 109*6185db85Sdougm */ 110*6185db85Sdougm break; 111*6185db85Sdougm } 112*6185db85Sdougm child_ino[index++] = st.st_ino; 113*6185db85Sdougm if (S_ISDIR(st.st_mode)) { 114*6185db85Sdougm p = strcpy(p, "/..") + 3; 115*6185db85Sdougm } else { 116*6185db85Sdougm p = strrchr(childdir, '/'); 117*6185db85Sdougm if (p == NULL) { 118*6185db85Sdougm p = strcpy(childdir, ".") + 1; 119*6185db85Sdougm } else { 120*6185db85Sdougm while (((p - 1) > childdir) && 121*6185db85Sdougm *(p - 1) == '/') { 122*6185db85Sdougm p--; 123*6185db85Sdougm } 124*6185db85Sdougm *p = '\0'; 125*6185db85Sdougm } 126*6185db85Sdougm } 127*6185db85Sdougm } 128*6185db85Sdougm valid = index; 129*6185db85Sdougm (void) strcpy(childdir, dir1); 130*6185db85Sdougm } 131*6185db85Sdougm 132*6185db85Sdougm /* 133*6185db85Sdougm * Perform the test 134*6185db85Sdougm */ 135*6185db85Sdougm if (!deveq(parent_st.st_dev, child_dev)) { 136*6185db85Sdougm return (0); 137*6185db85Sdougm } 138*6185db85Sdougm 139*6185db85Sdougm /* 140*6185db85Sdougm * Check rdev also in case of lofs 141*6185db85Sdougm */ 142*6185db85Sdougm if (((strcmp(parent_st.st_fstype, "lofs") == 0)) && 143*6185db85Sdougm (strcmp(child_fstype, "lofs") == 0)) { 144*6185db85Sdougm if (!deveq(parent_st.st_rdev, child_rdev)) { 145*6185db85Sdougm return (0); 146*6185db85Sdougm } 147*6185db85Sdougm } 148*6185db85Sdougm 149*6185db85Sdougm for (index = 0; index < valid; index++) { 150*6185db85Sdougm if (inoeq(child_ino[index], parent_st.st_ino)) { 151*6185db85Sdougm return (1); 152*6185db85Sdougm } 153*6185db85Sdougm } 154*6185db85Sdougm return (0); 155*6185db85Sdougm } 156