17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
2311606941Sjwahlig  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
327c478bd9Sstevel@tonic-gate  * The Regents of the University of California
337c478bd9Sstevel@tonic-gate  * All Rights Reserved
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
367c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
377c478bd9Sstevel@tonic-gate  * contributors.
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate  * Subdirectory detection: needed by exportfs and rpc.mountd.
427c478bd9Sstevel@tonic-gate  * The above programs call issubdir() frequently, so we make
437c478bd9Sstevel@tonic-gate  * it fast by caching the results of stat().
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate #include <sys/types.h>
467c478bd9Sstevel@tonic-gate #include <sys/param.h>
477c478bd9Sstevel@tonic-gate #include <sys/stat.h>
487c478bd9Sstevel@tonic-gate #include <string.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #define	MAXSTATS MAXPATHLEN/2	/* maximum number of stat()'s to save */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #define	inoeq(ino1, ino2)	((ino1) == (ino2))
537c478bd9Sstevel@tonic-gate #define	deveq(dev1, dev2)	((dev1) == (dev2))
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /*
567c478bd9Sstevel@tonic-gate  * dir1 is a subdirectory of dir2 within the same filesystem if
577c478bd9Sstevel@tonic-gate  *     (a) dir1 is identical to dir2
587c478bd9Sstevel@tonic-gate  *     (b) dir1's parent is dir2
597c478bd9Sstevel@tonic-gate  */
6011606941Sjwahlig int
issubdir(dir1,dir2)617c478bd9Sstevel@tonic-gate issubdir(dir1, dir2)
627c478bd9Sstevel@tonic-gate 	char *dir1;
637c478bd9Sstevel@tonic-gate 	char *dir2;
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 	struct stat st;
667c478bd9Sstevel@tonic-gate 	struct stat parent_st;
677c478bd9Sstevel@tonic-gate 	char *p;
687c478bd9Sstevel@tonic-gate 	int index;
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	static dev_t child_dev;
717c478bd9Sstevel@tonic-gate 	static dev_t child_rdev;
727c478bd9Sstevel@tonic-gate 	static ino_t child_ino[MAXSTATS];
737c478bd9Sstevel@tonic-gate 	static int valid;
747c478bd9Sstevel@tonic-gate 	static char childdir[MAXPATHLEN];
757c478bd9Sstevel@tonic-gate 	static char child_fstype[_ST_FSTYPSZ];
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	/*
787c478bd9Sstevel@tonic-gate 	 * Get parent directory info
797c478bd9Sstevel@tonic-gate 	 */
807c478bd9Sstevel@tonic-gate 	if (stat(dir2, &parent_st) < 0) {
817c478bd9Sstevel@tonic-gate 		return (0);
827c478bd9Sstevel@tonic-gate 	}
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	if (strcmp(childdir, dir1) != 0) {
857c478bd9Sstevel@tonic-gate 		/*
867c478bd9Sstevel@tonic-gate 		 * Not in cache: get child directory info
877c478bd9Sstevel@tonic-gate 		 */
887c478bd9Sstevel@tonic-gate 		p = strcpy(childdir, dir1) + strlen(dir1);
897c478bd9Sstevel@tonic-gate 		index = 0;
907c478bd9Sstevel@tonic-gate 		valid = 0;
917c478bd9Sstevel@tonic-gate 		for (;;) {
927c478bd9Sstevel@tonic-gate 			if (stat(childdir, &st) < 0) {
937c478bd9Sstevel@tonic-gate 				childdir[0] = 0;	/* invalidate cache */
947c478bd9Sstevel@tonic-gate 				return (0);
957c478bd9Sstevel@tonic-gate 			}
967c478bd9Sstevel@tonic-gate 			if (index == 0) {
977c478bd9Sstevel@tonic-gate 				child_dev = st.st_dev;
987c478bd9Sstevel@tonic-gate 				child_rdev = st.st_rdev;
997c478bd9Sstevel@tonic-gate 				(void) strncpy(child_fstype, st.st_fstype,
1007c478bd9Sstevel@tonic-gate 						sizeof (child_fstype));
1017c478bd9Sstevel@tonic-gate 			}
1027c478bd9Sstevel@tonic-gate 			if (index > 0 &&
1037c478bd9Sstevel@tonic-gate 			    (child_dev != st.st_dev ||
1047c478bd9Sstevel@tonic-gate 				inoeq(child_ino[index - 1], st.st_ino))) {
1057c478bd9Sstevel@tonic-gate 				/*
1067c478bd9Sstevel@tonic-gate 				 * Hit root: done
1077c478bd9Sstevel@tonic-gate 				 */
1087c478bd9Sstevel@tonic-gate 				break;
1097c478bd9Sstevel@tonic-gate 			}
1107c478bd9Sstevel@tonic-gate 			child_ino[index++] = st.st_ino;
1114bc0a2efScasper 			if (S_ISDIR(st.st_mode)) {
1127c478bd9Sstevel@tonic-gate 				p = strcpy(p, "/..") + 3;
1137c478bd9Sstevel@tonic-gate 			} else {
1147c478bd9Sstevel@tonic-gate 				p = strrchr(childdir, '/');
1157c478bd9Sstevel@tonic-gate 				if (p == NULL) {
1167c478bd9Sstevel@tonic-gate 					p = strcpy(childdir, ".") + 1;
1177c478bd9Sstevel@tonic-gate 				} else {
1187c478bd9Sstevel@tonic-gate 					while (((p - 1) > childdir) &&
1197c478bd9Sstevel@tonic-gate 						*(p - 1) == '/') {
1207c478bd9Sstevel@tonic-gate 						p--;
1217c478bd9Sstevel@tonic-gate 					}
1227c478bd9Sstevel@tonic-gate 					*p = '\0';
1237c478bd9Sstevel@tonic-gate 				}
1247c478bd9Sstevel@tonic-gate 			}
1257c478bd9Sstevel@tonic-gate 		}
1267c478bd9Sstevel@tonic-gate 		valid = index;
1277c478bd9Sstevel@tonic-gate 		(void) strcpy(childdir, dir1);
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	/*
1317c478bd9Sstevel@tonic-gate 	 * Perform the test
1327c478bd9Sstevel@tonic-gate 	 */
1337c478bd9Sstevel@tonic-gate 	if (!deveq(parent_st.st_dev, child_dev)) {
1347c478bd9Sstevel@tonic-gate 		return (0);
1357c478bd9Sstevel@tonic-gate 	}
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/*
1387c478bd9Sstevel@tonic-gate 	 * Check rdev also in case of lofs
1397c478bd9Sstevel@tonic-gate 	 */
1407c478bd9Sstevel@tonic-gate 	if (((strcmp(parent_st.st_fstype, "lofs") == 0)) &&
1417c478bd9Sstevel@tonic-gate 		(strcmp(child_fstype, "lofs") == 0)) {
1427c478bd9Sstevel@tonic-gate 		if (!deveq(parent_st.st_rdev, child_rdev)) {
1437c478bd9Sstevel@tonic-gate 			return (0);
1447c478bd9Sstevel@tonic-gate 		}
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	for (index = 0; index < valid; index++) {
1487c478bd9Sstevel@tonic-gate 		if (inoeq(child_ino[index], parent_st.st_ino)) {
1497c478bd9Sstevel@tonic-gate 			return (1);
1507c478bd9Sstevel@tonic-gate 		}
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 	return (0);
1537c478bd9Sstevel@tonic-gate }
154