1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * rmf_main.c :
28 *	The file containing main() for rmformat. The command line
29 *	options are parsed in this file.
30 */
31
32
33#include <priv_utils.h>
34#include "rmformat.h"
35
36int32_t b_flag = 0;
37int32_t c_flag = 0;
38int32_t D_flag = 0;
39int32_t e_flag = 0;
40int32_t F_flag = 0;
41int32_t H_flag = 0;
42int32_t l_flag = 0;
43int32_t p_flag = 0;
44int32_t R_flag = 0;
45int32_t s_flag = 0;
46int32_t U_flag = 0;
47int32_t V_flag = 0;
48int32_t W_flag = 0;
49int32_t w_flag = 0;
50
51static char *myname;
52char *slice_file = NULL;
53char *label;
54diskaddr_t repair_blk_no;
55int32_t quick_format = 0;
56int32_t long_format = 0;
57int32_t force_format = 0;
58int32_t rw_protect_enable = 0;
59int32_t rw_protect_disable = 0;
60int32_t wp_enable_passwd = 0;
61int32_t wp_disable_passwd = 0;
62int32_t wp_enable = 0;
63int32_t wp_disable = 0;
64int32_t verify_write = 0;
65char *dev_name = NULL;
66
67static void usage(char *);
68void check_invalid_combinations();
69void check_invalid_combinations_again(int32_t);
70extern uint64_t my_atoll(char *ptr);
71extern void my_perror(char *err_string);
72void process_options();
73
74int
75main(int32_t argc, char **argv)
76{
77	char i;
78	char *tmp_ptr;
79
80	/*
81	 * This program requires file_dac_read, file_dac_write,
82	 * proc_fork, proc_exec, and sys_devices privileges.
83	 *
84	 * child processes require the sys_mount privilege
85	 */
86	(void) __init_suid_priv(PU_INHERITPRIVS,
87	    PRIV_FILE_DAC_READ, PRIV_FILE_DAC_WRITE, PRIV_PROC_FORK,
88	    PRIV_PROC_EXEC, PRIV_SYS_MOUNT, PRIV_SYS_DEVICES, NULL);
89
90	(void) setlocale(LC_ALL, "");
91
92#if !defined(TEXT_DOMAIN)
93#define	TEXT_DOMAIN	"SYS_TEST"
94#endif
95
96	(void) textdomain(TEXT_DOMAIN);
97
98	myname = argv[0];
99	DPRINTF1("myname %s\n", myname);
100
101	while ((i = getopt(argc, argv, "b:c:DeF:HlpR:s:tUV:W:w:")) != -1) {
102		DPRINTF1("arg %c\n", i);
103		switch (i) {
104		case 'b' :
105			b_flag++;
106			label = strdup(optarg);
107			if (strlen(label) > 8) {
108				(void) fprintf(stderr, gettext("Label is \
109restricted to 8 characters.\n"));
110				__priv_relinquish();
111				exit(1);
112			}
113
114			break;
115
116		case 'c' :
117			c_flag++;
118			tmp_ptr = strdup(optarg);
119			errno = 0;
120			repair_blk_no = my_atoll(tmp_ptr);
121			if (repair_blk_no == (diskaddr_t)(-1)) {
122				free(tmp_ptr);
123				usage("invalid block number");
124			}
125
126			DPRINTF1(" block no. %llu\n", repair_blk_no);
127			free(tmp_ptr);
128			break;
129
130		case 'D' :
131			D_flag++;
132			break;
133
134		case 'e' :
135			e_flag++;
136			break;
137
138		case 'F' :
139			F_flag++;
140			tmp_ptr = strdup(optarg);
141			if (strcmp(tmp_ptr, "quick") == 0) {
142				DPRINTF("q");
143				quick_format = 1;
144			} else if (strcmp(tmp_ptr, "long") == 0) {
145				DPRINTF("l");
146				long_format = 1;
147			} else if (strcmp(tmp_ptr, "force") == 0) {
148				DPRINTF("f");
149				force_format = 1;
150			} else {
151				free(tmp_ptr);
152				usage("invalid argument for option -F");
153			}
154			free(tmp_ptr);
155			break;
156
157		case 'H' :
158			H_flag++;
159			break;
160
161		case 'l' :
162			l_flag++;
163			break;
164
165		case 'p' :
166			p_flag++;
167			break;
168
169		case 'R' :
170			R_flag++;
171			tmp_ptr = strdup(optarg);
172			if (strcmp(tmp_ptr, "enable") == 0) {
173				rw_protect_enable++;
174			} else if (strcmp(tmp_ptr, "disable") == 0) {
175				rw_protect_disable++;
176			} else {
177				usage("Invalid argument for -R option");
178			}
179			free(tmp_ptr);
180			break;
181
182		case 's' :
183			s_flag++;
184
185			slice_file = strdup(optarg);
186			break;
187
188		case 'U' :
189			U_flag++;
190			break;
191
192		case 'V' :
193			V_flag++;
194			tmp_ptr = strdup(optarg);
195			if (strcmp(tmp_ptr, "read") == 0) {
196				verify_write = 0;
197			} else if (strcmp(tmp_ptr, "write") == 0) {
198				verify_write = 1;
199			} else {
200				usage("Invalid argument for -V option");
201			}
202			free(tmp_ptr);
203			break;
204
205		case 'W' :
206			W_flag++;
207			tmp_ptr = strdup(optarg);
208			if (strcmp(tmp_ptr, "enable") == 0) {
209				wp_enable_passwd++;
210			} else if (strcmp(tmp_ptr, "disable") == 0) {
211				wp_disable_passwd++;
212			} else {
213				usage("Invalid argument for -W option");
214			}
215			free(tmp_ptr);
216			break;
217
218		case 'w' :
219			w_flag++;
220			tmp_ptr = strdup(optarg);
221			if (strcmp(tmp_ptr, "enable") == 0) {
222				wp_enable++;
223			} else if (strcmp(tmp_ptr, "disable") == 0) {
224				wp_disable++;
225			} else {
226				usage("Invalid arguments for -w option");
227			}
228			free(tmp_ptr);
229			break;
230
231		default:
232			usage("");
233			break;
234		}
235	}
236	if (optind < argc -1) {
237		usage("more than one device name argument");
238		/* NOTREACHED */
239	}
240
241	if (optind == argc -1) {
242		dev_name = argv[optind];
243	} else if (optind == 1) {
244		/* list devices by default */
245		l_flag++;
246	} else if ((optind == argc) && !l_flag) {
247		(void) fprintf(stderr,
248		    gettext("No device specified.\n"));
249		__priv_relinquish();
250		exit(1);
251#if 0
252		(void) printf("Using floppy device\n");
253		dev_name = "/dev/rdiskette";
254#endif /* 0 */
255	}
256
257	process_options();
258
259	/* Remove the privileges we gave. */
260	__priv_relinquish();
261	return (0);
262}
263
264static void
265usage(char *str)
266{
267
268	if (strlen(str)) {
269		(void) fprintf(stderr, "%s : ", myname);
270		(void) fprintf(stderr, gettext(str));
271		(void) fprintf(stderr, "\n");
272	}
273
274	(void) fprintf(stderr, "Usage:\n");
275	(void) fprintf(stderr, gettext("\t%s \
276[ -DeHpU ] [ -b label ] [ -c blockno ] [ -F quick|long|force ] \
277[ -R enable|disable ] [ -s filename ] [ -V read|write ] \
278[ -w enable|disable ] [ -W enable|disable ] devname \n"), myname);
279	(void) fprintf(stderr, gettext("\t%s -l [ devname ]\n"),
280	    myname);
281	__priv_relinquish();
282	exit(1);
283}
284
285void
286check_invalid_combinations()
287{
288
289	/* Inherited from FLOPPY */
290
291	if (D_flag && H_flag) {
292		usage("Options -D and -H incompatible");
293	}
294
295	if (D_flag && F_flag) {
296		usage("Options -D and -F incompatible");
297	}
298
299	if (H_flag && F_flag) {
300		usage("Options -H and -F incompatible");
301	}
302
303	/* rmformat additions */
304
305	if ((w_flag && W_flag) || (w_flag && R_flag) || (W_flag && R_flag)) {
306		usage("Options -w, -W and -R incompatible");
307	}
308
309	if (c_flag && F_flag) {
310		usage("Options -c, -F incompatible");
311	}
312
313	/* l_flag is mutually exclusive of these flags */
314	if (l_flag && (D_flag + e_flag + H_flag + p_flag + U_flag +
315	    b_flag + c_flag + F_flag + R_flag + s_flag + V_flag +
316	    w_flag + W_flag)) {
317		usage("Options incompatible");
318	}
319}
320
321
322void
323check_invalid_combinations_again(int32_t medium_type)
324{
325	if ((medium_type != SM_FLOPPY) &&
326	    (medium_type != SM_PCMCIA_MEM)) {
327		if (D_flag || H_flag) {
328			usage("-D, -H  options are compatible with floppy and \
329PCMCIA memory cards only.");
330		}
331	}
332}
333