1 /* $NetBSD: dkctl.c,v 1.1 2002/01/09 22:30:14 thorpej 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 struct command { 55 const char *cmd_name; 56 const char *arg_names; 57 void (*cmd_func)(int, char *[]); 58 int open_flags; 59 }; 60 61 int main(int, char *[]); 62 void usage(void); 63 64 int fd; /* file descriptor for device */ 65 const char *dvname; /* device name */ 66 char dvname_store[MAXPATHLEN]; /* for opendisk(3) */ 67 const char *cmdname; /* command user issued */ 68 const char *argnames; /* helpstring; expected arguments */ 69 70 void disk_getcache(int, char *[]); 71 void disk_setcache(int, char *[]); 72 void disk_synccache(int, char *[]); 73 74 struct command commands[] = { 75 { "getcache", 76 "", 77 disk_getcache, 78 O_RDONLY }, 79 80 { "setcache", 81 "none | r | w | rw [save]", 82 disk_setcache, 83 O_RDWR }, 84 85 { "synccache", 86 "[force]", 87 disk_synccache, 88 O_RDWR }, 89 90 { NULL, 91 NULL, 92 NULL, 93 0 }, 94 }; 95 96 int 97 main(int argc, char *argv[]) 98 { 99 int i; 100 101 /* Must have at least: device command */ 102 if (argc < 3) 103 usage(); 104 105 /* Skip program name, get and skip device name and command. */ 106 dvname = argv[1]; 107 cmdname = argv[2]; 108 argv += 3; 109 argc -= 3; 110 111 /* Look up and call the command. */ 112 for (i = 0; commands[i].cmd_name != NULL; i++) 113 if (strcmp(cmdname, commands[i].cmd_name) == 0) 114 break; 115 if (commands[i].cmd_name == NULL) 116 errx(1, "unknown command: %s", cmdname); 117 118 argnames = commands[i].arg_names; 119 120 /* Open the device. */ 121 fd = opendisk(dvname, commands[i].open_flags, dvname_store, 122 sizeof(dvname_store), 0); 123 if (fd == -1) 124 err(1, "%s", dvname); 125 126 dvname = dvname_store; 127 128 (*commands[i].cmd_func)(argc, argv); 129 exit(0); 130 } 131 132 void 133 usage() 134 { 135 int i; 136 137 fprintf(stderr, "Usage: %s device command [arg [...]]\n", 138 getprogname()); 139 140 fprintf(stderr, " Available commands:\n"); 141 for (i = 0; commands[i].cmd_name != NULL; i++) 142 fprintf(stderr, "\t%s %s\n", commands[i].cmd_name, 143 commands[i].arg_names); 144 145 exit(1); 146 } 147 148 void 149 disk_getcache(int argc, char *argv[]) 150 { 151 int bits; 152 153 if (ioctl(fd, DIOCGCACHE, &bits) == -1) 154 err(1, "%s: getcache", dvname); 155 156 if ((bits & (DKCACHE_READ|DKCACHE_WRITE)) == 0) 157 printf("%s: No caches enabled\n", dvname); 158 else { 159 if (bits & DKCACHE_READ) 160 printf("%s: read cache enabled\n", dvname); 161 if (bits & DKCACHE_WRITE) 162 printf("%s: write-back cache enabled\n", dvname); 163 } 164 165 printf("%s: read cache enable is %schangeable\n", dvname, 166 (bits & DKCACHE_RCHANGE) ? "" : "not "); 167 printf("%s: write cache enable is %schangeable\n", dvname, 168 (bits & DKCACHE_WCHANGE) ? "" : "not "); 169 170 printf("%s: cache parameters are %ssavable\n", dvname, 171 (bits & DKCACHE_SAVE) ? "" : "not "); 172 } 173 174 void 175 disk_setcache(int argc, char *argv[]) 176 { 177 int bits; 178 179 if (argc > 2 || argc == 0) 180 usage(); 181 182 if (strcmp(argv[0], "none") == 0) 183 bits = 0; 184 else if (strcmp(argv[0], "r") == 0) 185 bits = DKCACHE_READ; 186 else if (strcmp(argv[0], "w") == 0) 187 bits = DKCACHE_WRITE; 188 else if (strcmp(argv[0], "rw") == 0) 189 bits = DKCACHE_READ|DKCACHE_WRITE; 190 else 191 usage(); 192 193 if (argc == 2) { 194 if (strcmp(argv[1], "save") == 0) 195 bits |= DKCACHE_SAVE; 196 else 197 usage(); 198 } 199 200 if (ioctl(fd, DIOCSCACHE, &bits) == -1) 201 err(1, "%s: setcache", dvname); 202 } 203 204 void 205 disk_synccache(int argc, char *argv[]) 206 { 207 int force; 208 209 switch (argc) { 210 case 0: 211 force = 0; 212 break; 213 214 case 1: 215 if (strcmp(argv[0], "force") == 0) 216 force = 1; 217 else 218 usage(); 219 break; 220 221 default: 222 usage(); 223 } 224 225 if (ioctl(fd, DIOCCACHESYNC, &force) == -1) 226 err(1, "%s: sync cache", dvname); 227 } 228