1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2013 Damian Bogel. All rights reserved. 14 */ 15 16 #include <libfsd.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 21 fsd_handle_t handle; 22 23 int ret; 24 25 int 26 errout(fsd_handle_t *handle) 27 { 28 (void) fprintf(stderr, "Error: %s: %s\n", 29 fsd_strerr(handle->fsd_errno), strerror(handle->errno)); 30 31 return (-1); 32 } 33 34 void 35 print_fsd(fsd_t *fsd) 36 { 37 (void) printf("\tRead less: %d%% chance with range %d - %d\n", 38 (int)fsd->read_less_chance, 39 (int)fsd->read_less_r[0], 40 (int)fsd->read_less_r[1]); 41 } 42 43 void 44 info() 45 { 46 fsd_info_t info; 47 48 if (fsd_get_info(&handle, &info) != 0) { 49 ret = errout(&handle); 50 return; 51 } 52 53 if (info.fsdinf_enabled) { 54 (void) printf( 55 "Enabled: yes\n" 56 "Filesystems disturbed: %d\n", (int)info.fsdinf_count); 57 58 if (info.fsdinf_omni_on) { 59 (void) printf( 60 "Omnipresent disturbing: yes\n" 61 "Omnipresent params:\n"); 62 print_fsd(&info.fsdinf_omni_param); 63 } else { 64 (void) printf("Omnipresent disturbing: no\n"); 65 } 66 } 67 } 68 69 void 70 list() 71 { 72 fsd_info_t info; 73 fsd_fs_t *fslistp; 74 int i; 75 int count; 76 77 if (fsd_get_info(&handle, &info) != 0) { 78 ret = errout(&handle); 79 return; 80 } 81 count = info.fsdinf_count; 82 83 fslistp = calloc(info.fsdinf_count, sizeof (fsd_fs_t)); 84 if (fsd_get_list(&handle, fslistp, &count) != 0) { 85 ret = errout(&handle); 86 } else { 87 for (i = 0; i < count; i++) { 88 (void) printf("Mountpoint: %s\n", 89 fslistp[i].fsdf_name); 90 print_fsd(&fslistp[i].fsdf_param); 91 (void) printf("\n"); 92 93 } 94 } 95 96 free(fslistp); 97 } 98 99 int aflag; 100 int cflag; 101 int dflag; 102 int eflag; 103 int gflag; 104 int iflag; 105 int lflag; 106 int mflag; 107 int oflag; 108 int rflag; 109 int xflag; 110 111 char *mnt; 112 fsd_t param; 113 int chance; 114 int range[2]; 115 116 int 117 main(int argc, char *argv[]) 118 { 119 extern char *optarg; 120 extern int optind; 121 int opt; 122 123 if (argc < 2) 124 goto usage; 125 126 if (fsd_open(&handle) != 0) 127 return (errout(&handle)); 128 129 while ((opt = getopt(argc, argv, "ediam:gxoc:r:l")) != -1) { 130 switch (opt) { 131 case 'e': 132 eflag = 1; 133 break; 134 135 case 'd': 136 dflag = 1; 137 break; 138 139 case 'i': 140 iflag = 1; 141 break; 142 143 case 'a': 144 aflag = 1; 145 break; 146 147 case 'm': 148 mflag = 1; 149 mnt = optarg; 150 break; 151 152 case 'g': 153 gflag = 1; 154 break; 155 156 case 'x': 157 xflag = 1; 158 break; 159 160 case 'o': 161 oflag = 1; 162 break; 163 164 case 'c': 165 cflag = 1; 166 chance = atoi(optarg); 167 break; 168 169 case 'r': 170 rflag = 1; 171 if (optind > argc - 1) { 172 (void) fprintf(stderr, 173 "Error: -r requires two arguments\n"); 174 ret = -1; 175 goto end; 176 } 177 range[0] = atoi(argv[optind-1]); 178 range[1] = atoi(argv[optind]); 179 optind++; 180 break; 181 182 case 'l': 183 lflag = 1; 184 break; 185 186 case '?': 187 (void) fprintf(stderr, 188 "Error: Unrecognized option: -%c\n", optopt); 189 ret = -1; 190 goto end; 191 } 192 } 193 194 if (eflag) { 195 if (fsd_enable(&handle) != 0) 196 ret = errout(&handle); 197 198 } else if (dflag) { 199 if (fsd_disable(&handle) != 0) 200 ret = errout(&handle); 201 202 } else if (iflag) { 203 info(); 204 205 } else if (aflag) { 206 list(); 207 208 } else if (xflag) { 209 if (oflag) { 210 if (fsd_disturb_omni_off(&handle) != 0) 211 ret = errout(&handle); 212 213 } else if (mflag) { 214 if (fsd_disturb_off(&handle, mnt) != 0) 215 ret = errout(&handle); 216 217 } else { 218 (void) fprintf(stderr, "Don't know what to clear. " 219 "Use -o or -m PATH with -x option.\n"); 220 } 221 222 } else if (gflag) { 223 if (mflag) { 224 if (fsd_get_param(&handle, mnt, ¶m) != 0) { 225 ret = errout(&handle); 226 } else { 227 (void) printf("%s\n", mnt); 228 print_fsd(¶m); 229 } 230 } else { 231 (void) fprintf(stderr, "Don't know what to get. " 232 "Use -m PATH with -g option.\n"); 233 } 234 235 } else if (lflag) { /* add other disturbances here */ 236 if (!(cflag && rflag)) { 237 (void) fprintf(stderr, "Need chance and range."); 238 goto end; 239 } 240 241 param.read_less_chance = chance; 242 param.read_less_r[0] = range[0]; 243 param.read_less_r[1] = range[1]; 244 245 if (oflag) { 246 if (fsd_disturb_omni(&handle, ¶m) != 0) 247 ret = errout(&handle); 248 249 } else if (mflag) { 250 if (fsd_disturb(&handle, mnt, ¶m) != 0) 251 ret = errout(&handle); 252 253 } else { 254 (void) fprintf(stderr, 255 "Don't know what to disturb. " 256 "Use -o or -m PATH with this options."); 257 } 258 259 } else { 260 usage: 261 (void) fprintf(stderr, "Usage: fsdadm " 262 "[-ed] [-ai] [-o] [-x] [-g] [-l] " 263 "[-r range_start range_end]\n" 264 "\t[-c chance] [-m path]\n\n"); 265 266 (void) fprintf(stderr, 267 "\t -e enable fsd\n" 268 "\t -d disable fsd\n" 269 "\t -a display disturbance parameters for all disturbed\n" 270 "\t filesystems\n" 271 "\t -i display information about current fsd status\n" 272 "\t -o omnipresent switch\n" 273 "\t -x clear switch\n" 274 "\t -g get disturbance parameters\n" 275 "\t -l \"read less\" disturbance\n" 276 "\t every read operation would read n (from a given\n" 277 "\t range) bytes less than it was requested\n" 278 "\t -r range for some types of disturbances\n" 279 "\t -c chance of the disturbance\n" 280 "\t -m path to mountpoint (or a representative file)\n" 281 "\n"); 282 } 283 284 end: 285 fsd_close(&handle); 286 return (ret); 287 }