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 }