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