mirror of
https://github.com/Llewellynvdm/Tomb.git
synced 2024-11-16 01:27:08 +00:00
portable: remove strtosize and use MiB
This commit is contained in:
parent
0130fcf86d
commit
b5eae55c8b
@ -8,8 +8,7 @@ TOMB ?= test.tomb
|
|||||||
#########
|
#########
|
||||||
## BUILD
|
## BUILD
|
||||||
#########
|
#########
|
||||||
all:
|
test: create-open-close check-random-data
|
||||||
${CC} -O2 -Wall -Wextra --std=c99 --pedantic -o tomb-str2size strtosize.c
|
|
||||||
|
|
||||||
########
|
########
|
||||||
## TEST
|
## TEST
|
||||||
|
@ -1,214 +0,0 @@
|
|||||||
/* strtosize from util-linux */
|
|
||||||
|
|
||||||
/* No copyright is claimed. This code is in the public domain. */
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
static int do_scale_by_power (uintmax_t *x, int base, int power)
|
|
||||||
{
|
|
||||||
while (power--) {
|
|
||||||
if (UINTMAX_MAX / base < *x)
|
|
||||||
return -ERANGE;
|
|
||||||
*x *= base;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* strtosize() - convert string to size (uintmax_t).
|
|
||||||
*
|
|
||||||
* Supported suffixes:
|
|
||||||
*
|
|
||||||
* XiB or X for 2^N
|
|
||||||
* where X = {K,M,G,T,P,E,Z,Y}
|
|
||||||
* or X = {k,m,g,t,p,e} (undocumented for backward compatibility only)
|
|
||||||
* for example:
|
|
||||||
* 10KiB = 10240
|
|
||||||
* 10K = 10240
|
|
||||||
*
|
|
||||||
* XB for 10^N
|
|
||||||
* where X = {K,M,G,T,P,E,Z,Y}
|
|
||||||
* for example:
|
|
||||||
* 10KB = 10000
|
|
||||||
*
|
|
||||||
* The optional 'power' variable returns number associated with used suffix
|
|
||||||
* {K,M,G,T,P,E,Z,Y} = {1,2,3,4,5,6,7,8}.
|
|
||||||
*
|
|
||||||
* The function also supports decimal point, for example:
|
|
||||||
* 0.5MB = 500000
|
|
||||||
* 0.5MiB = 512000
|
|
||||||
*
|
|
||||||
* Note that the function does not accept numbers with '-' (negative sign)
|
|
||||||
* prefix.
|
|
||||||
*/
|
|
||||||
int strtosize(const char *str, uintmax_t *res, int *power)
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
char *end;
|
|
||||||
uintmax_t x, frac = 0;
|
|
||||||
int base = 1024, rc = 0, pwr = 0, frac_zeros = 0;
|
|
||||||
|
|
||||||
static const char *suf = "KMGTPEZY";
|
|
||||||
static const char *suf2 = "kmgtpezy";
|
|
||||||
const char *sp;
|
|
||||||
|
|
||||||
*res = 0;
|
|
||||||
|
|
||||||
if (!str || !*str) {
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only positive numbers are acceptable
|
|
||||||
*
|
|
||||||
* Note that this check is not perfect, it would be better to
|
|
||||||
* use lconv->negative_sign. But coreutils use the same solution,
|
|
||||||
* so it's probably good enough...
|
|
||||||
*/
|
|
||||||
p = str;
|
|
||||||
while (isspace((unsigned char) *p))
|
|
||||||
p++;
|
|
||||||
if (*p == '-') {
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0, end = NULL;
|
|
||||||
x = strtoumax(str, &end, 0);
|
|
||||||
|
|
||||||
if (end == str ||
|
|
||||||
(errno != 0 && (x == UINTMAX_MAX || x == 0))) {
|
|
||||||
rc = errno ? -errno : -EINVAL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (!end || !*end)
|
|
||||||
goto done; /* without suffix */
|
|
||||||
p = end;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check size suffixes
|
|
||||||
*/
|
|
||||||
check_suffix:
|
|
||||||
if (*(p + 1) == 'i' && (*(p + 2) == 'B' || *(p + 2) == 'b') && !*(p + 3))
|
|
||||||
base = 1024; /* XiB, 2^N */
|
|
||||||
else if ((*(p + 1) == 'B' || *(p + 1) == 'b') && !*(p + 2))
|
|
||||||
base = 1000; /* XB, 10^N */
|
|
||||||
else if (*(p + 1)) {
|
|
||||||
struct lconv const *l = localeconv();
|
|
||||||
const char *dp = l ? l->decimal_point : NULL;
|
|
||||||
size_t dpsz = dp ? strlen(dp) : 0;
|
|
||||||
|
|
||||||
if (frac == 0 && *p && dp && strncmp(dp, p, dpsz) == 0) {
|
|
||||||
const char *fstr = p + dpsz;
|
|
||||||
|
|
||||||
for (p = fstr; *p == '0'; p++)
|
|
||||||
frac_zeros++;
|
|
||||||
fstr = p;
|
|
||||||
if (isdigit(*fstr)) {
|
|
||||||
errno = 0, end = NULL;
|
|
||||||
frac = strtoumax(fstr, &end, 0);
|
|
||||||
if (end == fstr ||
|
|
||||||
(errno != 0 && (frac == UINTMAX_MAX || frac == 0))) {
|
|
||||||
rc = errno ? -errno : -EINVAL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
end = (char *) p;
|
|
||||||
|
|
||||||
if (frac && (!end || !*end)) {
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto err; /* without suffix, but with frac */
|
|
||||||
}
|
|
||||||
p = end;
|
|
||||||
goto check_suffix;
|
|
||||||
}
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto err; /* unexpected suffix */
|
|
||||||
}
|
|
||||||
|
|
||||||
sp = strchr(suf, *p);
|
|
||||||
if (sp)
|
|
||||||
pwr = (sp - suf) + 1;
|
|
||||||
else {
|
|
||||||
sp = strchr(suf2, *p);
|
|
||||||
if (sp)
|
|
||||||
pwr = (sp - suf2) + 1;
|
|
||||||
else {
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = do_scale_by_power(&x, base, pwr);
|
|
||||||
if (power)
|
|
||||||
*power = pwr;
|
|
||||||
if (frac && pwr) {
|
|
||||||
int i;
|
|
||||||
uintmax_t frac_div = 10, frac_poz = 1, frac_base = 1;
|
|
||||||
|
|
||||||
/* mega, giga, ... */
|
|
||||||
do_scale_by_power(&frac_base, base, pwr);
|
|
||||||
|
|
||||||
/* maximal divisor for last digit (e.g. for 0.05 is
|
|
||||||
* frac_div=100, for 0.054 is frac_div=1000, etc.)
|
|
||||||
*
|
|
||||||
* Reduce frac if too large.
|
|
||||||
*/
|
|
||||||
while (frac_div < frac) {
|
|
||||||
if (frac_div <= UINTMAX_MAX/10)
|
|
||||||
frac_div *= 10;
|
|
||||||
else
|
|
||||||
frac /= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 'frac' is without zeros (5 means 0.5 as well as 0.05) */
|
|
||||||
for (i = 0; i < frac_zeros; i++) {
|
|
||||||
if (frac_div <= UINTMAX_MAX/10)
|
|
||||||
frac_div *= 10;
|
|
||||||
else
|
|
||||||
frac /= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Go backwardly from last digit and add to result what the
|
|
||||||
* digit represents in the frac_base. For example 0.25G
|
|
||||||
*
|
|
||||||
* 5 means 1GiB / (100/5)
|
|
||||||
* 2 means 1GiB / (10/2)
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
unsigned int seg = frac % 10; /* last digit of the frac */
|
|
||||||
uintmax_t seg_div = frac_div / frac_poz; /* what represents the segment 1000, 100, .. */
|
|
||||||
|
|
||||||
frac /= 10; /* remove last digit from frac */
|
|
||||||
frac_poz *= 10;
|
|
||||||
|
|
||||||
if (seg && seg_div / seg)
|
|
||||||
x += frac_base / (seg_div / seg);
|
|
||||||
} while (frac);
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
*res = x;
|
|
||||||
err:
|
|
||||||
if (rc < 0)
|
|
||||||
errno = -rc;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
// TODO: secure check args
|
|
||||||
uint64_t size;
|
|
||||||
if(argc!=2) return(1);
|
|
||||||
int res = strtosize(argv[1], &size, NULL);
|
|
||||||
if(res==0) {
|
|
||||||
fprintf(stdout,"%lu\n",size);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,"%s\n",strerror(errno));
|
|
||||||
}
|
|
||||||
return(res);
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ load bats_setup
|
|||||||
@test "Dig tomb" {
|
@test "Dig tomb" {
|
||||||
rm -f "$TOMB"
|
rm -f "$TOMB"
|
||||||
>&3 echo "$TOMB"
|
>&3 echo "$TOMB"
|
||||||
./tomb dig -s 20MiB "$TOMB"
|
./tomb dig -s 20 "$TOMB"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "Forge key" {
|
@test "Forge key" {
|
||||||
|
@ -167,14 +167,14 @@ linux_mount() {
|
|||||||
# usage: echo PASSWORD | posix_create file size pim
|
# usage: echo PASSWORD | posix_create file size pim
|
||||||
posix_create() {
|
posix_create() {
|
||||||
file="$1" # must not exist
|
file="$1" # must not exist
|
||||||
size="$2" # veracrypt format (accepts M or G)
|
size="$2" # size in bytes
|
||||||
pim="$3" # any number
|
pim="$3" # any number
|
||||||
_verbose "posix_create $file $size $pim"
|
_verbose "posix_create $file $size $pim"
|
||||||
veracrypt --text --non-interactive --stdin \
|
veracrypt --text --non-interactive --stdin \
|
||||||
-m nokernelcrypto \
|
-m nokernelcrypto \
|
||||||
-c "$file" --volume-type normal \
|
-c "$file" --volume-type normal \
|
||||||
--hash sha512 --encryption serpent-aes \
|
--hash sha512 --encryption serpent-aes \
|
||||||
--filesystem none --size "$size" --pim "$pim" \
|
--filesystem none --size "${size}" --pim "$pim" \
|
||||||
--random-source /dev/urandom -k ''
|
--random-source /dev/urandom -k ''
|
||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
@ -274,20 +274,21 @@ case "$cmd" in
|
|||||||
_error "A tomb exists already. I'm not digging here:"
|
_error "A tomb exists already. I'm not digging here:"
|
||||||
ls -l "$tombfile"; exit 1
|
ls -l "$tombfile"; exit 1
|
||||||
}
|
}
|
||||||
_message "Commanded to dig tomb " "$tombfile" " sized $tombsize"
|
_message "Commanded to dig tomb " "$tombfile" " sized $tombsize MiB"
|
||||||
touch "$tombfile" || _failure "Error creating the tomb " "$tombfile"
|
touch "$tombfile" || _failure "Error creating the tomb " "$tombfile"
|
||||||
# dd if=/dev/urandom bs=1048576 count=$tombsize of="$tombfile" || {
|
# dd if=/dev/urandom bs=1048576 count=$tombsize of="$tombfile" || {
|
||||||
# _failure "Error creating the tomb " "$tombfile"
|
# _failure "Error creating the tomb " "$tombfile"
|
||||||
# exit 1
|
# exit 1
|
||||||
# }
|
# }
|
||||||
|
bytesize="$(( $tombsize * 1048576 ))"
|
||||||
|
[ "$bytesize" = "" ] &&
|
||||||
|
_failure "Error reading tomb size " "$tombsize"
|
||||||
if [ "$system" = "Linux" ]; then
|
if [ "$system" = "Linux" ]; then
|
||||||
fallocate -x -l "$tombsize" "$tombfile" ||
|
fallocate -x -l "$bytesize" "$tombfile" ||
|
||||||
_failure "Error creating the tomb " "$tombfile"
|
_failure "Error creating the tomb " "$tombfile"
|
||||||
else
|
else
|
||||||
bytesize="`tomb-str2size $tombsize`"
|
dd if=/dev/zero of="$tombfile" count="$tombsize" bs=1048576 ||
|
||||||
[ "$bytesize" = "" ] && _failure "Error reading tomb size " "$tombsize"
|
_failure "Error creating the tomb " "$tombfile of $tombsize MiB"
|
||||||
dd if=/dev/zero of="$tombfile" count="$(( bytesize / 1048576))" bs=1048576 ||
|
|
||||||
_failure "Error creating the tomb " "$tombfile of $tombsize"
|
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@ -327,18 +328,18 @@ EOF
|
|||||||
done
|
done
|
||||||
case "$system" in
|
case "$system" in
|
||||||
Linux)
|
Linux)
|
||||||
tombsize=`stat "$tombfile" | awk '/Size:/ {print $2; exit}'`
|
bytesize=`stat "$tombfile" | awk '/Size:/ {print $2; exit}'`
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
tombsize=`stat -f '%z' "$tombfile"`
|
bytesize=`stat -f '%z' "$tombfile"`
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
_message "Commanded to lock tomb " "$tombfile of $tombsize with key $tombkey"
|
_message "Commanded to lock tomb " "$tombfile with key $tombkey"
|
||||||
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
[ "$tombfile" = "" ] && _failure "Missing path to tomb"
|
||||||
[ -r "$tombfile" ] || _failure "Tomb file not readable"
|
[ -r "$tombfile" ] || _failure "Tomb file not readable"
|
||||||
[ "$tombkey" = "" ] && _failure "Missing path to key"
|
[ "$tombkey" = "" ] && _failure "Missing path to key"
|
||||||
[ -r "$tombkey" ] || _failure "Key file not readable"
|
[ -r "$tombkey" ] || _failure "Key file not readable"
|
||||||
"$create" "$tombfile" "$tombsize" "$PIM" < "$tombkey" || {
|
"$create" "$tombfile" "$bytesize" "$PIM" < "$tombkey" || {
|
||||||
_failure "Error creating the tomb " "$tombfile"
|
_failure "Error creating the tomb " "$tombfile"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user