blob: 4d5e5f5359ce251a230428091c72a7861413d01a [file] [log] [blame]
#!/bin/bash
# Copyright 2017 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Portable function to truncate a file to a given length.
fx-truncate() {
local -r file="$1"
local -r size="$2"
touch "${file}"
if [[ -z "${size}" ]]; then
echo >&2 "fx-truncate: size \"${size}\" not given"
return 1
fi
case $(uname) in
Darwin)
mkfile -n "${size}" "${file}"
;;
Linux)
truncate -s "${size}" "${file}"
;;
*)
head -c "${size}" /dev/zero > "${file}"
;;
esac
return $?
}
# Converts human-readable numbers to an integer. Uses power-of-two abbreviations (K == 1024, M ==
# 1048576, etc).
# 1314K => 1345536
# 13M => 13631488
# 1314000 => 1314000
convert_human_readable_num() {
if [[ -z "${1}" ]]; then
return 1
fi
conv=1
val="$1"
case ${1: -1} in
"K")
conv=1024
val="${val%?}"
;;
"M")
conv=1048576
val="${val%?}"
;;
"G")
conv=1073741824
val="${val%?}"
;;
esac
echo "$(( ${val} * ${conv} ))"
}
# Compares $1 to $2 where either can be a human-readable number (e.g. 12K).
# Prints -1, 0, or 1.
compare_human_readable_nums() {
left="$(convert_human_readable_num $1)"
right="$(convert_human_readable_num $2)"
if [[ -z "${left}" || -z "${right}" ]]; then
return 1
fi
if [[ "$left" == "$right" ]]; then
echo "0"
else
least=$(echo -e "$left\\n$right" | sort -n | head -n1)
if [[ "$least" == "$left" ]]; then
echo "-1"
else
echo "1"
fi
fi
}
_fx-extend-generic() {
local -r file="$1"
local -r size="$2"
len="$(wc -c < ${file} | awk '{print $1}')"
target="$(convert_human_readable_num ${size})"
if [[ "$len" -lt "$target" ]]; then
rem="$(( $target - $len ))"
head -c "${rem}" /dev/zero >> "${file}"
fi
}
# Like fx-truncate, but only ever extends a file (if the file would be truncated, this is a NOP).
fx-extend() {
local -r file="$1"
local -r size="$2"
touch "${file}"
if [[ -z "${size}" ]]; then
echo >&2 "fx-extend: size \"${size}\" not given"
return 1
fi
case $(uname) in
Darwin)
# mkfile isn't always available on macos.
if [[ -n "$(which mkfile)" ]]; then
len="$(stat -f %z ${file})"
if [[ "$(compare_human_readable_nums ${len} ${size})" -lt "0" ]]; then
mkfile -n "${size}" "${file}"
fi
else
_fx-extend-generic "${file}" "${size}"
fi
;;
Linux)
len="$(stat --format=%s ${file})"
if [[ "$(compare_human_readable_nums ${len} ${size})" -lt "0" ]]; then
truncate -s "${size}" "${file}"
fi
;;
*)
_fx-extend-generic "${file}" "${size}"
;;
esac
return $?
}
fx-need-mtools() {
for tool in "mmd" "mcopy"; do
if ! which "${tool}" >&1 > /dev/null; then
echo >&2 "Tool \"${tool}\" not found. You may need to install GNU mtools"
return 1
fi
done
}