summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshare/common/issubdir.c
diff options
context:
space:
mode:
authordougm <none@none>2006-11-01 16:37:33 -0800
committerdougm <none@none>2006-11-01 16:37:33 -0800
commit6185db853e024a486ff8837e6784dd290d866112 (patch)
tree63111669df90312edea60a2931a4ab3fed34e952 /usr/src/lib/libshare/common/issubdir.c
parentb4034a75a927c4d7d1850ef306cc6b1d49c48f20 (diff)
downloadillumos-joyent-6185db853e024a486ff8837e6784dd290d866112.tar.gz
PSARC 2005/374 Share management improvements
6281048 NFS needs simplified administration --HG-- rename : usr/src/cmd/dfs.cmds/share/Makefile => deleted_files/usr/src/cmd/dfs.cmds/share/Makefile rename : usr/src/cmd/dfs.cmds/share/share.c => deleted_files/usr/src/cmd/dfs.cmds/share/share.c rename : usr/src/cmd/fs.d/nfs/share/share.c => deleted_files/usr/src/cmd/fs.d/nfs/share/share.c rename : usr/src/cmd/fs.d/nfs/unshare/Makefile => deleted_files/usr/src/cmd/fs.d/nfs/unshare/Makefile rename : usr/src/cmd/fs.d/nfs/unshare/unshare.c => deleted_files/usr/src/cmd/fs.d/nfs/unshare/unshare.c rename : usr/src/cmd/fs.d/nfs/share/issubdir.c => usr/src/lib/libshare/common/issubdir.c
Diffstat (limited to 'usr/src/lib/libshare/common/issubdir.c')
-rw-r--r--usr/src/lib/libshare/common/issubdir.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/usr/src/lib/libshare/common/issubdir.c b/usr/src/lib/libshare/common/issubdir.c
new file mode 100644
index 0000000000..d24a4b89e5
--- /dev/null
+++ b/usr/src/lib/libshare/common/issubdir.c
@@ -0,0 +1,155 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Subdirectory detection: needed by exportfs and rpc.mountd.
+ * The above programs call issubdir() frequently, so we make
+ * it fast by caching the results of stat().
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#define MAXSTATS MAXPATHLEN/2 /* maximum number of stat()'s to save */
+
+#define inoeq(ino1, ino2) ((ino1) == (ino2))
+#define deveq(dev1, dev2) ((dev1) == (dev2))
+
+/*
+ * dir1 is a subdirectory of dir2 within the same filesystem if
+ * (a) dir1 is identical to dir2
+ * (b) dir1's parent is dir2
+ */
+int
+issubdir(dir1, dir2)
+ char *dir1;
+ char *dir2;
+{
+ struct stat st;
+ struct stat parent_st;
+ char *p;
+ int index;
+
+ static dev_t child_dev;
+ static dev_t child_rdev;
+ static ino_t child_ino[MAXSTATS];
+ static int valid;
+ static char childdir[MAXPATHLEN];
+ static char child_fstype[_ST_FSTYPSZ];
+
+ /*
+ * Get parent directory info
+ */
+ if (stat(dir2, &parent_st) < 0) {
+ return (0);
+ }
+
+ if (strcmp(childdir, dir1) != 0) {
+ /*
+ * Not in cache: get child directory info
+ */
+ p = strcpy(childdir, dir1) + strlen(dir1);
+ index = 0;
+ valid = 0;
+ for (;;) {
+ if (stat(childdir, &st) < 0) {
+ childdir[0] = 0; /* invalidate cache */
+ return (0);
+ }
+ if (index == 0) {
+ child_dev = st.st_dev;
+ child_rdev = st.st_rdev;
+ (void) strncpy(child_fstype, st.st_fstype,
+ sizeof (child_fstype));
+ }
+ if (index > 0 &&
+ (child_dev != st.st_dev ||
+ inoeq(child_ino[index - 1], st.st_ino))) {
+ /*
+ * Hit root: done
+ */
+ break;
+ }
+ child_ino[index++] = st.st_ino;
+ if (S_ISDIR(st.st_mode)) {
+ p = strcpy(p, "/..") + 3;
+ } else {
+ p = strrchr(childdir, '/');
+ if (p == NULL) {
+ p = strcpy(childdir, ".") + 1;
+ } else {
+ while (((p - 1) > childdir) &&
+ *(p - 1) == '/') {
+ p--;
+ }
+ *p = '\0';
+ }
+ }
+ }
+ valid = index;
+ (void) strcpy(childdir, dir1);
+ }
+
+ /*
+ * Perform the test
+ */
+ if (!deveq(parent_st.st_dev, child_dev)) {
+ return (0);
+ }
+
+ /*
+ * Check rdev also in case of lofs
+ */
+ if (((strcmp(parent_st.st_fstype, "lofs") == 0)) &&
+ (strcmp(child_fstype, "lofs") == 0)) {
+ if (!deveq(parent_st.st_rdev, child_rdev)) {
+ return (0);
+ }
+ }
+
+ for (index = 0; index < valid; index++) {
+ if (inoeq(child_ino[index], parent_st.st_ino)) {
+ return (1);
+ }
+ }
+ return (0);
+}