/* $OpenBSD: misc.c,v 1.88 2022/07/10 20:34:31 krw Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include "part.h" #include "disk.h" #include "misc.h" const struct unit_type unit_types[] = { { "b" , 1LL , "Bytes" }, { " " , 0LL , "Sectors" }, { "K" , 1024LL , "Kilobytes" }, { "M" , 1024LL * 1024 , "Megabytes" }, { "G" , 1024LL * 1024 *1024 , "Gigabytes" }, { "T" , 1024LL * 1024 * 1024 * 1024 , "Terabytes" }, }; #define SECTORS 1 double units_size(const char *units, const uint64_t sectors, const struct unit_type **ut) { double size; unsigned int i; *ut = &unit_types[SECTORS]; size = sectors; for (i = 0; i < nitems(unit_types); i++) { if (strncasecmp(unit_types[i].ut_abbr, units, 1) == 0) *ut = &unit_types[i]; } if ((*ut)->ut_conversion == 0) return size; else return (size * dl.d_secsize) / (*ut)->ut_conversion; } void string_from_line(char *buf, const size_t buflen, const int trim) { static char *line; static size_t sz; ssize_t len; size_t n; unsigned int i; len = getline(&line, &sz, stdin); if (len == -1) errx(1, "eof"); switch (trim) { case UNTRIMMED: line[strcspn(line, "\n")] = '\0'; n = strlcpy(buf, line, buflen); break; case TRIMMED: for (i = strlen(line); i > 0; i--) { if (isspace((unsigned char)line[i - 1]) == 0) break; line[i - 1] = '\0'; } n = strlcpy(buf, line + strspn(line, WHITESPACE), buflen); break; } if (n >= buflen) { printf("input too long\n"); memset(buf, 0, buflen); } } int ask_yn(const char *str) { int ch, first; extern int y_flag; if (y_flag) return 1; printf("%s [n] ", str); fflush(stdout); first = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (ch == EOF || first == EOF) errx(1, "eof"); return first == 'y' || first == 'Y'; } /* * adapted from sbin/disklabel/editor.c */ uint64_t getuint64(const char *prompt, uint64_t oval, const uint64_t minval, const uint64_t maxval) { char buf[BUFSIZ], *endptr, *p, operator = '\0'; const int secsize = dl.d_secsize; size_t n; int64_t mult = 1; double d, d2; int rslt, secpercyl, saveerr; char unit; if (oval > maxval) oval = maxval; if (oval < minval) oval = minval; secpercyl = disk.dk_sectors * disk.dk_heads; do { printf("%s [%llu - %llu]: [%llu] ", prompt, minval, maxval, oval); string_from_line(buf, sizeof(buf), TRIMMED); if (buf[0] == '\0') { rslt = snprintf(buf, sizeof(buf), "%llu", oval); if (rslt < 0 || rslt >= sizeof(buf)) errx(1, "default value too long"); } else if (buf[0] == '*' && buf[1] == '\0') { return maxval; } /* deal with units */ n = strlen(buf); switch (tolower((unsigned char)buf[n-1])) { case 'c': unit = 'c'; mult = secpercyl; buf[--n] = '\0'; break; case 'b': unit = 'b'; mult = -(int64_t)secsize; buf[--n] = '\0'; break; case 's': unit = 's'; mult = 1; buf[--n] = '\0'; break; case 'k': unit = 'k'; if (secsize > 1024) mult = -(int64_t)secsize / 1024LL; else mult = 1024LL / secsize; buf[--n] = '\0'; break; case 'm': unit = 'm'; mult = (1024LL * 1024) / secsize; buf[--n] = '\0'; break; case 'g': unit = 'g'; mult = (1024LL * 1024 * 1024) / secsize; buf[--n] = '\0'; break; case 't': unit = 't'; mult = (1024LL * 1024 * 1024 * 1024) / secsize; buf[--n] = '\0'; break; default: unit = ' '; mult = 1; break; } /* deal with the operator */ p = &buf[0]; if (*p == '+' || *p == '-') operator = *p++; else operator = ' '; endptr = p; errno = 0; d = strtod(p, &endptr); saveerr = errno; d2 = d; if (mult > 0) d *= mult; else { d /= (-mult); d2 = d; } /* Apply the operator */ if (operator == '+') d = oval + d; else if (operator == '-') { d = oval - d; d2 = d; } if (saveerr == ERANGE || d > maxval || d < minval || d < d2) { printf("%s is out of range: %c%s%c\n", prompt, operator, p, unit); } else if (*endptr != '\0') { printf("%s is invalid: %c%s%c\n", prompt, operator, p, unit); } else { break; } } while (1); return (uint64_t)d; } int hex_octet(char *buf) { char *cp; long num; cp = buf; num = strtol(buf, &cp, 16); if (cp == buf || *cp != '\0') return -1; if (num < 0 || num > 0xff) return -1; return num; }