17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23355d6bb5Sswilcox  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * This file contains functions that allow applications to roll the log.
297c478bd9Sstevel@tonic-gate  * It is intended for use by applications that open a raw device with the
307c478bd9Sstevel@tonic-gate  * understanding that it contains a Unix File System.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <errno.h>
347c478bd9Sstevel@tonic-gate #include <fcntl.h>
357c478bd9Sstevel@tonic-gate #include <stdio.h>
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <strings.h>
397c478bd9Sstevel@tonic-gate #include <unistd.h>
407c478bd9Sstevel@tonic-gate #include <sys/filio.h>
417c478bd9Sstevel@tonic-gate #include <sys/mnttab.h>
427c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
437c478bd9Sstevel@tonic-gate #include <sys/mount.h>
447c478bd9Sstevel@tonic-gate #include <sys/param.h>
457c478bd9Sstevel@tonic-gate #include <sys/types.h>
467c478bd9Sstevel@tonic-gate #include <sys/stat.h>
477c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_mount.h>
487c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
497c478bd9Sstevel@tonic-gate #include <libintl.h>
507c478bd9Sstevel@tonic-gate #include "roll_log.h"
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * The following is the template string passed to mktemp(3C).  This
547c478bd9Sstevel@tonic-gate  * string is used as the name of a temporary mount point which is
557c478bd9Sstevel@tonic-gate  * used to roll the log.
567c478bd9Sstevel@tonic-gate  */
577c478bd9Sstevel@tonic-gate #define	RLG_TEMPLATE	".rlg.XXXXXX"
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #define	SYSERR		(-1)
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #define	RLM_RW		0
627c478bd9Sstevel@tonic-gate #define	RLM_RO		1
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * Structure definitions:
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate typedef struct log_info {
697c478bd9Sstevel@tonic-gate 	char *li_blkname;	/* Path of block device. */
707c478bd9Sstevel@tonic-gate 	char *li_mntpoint;	/* Path of mounted device. */
717c478bd9Sstevel@tonic-gate 	char *li_tmpmp_parent;	/* Temporary parent directory of mount point */
727c478bd9Sstevel@tonic-gate 	char *li_tmpmp;		/* Temporary mount point. */
737c478bd9Sstevel@tonic-gate } log_info_t;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * Static function declarations:
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate static rl_result_t	is_mounted(log_info_t *lip, char *dev);
807c478bd9Sstevel@tonic-gate static void		cleanup(log_info_t *lip);
817c478bd9Sstevel@tonic-gate static rl_result_t	make_mp(log_info_t *lip);
827c478bd9Sstevel@tonic-gate static rl_result_t	rlflush(log_info_t *lip);
837c478bd9Sstevel@tonic-gate static rl_result_t	rlmount(log_info_t *lip, int mntopt);
847c478bd9Sstevel@tonic-gate static rl_result_t	rlumount(log_info_t *lip);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * NAME
887c478bd9Sstevel@tonic-gate  *	rl_roll_log
897c478bd9Sstevel@tonic-gate  *
907c478bd9Sstevel@tonic-gate  * SYNOPSIS
917c478bd9Sstevel@tonic-gate  *	rl_roll_log(block_dev)
927c478bd9Sstevel@tonic-gate  *
937c478bd9Sstevel@tonic-gate  * DESCRIPTION
947c478bd9Sstevel@tonic-gate  *	Roll the log for the block device "block_dev".
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate rl_result_t
rl_roll_log(char * bdev)987c478bd9Sstevel@tonic-gate rl_roll_log(char *bdev)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	log_info_t		li;
1017c478bd9Sstevel@tonic-gate 	rl_result_t		rv = RL_SUCCESS;
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	(void) memset((void *)&li, 0, (size_t)sizeof (li));
1047c478bd9Sstevel@tonic-gate 	if (is_mounted(&li, bdev) == RL_TRUE) {
1057c478bd9Sstevel@tonic-gate 		rv = rlflush(&li);
1067c478bd9Sstevel@tonic-gate 	} else {
1077c478bd9Sstevel@tonic-gate 		/*
1087c478bd9Sstevel@tonic-gate 		 * Device appears not to be mounted.
1097c478bd9Sstevel@tonic-gate 		 * We need to mount the device read only.
1107c478bd9Sstevel@tonic-gate 		 * This automatically causes the log to be rolled, then we can
1117c478bd9Sstevel@tonic-gate 		 * unmount the device again.  To do the mount, we need to
1127c478bd9Sstevel@tonic-gate 		 * create a temporary directory, and then remove it when we
1137c478bd9Sstevel@tonic-gate 		 * are done.
1147c478bd9Sstevel@tonic-gate 		 */
1157c478bd9Sstevel@tonic-gate 		rv = make_mp(&li);
1167c478bd9Sstevel@tonic-gate 		switch (rv) {
1177c478bd9Sstevel@tonic-gate 		case RL_CORRUPT:
1187c478bd9Sstevel@tonic-gate 			/* corrupt mnttab - the file sys really was mounted */
1197c478bd9Sstevel@tonic-gate 			rv = rlflush(&li);
1207c478bd9Sstevel@tonic-gate 			break;
1217c478bd9Sstevel@tonic-gate 		case RL_SUCCESS:
1227c478bd9Sstevel@tonic-gate 			rv = rlmount(&li, RLM_RO);
1237c478bd9Sstevel@tonic-gate 			if (rv == RL_SUCCESS) {
1247c478bd9Sstevel@tonic-gate 				rv = rlflush(&li);
1257c478bd9Sstevel@tonic-gate 				if (umount(li.li_blkname) == SYSERR) {
1267c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
1277c478bd9Sstevel@tonic-gate 		"WARNING: rl_roll_log(): Can't unmount %s\n", li.li_blkname);
1287c478bd9Sstevel@tonic-gate 				}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 			}
1317c478bd9Sstevel@tonic-gate 			break;
1327c478bd9Sstevel@tonic-gate 		}
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 	cleanup(&li);
1357c478bd9Sstevel@tonic-gate 	return (rv);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate  * Static function definitions:
1407c478bd9Sstevel@tonic-gate  */
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate  * NAME
1447c478bd9Sstevel@tonic-gate  *	cleanup
1457c478bd9Sstevel@tonic-gate  *
1467c478bd9Sstevel@tonic-gate  * SYNOPSIS
1477c478bd9Sstevel@tonic-gate  *	cleanup(log_infop)
1487c478bd9Sstevel@tonic-gate  *
1497c478bd9Sstevel@tonic-gate  * DESCRIPTION
1507c478bd9Sstevel@tonic-gate  *	Remove the temporary mount directroy and free the dynamically
1517c478bd9Sstevel@tonic-gate  *	allocated memory that is pointed to by log_infop.
1527c478bd9Sstevel@tonic-gate  */
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate static void
cleanup(log_info_t * lip)1557c478bd9Sstevel@tonic-gate cleanup(log_info_t *lip)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate 	if (lip->li_blkname != (char *)NULL) {
1587c478bd9Sstevel@tonic-gate 		free(lip->li_blkname);
1597c478bd9Sstevel@tonic-gate 		lip->li_blkname = (char *)NULL;
1607c478bd9Sstevel@tonic-gate 	}
1617c478bd9Sstevel@tonic-gate 	if (lip->li_mntpoint != (char *)NULL) {
1627c478bd9Sstevel@tonic-gate 		free(lip->li_mntpoint);
1637c478bd9Sstevel@tonic-gate 		lip->li_mntpoint = (char *)NULL;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	if (lip->li_tmpmp != (char *)NULL) {
1667c478bd9Sstevel@tonic-gate 		(void) rmdir(lip->li_tmpmp);
1677c478bd9Sstevel@tonic-gate 		free(lip->li_tmpmp);
1687c478bd9Sstevel@tonic-gate 		lip->li_tmpmp = (char *)NULL;
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate 	if (lip->li_tmpmp_parent != (char *)NULL) {
1717c478bd9Sstevel@tonic-gate 		(void) rmdir(lip->li_tmpmp_parent);
1727c478bd9Sstevel@tonic-gate 		free(lip->li_tmpmp_parent);
1737c478bd9Sstevel@tonic-gate 		lip->li_tmpmp_parent = (char *)NULL;
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate  * NAME
1797c478bd9Sstevel@tonic-gate  *	is_mounted
1807c478bd9Sstevel@tonic-gate  *
1817c478bd9Sstevel@tonic-gate  * SYNOPSIS
1827c478bd9Sstevel@tonic-gate  *	is_mounted(log_infop, dev)
1837c478bd9Sstevel@tonic-gate  *
1847c478bd9Sstevel@tonic-gate  * DESCRIPTION
1857c478bd9Sstevel@tonic-gate  *	Determine if device dev is mounted, and return RL_TRUE if it is.
1867c478bd9Sstevel@tonic-gate  *	As a side effect, li_blkname is set to point the the full path
1877c478bd9Sstevel@tonic-gate  *	names of the block device.  Memory for this path is dynamically
1887c478bd9Sstevel@tonic-gate  *	allocated and must be freed by the caller.
1897c478bd9Sstevel@tonic-gate  */
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate extern char *getfullblkname(char *);
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate static rl_result_t
is_mounted(log_info_t * lip,char * dev)1947c478bd9Sstevel@tonic-gate is_mounted(log_info_t *lip, char *dev)
1957c478bd9Sstevel@tonic-gate {
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	struct mnttab		mntbuf;
1987c478bd9Sstevel@tonic-gate 	FILE			*mnttable;
1997c478bd9Sstevel@tonic-gate 	rl_result_t		rv = RL_FALSE;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	/* Make sure that we have the full path name. */
2027c478bd9Sstevel@tonic-gate 	lip->li_blkname = getfullblkname(dev);
2037c478bd9Sstevel@tonic-gate 	if (lip->li_blkname == NULL)
2047c478bd9Sstevel@tonic-gate 		lip->li_blkname = strdup(dev);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	/* Search mnttab to see if it device is mounted. */
2077c478bd9Sstevel@tonic-gate 	if ((mnttable = fopen(MNTTAB, "r")) == NULL)
2087c478bd9Sstevel@tonic-gate 		return (rv);
209*8509e9caSToomas Soome 	while (getmntent(mnttable, &mntbuf) == 0) {
2107c478bd9Sstevel@tonic-gate 		if (strcmp(mntbuf.mnt_fstype, MNTTYPE_UFS) == 0) {
2117c478bd9Sstevel@tonic-gate 			/* Entry is UFS */
2127c478bd9Sstevel@tonic-gate 			if ((strcmp(mntbuf.mnt_mountp, dev) == 0) ||
2137c478bd9Sstevel@tonic-gate 			    (strcmp(mntbuf.mnt_special, lip->li_blkname)
214*8509e9caSToomas Soome 			    == 0) ||
2157c478bd9Sstevel@tonic-gate 			    (strcmp(mntbuf.mnt_special, dev) == 0)) {
2167c478bd9Sstevel@tonic-gate 				lip->li_mntpoint = strdup(mntbuf.mnt_mountp);
2177c478bd9Sstevel@tonic-gate 				rv = RL_TRUE;
2187c478bd9Sstevel@tonic-gate 				break;
2197c478bd9Sstevel@tonic-gate 			}
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 	}
2227c478bd9Sstevel@tonic-gate 	(void) fclose(mnttable);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	return (rv);
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate /*
2297c478bd9Sstevel@tonic-gate  * NAME
2307c478bd9Sstevel@tonic-gate  *	make_mp
2317c478bd9Sstevel@tonic-gate  *
2327c478bd9Sstevel@tonic-gate  * SYNOPSIS
2337c478bd9Sstevel@tonic-gate  *	make_mp(loginfop)
2347c478bd9Sstevel@tonic-gate  *
2357c478bd9Sstevel@tonic-gate  * DESCRIPTION
2367c478bd9Sstevel@tonic-gate  *	Create a temporary directory to be used as a mount point.  li_tmpmp
2377c478bd9Sstevel@tonic-gate  *	will be set to the path of the mount point. li_tmpmp_parent is the
2387c478bd9Sstevel@tonic-gate  *	parent directory of the mount point.  The parent directory is
2397c478bd9Sstevel@tonic-gate  *	created with restrictive permissions.   Memory pointed to by
2407c478bd9Sstevel@tonic-gate  *	li_tmpmp and li_tmpmp_parent should be freed by the caller.
2417c478bd9Sstevel@tonic-gate  */
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate static rl_result_t
make_mp(log_info_t * lip)2447c478bd9Sstevel@tonic-gate make_mp(log_info_t *lip)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate 	size_t			i;
2477c478bd9Sstevel@tonic-gate 	rl_result_t		rv = RL_FAIL;
2487c478bd9Sstevel@tonic-gate 	/*
2497c478bd9Sstevel@tonic-gate 	 * Note tmp_dir_list[] should all be directories in the
2507c478bd9Sstevel@tonic-gate 	 * original root file system.
2517c478bd9Sstevel@tonic-gate 	 */
252*8509e9caSToomas Soome 	static const char	*tmp_dir_list[] = {
2537c478bd9Sstevel@tonic-gate 							"/tmp/",
2547c478bd9Sstevel@tonic-gate 							"/var/tmp/",
2557c478bd9Sstevel@tonic-gate 							"/",
2567c478bd9Sstevel@tonic-gate 						};
2577c478bd9Sstevel@tonic-gate 	char			dirname[] = RLG_TEMPLATE;
2587c478bd9Sstevel@tonic-gate 	char			tmp_dir[MAXPATHLEN + 1];
2597c478bd9Sstevel@tonic-gate 	char			mountpt_dir[MAXPATHLEN + 1];
2607c478bd9Sstevel@tonic-gate 	static size_t		list_len = sizeof (tmp_dir_list) /
261*8509e9caSToomas Soome 	    sizeof (const char *);
262355d6bb5Sswilcox 	int			merr = 0;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	/*
2657c478bd9Sstevel@tonic-gate 	 * Sequence of events:
2667c478bd9Sstevel@tonic-gate 	 * - Create a random name using mktemp(3C) (e.g., ".rlg.123456")
2677c478bd9Sstevel@tonic-gate 	 * - Cycle through tmp_dir_list to find a path where we can create
2687c478bd9Sstevel@tonic-gate 	 *   a temporary parent directory (e.g., /tmp/.rlg.123456) with
2697c478bd9Sstevel@tonic-gate 	 *   restrictive permissions.  This prevents any non-root processes,
2707c478bd9Sstevel@tonic-gate 	 *   such as a 'find', from wandering in where it doesn't belong.
2717c478bd9Sstevel@tonic-gate 	 * - Create the mount-point (/tmp/.rlg.123456/.rlg.123456).
2727c478bd9Sstevel@tonic-gate 	 */
2737c478bd9Sstevel@tonic-gate 	(void) mktemp(dirname);
2747c478bd9Sstevel@tonic-gate 	for (i = 0; i < list_len; i++) {
2757c478bd9Sstevel@tonic-gate 		/* Make the directory containing the mount-point */
276355d6bb5Sswilcox 		(void) snprintf(tmp_dir, sizeof (tmp_dir), "%s%s",
277*8509e9caSToomas Soome 		    tmp_dir_list[i], dirname);
2787c478bd9Sstevel@tonic-gate 		if (mkdir(tmp_dir, 0) == SYSERR) {
2797c478bd9Sstevel@tonic-gate 			merr = errno;
2807c478bd9Sstevel@tonic-gate 			continue;
2817c478bd9Sstevel@tonic-gate 		}
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 		/* Now, make the mount-point */
284355d6bb5Sswilcox 		(void) snprintf(mountpt_dir, sizeof (mountpt_dir), "%s/%s",
285*8509e9caSToomas Soome 		    tmp_dir, dirname);
2867c478bd9Sstevel@tonic-gate 		if (mkdir(mountpt_dir, 0) == SYSERR) {
2877c478bd9Sstevel@tonic-gate 			merr = errno;
2887c478bd9Sstevel@tonic-gate 			continue;
2897c478bd9Sstevel@tonic-gate 		}
2907c478bd9Sstevel@tonic-gate 		lip->li_tmpmp = strdup(mountpt_dir);
2917c478bd9Sstevel@tonic-gate 		lip->li_tmpmp_parent = strdup(tmp_dir);
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 		/* Make sure that the strdup()s both succeeded */
2947c478bd9Sstevel@tonic-gate 		if ((lip->li_tmpmp != NULL) && (lip->li_tmpmp_parent != NULL)) {
2957c478bd9Sstevel@tonic-gate 			rv = RL_SUCCESS;
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 		break;
2987c478bd9Sstevel@tonic-gate 	}
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	/* Get some help if we cannot make the directory. */
3017c478bd9Sstevel@tonic-gate 	if (rv != RL_SUCCESS) {
3027c478bd9Sstevel@tonic-gate 		/*
3037c478bd9Sstevel@tonic-gate 		 * If we get a read only filesystem failure (EROFS)
3047c478bd9Sstevel@tonic-gate 		 * to make a directory in "/", then we must be fsck'ing
3057c478bd9Sstevel@tonic-gate 		 * at boot with a incorrect mnttab.
3067c478bd9Sstevel@tonic-gate 		 *
3077c478bd9Sstevel@tonic-gate 		 * Just return RL_CORRUPT to indicate it really
3087c478bd9Sstevel@tonic-gate 		 * was mounted.
3097c478bd9Sstevel@tonic-gate 		 */
3107c478bd9Sstevel@tonic-gate 		if (merr == EROFS) {
3117c478bd9Sstevel@tonic-gate 			lip->li_mntpoint = strdup("/");
3127c478bd9Sstevel@tonic-gate 			return (RL_CORRUPT);
3137c478bd9Sstevel@tonic-gate 		}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
316*8509e9caSToomas Soome 		    "Unable to create temporary "
317*8509e9caSToomas Soome 		    "directory in any of the directories listed "
318*8509e9caSToomas Soome 		    "below:\n"));
3197c478bd9Sstevel@tonic-gate 		for (i = 0; i < list_len; i++) {
3207c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "\t%s\n", tmp_dir_list[i]);
3217c478bd9Sstevel@tonic-gate 		}
3227c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
323*8509e9caSToomas Soome 		    "Please correct this problem "
324*8509e9caSToomas Soome 		    "and rerun the program.\n"));
3257c478bd9Sstevel@tonic-gate 	}
3267c478bd9Sstevel@tonic-gate 
3277c478bd9Sstevel@tonic-gate 	return (rv);
3287c478bd9Sstevel@tonic-gate }
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate /*
3317c478bd9Sstevel@tonic-gate  * NAME
3327c478bd9Sstevel@tonic-gate  *	rlflush
3337c478bd9Sstevel@tonic-gate  *
3347c478bd9Sstevel@tonic-gate  * SYNOPSIS
3357c478bd9Sstevel@tonic-gate  *	rlflush(log_infop)
3367c478bd9Sstevel@tonic-gate  *
3377c478bd9Sstevel@tonic-gate  * DESCRIPTION
3387c478bd9Sstevel@tonic-gate  *	Open the mount point of the file system (li_mntpoint) to get a
3397c478bd9Sstevel@tonic-gate  *	file descriptor.  Issue the _FIOFFS ioctl to flush the file system
3407c478bd9Sstevel@tonic-gate  *	and then close the device.
3417c478bd9Sstevel@tonic-gate  */
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate static rl_result_t
rlflush(log_info_t * lip)3447c478bd9Sstevel@tonic-gate rlflush(log_info_t *lip)
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 	int			fd;	/* File descriptor. */
3477c478bd9Sstevel@tonic-gate 	rl_result_t		rv = RL_SUCCESS;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	if ((fd = open((lip->li_mntpoint ? lip->li_mntpoint : lip->li_tmpmp),
350*8509e9caSToomas Soome 	    O_RDONLY)) == SYSERR) {
3517c478bd9Sstevel@tonic-gate 		return (RL_SYSERR);
3527c478bd9Sstevel@tonic-gate 	}
3537c478bd9Sstevel@tonic-gate 	if (ioctl(fd, _FIOFFS, NULL) == SYSERR) {
3547c478bd9Sstevel@tonic-gate 		rv = RL_SYSERR;
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 	(void) close(fd);
3577c478bd9Sstevel@tonic-gate 	return (rv);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate  * NAME
3627c478bd9Sstevel@tonic-gate  *	rlmount
3637c478bd9Sstevel@tonic-gate  *
3647c478bd9Sstevel@tonic-gate  * SYNOPSIS
3657c478bd9Sstevel@tonic-gate  *	rlmount(log_infop, mntopt)
3667c478bd9Sstevel@tonic-gate  *
3677c478bd9Sstevel@tonic-gate  * DESCRIPTION
3687c478bd9Sstevel@tonic-gate  *	Mount the device specified by li_blkname on li_tmpmp. mntopt specifies
3697c478bd9Sstevel@tonic-gate  *	whether it's mounted RLM_RO or RLM_RW.
3707c478bd9Sstevel@tonic-gate  */
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate static rl_result_t
rlmount(log_info_t * lip,int mntopt)3737c478bd9Sstevel@tonic-gate rlmount(log_info_t *lip, int mntopt)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	struct ufs_args		args;
3767c478bd9Sstevel@tonic-gate 	rl_result_t		rv = RL_SUCCESS;
3777c478bd9Sstevel@tonic-gate 	char			opt[MAX_MNTOPT_STR];
3787c478bd9Sstevel@tonic-gate 	char			*optstr;
3797c478bd9Sstevel@tonic-gate 	int			optflg;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	args.flags = 0;	/* Initialize ufs_args */
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	/*
3847c478bd9Sstevel@tonic-gate 	 * Use a minimal restrictive set of mount options.  Make sure
3857c478bd9Sstevel@tonic-gate 	 * to use "largefiles" option otherwise mount() can fail w/EFBIG.
3867c478bd9Sstevel@tonic-gate 	 * (Although "nosub" isn't a currently supported option on UFS,
3877c478bd9Sstevel@tonic-gate 	 * it would be a good one to have if it ever is implemented
3887c478bd9Sstevel@tonic-gate 	 * since submounts would prevent a umount.)
3897c478bd9Sstevel@tonic-gate 	 */
3907c478bd9Sstevel@tonic-gate 	args.flags |= UFSMNT_LARGEFILES;
3917c478bd9Sstevel@tonic-gate 	switch (mntopt) {
3927c478bd9Sstevel@tonic-gate 	case RLM_RO:
3937c478bd9Sstevel@tonic-gate 		optstr = MNTOPT_RO;
3947c478bd9Sstevel@tonic-gate 		optflg = MS_RDONLY;
3957c478bd9Sstevel@tonic-gate 		break;
3967c478bd9Sstevel@tonic-gate 	case RLM_RW:
3977c478bd9Sstevel@tonic-gate 		optstr = MNTOPT_RW;
3987c478bd9Sstevel@tonic-gate 		optflg = 0;
3997c478bd9Sstevel@tonic-gate 		break;
4007c478bd9Sstevel@tonic-gate 	default:
4017c478bd9Sstevel@tonic-gate 		return (RL_FAIL);
4027c478bd9Sstevel@tonic-gate 	}
403355d6bb5Sswilcox 	(void) snprintf(opt, sizeof (opt), "%s,%s,%s",
404*8509e9caSToomas Soome 	    optstr, MNTOPT_NOSUID, MNTOPT_LARGEFILES);
4057c478bd9Sstevel@tonic-gate 	if (mount(lip->li_blkname, lip->li_tmpmp,
406*8509e9caSToomas Soome 	    optflg | MS_DATA | MS_OPTIONSTR,
407*8509e9caSToomas Soome 	    MNTTYPE_UFS, &args, sizeof (args),
408*8509e9caSToomas Soome 	    opt, MAX_MNTOPT_STR) == SYSERR) {
4097c478bd9Sstevel@tonic-gate 		rv = RL_SYSERR;
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 	return (rv);
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate  * NAME
4167c478bd9Sstevel@tonic-gate  *	rlumount
4177c478bd9Sstevel@tonic-gate  *
4187c478bd9Sstevel@tonic-gate  * SYNOPSIS
4197c478bd9Sstevel@tonic-gate  *	rlumount(log_infop)
4207c478bd9Sstevel@tonic-gate  *
4217c478bd9Sstevel@tonic-gate  * DESCRIPTION
4227c478bd9Sstevel@tonic-gate  *	Unmounts the device specified by li_blkname, printing an
4237c478bd9Sstevel@tonic-gate  *	error message on failure.
4247c478bd9Sstevel@tonic-gate  */
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate static rl_result_t
rlumount(log_info_t * lip)4277c478bd9Sstevel@tonic-gate rlumount(log_info_t *lip)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	rl_result_t		rv = RL_SUCCESS;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	if (umount(lip->li_blkname) == SYSERR) {
4327c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
433*8509e9caSToomas Soome 		    "WARNING: rlumount(): Can't unmount %s\n"),
434*8509e9caSToomas Soome 		    lip->li_blkname);
4357c478bd9Sstevel@tonic-gate 		rv = RL_SYSERR;
4367c478bd9Sstevel@tonic-gate 	}
4377c478bd9Sstevel@tonic-gate 	return (rv);
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate /*
4417c478bd9Sstevel@tonic-gate  * NAME
4427c478bd9Sstevel@tonic-gate  *	rl_log_control
4437c478bd9Sstevel@tonic-gate  *
4447c478bd9Sstevel@tonic-gate  * SYNOPSIS
4457c478bd9Sstevel@tonic-gate  *	rl_log_control(block_dev, request)
4467c478bd9Sstevel@tonic-gate  *
4477c478bd9Sstevel@tonic-gate  * DESCRIPTION
4487c478bd9Sstevel@tonic-gate  *	Enable/disable logging for the block device "block_dev".
4497c478bd9Sstevel@tonic-gate  *	The request parameter should be set to _FIOLOGENABLE or
4507c478bd9Sstevel@tonic-gate  *	_FIOLOGDISABLE.
4517c478bd9Sstevel@tonic-gate  */
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate rl_result_t
rl_log_control(char * bdev,int request)4547c478bd9Sstevel@tonic-gate rl_log_control(char *bdev, int request)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate 	log_info_t	li;
4577c478bd9Sstevel@tonic-gate 	rl_result_t	rv = RL_SUCCESS;
4587c478bd9Sstevel@tonic-gate 	rl_result_t	alreadymounted;
4597c478bd9Sstevel@tonic-gate 	int		fd;
4607c478bd9Sstevel@tonic-gate 	fiolog_t	fl;
461355d6bb5Sswilcox 	int		logenabled = 0;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 	if ((request != _FIOLOGENABLE) && (request != _FIOLOGDISABLE))
4647c478bd9Sstevel@tonic-gate 		return (RL_FAIL);
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	(void) memset((void *)&li, '\0', (size_t)sizeof (li));
4677c478bd9Sstevel@tonic-gate 	if ((alreadymounted = is_mounted(&li, bdev)) != RL_TRUE) {
4687c478bd9Sstevel@tonic-gate 		/*
4697c478bd9Sstevel@tonic-gate 		 * Device is not mounted. Need to mount it rw to allow
4707c478bd9Sstevel@tonic-gate 		 * the log to be enabled/disabled. To do the mount, we need
4717c478bd9Sstevel@tonic-gate 		 * to create a temporary directory, and then remove it when
4727c478bd9Sstevel@tonic-gate 		 * we are done.
4737c478bd9Sstevel@tonic-gate 		 */
4747c478bd9Sstevel@tonic-gate 		if (make_mp(&li) != RL_SUCCESS) {
4757c478bd9Sstevel@tonic-gate 			cleanup(&li);
4767c478bd9Sstevel@tonic-gate 			return (RL_FAIL);
4777c478bd9Sstevel@tonic-gate 		}
4787c478bd9Sstevel@tonic-gate 		if (rlmount(&li, RLM_RW) != RL_SUCCESS) {
4797c478bd9Sstevel@tonic-gate 			cleanup(&li);
4807c478bd9Sstevel@tonic-gate 			return (RL_FAIL);
4817c478bd9Sstevel@tonic-gate 		}
4827c478bd9Sstevel@tonic-gate 	}
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 	if (alreadymounted == RL_TRUE)
4857c478bd9Sstevel@tonic-gate 		fd = open(li.li_mntpoint, O_RDONLY);
4867c478bd9Sstevel@tonic-gate 	else
4877c478bd9Sstevel@tonic-gate 		fd = open(li.li_tmpmp, O_RDONLY);
4887c478bd9Sstevel@tonic-gate 	if (fd == SYSERR) {
4897c478bd9Sstevel@tonic-gate 		perror("open");
4907c478bd9Sstevel@tonic-gate 		rv = RL_SYSERR;
4917c478bd9Sstevel@tonic-gate 		goto out;
4927c478bd9Sstevel@tonic-gate 	}
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	fl.nbytes_requested = 0;
4957c478bd9Sstevel@tonic-gate 	fl.nbytes_actual = 0;
4967c478bd9Sstevel@tonic-gate 	fl.error = FIOLOG_ENONE;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	if (ioctl(fd, request, &fl) == SYSERR) {
4997c478bd9Sstevel@tonic-gate 		perror("ioctl");
5007c478bd9Sstevel@tonic-gate 		(void) close(fd);
5017c478bd9Sstevel@tonic-gate 		rv = RL_SYSERR;
5027c478bd9Sstevel@tonic-gate 		goto out;
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 	if (ioctl(fd, _FIOISLOG, &logenabled) == SYSERR) {
5057c478bd9Sstevel@tonic-gate 		perror("ioctl");
5067c478bd9Sstevel@tonic-gate 		(void) close(fd);
5077c478bd9Sstevel@tonic-gate 		rv = RL_SYSERR;
5087c478bd9Sstevel@tonic-gate 		goto out;
5097c478bd9Sstevel@tonic-gate 	}
5107c478bd9Sstevel@tonic-gate 	if (((request == _FIOLOGENABLE) && (!logenabled)) ||
5117c478bd9Sstevel@tonic-gate 	    ((request == _FIOLOGDISABLE) && logenabled))
5127c478bd9Sstevel@tonic-gate 		rv = RL_FAIL;
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	(void) close(fd);
5157c478bd9Sstevel@tonic-gate out:
5167c478bd9Sstevel@tonic-gate 	if (alreadymounted != RL_TRUE)
5177c478bd9Sstevel@tonic-gate 		(void) rlumount(&li);
5187c478bd9Sstevel@tonic-gate 	cleanup(&li);
5197c478bd9Sstevel@tonic-gate 	return (rv);
5207c478bd9Sstevel@tonic-gate }
521