GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/fdisk/misc.c Lines: 0 165 0.0 %
Date: 2017-11-07 Branches: 0 124 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: misc.c,v 1.61 2015/11/26 08:15:07 tim Exp $	*/
2
3
/*
4
 * Copyright (c) 1997 Tobias Weingartner
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/disklabel.h>
21
22
#include <ctype.h>
23
#include <err.h>
24
#include <errno.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <uuid.h>
29
30
#include "disk.h"
31
#include "misc.h"
32
#include "part.h"
33
34
struct unit_type unit_types[] = {
35
	{ "b"	, 1LL				, "Bytes"	},
36
	{ " "	, 0LL				, "Sectors"	},
37
	{ "K"	, 1024LL			, "Kilobytes"	},
38
	{ "M"	, 1024LL * 1024			, "Megabytes"	},
39
	{ "G"	, 1024LL * 1024 *1024		, "Gigabytes"	},
40
	{ "T"	, 1024LL * 1024 * 1024 * 1024	, "Terabytes"	},
41
	{ NULL	, 0				, NULL		},
42
};
43
44
int
45
unit_lookup(char *units)
46
{
47
	int i = 0;
48
49
	if (units == NULL)
50
		return (SECTORS);
51
52
	while (unit_types[i].abbr != NULL) {
53
		if (strncasecmp(unit_types[i].abbr, units, 1) == 0)
54
			break;
55
		i++;
56
	}
57
	/* default */
58
	if (unit_types[i].abbr == NULL)
59
		return (SECTORS);
60
61
	return (i);
62
}
63
64
int
65
string_from_line(char *buf, size_t buflen)
66
{
67
	char *line;
68
	size_t sz;
69
70
	line = fgetln(stdin, &sz);
71
	if (line == NULL)
72
		return (1);
73
74
	if (line[sz - 1] == '\n')
75
		sz--;
76
	if (sz >= buflen)
77
		sz = buflen - 1;
78
79
	memcpy(buf, line, sz);
80
	buf[sz] = '\0';
81
82
	return (0);
83
}
84
85
void
86
ask_cmd(char **cmd, char **arg)
87
{
88
	static char lbuf[100];
89
	size_t cmdstart, cmdend, argstart;
90
91
	/* Get NUL terminated string from stdin. */
92
	if (string_from_line(lbuf, sizeof(lbuf)))
93
		errx(1, "eof");
94
95
	cmdstart = strspn(lbuf, " \t");
96
	cmdend = cmdstart + strcspn(&lbuf[cmdstart], " \t");
97
	argstart = cmdend + strspn(&lbuf[cmdend], " \t");
98
99
	/* *cmd and *arg may be set to point at final NUL! */
100
	*cmd = &lbuf[cmdstart];
101
	lbuf[cmdend] = '\0';
102
	*arg = &lbuf[argstart];
103
}
104
105
int
106
ask_num(const char *str, int dflt, int low, int high)
107
{
108
	char lbuf[100];
109
	const char *errstr;
110
	int num;
111
112
	if (dflt < low)
113
		dflt = low;
114
	else if (dflt > high)
115
		dflt = high;
116
117
	do {
118
		printf("%s [%d - %d]: [%d] ", str, low, high, dflt);
119
120
		if (string_from_line(lbuf, sizeof(lbuf)))
121
			errx(1, "eof");
122
123
		if (lbuf[0] == '\0') {
124
			num = dflt;
125
			errstr = NULL;
126
		} else {
127
			num = (int)strtonum(lbuf, low, high, &errstr);
128
			if (errstr)
129
				printf("%s is %s: %s.\n", str, errstr, lbuf);
130
		}
131
	} while (errstr);
132
133
	return (num);
134
}
135
136
int
137
ask_pid(int dflt, struct uuid *guid)
138
{
139
	char lbuf[100], *cp;
140
	int num = -1, status;
141
142
	do {
143
		printf("Partition id ('0' to disable) [01 - FF]: [%X] ", dflt);
144
		printf("(? for help) ");
145
146
		if (string_from_line(lbuf, sizeof(lbuf)))
147
			errx(1, "eof");
148
149
		if (lbuf[0] == '?') {
150
			PRT_printall();
151
			continue;
152
		}
153
154
		if (guid && strlen(lbuf) == UUID_STR_LEN) {
155
			uuid_from_string(lbuf, guid, &status);
156
			if (status == uuid_s_ok)
157
				return (0x100);
158
		}
159
160
		/* Convert */
161
		cp = lbuf;
162
		num = strtol(lbuf, &cp, 16);
163
164
		/* Make sure only number present */
165
		if (cp == lbuf)
166
			num = dflt;
167
		if (*cp != '\0') {
168
			printf("'%s' is not a valid number.\n", lbuf);
169
			num = -1;
170
		} else if (num == 0) {
171
			break;
172
		} else if (num < 0 || num > 0xff) {
173
			printf("'%x' is out of range.\n", num);
174
		}
175
	} while (num < 0 || num > 0xff);
176
177
	return (num);
178
}
179
180
int
181
ask_yn(const char *str)
182
{
183
	int ch, first;
184
	extern int y_flag;
185
186
	if (y_flag)
187
		return (1);
188
189
	printf("%s [n] ", str);
190
	fflush(stdout);
191
192
	first = ch = getchar();
193
	while (ch != '\n' && ch != EOF)
194
		ch = getchar();
195
196
	if (ch == EOF || first == EOF)
197
		errx(1, "eof");
198
199
	return (first == 'y' || first == 'Y');
200
}
201
202
/*
203
 * adapted from sbin/disklabel/editor.c
204
 */
205
u_int64_t
206
getuint64(char *prompt, u_int64_t oval, u_int64_t minval, u_int64_t maxval)
207
{
208
	const int secsize = unit_types[SECTORS].conversion;
209
	char buf[BUFSIZ], *endptr, *p, operator = '\0';
210
	size_t n;
211
	int64_t mult = 1;
212
	double d, d2;
213
	int secpercyl, saveerr;
214
	char unit;
215
216
	if (oval > maxval)
217
		oval = maxval;
218
	if (oval < minval)
219
		oval = minval;
220
221
	secpercyl = disk.sectors * disk.heads;
222
223
	do {
224
		printf("%s [%llu - %llu]: [%llu] ", prompt, minval, maxval,
225
		    oval);
226
227
		if (string_from_line(buf, sizeof(buf)))
228
			errx(1, "eof");
229
230
		if (buf[0] == '\0') {
231
			return (oval);
232
		} else if (buf[0] == '*' && buf[1] == '\0') {
233
			return (maxval);
234
		}
235
236
		/* deal with units */
237
		n = strlen(buf);
238
		switch (tolower((unsigned char)buf[n-1])) {
239
		case 'c':
240
			unit = 'c';
241
			mult = secpercyl;
242
			buf[--n] = '\0';
243
			break;
244
		case 'b':
245
			unit = 'b';
246
			mult = -(int64_t)secsize;
247
			buf[--n] = '\0';
248
			break;
249
		case 's':
250
			unit = 's';
251
			mult = 1;
252
			buf[--n] = '\0';
253
			break;
254
		case 'k':
255
			unit = 'k';
256
			if (secsize > 1024)
257
				mult = -(int64_t)secsize / 1024LL;
258
			else
259
				mult = 1024LL / secsize;
260
			buf[--n] = '\0';
261
			break;
262
		case 'm':
263
			unit = 'm';
264
			mult = (1024LL * 1024) / secsize;
265
			buf[--n] = '\0';
266
			break;
267
		case 'g':
268
			unit = 'g';
269
			mult = (1024LL * 1024 * 1024) / secsize;
270
			buf[--n] = '\0';
271
			break;
272
		case 't':
273
			unit = 't';
274
			mult = (1024LL * 1024 * 1024 * 1024) / secsize;
275
			buf[--n] = '\0';
276
			break;
277
		default:
278
			unit = ' ';
279
			mult = 1;
280
			break;
281
		}
282
283
		/* deal with the operator */
284
		p = &buf[0];
285
		if (*p == '+' || *p == '-')
286
			operator = *p++;
287
		else
288
			operator = ' ';
289
290
		endptr = p;
291
		errno = 0;
292
		d = strtod(p, &endptr);
293
		saveerr = errno;
294
		d2 = d;
295
		if (mult > 0)
296
			d *= mult;
297
		else {
298
			d /= (-mult);
299
			d2 = d;
300
		}
301
302
		/* Apply the operator */
303
		if (operator == '+')
304
			d = oval + d;
305
		else if (operator == '-') {
306
			d = oval - d;
307
			d2 = d;
308
		}
309
310
		if (saveerr == ERANGE || d > maxval || d < minval || d < d2) {
311
			printf("%s is out of range: %c%s%c\n", prompt, operator,
312
			    p, unit);
313
		} else if (*endptr != '\0') {
314
			printf("%s is invalid: %c%s%c\n", prompt, operator,
315
			    p, unit);
316
		} else {
317
			break;
318
		}
319
	} while (1);
320
321
	return((u_int64_t)d);
322
}
323
324
char *
325
ask_string(const char *prompt, const char *oval)
326
{
327
	static char buf[37];
328
329
	buf[0] = '\0';
330
	printf("%s: [%s] ", prompt, oval ? oval : "");
331
	if (string_from_line(buf, sizeof(buf)))
332
		errx(1, "eof");
333
334
	if (buf[0] == '\0' && oval)
335
		strlcpy(buf, oval, sizeof(buf));
336
337
	return(buf);
338
}
339
340
/*
341
 * Adapted from Hacker's Delight crc32b().
342
 *
343
 * To quote http://www.hackersdelight.org/permissions.htm :
344
 *
345
 * "You are free to use, copy, and distribute any of the code on
346
 *  this web site, whether modified by you or not. You need not give
347
 *  attribution. This includes the algorithms (some of which appear
348
 *  in Hacker's Delight), the Hacker's Assistant, and any code submitted
349
 *  by readers. Submitters implicitly agree to this."
350
 */
351
u_int32_t
352
crc32(const u_char *buf, const u_int32_t size)
353
{
354
	int j;
355
	u_int32_t i, byte, crc, mask;
356
357
	crc = 0xFFFFFFFF;
358
359
	for (i = 0; i < size; i++) {
360
		byte = buf[i];			/* Get next byte. */
361
		crc = crc ^ byte;
362
		for (j = 7; j >= 0; j--) {	/* Do eight times. */
363
			mask = -(crc & 1);
364
			crc = (crc >> 1) ^ (0xEDB88320 & mask);
365
		}
366
	}
367
368
	return ~crc;
369
}
370
371
char *
372
utf16le_to_string(u_int16_t *utf)
373
{
374
	static char name[GPTPARTNAMESIZE];
375
	int i;
376
377
	for (i = 0; i < GPTPARTNAMESIZE; i++) {
378
		name[i] = letoh16(utf[i]) & 0x7F;
379
		if (name[i] == '\0')
380
			break;
381
	}
382
	if (i == GPTPARTNAMESIZE)
383
		name[i - 1] = '\0';
384
385
	return (name);
386
}
387
388
u_int16_t *
389
string_to_utf16le(char *ch)
390
{
391
	static u_int16_t utf[GPTPARTNAMESIZE];
392
	int i;
393
394
	for (i = 0; i < GPTPARTNAMESIZE; i++) {
395
		utf[i] = htole16((unsigned int)ch[i]);
396
		if (utf[i] == 0)
397
			break;
398
	}
399
	if (i == GPTPARTNAMESIZE)
400
		utf[i - 1] = 0;
401
402
	return (utf);
403
}