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, &param) != 0) {
 225                                 ret = errout(&handle);
 226                         } else {
 227                                 (void) printf("%s\n", mnt);
 228                                 print_fsd(&param);
 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, &param) != 0)
 247                                 ret = errout(&handle);
 248 
 249                 } else if (mflag) {
 250                         if (fsd_disturb(&handle, mnt, &param) != 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 }