Home | History | Annotate | Line # | Download | only in dkctl
dkctl.c revision 1.2
      1 /*	$NetBSD: dkctl.c,v 1.2 2002/07/01 18:49:57 yamt Exp $	*/
      2 
      3 /*
      4  * Copyright 2001 Wasabi Systems, Inc.
      5  * All rights reserved.
      6  *
      7  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed for the NetBSD Project by
     20  *	Wasabi Systems, Inc.
     21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22  *    or promote products derived from this software without specific prior
     23  *    written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35  * POSSIBILITY OF SUCH DAMAGE.
     36  */
     37 
     38 /*
     39  * dkctl(8) -- a program to manipulate disks.
     40  */
     41 
     42 #include <sys/param.h>
     43 #include <sys/ioctl.h>
     44 #include <sys/dkio.h>
     45 #include <err.h>
     46 #include <errno.h>
     47 #include <fcntl.h>
     48 #include <stdio.h>
     49 #include <stdlib.h>
     50 #include <string.h>
     51 #include <unistd.h>
     52 #include <util.h>
     53 
     54 #define	YES	1
     55 #define	NO	0
     56 
     57 /* I don't think nl_langinfo is suitable in this case */
     58 #define	YES_STR	"yes"
     59 #define	NO_STR	"no"
     60 #define YESNO_ARG	YES_STR " | " NO_STR
     61 
     62 struct command {
     63 	const char *cmd_name;
     64 	const char *arg_names;
     65 	void (*cmd_func)(int, char *[]);
     66 	int open_flags;
     67 };
     68 
     69 int	main(int, char *[]);
     70 void	usage(void);
     71 
     72 int	fd;				/* file descriptor for device */
     73 const	char *dvname;			/* device name */
     74 char	dvname_store[MAXPATHLEN];	/* for opendisk(3) */
     75 const	char *cmdname;			/* command user issued */
     76 const	char *argnames;			/* helpstring; expected arguments */
     77 
     78 int yesno(const char *);
     79 
     80 void	disk_getcache(int, char *[]);
     81 void	disk_setcache(int, char *[]);
     82 void	disk_synccache(int, char *[]);
     83 void	disk_keeplabel(int, char *[]);
     84 
     85 struct command commands[] = {
     86 	{ "getcache",
     87 	  "",
     88 	  disk_getcache,
     89 	  O_RDONLY },
     90 
     91 	{ "setcache",
     92 	  "none | r | w | rw [save]",
     93 	  disk_setcache,
     94 	  O_RDWR },
     95 
     96 	{ "synccache",
     97 	  "[force]",
     98 	  disk_synccache,
     99 	  O_RDWR },
    100 
    101 	{ "keeplabel",
    102 	  YESNO_ARG,
    103 	  disk_keeplabel,
    104 	  O_RDWR },
    105 
    106 	{ NULL,
    107 	  NULL,
    108 	  NULL,
    109 	  0 },
    110 };
    111 
    112 int
    113 main(int argc, char *argv[])
    114 {
    115 	int i;
    116 
    117 	/* Must have at least: device command */
    118 	if (argc < 3)
    119 		usage();
    120 
    121 	/* Skip program name, get and skip device name and command. */
    122 	dvname = argv[1];
    123 	cmdname = argv[2];
    124 	argv += 3;
    125 	argc -= 3;
    126 
    127 	/* Look up and call the command. */
    128 	for (i = 0; commands[i].cmd_name != NULL; i++)
    129 		if (strcmp(cmdname, commands[i].cmd_name) == 0)
    130 			break;
    131 	if (commands[i].cmd_name == NULL)
    132 		errx(1, "unknown command: %s", cmdname);
    133 
    134 	argnames = commands[i].arg_names;
    135 
    136 	/* Open the device. */
    137 	fd = opendisk(dvname, commands[i].open_flags, dvname_store,
    138 	    sizeof(dvname_store), 0);
    139 	if (fd == -1)
    140 		err(1, "%s", dvname);
    141 
    142 	dvname = dvname_store;
    143 
    144 	(*commands[i].cmd_func)(argc, argv);
    145 	exit(0);
    146 }
    147 
    148 void
    149 usage()
    150 {
    151 	int i;
    152 
    153 	fprintf(stderr, "Usage: %s device command [arg [...]]\n",
    154 	    getprogname());
    155 
    156 	fprintf(stderr, "   Available commands:\n");
    157 	for (i = 0; commands[i].cmd_name != NULL; i++)
    158 		fprintf(stderr, "\t%s %s\n", commands[i].cmd_name,
    159 		    commands[i].arg_names);
    160 
    161 	exit(1);
    162 }
    163 
    164 void
    165 disk_getcache(int argc, char *argv[])
    166 {
    167 	int bits;
    168 
    169 	if (ioctl(fd, DIOCGCACHE, &bits) == -1)
    170 		err(1, "%s: getcache", dvname);
    171 
    172 	if ((bits & (DKCACHE_READ|DKCACHE_WRITE)) == 0)
    173 		printf("%s: No caches enabled\n", dvname);
    174 	else {
    175 		if (bits & DKCACHE_READ)
    176 			printf("%s: read cache enabled\n", dvname);
    177 		if (bits & DKCACHE_WRITE)
    178 			printf("%s: write-back cache enabled\n", dvname);
    179 	}
    180 
    181 	printf("%s: read cache enable is %schangeable\n", dvname,
    182 	    (bits & DKCACHE_RCHANGE) ? "" : "not ");
    183 	printf("%s: write cache enable is %schangeable\n", dvname,
    184 	    (bits & DKCACHE_WCHANGE) ? "" : "not ");
    185 
    186 	printf("%s: cache parameters are %ssavable\n", dvname,
    187 	    (bits & DKCACHE_SAVE) ? "" : "not ");
    188 }
    189 
    190 void
    191 disk_setcache(int argc, char *argv[])
    192 {
    193 	int bits;
    194 
    195 	if (argc > 2 || argc == 0)
    196 		usage();
    197 
    198 	if (strcmp(argv[0], "none") == 0)
    199 		bits = 0;
    200 	else if (strcmp(argv[0], "r") == 0)
    201 		bits = DKCACHE_READ;
    202 	else if (strcmp(argv[0], "w") == 0)
    203 		bits = DKCACHE_WRITE;
    204 	else if (strcmp(argv[0], "rw") == 0)
    205 		bits = DKCACHE_READ|DKCACHE_WRITE;
    206 	else
    207 		usage();
    208 
    209 	if (argc == 2) {
    210 		if (strcmp(argv[1], "save") == 0)
    211 			bits |= DKCACHE_SAVE;
    212 		else
    213 			usage();
    214 	}
    215 
    216 	if (ioctl(fd, DIOCSCACHE, &bits) == -1)
    217 		err(1, "%s: setcache", dvname);
    218 }
    219 
    220 void
    221 disk_synccache(int argc, char *argv[])
    222 {
    223 	int force;
    224 
    225 	switch (argc) {
    226 	case 0:
    227 		force = 0;
    228 		break;
    229 
    230 	case 1:
    231 		if (strcmp(argv[0], "force") == 0)
    232 			force = 1;
    233 		else
    234 			usage();
    235 		break;
    236 
    237 	default:
    238 		usage();
    239 	}
    240 
    241 	if (ioctl(fd, DIOCCACHESYNC, &force) == -1)
    242 		err(1, "%s: sync cache", dvname);
    243 }
    244 
    245 void
    246 disk_keeplabel(int argc, char *argv[])
    247 {
    248 	int keep;
    249 	int yn;
    250 
    251 	if (argc != 1)
    252 		usage();
    253 
    254 	yn = yesno(argv[0]);
    255 	if (yn < 0)
    256 		usage();
    257 
    258 	keep = yn == YES;
    259 
    260 	if (ioctl(fd, DIOCKLABEL, &keep) == -1)
    261 		err(1, "%s: keep label", dvname);
    262 }
    263 
    264 /*
    265  * return YES, NO or -1.
    266  */
    267 int
    268 yesno(const char *p)
    269 {
    270 
    271 	if (!strcmp(p, YES_STR))
    272 		return YES;
    273 	if (!strcmp(p, NO_STR))
    274 		return NO;
    275 	return -1;
    276 }
    277