Ian Kent e6cf32
diff -up autofs-5.0.3/daemon/indirect.c.device-node-control autofs-5.0.3/daemon/indirect.c
Ian Kent e6cf32
--- autofs-5.0.3/daemon/indirect.c.device-node-control	2008-02-25 08:58:46.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/daemon/indirect.c	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -43,6 +43,8 @@ extern pthread_attr_t thread_attr;
Ian Kent e6cf32
 static pthread_mutex_t ma_mutex = PTHREAD_MUTEX_INITIALIZER;
Ian Kent e6cf32
 static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
Ian Kent e6cf32
 
Ian Kent e6cf32
+static const unsigned int indirect = AUTOFS_TYPE_INDIRECT;
Ian Kent e6cf32
+
Ian Kent e6cf32
 static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts)
Ian Kent e6cf32
 {
Ian Kent e6cf32
 	struct mnt_list *this;
Ian Kent e6cf32
@@ -88,19 +90,20 @@ static int unlink_mount_tree(struct auto
Ian Kent e6cf32
 
Ian Kent e6cf32
 static int do_mount_autofs_indirect(struct autofs_point *ap)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	time_t timeout = ap->exp_timeout;
Ian Kent e6cf32
 	char *options = NULL;
Ian Kent e6cf32
 	const char *type, *map_name = NULL;
Ian Kent e6cf32
 	struct stat st;
Ian Kent e6cf32
 	struct mnt_list *mnts;
Ian Kent e6cf32
-	int cl_flags, ret;
Ian Kent e6cf32
+	int ret;
Ian Kent e6cf32
 
Ian Kent e6cf32
 	mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 1);
Ian Kent e6cf32
 	if (mnts) {
Ian Kent e6cf32
 		ret = unlink_mount_tree(ap, mnts);
Ian Kent e6cf32
 		free_mnt_list(mnts);
Ian Kent e6cf32
 		if (!ret) {
Ian Kent e6cf32
-			debug(ap->logopt,
Ian Kent e6cf32
+			error(ap->logopt,
Ian Kent e6cf32
 			      "already mounted as other than autofs "
Ian Kent e6cf32
 			      "or failed to unlink entry in tree");
Ian Kent e6cf32
 			goto out_err;
Ian Kent e6cf32
@@ -108,8 +111,10 @@ static int do_mount_autofs_indirect(stru
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
 	options = make_options_string(ap->path, ap->kpipefd, NULL);
Ian Kent e6cf32
-	if (!options)
Ian Kent e6cf32
+	if (!options) {
Ian Kent e6cf32
+		error(ap->logopt, "options string error");
Ian Kent e6cf32
 		goto out_err;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
 
Ian Kent e6cf32
 	/* In case the directory doesn't exist, try to mkdir it */
Ian Kent e6cf32
 	if (mkdir_path(ap->path, 0555) < 0) {
Ian Kent e6cf32
@@ -147,22 +152,15 @@ static int do_mount_autofs_indirect(stru
Ian Kent e6cf32
 
Ian Kent e6cf32
 	options = NULL;
Ian Kent e6cf32
 
Ian Kent e6cf32
-	/* Root directory for ioctl()'s */
Ian Kent e6cf32
-	ap->ioctlfd = open(ap->path, O_RDONLY);
Ian Kent e6cf32
-	if (ap->ioctlfd < 0) {
Ian Kent e6cf32
+	if (ops->open(ap->logopt, &ap->ioctlfd, -1, ap->path, indirect)) {
Ian Kent e6cf32
 		crit(ap->logopt,
Ian Kent e6cf32
 		     "failed to create ioctl fd for autofs path %s", ap->path);
Ian Kent e6cf32
 		goto out_umount;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	if ((cl_flags = fcntl(ap->ioctlfd, F_GETFD, 0)) != -1) {
Ian Kent e6cf32
-		cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
-		fcntl(ap->ioctlfd, F_SETFD, cl_flags);
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
 	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
Ian Kent e6cf32
 
Ian Kent e6cf32
-	ioctl(ap->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout);
Ian Kent e6cf32
+	ops->timeout(ap->logopt, ap->ioctlfd, &timeout);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (ap->exp_timeout)
Ian Kent e6cf32
 		info(ap->logopt,
Ian Kent e6cf32
@@ -235,8 +233,10 @@ int mount_autofs_indirect(struct autofs_
Ian Kent e6cf32
 
Ian Kent e6cf32
 int umount_autofs_indirect(struct autofs_point *ap)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
-	int ret, rv, retries;
Ian Kent e6cf32
+	int rv, retries;
Ian Kent e6cf32
+	unsigned int ret;
Ian Kent e6cf32
 
Ian Kent e6cf32
 	/*
Ian Kent e6cf32
 	 * Since submounts look after themselves the parent never knows
Ian Kent e6cf32
@@ -248,7 +248,7 @@ int umount_autofs_indirect(struct autofs
Ian Kent e6cf32
 		lookup_source_close_ioctlfd(ap->parent, ap->path);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	/* If we are trying to shutdown make sure we can umount */
Ian Kent e6cf32
-	rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret;;
Ian Kent e6cf32
+	rv = ops->askumount(ap->logopt, ap->ioctlfd, &ret;;
Ian Kent e6cf32
 	if (rv == -1) {
Ian Kent e6cf32
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 		logerr("ioctl failed: %s", estr);
Ian Kent e6cf32
@@ -258,8 +258,8 @@ int umount_autofs_indirect(struct autofs
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	ioctl(ap->ioctlfd, AUTOFS_IOC_CATATONIC, 0);
Ian Kent e6cf32
-	close(ap->ioctlfd);
Ian Kent e6cf32
+	ops->catatonic(ap->logopt, ap->ioctlfd);
Ian Kent e6cf32
+	ops->close(ap->logopt, ap->ioctlfd);
Ian Kent e6cf32
 	ap->ioctlfd = -1;
Ian Kent e6cf32
 	close(ap->state_pipe[0]);
Ian Kent e6cf32
 	close(ap->state_pipe[1]);
Ian Kent e6cf32
@@ -320,48 +320,6 @@ force_umount:
Ian Kent e6cf32
 	return rv;
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
-static int expire_indirect(struct autofs_point *ap, int ioctlfd, const char *path, unsigned int when)
Ian Kent e6cf32
-{
Ian Kent e6cf32
-	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
-	int ret, retries;
Ian Kent e6cf32
-	struct stat st;
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (fstat(ioctlfd, &st) == -1) {
Ian Kent e6cf32
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
-		debug(ap->logopt, "fstat failed: %s", estr);
Ian Kent e6cf32
-		return 0;
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
-	retries = (count_mounts(ap->logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
Ian Kent e6cf32
-
Ian Kent e6cf32
-	while (retries--) {
Ian Kent e6cf32
-		struct timespec tm = {0, 100000000};
Ian Kent e6cf32
-
Ian Kent e6cf32
-		/* Ggenerate expire message for the mount. */
Ian Kent e6cf32
-		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when);
Ian Kent e6cf32
-		if (ret == -1) {
Ian Kent e6cf32
-			/* Mount has gone away */
Ian Kent e6cf32
-			if (errno == EBADF || errno == EINVAL)
Ian Kent e6cf32
-				return 1;
Ian Kent e6cf32
-
Ian Kent e6cf32
-			/*
Ian Kent e6cf32
-			 * Other than EAGAIN is an expire error so continue.
Ian Kent e6cf32
-			 * Kernel will try the next mount.
Ian Kent e6cf32
-			 */
Ian Kent e6cf32
-			if (errno == EAGAIN)
Ian Kent e6cf32
-				break;
Ian Kent e6cf32
-		}
Ian Kent e6cf32
-		nanosleep(&tm, NULL);
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (!ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) {
Ian Kent e6cf32
-		if (!ret)
Ian Kent e6cf32
-			return 0;
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
-	return 1;
Ian Kent e6cf32
-}
Ian Kent e6cf32
-
Ian Kent e6cf32
 static void mnts_cleanup(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
 	struct mnt_list *mnts = (struct mnt_list *) arg;
Ian Kent e6cf32
@@ -371,6 +329,7 @@ static void mnts_cleanup(void *arg)
Ian Kent e6cf32
 
Ian Kent e6cf32
 void *expire_proc_indirect(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct autofs_point *ap;
Ian Kent e6cf32
 	struct mapent *me = NULL;
Ian Kent e6cf32
 	struct mnt_list *mnts = NULL, *next;
Ian Kent e6cf32
@@ -458,8 +417,8 @@ void *expire_proc_indirect(void *arg)
Ian Kent e6cf32
 		debug(ap->logopt, "expire %s", next->path);
Ian Kent e6cf32
 
Ian Kent e6cf32
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Ian Kent e6cf32
-		ret = expire_indirect(ap, ioctlfd, next->path, now);
Ian Kent e6cf32
-		if (!ret)
Ian Kent e6cf32
+		ret = ops->expire(ap->logopt, ioctlfd, next->path, now);
Ian Kent e6cf32
+		if (ret)
Ian Kent e6cf32
 			left++;
Ian Kent e6cf32
 		pthread_setcancelstate(cur_state, NULL);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
@@ -472,8 +431,8 @@ void *expire_proc_indirect(void *arg)
Ian Kent e6cf32
 	 */
Ian Kent e6cf32
 	if (mnts) {
Ian Kent e6cf32
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Ian Kent e6cf32
-		ret = expire_indirect(ap, ap->ioctlfd, ap->path, now);
Ian Kent e6cf32
-		if (!ret)
Ian Kent e6cf32
+		ret = ops->expire(ap->logopt, ap->ioctlfd, ap->path, now);
Ian Kent e6cf32
+		if (ret)
Ian Kent e6cf32
 			left++;
Ian Kent e6cf32
 		pthread_setcancelstate(cur_state, NULL);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
@@ -495,8 +454,8 @@ void *expire_proc_indirect(void *arg)
Ian Kent e6cf32
 	pthread_cleanup_pop(1);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (submnts)
Ian Kent e6cf32
-		debug(ap->logopt,
Ian Kent e6cf32
-		      "%d submounts remaining in %s", submnts, ap->path);
Ian Kent e6cf32
+		info(ap->logopt,
Ian Kent e6cf32
+		     "%d submounts remaining in %s", submnts, ap->path);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	/* 
Ian Kent e6cf32
 	 * EXPIRE_MULTI is synchronous, so we can be sure (famous last
Ian Kent e6cf32
@@ -527,8 +486,11 @@ static void pending_cond_destroy(void *a
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void expire_send_fail(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt = arg;
Ian Kent e6cf32
-	send_fail(mt->ap->logopt, mt->ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+	struct autofs_point *ap = mt->ap;
Ian Kent e6cf32
+	ops->send_fail(ap->logopt,
Ian Kent e6cf32
+		       ap->ioctlfd, mt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void free_pending_args(void *arg)
Ian Kent e6cf32
@@ -546,6 +508,7 @@ static void expire_mutex_unlock(void *ar
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void *do_expire_indirect(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt;
Ian Kent e6cf32
 	struct autofs_point *ap;
Ian Kent e6cf32
 	int status, state;
Ian Kent e6cf32
@@ -572,9 +535,11 @@ static void *do_expire_indirect(void *ar
Ian Kent e6cf32
 	status = do_expire(mt->ap, mt->name, mt->len);
Ian Kent e6cf32
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
Ian Kent e6cf32
 	if (status)
Ian Kent e6cf32
-		send_fail(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ap->ioctlfd, mt->wait_queue_token, -status);
Ian Kent e6cf32
 	else
Ian Kent e6cf32
-		send_ready(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_ready(ap->logopt,
Ian Kent e6cf32
+				ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
 	pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	pthread_cleanup_pop(0);
Ian Kent e6cf32
@@ -586,6 +551,7 @@ static void *do_expire_indirect(void *ar
Ian Kent e6cf32
 
Ian Kent e6cf32
 int handle_packet_expire_indirect(struct autofs_point *ap, autofs_packet_expire_indirect_t *pkt)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt;
Ian Kent e6cf32
 	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
 	pthread_t thid;
Ian Kent e6cf32
@@ -600,7 +566,8 @@ int handle_packet_expire_indirect(struct
Ian Kent e6cf32
 	if (!mt) {
Ian Kent e6cf32
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 		logerr("malloc: %s", estr);
Ian Kent e6cf32
-		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ap->ioctlfd, pkt->wait_queue_token, -ENOMEM);
Ian Kent e6cf32
 		pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
@@ -622,7 +589,8 @@ int handle_packet_expire_indirect(struct
Ian Kent e6cf32
 	status = pthread_create(&thid, &thread_attr, do_expire_indirect, mt);
Ian Kent e6cf32
 	if (status) {
Ian Kent e6cf32
 		error(ap->logopt, "expire thread create failed");
Ian Kent e6cf32
-		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ap->ioctlfd, pkt->wait_queue_token, -status);
Ian Kent e6cf32
 		expire_mutex_unlock(NULL);
Ian Kent e6cf32
 		pending_cond_destroy(mt);
Ian Kent e6cf32
 		free_pending_args(mt);
Ian Kent e6cf32
@@ -647,8 +615,11 @@ int handle_packet_expire_indirect(struct
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void mount_send_fail(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt = arg;
Ian Kent e6cf32
-	send_fail(mt->ap->logopt, mt->ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+	struct autofs_point *ap = mt->ap;
Ian Kent e6cf32
+	ops->send_fail(ap->logopt,
Ian Kent e6cf32
+		       ap->ioctlfd, mt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void mount_mutex_unlock(void *arg)
Ian Kent e6cf32
@@ -660,6 +631,7 @@ static void mount_mutex_unlock(void *arg
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void *do_mount_indirect(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt;
Ian Kent e6cf32
 	struct autofs_point *ap;
Ian Kent e6cf32
 	char buf[PATH_MAX + 1];
Ian Kent e6cf32
@@ -837,10 +809,13 @@ cont:
Ian Kent e6cf32
 	status = lookup_nss_mount(ap, NULL, mt->name, mt->len);
Ian Kent e6cf32
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
Ian Kent e6cf32
 	if (status) {
Ian Kent e6cf32
-		send_ready(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_ready(ap->logopt,
Ian Kent e6cf32
+				ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
 		info(ap->logopt, "mounted %s", buf);
Ian Kent e6cf32
 	} else {
Ian Kent e6cf32
-		send_fail(ap->logopt, ap->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+		/* TODO: get mount return status from lookup_nss_mount */
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ap->ioctlfd, mt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
 		info(ap->logopt, "failed to mount %s", buf);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 	pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
@@ -854,6 +829,7 @@ cont:
Ian Kent e6cf32
 
Ian Kent e6cf32
 int handle_packet_missing_indirect(struct autofs_point *ap, autofs_packet_missing_indirect_t *pkt)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	pthread_t thid;
Ian Kent e6cf32
 	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
 	struct pending_args *mt;
Ian Kent e6cf32
@@ -868,7 +844,8 @@ int handle_packet_missing_indirect(struc
Ian Kent e6cf32
 	if (ap->shutdown ||
Ian Kent e6cf32
 	    ap->state == ST_SHUTDOWN_FORCE ||
Ian Kent e6cf32
 	    ap->state == ST_SHUTDOWN) {
Ian Kent e6cf32
-		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ap->ioctlfd, pkt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
 		pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 		return 0;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
@@ -877,7 +854,8 @@ int handle_packet_missing_indirect(struc
Ian Kent e6cf32
 	if (!mt) {
Ian Kent e6cf32
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 		logerr("malloc: %s", estr);
Ian Kent e6cf32
-		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ap->ioctlfd, pkt->wait_queue_token, -ENOMEM);
Ian Kent e6cf32
 		pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
@@ -903,7 +881,8 @@ int handle_packet_missing_indirect(struc
Ian Kent e6cf32
 	status = pthread_create(&thid, &thread_attr, do_mount_indirect, mt);
Ian Kent e6cf32
 	if (status) {
Ian Kent e6cf32
 		error(ap->logopt, "expire thread create failed");
Ian Kent e6cf32
-		send_fail(ap->logopt, ap->ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ap->ioctlfd, pkt->wait_queue_token, -status);
Ian Kent e6cf32
 		mount_mutex_unlock(NULL);
Ian Kent e6cf32
 		pending_cond_destroy(mt);
Ian Kent e6cf32
 		free_pending_args(mt);
Ian Kent e6cf32
diff -up autofs-5.0.3/daemon/state.c.device-node-control autofs-5.0.3/daemon/state.c
Ian Kent e6cf32
--- autofs-5.0.3/daemon/state.c.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/daemon/state.c	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -93,6 +93,7 @@ void nextstate(int statefd, enum states 
Ian Kent e6cf32
  */
Ian Kent e6cf32
 void expire_cleanup(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	pthread_t thid = pthread_self();
Ian Kent e6cf32
 	struct expire_args *ec;
Ian Kent e6cf32
 	struct autofs_point *ap;
Ian Kent e6cf32
@@ -113,7 +114,8 @@ void expire_cleanup(void *arg)
Ian Kent e6cf32
 
Ian Kent e6cf32
 	/* Check to see if expire process finished */
Ian Kent e6cf32
 	if (thid == ap->exp_thread) {
Ian Kent e6cf32
-		int rv, idle;
Ian Kent e6cf32
+		unsigned int idle;
Ian Kent e6cf32
+		int rv;
Ian Kent e6cf32
 
Ian Kent e6cf32
 		ap->exp_thread = 0;
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -135,7 +137,7 @@ void expire_cleanup(void *arg)
Ian Kent e6cf32
 			 * allowing it to shutdown.
Ian Kent e6cf32
 			 */
Ian Kent e6cf32
 			if (ap->submount && !success) {
Ian Kent e6cf32
-				rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &idle);
Ian Kent e6cf32
+				rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
Ian Kent e6cf32
 				if (!rv && idle && ap->submount > 1) {
Ian Kent e6cf32
 					next = ST_SHUTDOWN_PENDING;
Ian Kent e6cf32
 					break;
Ian Kent e6cf32
@@ -160,7 +162,7 @@ void expire_cleanup(void *arg)
Ian Kent e6cf32
 			 * shutdown return to ready state unless we have
Ian Kent e6cf32
 			 * been signaled to shutdown.
Ian Kent e6cf32
 			 */
Ian Kent e6cf32
-			rv = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &idle);
Ian Kent e6cf32
+			rv = ops->askumount(ap->logopt, ap->ioctlfd, &idle);
Ian Kent e6cf32
 			if (!idle && !ap->shutdown) {
Ian Kent e6cf32
 				next = ST_READY;
Ian Kent e6cf32
 				if (!ap->submount)
Ian Kent e6cf32
diff -up autofs-5.0.3/daemon/lookup.c.device-node-control autofs-5.0.3/daemon/lookup.c
Ian Kent e6cf32
--- autofs-5.0.3/daemon/lookup.c.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/daemon/lookup.c	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -1148,7 +1148,8 @@ int lookup_source_close_ioctlfd(struct a
Ian Kent e6cf32
 		me = cache_lookup_distinct(mc, key);
Ian Kent e6cf32
 		if (me) {
Ian Kent e6cf32
 			if (me->ioctlfd != -1) {
Ian Kent e6cf32
-				close(me->ioctlfd);
Ian Kent e6cf32
+				struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
+				ops->close(ap->logopt, me->ioctlfd);
Ian Kent e6cf32
 				me->ioctlfd = -1;
Ian Kent e6cf32
 			}
Ian Kent e6cf32
 			cache_unlock(mc);
Ian Kent e6cf32
diff -up autofs-5.0.3/daemon/direct.c.device-node-control autofs-5.0.3/daemon/direct.c
Ian Kent e6cf32
--- autofs-5.0.3/daemon/direct.c.device-node-control	2008-02-25 08:58:46.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/daemon/direct.c	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -42,6 +42,9 @@
Ian Kent e6cf32
 
Ian Kent e6cf32
 extern pthread_attr_t thread_attr;
Ian Kent e6cf32
 
Ian Kent e6cf32
+static const unsigned int direct = AUTOFS_TYPE_DIRECT;
Ian Kent e6cf32
+static const unsigned int offset = AUTOFS_TYPE_OFFSET;
Ian Kent e6cf32
+
Ian Kent e6cf32
 struct mnt_params {
Ian Kent e6cf32
 	char *options;
Ian Kent e6cf32
 };
Ian Kent e6cf32
@@ -88,6 +91,7 @@ static void mnts_cleanup(void *arg)
Ian Kent e6cf32
 
Ian Kent e6cf32
 int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
 	int ioctlfd, rv, left, retries;
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -106,23 +110,13 @@ int do_umount_autofs_direct(struct autof
Ian Kent e6cf32
 			return 1;
Ian Kent e6cf32
 		}
Ian Kent e6cf32
 		ioctlfd = me->ioctlfd;
Ian Kent e6cf32
-	} else {
Ian Kent e6cf32
-		int cl_flags;
Ian Kent e6cf32
-
Ian Kent e6cf32
-		ioctlfd = open(me->key, O_RDONLY);
Ian Kent e6cf32
-		if (ioctlfd != -1) {
Ian Kent e6cf32
-			if ((cl_flags = fcntl(ioctlfd, F_GETFD, 0)) != -1) {
Ian Kent e6cf32
-				cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
-				fcntl(ioctlfd, F_SETFD, cl_flags);
Ian Kent e6cf32
-			}
Ian Kent e6cf32
-		}
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
+	} else
Ian Kent e6cf32
+		ops->open(ap->logopt, &ioctlfd, -1, me->key, direct);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (ioctlfd >= 0) {
Ian Kent e6cf32
-		int status = 1;
Ian Kent e6cf32
+		unsigned int status = 1;
Ian Kent e6cf32
 
Ian Kent e6cf32
-		rv = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status);
Ian Kent e6cf32
+		rv = ops->askumount(ap->logopt, ioctlfd, &status);
Ian Kent e6cf32
 		if (rv) {
Ian Kent e6cf32
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 			error(ap->logopt, "ioctl failed: %s", estr);
Ian Kent e6cf32
@@ -135,19 +129,17 @@ int do_umount_autofs_direct(struct autof
Ian Kent e6cf32
 				return 1;
Ian Kent e6cf32
 			} else {
Ian Kent e6cf32
 				me->ioctlfd = -1;
Ian Kent e6cf32
-				ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
Ian Kent e6cf32
-				close(ioctlfd);
Ian Kent e6cf32
+				ops->catatonic(ap->logopt, ioctlfd);
Ian Kent e6cf32
+				ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 				goto force_umount;
Ian Kent e6cf32
 			}
Ian Kent e6cf32
 		}
Ian Kent e6cf32
 		me->ioctlfd = -1;
Ian Kent e6cf32
-		ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
Ian Kent e6cf32
-		close(ioctlfd);
Ian Kent e6cf32
+		ops->catatonic(ap->logopt, ioctlfd);
Ian Kent e6cf32
+		ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 	} else {
Ian Kent e6cf32
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 		error(ap->logopt,
Ian Kent e6cf32
 		      "couldn't get ioctl fd for direct mount %s", me->key);
Ian Kent e6cf32
-		debug(ap->logopt, "open: %s", estr);
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -297,10 +289,11 @@ static int unlink_mount_tree(struct auto
Ian Kent e6cf32
 
Ian Kent e6cf32
 int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct mnt_params *mp;
Ian Kent e6cf32
 	time_t timeout = ap->exp_timeout;
Ian Kent e6cf32
 	struct stat st;
Ian Kent e6cf32
-	int status, ret, ioctlfd, cl_flags;
Ian Kent e6cf32
+	int status, ret, ioctlfd;
Ian Kent e6cf32
 	struct list_head list;
Ian Kent e6cf32
 	const char *map_name;
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -313,16 +306,8 @@ int do_mount_autofs_direct(struct autofs
Ian Kent e6cf32
 
Ian Kent e6cf32
 			save_ioctlfd = ioctlfd = me->ioctlfd;
Ian Kent e6cf32
 
Ian Kent e6cf32
-			if (ioctlfd == -1) {
Ian Kent e6cf32
-				ioctlfd = open(me->key, O_RDONLY);
Ian Kent e6cf32
-				if (ioctlfd != -1) {
Ian Kent e6cf32
-					cl_flags = fcntl(ioctlfd, F_GETFD, 0);
Ian Kent e6cf32
-					if (cl_flags != -1) {
Ian Kent e6cf32
-						cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
-						fcntl(ioctlfd, F_SETFD, cl_flags);
Ian Kent e6cf32
-					}
Ian Kent e6cf32
-				}
Ian Kent e6cf32
-			}
Ian Kent e6cf32
+			if (ioctlfd == -1)
Ian Kent e6cf32
+				ops->open(ap->logopt, &ioctlfd, -1, me->key, direct);
Ian Kent e6cf32
 
Ian Kent e6cf32
 			if (ioctlfd < 0) {
Ian Kent e6cf32
 				error(ap->logopt,
Ian Kent e6cf32
@@ -331,13 +316,14 @@ int do_mount_autofs_direct(struct autofs
Ian Kent e6cf32
 				return 0;
Ian Kent e6cf32
 			}
Ian Kent e6cf32
 
Ian Kent e6cf32
-			ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout);
Ian Kent e6cf32
+			ops->timeout(ap->logopt, ioctlfd, &tout);
Ian Kent e6cf32
 
Ian Kent e6cf32
 			if (save_ioctlfd == -1)
Ian Kent e6cf32
-				close(ioctlfd);
Ian Kent e6cf32
+				ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 
Ian Kent e6cf32
 			return 0;
Ian Kent e6cf32
 		}
Ian Kent e6cf32
+
Ian Kent e6cf32
 		if (!unlink_mount_tree(ap, &list)) {
Ian Kent e6cf32
 			debug(ap->logopt,
Ian Kent e6cf32
 			      "already mounted as other than autofs "
Ian Kent e6cf32
@@ -402,22 +388,16 @@ int do_mount_autofs_direct(struct autofs
Ian Kent e6cf32
 		goto out_err;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	/* Root directory for ioctl()'s */
Ian Kent e6cf32
-	ioctlfd = open(me->key, O_RDONLY);
Ian Kent e6cf32
+	ops->open(ap->logopt, &ioctlfd, -1, me->key, direct);
Ian Kent e6cf32
 	if (ioctlfd < 0) {
Ian Kent e6cf32
 		crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
Ian Kent e6cf32
 		goto out_umount;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	if ((cl_flags = fcntl(ioctlfd, F_GETFD, 0)) != -1) {
Ian Kent e6cf32
-		cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
-		fcntl(ioctlfd, F_SETFD, cl_flags);
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
 	/* Calculate the timeouts */
Ian Kent e6cf32
 	ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
Ian Kent e6cf32
 
Ian Kent e6cf32
-	ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout);
Ian Kent e6cf32
+	ops->timeout(ap->logopt, ioctlfd, &timeout);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (ap->exp_timeout)
Ian Kent e6cf32
 		info(ap->logopt,
Ian Kent e6cf32
@@ -438,14 +418,14 @@ int do_mount_autofs_direct(struct autofs
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
Ian Kent e6cf32
 
Ian Kent e6cf32
-	close(ioctlfd);
Ian Kent e6cf32
+	ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	debug(ap->logopt, "mounted trigger %s", me->key);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	return 0;
Ian Kent e6cf32
 
Ian Kent e6cf32
 out_close:
Ian Kent e6cf32
-	close(ioctlfd);
Ian Kent e6cf32
+	ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 out_umount:
Ian Kent e6cf32
 	/* TODO: maybe force umount (-l) */
Ian Kent e6cf32
 	umount(me->key);
Ian Kent e6cf32
@@ -537,8 +517,9 @@ int mount_autofs_direct(struct autofs_po
Ian Kent e6cf32
 
Ian Kent e6cf32
 int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
-	int ioctlfd, cl_flags, rv = 1, retries;
Ian Kent e6cf32
+	int ioctlfd, rv = 1, retries;
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (me->ioctlfd != -1) {
Ian Kent e6cf32
 		if (is_mounted(_PATH_MOUNTED, me->key, MNTS_REAL)) {
Ian Kent e6cf32
@@ -555,20 +536,13 @@ int umount_autofs_offset(struct autofs_p
Ian Kent e6cf32
 			      me->key);
Ian Kent e6cf32
 			return 0;
Ian Kent e6cf32
 		}
Ian Kent e6cf32
-
Ian Kent e6cf32
-		ioctlfd = open(me->key, O_RDONLY);
Ian Kent e6cf32
-		if (ioctlfd != -1) {
Ian Kent e6cf32
-			if ((cl_flags = fcntl(ioctlfd, F_GETFD, 0)) != -1) {
Ian Kent e6cf32
-				cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
-				fcntl(ioctlfd, F_SETFD, cl_flags);
Ian Kent e6cf32
-			}
Ian Kent e6cf32
-		}
Ian Kent e6cf32
+		ops->open(ap->logopt, &ioctlfd, -1, me->key, offset);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (ioctlfd >= 0) {
Ian Kent e6cf32
-		int status = 1;
Ian Kent e6cf32
+		unsigned int status = 1;
Ian Kent e6cf32
 
Ian Kent e6cf32
-		rv = ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &status);
Ian Kent e6cf32
+		rv = ops->askumount(ap->logopt, ioctlfd, &status);
Ian Kent e6cf32
 		if (rv) {
Ian Kent e6cf32
 			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 			logerr("ioctl failed: %s", estr);
Ian Kent e6cf32
@@ -581,14 +555,14 @@ int umount_autofs_offset(struct autofs_p
Ian Kent e6cf32
 				return 1;
Ian Kent e6cf32
 			} else {
Ian Kent e6cf32
 				me->ioctlfd = -1;
Ian Kent e6cf32
-				ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
Ian Kent e6cf32
-				close(ioctlfd);
Ian Kent e6cf32
+				ops->catatonic(ap->logopt, ioctlfd);
Ian Kent e6cf32
+				ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 				goto force_umount;
Ian Kent e6cf32
 			}
Ian Kent e6cf32
 		}
Ian Kent e6cf32
 		me->ioctlfd = -1;
Ian Kent e6cf32
-		ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
Ian Kent e6cf32
-		close(ioctlfd);
Ian Kent e6cf32
+		ops->catatonic(ap->logopt, ioctlfd);
Ian Kent e6cf32
+		ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 	} else {
Ian Kent e6cf32
 		struct stat st;
Ian Kent e6cf32
 		char *estr;
Ian Kent e6cf32
@@ -653,11 +627,12 @@ force_umount:
Ian Kent e6cf32
 
Ian Kent e6cf32
 int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
 	struct mnt_params *mp;
Ian Kent e6cf32
 	time_t timeout = ap->exp_timeout;
Ian Kent e6cf32
 	struct stat st;
Ian Kent e6cf32
-	int ioctlfd, cl_flags, status, ret;
Ian Kent e6cf32
+	int ioctlfd, status, ret;
Ian Kent e6cf32
 	const char *type, *map_name = NULL;
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) {
Ian Kent e6cf32
@@ -760,19 +735,13 @@ int mount_autofs_offset(struct autofs_po
Ian Kent e6cf32
 		goto out_err;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	/* Root directory for ioctl()'s */
Ian Kent e6cf32
-	ioctlfd = open(me->key, O_RDONLY);
Ian Kent e6cf32
+	ops->open(ap->logopt, &ioctlfd, -1, me->key, offset);
Ian Kent e6cf32
 	if (ioctlfd < 0) {
Ian Kent e6cf32
 		crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
Ian Kent e6cf32
 		goto out_umount;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	if ((cl_flags = fcntl(ioctlfd, F_GETFD, 0)) != -1) {
Ian Kent e6cf32
-		cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
-		fcntl(ioctlfd, F_SETFD, cl_flags);
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
-	ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout);
Ian Kent e6cf32
+	ops->timeout(ap->logopt, ioctlfd, &timeout);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	ret = fstat(ioctlfd, &st);
Ian Kent e6cf32
 	if (ret == -1) {
Ian Kent e6cf32
@@ -783,14 +752,14 @@ int mount_autofs_offset(struct autofs_po
Ian Kent e6cf32
 
Ian Kent e6cf32
 	cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
Ian Kent e6cf32
 
Ian Kent e6cf32
-	close(ioctlfd);
Ian Kent e6cf32
+	ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	debug(ap->logopt, "mounted trigger %s", me->key);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	return 0;
Ian Kent e6cf32
 
Ian Kent e6cf32
 out_close:
Ian Kent e6cf32
-	close(ioctlfd);
Ian Kent e6cf32
+	ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 out_umount:
Ian Kent e6cf32
 	umount(me->key);
Ian Kent e6cf32
 out_err:
Ian Kent e6cf32
@@ -800,53 +769,9 @@ out_err:
Ian Kent e6cf32
 	return -1;
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
-static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt)
Ian Kent e6cf32
-{
Ian Kent e6cf32
-	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
-	int ret, retries;
Ian Kent e6cf32
-	struct stat st;
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (fstat(ioctlfd, &st) == -1) {
Ian Kent e6cf32
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
-		debug(logopt, "fstat failed: %s", estr);
Ian Kent e6cf32
-		return 0;
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
-	retries = (count_mounts(logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
Ian Kent e6cf32
-
Ian Kent e6cf32
-	while (retries--) {
Ian Kent e6cf32
-		struct timespec tm = {0, 100000000};
Ian Kent e6cf32
-
Ian Kent e6cf32
-		/* Ggenerate expire message for the mount. */
Ian Kent e6cf32
-		ret = ioctl(ioctlfd, AUTOFS_IOC_EXPIRE_DIRECT, &when);
Ian Kent e6cf32
-		if (ret == -1) {
Ian Kent e6cf32
-			/* Mount has gone away */
Ian Kent e6cf32
-			if (errno == EBADF || errno == EINVAL)
Ian Kent e6cf32
-				return 1;
Ian Kent e6cf32
-
Ian Kent e6cf32
-			/*
Ian Kent e6cf32
-			 * Other than EAGAIN is an expire error so continue.
Ian Kent e6cf32
-			 * Kernel try the same mount again, limited by
Ian Kent e6cf32
-			 * retries (ie. number of mounts directly under
Ian Kent e6cf32
-			 * mount point, should always be one for direct
Ian Kent e6cf32
-			 * mounts).
Ian Kent e6cf32
-			 */
Ian Kent e6cf32
-			if (errno == EAGAIN)
Ian Kent e6cf32
-				break;
Ian Kent e6cf32
-		}
Ian Kent e6cf32
-		nanosleep(&tm, NULL);
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (!ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, &ret)) {
Ian Kent e6cf32
-		if (!ret)
Ian Kent e6cf32
-			return 0;
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
-	return 1;
Ian Kent e6cf32
-}
Ian Kent e6cf32
-
Ian Kent e6cf32
 void *expire_proc_direct(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct mnt_list *mnts = NULL, *next;
Ian Kent e6cf32
 	struct list_head list, *p;
Ian Kent e6cf32
 	struct expire_args *ea;
Ian Kent e6cf32
@@ -958,8 +883,8 @@ void *expire_proc_direct(void *arg)
Ian Kent e6cf32
 
Ian Kent e6cf32
 			ioctlfd = me->ioctlfd;
Ian Kent e6cf32
 
Ian Kent e6cf32
-			ret = expire_direct(ioctlfd, next->path, now, ap->logopt);
Ian Kent e6cf32
-			if (!ret) {
Ian Kent e6cf32
+			ret = ops->expire(ap->logopt, ioctlfd, next->path, now);
Ian Kent e6cf32
+			if (ret) {
Ian Kent e6cf32
 				left++;
Ian Kent e6cf32
 				pthread_setcancelstate(cur_state, NULL);
Ian Kent e6cf32
 				continue;
Ian Kent e6cf32
@@ -991,8 +916,8 @@ void *expire_proc_direct(void *arg)
Ian Kent e6cf32
 		debug(ap->logopt, "send expire to trigger %s", next->path);
Ian Kent e6cf32
 
Ian Kent e6cf32
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Ian Kent e6cf32
-		ret = expire_direct(ioctlfd, next->path, now, ap->logopt);
Ian Kent e6cf32
-		if (!ret)
Ian Kent e6cf32
+		ret = ops->expire(ap->logopt, ioctlfd, next->path, now);
Ian Kent e6cf32
+		if (ret)
Ian Kent e6cf32
 			left++;
Ian Kent e6cf32
 		pthread_setcancelstate(cur_state, NULL);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
@@ -1023,8 +948,11 @@ static void pending_cond_destroy(void *a
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void expire_send_fail(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt = arg;
Ian Kent e6cf32
-	send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+	struct autofs_point *ap = mt->ap;
Ian Kent e6cf32
+	ops->send_fail(ap->logopt,
Ian Kent e6cf32
+		       mt->ioctlfd, mt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void free_pending_args(void *arg)
Ian Kent e6cf32
@@ -1042,6 +970,7 @@ static void expire_mutex_unlock(void *ar
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void *do_expire_direct(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt;
Ian Kent e6cf32
 	struct autofs_point *ap;
Ian Kent e6cf32
 	size_t len;
Ian Kent e6cf32
@@ -1076,15 +1005,16 @@ static void *do_expire_direct(void *arg)
Ian Kent e6cf32
 	status = do_expire(ap, mt->name, len);
Ian Kent e6cf32
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
Ian Kent e6cf32
 	if (status)
Ian Kent e6cf32
-		send_fail(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       mt->ioctlfd, mt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
 	else {
Ian Kent e6cf32
 		struct mapent *me;
Ian Kent e6cf32
 		cache_readlock(mt->mc);
Ian Kent e6cf32
 		me = cache_lookup_distinct(mt->mc, mt->name);
Ian Kent e6cf32
 		me->ioctlfd = -1;
Ian Kent e6cf32
 		cache_unlock(mt->mc);
Ian Kent e6cf32
-		send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
-		close(mt->ioctlfd);
Ian Kent e6cf32
+		ops->send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+		ops->close(ap->logopt, mt->ioctlfd);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 	pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -1097,6 +1027,7 @@ static void *do_expire_direct(void *arg)
Ian Kent e6cf32
 
Ian Kent e6cf32
 int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_direct_t *pkt)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct map_source *map;
Ian Kent e6cf32
 	struct mapent_cache *mc = NULL;
Ian Kent e6cf32
 	struct mapent *me = NULL;
Ian Kent e6cf32
@@ -1146,7 +1077,8 @@ int handle_packet_expire_direct(struct a
Ian Kent e6cf32
 	if (!mt) {
Ian Kent e6cf32
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 		error(ap->logopt, "malloc: %s", estr);
Ian Kent e6cf32
-		send_fail(ap->logopt, me->ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       me->ioctlfd, pkt->wait_queue_token, -ENOMEM);
Ian Kent e6cf32
 		cache_unlock(mc);
Ian Kent e6cf32
 		pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
@@ -1175,7 +1107,8 @@ int handle_packet_expire_direct(struct a
Ian Kent e6cf32
 	status = pthread_create(&thid, &thread_attr, do_expire_direct, mt);
Ian Kent e6cf32
 	if (status) {
Ian Kent e6cf32
 		error(ap->logopt, "expire thread create failed");
Ian Kent e6cf32
-		send_fail(ap->logopt, mt->ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       mt->ioctlfd, pkt->wait_queue_token, -status);
Ian Kent e6cf32
 		cache_unlock(mc);
Ian Kent e6cf32
 		expire_mutex_unlock(NULL);
Ian Kent e6cf32
 		pending_cond_destroy(mt);
Ian Kent e6cf32
@@ -1203,9 +1136,11 @@ int handle_packet_expire_direct(struct a
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void mount_send_fail(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt = arg;
Ian Kent e6cf32
-	send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
-	close(mt->ioctlfd);
Ian Kent e6cf32
+	struct autofs_point *ap = mt->ap;
Ian Kent e6cf32
+	ops->send_fail(ap->logopt, mt->ioctlfd, mt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
+	ops->close(ap->logopt, mt->ioctlfd);
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void mount_mutex_unlock(void *arg)
Ian Kent e6cf32
@@ -1217,6 +1152,7 @@ static void mount_mutex_unlock(void *arg
Ian Kent e6cf32
 
Ian Kent e6cf32
 static void *do_mount_direct(void *arg)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct pending_args *mt;
Ian Kent e6cf32
 	struct autofs_point *ap;
Ian Kent e6cf32
 	struct passwd pw;
Ian Kent e6cf32
@@ -1409,15 +1345,19 @@ cont:
Ian Kent e6cf32
 		cache_unlock(mt->mc);
Ian Kent e6cf32
 		if (set_fd) {
Ian Kent e6cf32
 			me->ioctlfd = mt->ioctlfd;
Ian Kent e6cf32
-			send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+			ops->send_ready(ap->logopt,
Ian Kent e6cf32
+					mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
 		} else {
Ian Kent e6cf32
-			send_ready(ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
-			close(mt->ioctlfd);
Ian Kent e6cf32
+			ops->send_ready(ap->logopt,
Ian Kent e6cf32
+					mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
+			ops->close(ap->logopt, mt->ioctlfd);
Ian Kent e6cf32
 		}
Ian Kent e6cf32
 		info(ap->logopt, "mounted %s", mt->name);
Ian Kent e6cf32
 	} else {
Ian Kent e6cf32
-		send_fail(mt->ap->logopt, mt->ioctlfd, mt->wait_queue_token);
Ian Kent e6cf32
-		close(mt->ioctlfd);
Ian Kent e6cf32
+		/* TODO: get mount return status from lookup_nss_mount */
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       mt->ioctlfd, mt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
+		ops->close(ap->logopt, mt->ioctlfd);
Ian Kent e6cf32
 		info(ap->logopt, "failed to mount %s", mt->name);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 	pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
@@ -1431,6 +1371,7 @@ cont:
Ian Kent e6cf32
 
Ian Kent e6cf32
 int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_direct_t *pkt)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	struct map_source *map;
Ian Kent e6cf32
 	struct mapent_cache *mc = NULL;
Ian Kent e6cf32
 	struct mapent *me = NULL;
Ian Kent e6cf32
@@ -1438,7 +1379,8 @@ int handle_packet_missing_direct(struct 
Ian Kent e6cf32
 	struct pending_args *mt;
Ian Kent e6cf32
 	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
 	int status = 0;
Ian Kent e6cf32
-	int ioctlfd, cl_flags, state;
Ian Kent e6cf32
+	int ioctlfd, state;
Ian Kent e6cf32
+	unsigned int type;
Ian Kent e6cf32
 
Ian Kent e6cf32
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -1475,12 +1417,16 @@ int handle_packet_missing_direct(struct 
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
+	type = direct;
Ian Kent e6cf32
+	if (me->multi != me && !list_empty(&me->multi_list))
Ian Kent e6cf32
+		type = offset;
Ian Kent e6cf32
+
Ian Kent e6cf32
 	if (me->ioctlfd != -1) {
Ian Kent e6cf32
 		/* Maybe someone did a manual umount, clean up ! */
Ian Kent e6cf32
 		ioctlfd = me->ioctlfd;
Ian Kent e6cf32
 		me->ioctlfd = -1;
Ian Kent e6cf32
 	} else
Ian Kent e6cf32
-		ioctlfd = open(me->key, O_RDONLY);
Ian Kent e6cf32
+		ops->open(ap->logopt, &ioctlfd, -1, me->key, type);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	if (ioctlfd == -1) {
Ian Kent e6cf32
 		cache_unlock(mc);
Ian Kent e6cf32
@@ -1490,11 +1436,6 @@ int handle_packet_missing_direct(struct 
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	if ((cl_flags = fcntl(ioctlfd, F_GETFD, 0)) != -1) {
Ian Kent e6cf32
-		cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
-		fcntl(ioctlfd, F_SETFD, cl_flags);
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-
Ian Kent e6cf32
 	debug(ap->logopt, "token %ld, name %s, request pid %u",
Ian Kent e6cf32
 		  (unsigned long) pkt->wait_queue_token, me->key, pkt->pid);
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -1502,8 +1443,9 @@ int handle_packet_missing_direct(struct 
Ian Kent e6cf32
 	if (ap->shutdown ||
Ian Kent e6cf32
 	    ap->state == ST_SHUTDOWN_FORCE ||
Ian Kent e6cf32
 	    ap->state == ST_SHUTDOWN) {
Ian Kent e6cf32
-		send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
-		close(ioctlfd);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ioctlfd, pkt->wait_queue_token, -ENOENT);
Ian Kent e6cf32
+		ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 		cache_unlock(mc);
Ian Kent e6cf32
 		pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
@@ -1513,8 +1455,9 @@ int handle_packet_missing_direct(struct 
Ian Kent e6cf32
 	if (!mt) {
Ian Kent e6cf32
 		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
 		error(ap->logopt, "malloc: %s", estr);
Ian Kent e6cf32
-		send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
-		close(ioctlfd);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ioctlfd, pkt->wait_queue_token, -ENOMEM);
Ian Kent e6cf32
+		ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 		cache_unlock(mc);
Ian Kent e6cf32
 		pthread_setcancelstate(state, NULL);
Ian Kent e6cf32
 		return 1;
Ian Kent e6cf32
@@ -1542,8 +1485,9 @@ int handle_packet_missing_direct(struct 
Ian Kent e6cf32
 	status = pthread_create(&thid, &thread_attr, do_mount_direct, mt);
Ian Kent e6cf32
 	if (status) {
Ian Kent e6cf32
 		error(ap->logopt, "missing mount thread create failed");
Ian Kent e6cf32
-		send_fail(ap->logopt, ioctlfd, pkt->wait_queue_token);
Ian Kent e6cf32
-		close(ioctlfd);
Ian Kent e6cf32
+		ops->send_fail(ap->logopt,
Ian Kent e6cf32
+			       ioctlfd, pkt->wait_queue_token, -status);
Ian Kent e6cf32
+		ops->close(ap->logopt, ioctlfd);
Ian Kent e6cf32
 		cache_unlock(mc);
Ian Kent e6cf32
 		mount_mutex_unlock(NULL);
Ian Kent e6cf32
 		pending_cond_destroy(mt);
Ian Kent e6cf32
diff -up autofs-5.0.3/daemon/automount.c.device-node-control autofs-5.0.3/daemon/automount.c
Ian Kent e6cf32
--- autofs-5.0.3/daemon/automount.c.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/daemon/automount.c	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -579,40 +579,6 @@ int umount_autofs(struct autofs_point *a
Ian Kent e6cf32
 	return ret;
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
-int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token)
Ian Kent e6cf32
-{
Ian Kent e6cf32
-	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (wait_queue_token == 0)
Ian Kent e6cf32
-		return 0;
Ian Kent e6cf32
-
Ian Kent e6cf32
-	debug(logopt, "token = %d", wait_queue_token);
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (ioctl(ioctlfd, AUTOFS_IOC_READY, wait_queue_token) < 0) {
Ian Kent e6cf32
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
-		logerr("AUTOFS_IOC_READY: error %s", estr);
Ian Kent e6cf32
-		return 1;
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-	return 0;
Ian Kent e6cf32
-}
Ian Kent e6cf32
-
Ian Kent e6cf32
-int send_fail(unsigned logopt, int ioctlfd, unsigned int wait_queue_token)
Ian Kent e6cf32
-{
Ian Kent e6cf32
-	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (wait_queue_token == 0)
Ian Kent e6cf32
-		return 0;
Ian Kent e6cf32
-
Ian Kent e6cf32
-	debug(logopt, "token = %d", wait_queue_token);
Ian Kent e6cf32
-
Ian Kent e6cf32
-	if (ioctl(ioctlfd, AUTOFS_IOC_FAIL, wait_queue_token) < 0) {
Ian Kent e6cf32
-		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
-		logerr("AUTOFS_IOC_FAIL: error %s", estr);
Ian Kent e6cf32
-		return 1;
Ian Kent e6cf32
-	}
Ian Kent e6cf32
-	return 0;
Ian Kent e6cf32
-}
Ian Kent e6cf32
-
Ian Kent e6cf32
 static size_t get_kpkt_len(void)
Ian Kent e6cf32
 {
Ian Kent e6cf32
 	size_t pkt_len = sizeof(struct autofs_v5_packet);
Ian Kent e6cf32
@@ -1540,7 +1506,9 @@ void *handle_mounts(void *arg)
Ian Kent e6cf32
 
Ian Kent e6cf32
 	while (ap->state != ST_SHUTDOWN) {
Ian Kent e6cf32
 		if (handle_packet(ap)) {
Ian Kent e6cf32
-			int ret, result;
Ian Kent e6cf32
+			struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
+			unsigned int result;
Ian Kent e6cf32
+			int ret;
Ian Kent e6cf32
 
Ian Kent e6cf32
 			state_mutex_lock(ap);
Ian Kent e6cf32
 			/*
Ian Kent e6cf32
@@ -1557,7 +1525,7 @@ void *handle_mounts(void *arg)
Ian Kent e6cf32
 			 * If the ioctl fails assume the kernel doesn't have
Ian Kent e6cf32
 			 * AUTOFS_IOC_ASKUMOUNT and just continue.
Ian Kent e6cf32
 			 */
Ian Kent e6cf32
-			ret = ioctl(ap->ioctlfd, AUTOFS_IOC_ASKUMOUNT, &result);
Ian Kent e6cf32
+			ret = ops->askumount(ap->logopt, ap->ioctlfd, &result);
Ian Kent e6cf32
 			if (ret == -1) {
Ian Kent e6cf32
 				state_mutex_unlock(ap);
Ian Kent e6cf32
 				break;
Ian Kent e6cf32
@@ -2055,6 +2023,8 @@ int main(int argc, char *argv[])
Ian Kent e6cf32
 		exit(1);
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
+	init_ioctl_ctl();
Ian Kent e6cf32
+
Ian Kent e6cf32
 	if (!alarm_start_handler()) {
Ian Kent e6cf32
 		logerr("%s: failed to create alarm handler thread!", program);
Ian Kent e6cf32
 		master_kill(master_list);
Ian Kent e6cf32
@@ -2099,6 +2069,8 @@ int main(int argc, char *argv[])
Ian Kent e6cf32
 	if (dh)
Ian Kent e6cf32
 		dlclose(dh);
Ian Kent e6cf32
 #endif
Ian Kent e6cf32
+	close_ioctl_ctl();
Ian Kent e6cf32
+
Ian Kent e6cf32
 	info(logging, "autofs stopped");
Ian Kent e6cf32
 
Ian Kent e6cf32
 	exit(0);
Ian Kent e6cf32
diff -up autofs-5.0.3/include/automount.h.device-node-control autofs-5.0.3/include/automount.h
Ian Kent e6cf32
--- autofs-5.0.3/include/automount.h.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/include/automount.h	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -29,6 +29,7 @@
Ian Kent e6cf32
 #include "log.h"
Ian Kent e6cf32
 #include "rpc_subs.h"
Ian Kent e6cf32
 #include "parse_subs.h"
Ian Kent e6cf32
+#include "dev-ioctl-lib.h"
Ian Kent e6cf32
 
Ian Kent e6cf32
 #ifdef WITH_DMALLOC
Ian Kent e6cf32
 #include <dmalloc.h>
Ian Kent e6cf32
@@ -70,6 +71,10 @@ int load_autofs4_module(void);
Ian Kent e6cf32
 #define SMB_SUPER_MAGIC    0x0000517BL
Ian Kent e6cf32
 #define CIFS_MAGIC_NUMBER  0xFF534D42L
Ian Kent e6cf32
 
Ian Kent e6cf32
+#define AUTOFS_TYPE_INDIRECT     0x0001
Ian Kent e6cf32
+#define AUTOFS_TYPE_DIRECT       0x0002
Ian Kent e6cf32
+#define AUTOFS_TYPE_OFFSET       0x0004
Ian Kent e6cf32
+
Ian Kent e6cf32
 /* This sould be enough for at least 20 host aliases */
Ian Kent e6cf32
 #define HOST_ENT_BUF_SIZE	2048
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -367,7 +372,7 @@ void free_mnt_list(struct mnt_list *list
Ian Kent e6cf32
 int contained_in_local_fs(const char *path);
Ian Kent e6cf32
 int is_mounted(const char *table, const char *path, unsigned int type);
Ian Kent e6cf32
 int has_fstab_option(const char *opt);
Ian Kent e6cf32
-char *find_mnt_ino(const char *table, dev_t dev, ino_t ino);
Ian Kent e6cf32
+int find_mnt_devid(const char *table, const char *path, char *devid, unsigned int type);
Ian Kent e6cf32
 char *get_offset(const char *prefix, char *offset,
Ian Kent e6cf32
                  struct list_head *head, struct list_head **pos);
Ian Kent e6cf32
 void add_ordered_list(struct mnt_list *ent, struct list_head *head);
Ian Kent e6cf32
@@ -377,6 +382,7 @@ int tree_get_mnt_list(struct mnt_list *m
Ian Kent e6cf32
 int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
Ian Kent e6cf32
 int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path);
Ian Kent e6cf32
 int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type);
Ian Kent e6cf32
+int tree_find_mnt_devid(struct mnt_list *mnts, const char *path, char *devid, unsigned int type);
Ian Kent e6cf32
 
Ian Kent e6cf32
 /* Core automount definitions */
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -470,8 +476,6 @@ struct autofs_point {
Ian Kent e6cf32
 
Ian Kent e6cf32
 void *handle_mounts(void *arg);
Ian Kent e6cf32
 int umount_multi(struct autofs_point *ap, const char *path, int incl);
Ian Kent e6cf32
-int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token);
Ian Kent e6cf32
-int send_fail(unsigned logopt, int ioctlfd, unsigned int wait_queue_token);
Ian Kent e6cf32
 int do_expire(struct autofs_point *ap, const char *name, int namelen);
Ian Kent e6cf32
 void *expire_proc_indirect(void *);
Ian Kent e6cf32
 void *expire_proc_direct(void *);
Ian Kent e6cf32
diff -up /dev/null autofs-5.0.3/include/linux/auto_dev-ioctl.h
Ian Kent e6cf32
--- /dev/null	2008-02-25 17:16:11.149000952 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/include/linux/auto_dev-ioctl.h	2008-02-25 09:03:44.000000000 +0900
Ian Kent e6cf32
@@ -0,0 +1,113 @@
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * linux/include/linux/auto_dev-ioctl.h
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * Copyright 2008 Red Hat, Inc. All rights reserved.
Ian Kent e6cf32
+ * Copyright 2008 Ian Kent <raven@themaw.net>
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * This file is part of the Linux kernel and is made available under
Ian Kent e6cf32
+ * the terms of the GNU General Public License, version 2, or at your
Ian Kent e6cf32
+ * option, any later version, incorporated herein by reference.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+
Ian Kent e6cf32
+#ifndef _LINUX_AUTO_DEV_IOCTL_H
Ian Kent e6cf32
+#define _LINUX_AUTO_DEV_IOCTL_H
Ian Kent e6cf32
+
Ian Kent e6cf32
+#include <linux/types.h>
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_VERSION_MAJOR	1
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_VERSION_MINOR	0
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define AUTOFS_DEVID_LEN		16
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * An ioctl interface for autofs mount point control.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * All theioctls use this structure.
Ian Kent e6cf32
+ * When sending a path size must account for the total length
Ian Kent e6cf32
+ * of the chunk of memory.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+
Ian Kent e6cf32
+struct autofs_dev_ioctl {
Ian Kent e6cf32
+	__u32 ver_major;
Ian Kent e6cf32
+	__u32 ver_minor;
Ian Kent e6cf32
+	__u32 size;		/* total size of data passed in
Ian Kent e6cf32
+				 * including this struct */
Ian Kent e6cf32
+	__s32 ioctlfd;		/* automount command fd */
Ian Kent e6cf32
+
Ian Kent e6cf32
+	__u32 arg1;		/* Command parameters */
Ian Kent e6cf32
+	__u32 arg2;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	char path[0];
Ian Kent e6cf32
+};
Ian Kent e6cf32
+
Ian Kent e6cf32
+static inline void init_autofs_dev_ioctl(struct autofs_dev_ioctl *in)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	in->ver_major = AUTOFS_DEV_IOCTL_VERSION_MAJOR;
Ian Kent e6cf32
+	in->ver_minor = AUTOFS_DEV_IOCTL_VERSION_MINOR;
Ian Kent e6cf32
+	in->size = sizeof(struct autofs_dev_ioctl);
Ian Kent e6cf32
+	in->ioctlfd = -1;
Ian Kent e6cf32
+	in->arg1 = 0;
Ian Kent e6cf32
+	in->arg2 = 0;
Ian Kent e6cf32
+	return;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * If you change this make sure you make the corresponding change
Ian Kent e6cf32
+ * to autofs-dev-ioctl.c:lookup_ioctl()
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+enum {
Ian Kent e6cf32
+	/* Get various version info */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_VERSION_CMD = 0x71,
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_PROTOVER_CMD,
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Set mount we're acting on */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_OPENMOUNT_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Close mount ioctl fd */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Mount/expire status returns */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_READY_CMD,
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_FAIL_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Automount active/inactive */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_SETPIPEFD_CMD,
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_CATATONIC_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Expiry timeout */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_TIMEOUT_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Get mount last requesting uid and gid */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_REQUESTOR_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Check for eligible expire candidates */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_EXPIRE_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Request busy status */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD,
Ian Kent e6cf32
+
Ian Kent e6cf32
+	/* Check if path is a mountpoint */
Ian Kent e6cf32
+	AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD,
Ian Kent e6cf32
+};
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define AUTOFS_IOCTL 0x93
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_VERSION	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_VERSION_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_PROTOVER	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_PROTOVER_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_PROTOSUBVER	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_PROTOSUBVER_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_OPENMOUNT	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_OPENMOUNT_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_CLOSEMOUNT	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_CLOSEMOUNT_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_READY		_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_READY_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_FAIL		_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_FAIL_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_SETPIPEFD	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_SETPIPEFD_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_CATATONIC	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_CATATONIC_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_TIMEOUT	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_TIMEOUT_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_REQUESTOR	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_REQUESTOR_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_EXPIRE		_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_EXPIRE_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_ASKUMOUNT	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_ASKUMOUNT_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_ISMOUNTPOINT	_IOWR(AUTOFS_IOCTL, AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD, struct autofs_dev_ioctl)
Ian Kent e6cf32
+
Ian Kent e6cf32
+#endif	/* _LINUX_AUTO_DEV_IOCTL_H */
Ian Kent e6cf32
diff -up /dev/null autofs-5.0.3/include/mounts.h
Ian Kent e6cf32
--- /dev/null	2008-02-25 17:16:11.149000952 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/include/mounts.h	2008-02-25 09:03:44.000000000 +0900
Ian Kent e6cf32
@@ -0,0 +1,96 @@
Ian Kent e6cf32
+/* ----------------------------------------------------------------------- *
Ian Kent e6cf32
+ *   
Ian Kent e6cf32
+ *  mounts.h - header file for mount utilities module.
Ian Kent e6cf32
+ * 
Ian Kent e6cf32
+ *   Copyright 2008 Red Hat, Inc. All rights reserved.
Ian Kent e6cf32
+ *   Copyright 2004-2006 Ian Kent <raven@themaw.net> - All Rights Reserved.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ *   This program is free software; you can redistribute it and/or modify
Ian Kent e6cf32
+ *   it under the terms of the GNU General Public License as published by
Ian Kent e6cf32
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
Ian Kent e6cf32
+ *   USA; either version 2 of the License, or (at your option) any later
Ian Kent e6cf32
+ *   version; incorporated herein by reference.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * ----------------------------------------------------------------------- */
Ian Kent e6cf32
+
Ian Kent e6cf32
+#ifndef MOUNTS_H
Ian Kent e6cf32
+#define MOUNTS_H
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define AUTOFS_TYPE_INDIRECT     0x0001
Ian Kent e6cf32
+#define AUTOFS_TYPE_DIRECT       0x0002
Ian Kent e6cf32
+#define AUTOFS_TYPE_OFFSET       0x0004
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define MNTS_ALL	0x0001
Ian Kent e6cf32
+#define MNTS_REAL	0x0002
Ian Kent e6cf32
+#define MNTS_AUTOFS	0x0004
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define REMOUNT_SUCCESS		0x0000
Ian Kent e6cf32
+#define REMOUNT_OPEN_FAIL	0x0001
Ian Kent e6cf32
+#define REMOUNT_STAT_FAIL	0x0002
Ian Kent e6cf32
+#define REMOUNT_READ_MAP	0x0004
Ian Kent e6cf32
+
Ian Kent e6cf32
+extern const unsigned int indirect;
Ian Kent e6cf32
+extern const unsigned int direct;
Ian Kent e6cf32
+extern const unsigned int offset;
Ian Kent e6cf32
+
Ian Kent e6cf32
+struct mapent;
Ian Kent e6cf32
+
Ian Kent e6cf32
+struct mnt_list {
Ian Kent e6cf32
+	char *path;
Ian Kent e6cf32
+	char *fs_name;
Ian Kent e6cf32
+	char *fs_type;
Ian Kent e6cf32
+	char *opts;
Ian Kent e6cf32
+	pid_t owner;
Ian Kent e6cf32
+	/*
Ian Kent e6cf32
+	 * List operations ie. get_mnt_list.
Ian Kent e6cf32
+	 */
Ian Kent e6cf32
+	struct mnt_list *next;
Ian Kent e6cf32
+	/*
Ian Kent e6cf32
+	 * Tree operations ie. tree_make_tree,
Ian Kent e6cf32
+	 * tree_get_mnt_list etc.
Ian Kent e6cf32
+	 */
Ian Kent e6cf32
+	struct mnt_list *left;
Ian Kent e6cf32
+	struct mnt_list *right;
Ian Kent e6cf32
+	struct list_head self;
Ian Kent e6cf32
+	struct list_head list;
Ian Kent e6cf32
+	struct list_head entries;
Ian Kent e6cf32
+	struct list_head sublist;
Ian Kent e6cf32
+	/*
Ian Kent e6cf32
+	 * Offset mount handling ie. add_ordered_list
Ian Kent e6cf32
+	 * and get_offset.
Ian Kent e6cf32
+	 */
Ian Kent e6cf32
+	struct list_head ordered;
Ian Kent e6cf32
+};
Ian Kent e6cf32
+
Ian Kent e6cf32
+unsigned int query_kproto_ver(void);
Ian Kent e6cf32
+unsigned int get_kver_major(void);
Ian Kent e6cf32
+unsigned int get_kver_minor(void);
Ian Kent e6cf32
+char *make_options_string(char *path, int kernel_pipefd, char *extra);
Ian Kent e6cf32
+char *make_mnt_name_string(char *path);
Ian Kent e6cf32
+struct mnt_list *get_mnt_list(const char *table, const char *path, int include);
Ian Kent e6cf32
+struct mnt_list *reverse_mnt_list(struct mnt_list *list);
Ian Kent e6cf32
+void free_mnt_list(struct mnt_list *list);
Ian Kent e6cf32
+int contained_in_local_fs(const char *path);
Ian Kent e6cf32
+int is_mounted(const char *table, const char *path, unsigned int type);
Ian Kent e6cf32
+int has_fstab_option(const char *opt);
Ian Kent e6cf32
+int find_mnt_devid(const char *table, const char *path, char *devid, const unsigned int type);
Ian Kent e6cf32
+char *get_offset(const char *prefix, char *offset,
Ian Kent e6cf32
+                 struct list_head *head, struct list_head **pos);
Ian Kent e6cf32
+void add_ordered_list(struct mnt_list *ent, struct list_head *head);
Ian Kent e6cf32
+void tree_free_mnt_tree(struct mnt_list *tree);
Ian Kent e6cf32
+struct mnt_list *tree_make_mnt_tree(const char *table, const char *path);
Ian Kent e6cf32
+int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
Ian Kent e6cf32
+int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
Ian Kent e6cf32
+int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path);
Ian Kent e6cf32
+int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type);
Ian Kent e6cf32
+int tree_find_mnt_devid(struct mnt_list *mnts, const char *path, char *devid, const unsigned int type);
Ian Kent e6cf32
+void set_tsd_user_vars(unsigned int, uid_t, gid_t);
Ian Kent e6cf32
+const char *mount_type_str(unsigned int);
Ian Kent e6cf32
+void notify_mount_result(struct autofs_point *, const char *, const char *);
Ian Kent e6cf32
+int remount_active_mount(struct autofs_point *, struct mapent_cache *,
Ian Kent e6cf32
+			 const char *, dev_t devid, const unsigned int, int *);
Ian Kent e6cf32
+int umount_ent(struct autofs_point *, const char *);
Ian Kent e6cf32
+int mount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
Ian Kent e6cf32
+int umount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
Ian Kent e6cf32
+
Ian Kent e6cf32
+#endif
Ian Kent e6cf32
diff -up /dev/null autofs-5.0.3/include/dev-ioctl-lib.h
Ian Kent e6cf32
--- /dev/null	2008-02-25 17:16:11.149000952 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/include/dev-ioctl-lib.h	2008-02-25 09:03:44.000000000 +0900
Ian Kent e6cf32
@@ -0,0 +1,62 @@
Ian Kent e6cf32
+/* ----------------------------------------------------------------------- *
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ *  dev-ioctl-lib.h - autofs device control.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ *   Copyright 2008 Red Hat, Inc. All rights reserved.
Ian Kent e6cf32
+ *   Copyright 2008 Ian Kent <raven@themaw.net>
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ *   This program is free software; you can redistribute it and/or modify
Ian Kent e6cf32
+ *   it under the terms of the GNU General Public License as published by
Ian Kent e6cf32
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
Ian Kent e6cf32
+ *   USA; either version 2 of the License, or (at your option) any later
Ian Kent e6cf32
+ *   version.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ *   This program is distributed in the hope that it will be useful,
Ian Kent e6cf32
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Ian Kent e6cf32
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ian Kent e6cf32
+ *   GNU General Public License for more details.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * ----------------------------------------------------------------------- */
Ian Kent e6cf32
+
Ian Kent e6cf32
+#ifndef AUTOFS_DEV_IOCTL_LIB_H
Ian Kent e6cf32
+#define AUTOFS_DEV_IOCTL_LIB_H
Ian Kent e6cf32
+
Ian Kent e6cf32
+#include <sys/types.h>
Ian Kent e6cf32
+#include "linux/auto_dev-ioctl.h"
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define CONTROL_DEVICE  "/dev/autofs"
Ian Kent e6cf32
+
Ian Kent e6cf32
+#define DEV_IOCTL_IS_MOUNTED	0x0001
Ian Kent e6cf32
+#define DEV_IOCTL_IS_AUTOFS	0x0002
Ian Kent e6cf32
+#define DEV_IOCTL_IS_OTHER	0x0004
Ian Kent e6cf32
+
Ian Kent e6cf32
+struct ioctl_ctl {
Ian Kent e6cf32
+	int devfd;
Ian Kent e6cf32
+	struct ioctl_ops *ops;
Ian Kent e6cf32
+};
Ian Kent e6cf32
+
Ian Kent e6cf32
+struct ioctl_ops {
Ian Kent e6cf32
+	int (*version)(unsigned int, int, struct autofs_dev_ioctl *);
Ian Kent e6cf32
+	int (*protover)(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+	int (*protosubver)(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+	int (*open)(unsigned int, int *, dev_t, const char *, unsigned int);
Ian Kent e6cf32
+	int (*close)(unsigned int, int);
Ian Kent e6cf32
+	int (*send_ready)(unsigned int, int, unsigned int);
Ian Kent e6cf32
+	int (*send_fail)(unsigned int, int, unsigned int, int);
Ian Kent e6cf32
+	int (*setpipefd)(unsigned int, int, int);
Ian Kent e6cf32
+	int (*catatonic)(unsigned int, int);
Ian Kent e6cf32
+	int (*timeout)(unsigned int, int, time_t *);
Ian Kent e6cf32
+	int (*requestor)(unsigned int, int, const char *, uid_t *, gid_t *);
Ian Kent e6cf32
+	int (*expire)(unsigned int, int, const char *, unsigned int);
Ian Kent e6cf32
+	int (*askumount)(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+	int (*ismountpoint)(unsigned int, int, const char *, unsigned int *);
Ian Kent e6cf32
+};
Ian Kent e6cf32
+
Ian Kent e6cf32
+void init_ioctl_ctl(void);
Ian Kent e6cf32
+void close_ioctl_ctl(void);
Ian Kent e6cf32
+struct ioctl_ops *get_ioctl_ops(void);
Ian Kent e6cf32
+struct autofs_dev_ioctl *alloc_ioctl_ctl_open(const char *, unsigned int);
Ian Kent e6cf32
+void free_ioctl_ctl_open(struct autofs_dev_ioctl *);
Ian Kent e6cf32
+
Ian Kent e6cf32
+#endif
Ian Kent e6cf32
+
Ian Kent e6cf32
diff -up autofs-5.0.3/CHANGELOG.device-node-control autofs-5.0.3/CHANGELOG
Ian Kent e6cf32
--- autofs-5.0.3/CHANGELOG.device-node-control	2008-02-25 08:58:46.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/CHANGELOG	2008-02-25 09:07:32.000000000 +0900
Ian Kent e6cf32
@@ -8,6 +8,7 @@
Ian Kent e6cf32
 - another fix for don't fail on empty master map.
Ian Kent e6cf32
 - fix expire working harder than needed.
Ian Kent e6cf32
 - fix unlink of mount tree incorrectly causing autofs mount fail.
Ian Kent e6cf32
+- add miscellaneous device node interface library.
Ian Kent e6cf32
  
Ian Kent e6cf32
 14/01/2008 autofs-5.0.3
Ian Kent e6cf32
 -----------------------
Ian Kent e6cf32
diff -up autofs-5.0.3/redhat/autofs.init.in.device-node-control autofs-5.0.3/redhat/autofs.init.in
Ian Kent e6cf32
--- autofs-5.0.3/redhat/autofs.init.in.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/redhat/autofs.init.in	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -13,6 +13,7 @@
Ian Kent e6cf32
 DAEMON=@@sbindir@@/automount
Ian Kent e6cf32
 prog=`basename $DAEMON`
Ian Kent e6cf32
 MODULE="autofs4"
Ian Kent e6cf32
+DEVICE="autofs"
Ian Kent e6cf32
 initdir=@@initdir@@
Ian Kent e6cf32
 confdir=@@autofsconfdir@@
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -56,6 +57,15 @@ function start() {
Ian Kent e6cf32
 		echo
Ian Kent e6cf32
 		return $RETVAL
Ian Kent e6cf32
 	fi
Ian Kent e6cf32
+
Ian Kent e6cf32
+	# Check misc device
Ian Kent e6cf32
+	if [ -e "/proc/misc" ]; then
Ian Kent e6cf32
+		MINOR=`awk "/$DEVICE/ {print \\$1}" /proc/misc`
Ian Kent e6cf32
+		if [ -n "$MINOR" -a ! -c "/dev/$DEVICE" ]; then
Ian Kent e6cf32
+			mknod -m 0600 /dev/$DEVICE c 10 $MINOR
Ian Kent e6cf32
+		fi
Ian Kent e6cf32
+	fi
Ian Kent e6cf32
+
Ian Kent e6cf32
 	echo -n $"Starting $prog: "
Ian Kent e6cf32
 	$prog $OPTIONS 
Ian Kent e6cf32
 	RETVAL=$?
Ian Kent e6cf32
diff -up autofs-5.0.3/lib/master_parse.y.device-node-control autofs-5.0.3/lib/master_parse.y
Ian Kent e6cf32
--- autofs-5.0.3/lib/master_parse.y.device-node-control	2008-02-25 08:58:46.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/lib/master_parse.y	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -796,6 +796,7 @@ int master_parse_entry(const char *buffe
Ian Kent e6cf32
 			return 0;
Ian Kent e6cf32
 		}
Ian Kent e6cf32
 	} else {
Ian Kent e6cf32
+		struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 		struct autofs_point *ap = entry->ap;
Ian Kent e6cf32
 		time_t tout = timeout;
Ian Kent e6cf32
 
Ian Kent e6cf32
@@ -807,7 +808,7 @@ int master_parse_entry(const char *buffe
Ian Kent e6cf32
 			ap->exp_timeout = timeout;
Ian Kent e6cf32
 			ap->exp_runfreq = (ap->exp_timeout + CHECK_RATIO - 1) / CHECK_RATIO;
Ian Kent e6cf32
 			if (ap->ioctlfd != -1 && ap->type == LKP_INDIRECT)
Ian Kent e6cf32
-				ioctl(ap->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &tout);
Ian Kent e6cf32
+				ops->timeout(ap->logopt, ap->ioctlfd, &tout);
Ian Kent e6cf32
 		}
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 	entry->ap->random_selection = random_selection;
Ian Kent e6cf32
diff -up autofs-5.0.3/lib/mounts.c.device-node-control autofs-5.0.3/lib/mounts.c
Ian Kent e6cf32
--- autofs-5.0.3/lib/mounts.c.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/lib/mounts.c	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -38,6 +38,7 @@ static const char kver_options_template[
Ian Kent e6cf32
 
Ian Kent e6cf32
 unsigned int query_kproto_ver(void)
Ian Kent e6cf32
 {
Ian Kent e6cf32
+	struct ioctl_ops *ops = get_ioctl_ops();
Ian Kent e6cf32
 	char dir[] = "/tmp/autoXXXXXX", *t_dir;
Ian Kent e6cf32
 	char options[MAX_OPTIONS_LEN + 1];
Ian Kent e6cf32
 	pid_t pgrp = getpgrp();
Ian Kent e6cf32
@@ -70,7 +71,7 @@ unsigned int query_kproto_ver(void)
Ian Kent e6cf32
 
Ian Kent e6cf32
 	close(pipefd[1]);
Ian Kent e6cf32
 
Ian Kent e6cf32
-	ioctlfd = open(t_dir, O_RDONLY);
Ian Kent e6cf32
+	ops->open(LOGOPT_NONE, &ioctlfd, -1, t_dir, AUTOFS_TYPE_INDIRECT);
Ian Kent e6cf32
 	if (ioctlfd == -1) {
Ian Kent e6cf32
 		umount(t_dir);
Ian Kent e6cf32
 		close(pipefd[0]);
Ian Kent e6cf32
@@ -78,11 +79,11 @@ unsigned int query_kproto_ver(void)
Ian Kent e6cf32
 		return 0;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
Ian Kent e6cf32
+	ops->catatonic(LOGOPT_NONE, ioctlfd);
Ian Kent e6cf32
 
Ian Kent e6cf32
 	/* If this ioctl() doesn't work, it is kernel version 2 */
Ian Kent e6cf32
-	if (ioctl(ioctlfd, AUTOFS_IOC_PROTOVER, &kver.major) == -1) {
Ian Kent e6cf32
-		close(ioctlfd);
Ian Kent e6cf32
+	if (ops->protover(LOGOPT_NONE, ioctlfd, &kver.major)) {
Ian Kent e6cf32
+		ops->close(LOGOPT_NONE, ioctlfd);
Ian Kent e6cf32
 		umount(t_dir);
Ian Kent e6cf32
 		close(pipefd[0]);
Ian Kent e6cf32
 		rmdir(t_dir);
Ian Kent e6cf32
@@ -90,15 +91,15 @@ unsigned int query_kproto_ver(void)
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
 	/* If this ioctl() doesn't work, version is 4 or less */
Ian Kent e6cf32
-	if (ioctl(ioctlfd, AUTOFS_IOC_PROTOSUBVER, &kver.minor) == -1) {
Ian Kent e6cf32
-		close(ioctlfd);
Ian Kent e6cf32
+	if (ops->protosubver(LOGOPT_NONE, ioctlfd, &kver.minor)) {
Ian Kent e6cf32
+		ops->close(LOGOPT_NONE, ioctlfd);
Ian Kent e6cf32
 		umount(t_dir);
Ian Kent e6cf32
 		close(pipefd[0]);
Ian Kent e6cf32
 		rmdir(t_dir);
Ian Kent e6cf32
 		return 0;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
-	close(ioctlfd);
Ian Kent e6cf32
+	ops->close(LOGOPT_NONE, ioctlfd);
Ian Kent e6cf32
 	umount(t_dir);
Ian Kent e6cf32
 	close(pipefd[0]);
Ian Kent e6cf32
 	rmdir(t_dir);
Ian Kent e6cf32
@@ -456,49 +457,75 @@ int has_fstab_option(const char *opt)
Ian Kent e6cf32
 	return ret;
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
-char *find_mnt_ino(const char *table, dev_t dev, ino_t ino)
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Find the device number of an autofs mount with given path and
Ian Kent e6cf32
+ * type (eg..AUTOFS_TYPE_DIRECT). An autofs display mount option
Ian Kent e6cf32
+ * "dev=<device number>" is provided by the kernel module for this.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * The device number is used by the kernel to identify the autofs
Ian Kent e6cf32
+ * super block when searching for the mount.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+int find_mnt_devid(const char *table,
Ian Kent e6cf32
+		   const char *path, char *devid, unsigned int type)
Ian Kent e6cf32
 {
Ian Kent e6cf32
-	struct mntent mnt_wrk;
Ian Kent e6cf32
 	struct mntent *mnt;
Ian Kent e6cf32
+	struct mntent mnt_wrk;
Ian Kent e6cf32
 	char buf[PATH_MAX * 3];
Ian Kent e6cf32
-	char *path = NULL;
Ian Kent e6cf32
-	unsigned long l_dev = (unsigned long) dev;
Ian Kent e6cf32
-	unsigned long l_ino = (unsigned long) ino;
Ian Kent e6cf32
 	FILE *tab;
Ian Kent e6cf32
+	char *dev;
Ian Kent e6cf32
 
Ian Kent e6cf32
 	tab = setmntent(table, "r");
Ian Kent e6cf32
 	if (!tab) {
Ian Kent e6cf32
-		char *estr = strerror_r(errno, buf, (size_t) PATH_MAX - 1);
Ian Kent e6cf32
-		logerr("setmntent: %s", estr);
Ian Kent e6cf32
+		printf("failed to open mount table\n");
Ian Kent e6cf32
 		return 0;
Ian Kent e6cf32
 	}
Ian Kent e6cf32
 
Ian Kent e6cf32
+	dev = NULL;
Ian Kent e6cf32
 	while ((mnt = getmntent_r(tab, &mnt_wrk, buf, PATH_MAX * 3))) {
Ian Kent e6cf32
-		char *p_dev, *p_ino;
Ian Kent e6cf32
-		unsigned long m_dev, m_ino;
Ian Kent e6cf32
-
Ian Kent e6cf32
 		if (strcmp(mnt->mnt_type, "autofs"))
Ian Kent e6cf32
 			continue;
Ian Kent e6cf32
 
Ian Kent e6cf32
-		p_dev = strstr(mnt->mnt_opts, "dev=");
Ian Kent e6cf32
-		if (!p_dev)
Ian Kent e6cf32
-			continue;
Ian Kent e6cf32
-		sscanf(p_dev, "dev=%lu", &m_dev);
Ian Kent e6cf32
-		if (m_dev != l_dev)
Ian Kent e6cf32
+		if (strcmp(mnt->mnt_dir, path))
Ian Kent e6cf32
 			continue;
Ian Kent e6cf32
 
Ian Kent e6cf32
-		p_ino = strstr(mnt->mnt_opts, "ino=");
Ian Kent e6cf32
-		if (!p_ino)
Ian Kent e6cf32
-			continue;
Ian Kent e6cf32
-		sscanf(p_ino, "ino=%lu", &m_ino);
Ian Kent e6cf32
-		if (m_ino == l_ino) {
Ian Kent e6cf32
-			path = strdup(mnt->mnt_dir);
Ian Kent e6cf32
+		switch (type) {
Ian Kent e6cf32
+		case AUTOFS_TYPE_INDIRECT:
Ian Kent e6cf32
+			if (!hasmntopt(mnt, "indirect"))
Ian Kent e6cf32
+				continue;
Ian Kent e6cf32
+			break;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		case AUTOFS_TYPE_DIRECT:
Ian Kent e6cf32
+			if (!hasmntopt(mnt, "direct"))
Ian Kent e6cf32
+				continue;
Ian Kent e6cf32
+			break;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		case AUTOFS_TYPE_OFFSET:
Ian Kent e6cf32
+			if (!hasmntopt(mnt, "offset"))
Ian Kent e6cf32
+				continue;
Ian Kent e6cf32
+			break;
Ian Kent e6cf32
+		}
Ian Kent e6cf32
+
Ian Kent e6cf32
+		dev = hasmntopt(mnt, "dev");
Ian Kent e6cf32
+		if (dev) {
Ian Kent e6cf32
+			char *start = strchr(dev, '=') + 1;
Ian Kent e6cf32
+			char *end = strchr(start, ',');
Ian Kent e6cf32
+			if (end)
Ian Kent e6cf32
+				*end = '\0';
Ian Kent e6cf32
+			if (start) {
Ian Kent e6cf32
+				int len = strlen(start);
Ian Kent e6cf32
+				memcpy(devid, start, len);
Ian Kent e6cf32
+				devid[len] = '\0';
Ian Kent e6cf32
+			}
Ian Kent e6cf32
 			break;
Ian Kent e6cf32
 		}
Ian Kent e6cf32
 	}
Ian Kent e6cf32
+
Ian Kent e6cf32
 	endmntent(tab);
Ian Kent e6cf32
 
Ian Kent e6cf32
-	return path;
Ian Kent e6cf32
+	if (!dev)
Ian Kent e6cf32
+		return 0;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 1;
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
 char *get_offset(const char *prefix, char *offset,
Ian Kent e6cf32
@@ -976,3 +1003,70 @@ int tree_is_mounted(struct mnt_list *mnt
Ian Kent e6cf32
 	return mounted;
Ian Kent e6cf32
 }
Ian Kent e6cf32
 
Ian Kent e6cf32
+int tree_find_mnt_devid(struct mnt_list *mnts,
Ian Kent e6cf32
+			const char *path, char *devid, unsigned int type)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct list_head *p;
Ian Kent e6cf32
+	struct list_head list;
Ian Kent e6cf32
+	size_t len = strlen(path);
Ian Kent e6cf32
+	char *dev;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	INIT_LIST_HEAD(&list);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (!tree_find_mnt_ents(mnts, &list, path))
Ian Kent e6cf32
+		return 0;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	dev = NULL;
Ian Kent e6cf32
+	list_for_each(p, &list) {
Ian Kent e6cf32
+		struct mnt_list *mptr;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		mptr = list_entry(p, struct mnt_list, entries);
Ian Kent e6cf32
+
Ian Kent e6cf32
+		if (strcmp(mptr->fs_type, "autofs"))
Ian Kent e6cf32
+			continue;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		if (strlen(mptr->path) < len)
Ian Kent e6cf32
+			return 0;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		if (strcmp(mptr->path, path))
Ian Kent e6cf32
+			continue;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		switch (type) {
Ian Kent e6cf32
+		case AUTOFS_TYPE_INDIRECT:
Ian Kent e6cf32
+			if (!strstr(mptr->opts, "indirect"))
Ian Kent e6cf32
+				continue;
Ian Kent e6cf32
+			break;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		case AUTOFS_TYPE_DIRECT:
Ian Kent e6cf32
+			if (!strstr(mptr->opts, "direct"))
Ian Kent e6cf32
+				continue;
Ian Kent e6cf32
+			break;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		case AUTOFS_TYPE_OFFSET:
Ian Kent e6cf32
+			if (!strstr(mptr->opts, "offset"))
Ian Kent e6cf32
+				continue;
Ian Kent e6cf32
+			break;
Ian Kent e6cf32
+		}
Ian Kent e6cf32
+
Ian Kent e6cf32
+		dev = strstr(mptr->opts, "dev");
Ian Kent e6cf32
+		if (dev) {
Ian Kent e6cf32
+			char *start = strchr(dev, '=') + 1;
Ian Kent e6cf32
+			char *end = strchr(start, ',');
Ian Kent e6cf32
+			if (end)
Ian Kent e6cf32
+				*end = '\0';
Ian Kent e6cf32
+			if (start) {
Ian Kent e6cf32
+				int len = strlen(start);
Ian Kent e6cf32
+				memcpy(devid, start, len);
Ian Kent e6cf32
+				devid[len] = '\0';
Ian Kent e6cf32
+			}
Ian Kent e6cf32
+			*end = ',';
Ian Kent e6cf32
+			break;
Ian Kent e6cf32
+		}
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (!dev)
Ian Kent e6cf32
+		return 0;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 1;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
diff -up autofs-5.0.3/lib/Makefile.device-node-control autofs-5.0.3/lib/Makefile
Ian Kent e6cf32
--- autofs-5.0.3/lib/Makefile.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/lib/Makefile	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -7,12 +7,13 @@ include ../Makefile.rules
Ian Kent e6cf32
 
Ian Kent e6cf32
 SRCS = cache.c cat_path.c rpc_subs.c mounts.c log.c nsswitch.c \
Ian Kent e6cf32
 	master_tok.l master_parse.y nss_tok.c nss_parse.tab.c \
Ian Kent e6cf32
-	args.c alarm.c macros.c master.c defaults.c parse_subs.c
Ian Kent e6cf32
+	args.c alarm.c macros.c master.c defaults.c parse_subs.c \
Ian Kent e6cf32
+	dev-ioctl-lib.c
Ian Kent e6cf32
 RPCS = mount.h mount_clnt.c mount_xdr.c
Ian Kent e6cf32
 OBJS = cache.o mount_clnt.o mount_xdr.o cat_path.o rpc_subs.o \
Ian Kent e6cf32
 	mounts.o log.o nsswitch.o master_tok.o master_parse.tab.o \
Ian Kent e6cf32
 	nss_tok.o nss_parse.tab.o args.o alarm.o macros.o master.o \
Ian Kent e6cf32
-	defaults.o parse_subs.o
Ian Kent e6cf32
+	defaults.o parse_subs.o dev-ioctl-lib.o
Ian Kent e6cf32
 
Ian Kent e6cf32
 YACCSRC = nss_tok.c nss_parse.tab.c nss_parse.tab.h \
Ian Kent e6cf32
 	  master_tok.c master_parse.tab.c master_parse.tab.h
Ian Kent e6cf32
diff -up /dev/null autofs-5.0.3/lib/dev-ioctl-lib.c
Ian Kent e6cf32
--- /dev/null	2008-02-25 17:16:11.149000952 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/lib/dev-ioctl-lib.c	2008-02-25 09:03:44.000000000 +0900
Ian Kent e6cf32
@@ -0,0 +1,747 @@
Ian Kent e6cf32
+/* ----------------------------------------------------------------------- *
Ian Kent e6cf32
+ *   
Ian Kent e6cf32
+ *  ctl-dev-lib.c - module for Linux automount mount table lookup functions
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ *   Copyright 2008 Red Hat, Inc. All rights reserved.
Ian Kent e6cf32
+ *   Copyright 2008 Ian Kent <raven@themaw.net> - All Rights Reserved
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ *   This program is free software; you can redistribute it and/or modify
Ian Kent e6cf32
+ *   it under the terms of the GNU General Public License as published by
Ian Kent e6cf32
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
Ian Kent e6cf32
+ *   USA; either version 2 of the License, or (at your option) any later
Ian Kent e6cf32
+ *   version; incorporated herein by reference.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * ----------------------------------------------------------------------- */
Ian Kent e6cf32
+
Ian Kent e6cf32
+#include <stdio.h>
Ian Kent e6cf32
+#include <stdlib.h>
Ian Kent e6cf32
+#include <string.h>
Ian Kent e6cf32
+#include <errno.h>
Ian Kent e6cf32
+#include <limits.h>
Ian Kent e6cf32
+#include <sys/types.h>
Ian Kent e6cf32
+#include <sys/stat.h>
Ian Kent e6cf32
+#include <sys/ioctl.h>
Ian Kent e6cf32
+#include <fcntl.h>
Ian Kent e6cf32
+#include <mntent.h>
Ian Kent e6cf32
+#include <errno.h>
Ian Kent e6cf32
+#include <sys/vfs.h>
Ian Kent e6cf32
+
Ian Kent e6cf32
+#include "automount.h"
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* ioctld control function interface */
Ian Kent e6cf32
+static struct ioctl_ctl ctl = { -1, NULL };
Ian Kent e6cf32
+
Ian Kent e6cf32
+#ifndef AUTOFS_SUPER_MAGIC
Ian Kent e6cf32
+#define AUTOFS_SUPER_MAGIC      0x0187
Ian Kent e6cf32
+#endif
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Define functions for autofs ioctl control.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * We provide two interfaces. One which routes ioctls via a
Ian Kent e6cf32
+ * miscelaneous device node and can be used to obtain an ioctl
Ian Kent e6cf32
+ * file descriptor for autofs mounts that are covered by an
Ian Kent e6cf32
+ * active mount (eg. active direct or multi-mount offsets).
Ian Kent e6cf32
+ * The other provides the traditional autofs ioctl implementation.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * The miscielaneous device control functions are prefixed with
Ian Kent e6cf32
+ * dev_ctl_ and the traditional ones are prefixed with ioctl_.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static int dev_ioctl_version(unsigned int, int, struct autofs_dev_ioctl *);
Ian Kent e6cf32
+static int dev_ioctl_protover(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+static int dev_ioctl_protosubver(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+static int dev_ioctl_open(unsigned int, int *, dev_t, const char *, unsigned int);
Ian Kent e6cf32
+static int dev_ioctl_close(unsigned int, int);
Ian Kent e6cf32
+static int dev_ioctl_send_ready(unsigned int, int, unsigned int);
Ian Kent e6cf32
+static int dev_ioctl_send_fail(unsigned int, int, unsigned int, int);
Ian Kent e6cf32
+static int dev_ioctl_setpipefd(unsigned int, int, int);
Ian Kent e6cf32
+static int dev_ioctl_catatonic(unsigned int, int);
Ian Kent e6cf32
+static int dev_ioctl_timeout(unsigned int, int, time_t *);
Ian Kent e6cf32
+static int dev_ioctl_requestor(unsigned int, int, const char *, uid_t *, gid_t *);
Ian Kent e6cf32
+static int dev_ioctl_expire(unsigned int, int, const char *, unsigned int);
Ian Kent e6cf32
+static int dev_ioctl_askumount(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+static int dev_ioctl_ismountpoint(unsigned int, int, const char *, unsigned int *);
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_protover(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+static int ioctl_protosubver(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+static int ioctl_open(unsigned int, int *, dev_t, const char *, unsigned int);
Ian Kent e6cf32
+static int ioctl_close(unsigned int, int);
Ian Kent e6cf32
+static int ioctl_send_ready(unsigned int, int, unsigned int);
Ian Kent e6cf32
+static int ioctl_send_fail(unsigned int, int, unsigned int, int);
Ian Kent e6cf32
+static int ioctl_catatonic(unsigned int, int);
Ian Kent e6cf32
+static int ioctl_timeout(unsigned int, int, time_t *);
Ian Kent e6cf32
+static int ioctl_expire(unsigned int, int, const char *, unsigned int);
Ian Kent e6cf32
+static int ioctl_askumount(unsigned int, int, unsigned int *);
Ian Kent e6cf32
+
Ian Kent e6cf32
+static struct ioctl_ops dev_ioctl_ops = {
Ian Kent e6cf32
+	.version	= dev_ioctl_version,
Ian Kent e6cf32
+	.protover	= dev_ioctl_protover,
Ian Kent e6cf32
+	.protosubver	= dev_ioctl_protosubver,
Ian Kent e6cf32
+	.open		= dev_ioctl_open,
Ian Kent e6cf32
+	.close		= dev_ioctl_close,
Ian Kent e6cf32
+	.send_ready	= dev_ioctl_send_ready,
Ian Kent e6cf32
+	.send_fail	= dev_ioctl_send_fail,
Ian Kent e6cf32
+	.setpipefd	= dev_ioctl_setpipefd,
Ian Kent e6cf32
+	.catatonic	= dev_ioctl_catatonic,
Ian Kent e6cf32
+	.timeout	= dev_ioctl_timeout,
Ian Kent e6cf32
+	.requestor	= dev_ioctl_requestor,
Ian Kent e6cf32
+	.expire		= dev_ioctl_expire,
Ian Kent e6cf32
+	.askumount	= dev_ioctl_askumount,
Ian Kent e6cf32
+	.ismountpoint	= dev_ioctl_ismountpoint
Ian Kent e6cf32
+};
Ian Kent e6cf32
+
Ian Kent e6cf32
+static struct ioctl_ops ioctl_ops = {
Ian Kent e6cf32
+	.version	= NULL,
Ian Kent e6cf32
+	.protover	= ioctl_protover,
Ian Kent e6cf32
+	.protosubver	= ioctl_protosubver,
Ian Kent e6cf32
+	.open		= ioctl_open,
Ian Kent e6cf32
+	.close		= ioctl_close,
Ian Kent e6cf32
+	.send_ready	= ioctl_send_ready,
Ian Kent e6cf32
+	.send_fail	= ioctl_send_fail,
Ian Kent e6cf32
+	.setpipefd	= NULL,
Ian Kent e6cf32
+	.catatonic	= ioctl_catatonic,
Ian Kent e6cf32
+	.timeout	= ioctl_timeout,
Ian Kent e6cf32
+	.requestor	= NULL,
Ian Kent e6cf32
+	.expire		= ioctl_expire,
Ian Kent e6cf32
+	.askumount	= ioctl_askumount,
Ian Kent e6cf32
+	.ismountpoint	= NULL
Ian Kent e6cf32
+};
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Allocate the control struct that holds the misc device file
Ian Kent e6cf32
+ * descriptor and operation despatcher table.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+void init_ioctl_ctl(void)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	int devfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ctl.ops)
Ian Kent e6cf32
+		return;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	devfd = open(CONTROL_DEVICE, O_RDONLY);
Ian Kent e6cf32
+	if (devfd == -1)
Ian Kent e6cf32
+		ctl.ops = &ioctl_ops;
Ian Kent e6cf32
+	else {
Ian Kent e6cf32
+		int cl_flags = fcntl(devfd, F_GETFD, 0);
Ian Kent e6cf32
+		if (cl_flags != -1) {
Ian Kent e6cf32
+			cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
+			fcntl(devfd, F_SETFD, cl_flags);
Ian Kent e6cf32
+		}
Ian Kent e6cf32
+		ctl.devfd = devfd;
Ian Kent e6cf32
+		ctl.ops = &dev_ioctl_ops;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+	return;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+void close_ioctl_ctl(void)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	if (ctl.devfd != -1) {
Ian Kent e6cf32
+		close(ctl.devfd);
Ian Kent e6cf32
+		ctl.devfd = -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+	ctl.ops = NULL;
Ian Kent e6cf32
+	return;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Return a pointer to the operations control struct */
Ian Kent e6cf32
+struct ioctl_ops *get_ioctl_ops(void)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	if (!ctl.ops)
Ian Kent e6cf32
+		init_ioctl_ctl();
Ian Kent e6cf32
+	return ctl.ops;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Get kenrel version of misc device code */
Ian Kent e6cf32
+static int dev_ioctl_version(unsigned int logopt,
Ian Kent e6cf32
+			     int ioctlfd, struct autofs_dev_ioctl *param)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	param->ioctlfd = ioctlfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_VERSION, param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Get major version of autofs kernel module mount protocol */
Ian Kent e6cf32
+static int dev_ioctl_protover(unsigned int logopt,
Ian Kent e6cf32
+			      int ioctlfd, unsigned int *major)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOVER, &param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*major = param.arg1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_protover(unsigned int logopt,
Ian Kent e6cf32
+			  int ioctlfd, unsigned int *major)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	return ioctl(ioctlfd, AUTOFS_IOC_PROTOVER, major);
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Get minor version of autofs kernel module mount protocol */
Ian Kent e6cf32
+static int dev_ioctl_protosubver(unsigned int logopt,
Ian Kent e6cf32
+				 int ioctlfd, unsigned int *minor)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_PROTOSUBVER, &param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*minor = param.arg1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_protosubver(unsigned int logopt,
Ian Kent e6cf32
+			     int ioctlfd, unsigned int *minor)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	return ioctl(ioctlfd, AUTOFS_IOC_PROTOSUBVER, minor);
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Allocate a parameter struct for misc device ioctl used when
Ian Kent e6cf32
+ * opening an autofs mount point. Attach the path to the end
Ian Kent e6cf32
+ * of the struct. and lookup the device number if not given.
Ian Kent e6cf32
+ * Locating the device number relies on the mount option
Ian Kent e6cf32
+ * "dev=<device number>" being present in the autofs fs mount
Ian Kent e6cf32
+ * options.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static struct autofs_dev_ioctl *alloc_dev_ioctl_open(const char *path, dev_t devid, unsigned int type)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl *ioctl;
Ian Kent e6cf32
+	size_t size, p_len;
Ian Kent e6cf32
+	dev_t devno = devid;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (!path)
Ian Kent e6cf32
+		return NULL;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (devno == -1) {
Ian Kent e6cf32
+		char device[AUTOFS_DEVID_LEN];
Ian Kent e6cf32
+
Ian Kent e6cf32
+		if (!find_mnt_devid(_PROC_MOUNTS, path, device, type)) {
Ian Kent e6cf32
+			errno = ENOENT;
Ian Kent e6cf32
+			return NULL;
Ian Kent e6cf32
+		}
Ian Kent e6cf32
+		devno = strtoul(device, NULL, 0);
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	p_len = strlen(path);
Ian Kent e6cf32
+	size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
Ian Kent e6cf32
+	ioctl = malloc(size);
Ian Kent e6cf32
+	if (!ioctl) {
Ian Kent e6cf32
+		errno = ENOMEM;
Ian Kent e6cf32
+		return NULL;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(ioctl);
Ian Kent e6cf32
+	ioctl->size = size;
Ian Kent e6cf32
+	memcpy(ioctl->path, path, p_len);
Ian Kent e6cf32
+	ioctl->path[p_len] = '\0';
Ian Kent e6cf32
+	ioctl->arg1 = devno;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return ioctl;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static void free_dev_ioctl_open(struct autofs_dev_ioctl *ioctl)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	free(ioctl);
Ian Kent e6cf32
+	return;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Allocate a parameter struct for misc device ioctl which includes
Ian Kent e6cf32
+ * a path. This is used when getting the last mount requestor uid
Ian Kent e6cf32
+ * and gid and when checking if a path within the autofs filesystem
Ian Kent e6cf32
+ * is a mount point. We add the path to the end of the struct.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static struct autofs_dev_ioctl *alloc_dev_ioctl_path(int ioctlfd, const char *path)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl *ioctl;
Ian Kent e6cf32
+	size_t size, p_len;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (!path)
Ian Kent e6cf32
+		return NULL;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	p_len = strlen(path);
Ian Kent e6cf32
+	size = sizeof(struct autofs_dev_ioctl) + p_len + 1;
Ian Kent e6cf32
+	ioctl = malloc(size);
Ian Kent e6cf32
+	if (!ioctl) {
Ian Kent e6cf32
+		errno = ENOMEM;
Ian Kent e6cf32
+		return NULL;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(ioctl);
Ian Kent e6cf32
+	ioctl->ioctlfd = ioctlfd;
Ian Kent e6cf32
+	ioctl->size = size;
Ian Kent e6cf32
+	memcpy(ioctl->path, path, p_len);
Ian Kent e6cf32
+	ioctl->path[p_len] = '\0';
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return ioctl;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static void free_dev_ioctl_path(struct autofs_dev_ioctl *ioctl)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	free(ioctl);
Ian Kent e6cf32
+	return;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Get a file descriptor for control operations */
Ian Kent e6cf32
+static int dev_ioctl_open(unsigned int logopt, int *ioctlfd,
Ian Kent e6cf32
+			  dev_t devid, const char *path, unsigned int type)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl *param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*ioctlfd = -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	param = alloc_dev_ioctl_open(path, devid, type);
Ian Kent e6cf32
+	if (!param)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_OPENMOUNT, param) == -1) {
Ian Kent e6cf32
+		int save_errno = errno;
Ian Kent e6cf32
+		free_dev_ioctl_open(param);
Ian Kent e6cf32
+		errno = save_errno;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*ioctlfd = param->ioctlfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	free_dev_ioctl_open(param);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_open(unsigned int logopt, int *ioctlfd,
Ian Kent e6cf32
+		      dev_t devid, const char *path, unsigned int type)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct statfs sfs;
Ian Kent e6cf32
+	int save_errno, fd, cl_flags;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*ioctlfd = -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	fd = open(path, O_RDONLY);
Ian Kent e6cf32
+	if (fd == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	cl_flags = fcntl(fd, F_GETFD, 0);
Ian Kent e6cf32
+	if (cl_flags != -1) {
Ian Kent e6cf32
+		cl_flags |= FD_CLOEXEC;
Ian Kent e6cf32
+		fcntl(fd, F_SETFD, cl_flags);
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (fstatfs(fd, &sfs) == -1) {
Ian Kent e6cf32
+		save_errno = errno;
Ian Kent e6cf32
+		goto err;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (sfs.f_type != AUTOFS_SUPER_MAGIC) {
Ian Kent e6cf32
+		save_errno = ENOENT;
Ian Kent e6cf32
+		goto err;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*ioctlfd = fd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+err:
Ian Kent e6cf32
+	close(fd);
Ian Kent e6cf32
+	errno = save_errno;
Ian Kent e6cf32
+	return -1;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Close */
Ian Kent e6cf32
+static int dev_ioctl_close(unsigned int logopt, int ioctlfd)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CLOSEMOUNT, &param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_close(unsigned int logopt, int ioctlfd)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	return close(ioctlfd);
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Send ready status for given token */
Ian Kent e6cf32
+static int dev_ioctl_send_ready(unsigned int logopt,
Ian Kent e6cf32
+				int ioctlfd, unsigned int token)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (token == 0) {
Ian Kent e6cf32
+		errno = EINVAL;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	debug(logopt, "token = %d", token);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+	param.arg1 = token;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_READY, &param) == -1) {
Ian Kent e6cf32
+		char *estr, buf[MAX_ERR_BUF];
Ian Kent e6cf32
+		int save_errno = errno;
Ian Kent e6cf32
+		estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
+		logerr("AUTOFS_DEV_IOCTL_READY: error %s", estr);
Ian Kent e6cf32
+		errno = save_errno;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_send_ready(unsigned int logopt,
Ian Kent e6cf32
+			    int ioctlfd, unsigned int token)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	if (token == 0) {
Ian Kent e6cf32
+		errno = EINVAL;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	debug(logopt, "token = %d", token);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ioctlfd, AUTOFS_IOC_READY, token) == -1) {
Ian Kent e6cf32
+		char *estr, buf[MAX_ERR_BUF];
Ian Kent e6cf32
+		int save_errno = errno;
Ian Kent e6cf32
+		estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
+		logerr("AUTOFS_IOC_READY: error %s", estr);
Ian Kent e6cf32
+		errno = save_errno;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Send ready status for given token.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * The device node ioctl implementation allows for sending a status
Ian Kent e6cf32
+ * of other than ENOENT, unlike the tradional interface.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static int dev_ioctl_send_fail(unsigned int logopt,
Ian Kent e6cf32
+			       int ioctlfd, unsigned int token, int status)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (token == 0) {
Ian Kent e6cf32
+		errno = EINVAL;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	debug(logopt, "token = %d", token);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+	param.arg1 = token;
Ian Kent e6cf32
+	param.arg2 = status;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_FAIL, &param) == -1) {
Ian Kent e6cf32
+		char *estr, buf[MAX_ERR_BUF];
Ian Kent e6cf32
+		int save_errno = errno;
Ian Kent e6cf32
+		estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
+		logerr("AUTOFS_DEV_IOCTL_FAIL: error %s", estr);
Ian Kent e6cf32
+		errno = save_errno;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_send_fail(unsigned int logopt,
Ian Kent e6cf32
+			   int ioctlfd, unsigned int token, int status)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	if (token == 0) {
Ian Kent e6cf32
+		errno = EINVAL;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	debug(logopt, "token = %d", token);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ioctlfd, AUTOFS_IOC_FAIL, token) == -1) {
Ian Kent e6cf32
+		char *estr, buf[MAX_ERR_BUF];
Ian Kent e6cf32
+		int save_errno = errno;
Ian Kent e6cf32
+		estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
+		logerr("AUTOFS_IOC_FAIL: error %s", estr);
Ian Kent e6cf32
+		errno = save_errno;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Set the pipe fd for kernel communication.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * Normally this is set at mount using an option but if we
Ian Kent e6cf32
+ * are reconnecting to a busy mount then we need to use this
Ian Kent e6cf32
+ * to tell the autofs kernel module about the new pipe fd. In
Ian Kent e6cf32
+ * order to protect mounts against incorrectly setting the
Ian Kent e6cf32
+ * pipefd we also require that the autofs mount be catatonic.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * If successful this also sets the process group id used to
Ian Kent e6cf32
+ * identify the controlling process to the process group of
Ian Kent e6cf32
+ * the caller.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static int dev_ioctl_setpipefd(unsigned int logopt, int ioctlfd, int pipefd)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (pipefd == -1) {
Ian Kent e6cf32
+		errno = EBADF;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+	param.arg1 = pipefd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_SETPIPEFD, &param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Make the autofs mount point catatonic, no longer responsive to
Ian Kent e6cf32
+ * mount requests. Also closes the kernel pipe file descriptor.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static int dev_ioctl_catatonic(unsigned int logopt, int ioctlfd)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_CATATONIC, &param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_catatonic(unsigned int logopt, int ioctlfd)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	return ioctl(ioctlfd, AUTOFS_IOC_CATATONIC, 0);
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Set the autofs mount timeout */
Ian Kent e6cf32
+static int dev_ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+	param.arg1 = *timeout;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_TIMEOUT, &param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*timeout = param.arg1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_timeout(unsigned int logopt, int ioctlfd, time_t *timeout)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	return ioctl(ioctlfd, AUTOFS_IOC_SETTIMEOUT, timeout);
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Get the uid and gid of the last request for the mountpoint, path.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * When reconstructing an autofs mount tree with active mounts
Ian Kent e6cf32
+ * we need to re-connect to mounts that may have used the original
Ian Kent e6cf32
+ * process uid and gid (or string variations of them) for mount
Ian Kent e6cf32
+ * lookups within the map entry.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static int dev_ioctl_requestor(unsigned int logopt,
Ian Kent e6cf32
+			       int ioctlfd, const char *path,
Ian Kent e6cf32
+			       uid_t *uid, gid_t *gid)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl *param;
Ian Kent e6cf32
+	int err;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (!path)
Ian Kent e6cf32
+		errno = EINVAL;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*uid = -1;
Ian Kent e6cf32
+	*gid = -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+
Ian Kent e6cf32
+	param = alloc_dev_ioctl_path(ioctlfd, path);
Ian Kent e6cf32
+	if (!param) 
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_REQUESTOR, param);
Ian Kent e6cf32
+	if (err == -1) {
Ian Kent e6cf32
+		int save_errno = errno;
Ian Kent e6cf32
+		free_dev_ioctl_open(param);
Ian Kent e6cf32
+		errno = save_errno;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*uid = param->arg1;
Ian Kent e6cf32
+	*gid = param->arg2;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	free_dev_ioctl_path(param);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Call repeatedly until it returns EAGAIN, meaning there's nothing
Ian Kent e6cf32
+ * more that can be done.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static int expire(unsigned int logopt, int cmd, int fd,
Ian Kent e6cf32
+		  int ioctlfd, const char *path, void *arg)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	char buf[MAX_ERR_BUF];
Ian Kent e6cf32
+	struct stat st;
Ian Kent e6cf32
+	unsigned int retries;
Ian Kent e6cf32
+	unsigned int ret;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (fstat(ioctlfd, &st) == -1) {
Ian Kent e6cf32
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent e6cf32
+		debug(logopt, "fstat failed: %s", estr);
Ian Kent e6cf32
+		return 0;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	retries = (count_mounts(logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	while (retries--) {
Ian Kent e6cf32
+		struct timespec tm = {0, 100000000};
Ian Kent e6cf32
+
Ian Kent e6cf32
+		ret = ioctl(fd, cmd, arg);
Ian Kent e6cf32
+		if (ret == -1) {
Ian Kent e6cf32
+			/* Mount has gone away */
Ian Kent e6cf32
+			if (errno == EBADF || errno == EINVAL)
Ian Kent e6cf32
+				return 0;
Ian Kent e6cf32
+
Ian Kent e6cf32
+			/*
Ian Kent e6cf32
+			 *  Other than EAGAIN is an expire error so continue.
Ian Kent e6cf32
+			 *  Kernel will try the next mount for indirect
Ian Kent e6cf32
+			 *  mounts. For direct mounts it will just try the
Ian Kent e6cf32
+			 *  same mount again, limited by retries (ie. number
Ian Kent e6cf32
+			 *  of mounts directly under mount point, should
Ian Kent e6cf32
+			 *  always be one for direct mounts).
Ian Kent e6cf32
+			 */
Ian Kent e6cf32
+			if (errno == EAGAIN)
Ian Kent e6cf32
+				break;
Ian Kent e6cf32
+		}
Ian Kent e6cf32
+		nanosleep(&tm, NULL);
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ctl.ops->askumount(logopt, ioctlfd, &ret))
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (!ret)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int dev_ioctl_expire(unsigned int logopt,
Ian Kent e6cf32
+			    int ioctlfd, const char *path, unsigned int when)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+	param.arg1 = when;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return expire(logopt, AUTOFS_DEV_IOCTL_EXPIRE,
Ian Kent e6cf32
+		      ctl.devfd, ioctlfd, path, (void *) ¶m;;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_expire(unsigned int logopt,
Ian Kent e6cf32
+		        int ioctlfd, const char *path, unsigned int when)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	return expire(logopt, AUTOFS_IOC_EXPIRE_MULTI,
Ian Kent e6cf32
+		      ioctlfd, ioctlfd, path, (void *) &when);
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/* Check if autofs mount point is in use */
Ian Kent e6cf32
+static int dev_ioctl_askumount(unsigned int logopt,
Ian Kent e6cf32
+			       int ioctlfd, unsigned int *busy)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl param;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	init_autofs_dev_ioctl(¶m;;
Ian Kent e6cf32
+	param.ioctlfd = ioctlfd;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ASKUMOUNT, &param) == -1)
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*busy = param.arg1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+static int ioctl_askumount(unsigned int logopt,
Ian Kent e6cf32
+			   int ioctlfd, unsigned int *busy)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	return ioctl(ioctlfd, AUTOFS_IOC_ASKUMOUNT, busy);
Ian Kent e6cf32
+}
Ian Kent e6cf32
+
Ian Kent e6cf32
+/*
Ian Kent e6cf32
+ * Check if the given path is a mountpoint.
Ian Kent e6cf32
+ *
Ian Kent e6cf32
+ * The path is considered a mountpoint if it is itself a mountpoint
Ian Kent e6cf32
+ * or contains a mount, such as a multi-mount without a root mount.
Ian Kent e6cf32
+ * In addition, if the path is itself a mountpoint we return whether
Ian Kent e6cf32
+ * the mounted file system is an autofs filesystem or other file
Ian Kent e6cf32
+ * system.
Ian Kent e6cf32
+ */
Ian Kent e6cf32
+static int dev_ioctl_ismountpoint(unsigned int logopt,
Ian Kent e6cf32
+				  int ioctlfd, const char *path,
Ian Kent e6cf32
+				  unsigned int *mountpoint)
Ian Kent e6cf32
+{
Ian Kent e6cf32
+	struct autofs_dev_ioctl *param;
Ian Kent e6cf32
+	int err;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	*mountpoint = 0;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (!path) {
Ian Kent e6cf32
+		errno = EINVAL;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	param = alloc_dev_ioctl_path(ioctlfd, path);
Ian Kent e6cf32
+	if (!param) 
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+
Ian Kent e6cf32
+	err = ioctl(ctl.devfd, AUTOFS_DEV_IOCTL_ISMOUNTPOINT, param);
Ian Kent e6cf32
+	if (err == -1) {
Ian Kent e6cf32
+		int save_errno = errno;
Ian Kent e6cf32
+		free_dev_ioctl_open(param);
Ian Kent e6cf32
+		errno = save_errno;
Ian Kent e6cf32
+		return -1;
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	if (param->arg1) {
Ian Kent e6cf32
+		*mountpoint = DEV_IOCTL_IS_MOUNTED;
Ian Kent e6cf32
+
Ian Kent e6cf32
+		if (param->arg2) {
Ian Kent e6cf32
+			if (param->arg2 == AUTOFS_SUPER_MAGIC)
Ian Kent e6cf32
+				*mountpoint |= DEV_IOCTL_IS_AUTOFS;
Ian Kent e6cf32
+			else
Ian Kent e6cf32
+				*mountpoint |= DEV_IOCTL_IS_OTHER;
Ian Kent e6cf32
+		}
Ian Kent e6cf32
+	}
Ian Kent e6cf32
+
Ian Kent e6cf32
+	free_dev_ioctl_path(param);
Ian Kent e6cf32
+
Ian Kent e6cf32
+	return 0;
Ian Kent e6cf32
+}
Ian Kent e6cf32
diff -up autofs-5.0.3/samples/rc.autofs.in.device-node-control autofs-5.0.3/samples/rc.autofs.in
Ian Kent e6cf32
--- autofs-5.0.3/samples/rc.autofs.in.device-node-control	2008-01-14 13:39:16.000000000 +0900
Ian Kent e6cf32
+++ autofs-5.0.3/samples/rc.autofs.in	2008-02-25 09:03:12.000000000 +0900
Ian Kent e6cf32
@@ -12,6 +12,7 @@
Ian Kent e6cf32
 DAEMON=@@sbindir@@/automount
Ian Kent e6cf32
 prog=`basename $DAEMON`
Ian Kent e6cf32
 MODULE="autofs4"
Ian Kent e6cf32
+DEVICE="autofs"
Ian Kent e6cf32
 confdir=@@autofsconfdir@@
Ian Kent e6cf32
 
Ian Kent e6cf32
 test -e $DAEMON || exit 0
Ian Kent e6cf32
@@ -47,6 +48,14 @@ function start() {
Ian Kent e6cf32
 		return 1
Ian Kent e6cf32
 	fi
Ian Kent e6cf32
 
Ian Kent e6cf32
+	# Check misc device
Ian Kent e6cf32
+	if [ -e "/proc/misc" ]; then
Ian Kent e6cf32
+		MINOR=`awk "/$DEVICE/ {print \\$1}" /proc/misc`
Ian Kent e6cf32
+		if [ -n "$MINOR" -a ! -c "/dev/$DEVICE" ]; then
Ian Kent e6cf32
+			mknod -m 0600 /dev/$DEVICE c 10 $MINOR
Ian Kent e6cf32
+		fi
Ian Kent e6cf32
+	fi
Ian Kent e6cf32
+
Ian Kent e6cf32
 	$prog $OPTIONS 
Ian Kent e6cf32
 	RETVAL=$?
Ian Kent e6cf32
 	if [ $RETVAL -eq 0 ] ; then