Merge changes I1f55c6e1,Ib2adcf0a
am: 395131df7b
Change-Id: Ib0b871e1982828016cefc71976a0e5421388d004
This commit is contained in:
commit
4a9a08183e
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
@ -31,14 +32,20 @@ namespace base {
|
|||
// otherwise valid values will be rejected. Returns boolean success; 'out'
|
||||
// is untouched if parsing fails.
|
||||
template <typename T>
|
||||
bool ParseUint(const char* s, T* out,
|
||||
T max = std::numeric_limits<T>::max()) {
|
||||
bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
|
||||
bool allow_suffixes = false) {
|
||||
int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
|
||||
errno = 0;
|
||||
char* end;
|
||||
unsigned long long int result = strtoull(s, &end, base);
|
||||
if (errno != 0 || s == end || *end != '\0') {
|
||||
return false;
|
||||
if (errno != 0 || end == s) return false;
|
||||
if (*end != '\0') {
|
||||
const char* suffixes = "bkmgtpe";
|
||||
const char* suffix;
|
||||
if (!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) return false;
|
||||
#if __clang__ // TODO: win32 still builds with GCC :-(
|
||||
if (__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) return false;
|
||||
#endif
|
||||
}
|
||||
if (max < result) {
|
||||
return false;
|
||||
|
@ -49,9 +56,20 @@ bool ParseUint(const char* s, T* out,
|
|||
|
||||
// TODO: string_view
|
||||
template <typename T>
|
||||
bool ParseUint(const std::string& s, T* out,
|
||||
T max = std::numeric_limits<T>::max()) {
|
||||
return ParseUint(s.c_str(), out, max);
|
||||
bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
|
||||
bool allow_suffixes = false) {
|
||||
return ParseUint(s.c_str(), out, max, allow_suffixes);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
|
||||
return ParseUint(s, out, max, true);
|
||||
}
|
||||
|
||||
// TODO: string_view
|
||||
template <typename T>
|
||||
bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
|
||||
return ParseByteCount(s.c_str(), out, max);
|
||||
}
|
||||
|
||||
// Parses the signed decimal integer in the string 's' and sets 'out' to
|
||||
|
|
|
@ -96,3 +96,44 @@ TEST(parseint, untouched_on_failure) {
|
|||
ASSERT_FALSE(android::base::ParseInt("456x", &u));
|
||||
ASSERT_EQ(123u, u);
|
||||
}
|
||||
|
||||
TEST(parseint, ParseByteCount) {
|
||||
uint64_t i = 0;
|
||||
ASSERT_TRUE(android::base::ParseByteCount("123b", &i));
|
||||
ASSERT_EQ(123ULL, i);
|
||||
|
||||
ASSERT_TRUE(android::base::ParseByteCount("8k", &i));
|
||||
ASSERT_EQ(8ULL * 1024, i);
|
||||
|
||||
ASSERT_TRUE(android::base::ParseByteCount("8M", &i));
|
||||
ASSERT_EQ(8ULL * 1024 * 1024, i);
|
||||
|
||||
ASSERT_TRUE(android::base::ParseByteCount("6g", &i));
|
||||
ASSERT_EQ(6ULL * 1024 * 1024 * 1024, i);
|
||||
|
||||
ASSERT_TRUE(android::base::ParseByteCount("1T", &i));
|
||||
ASSERT_EQ(1ULL * 1024 * 1024 * 1024 * 1024, i);
|
||||
|
||||
ASSERT_TRUE(android::base::ParseByteCount("2p", &i));
|
||||
ASSERT_EQ(2ULL * 1024 * 1024 * 1024 * 1024 * 1024, i);
|
||||
|
||||
ASSERT_TRUE(android::base::ParseByteCount("4e", &i));
|
||||
ASSERT_EQ(4ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, i);
|
||||
}
|
||||
|
||||
TEST(parseint, ParseByteCount_invalid_suffix) {
|
||||
unsigned u;
|
||||
ASSERT_FALSE(android::base::ParseByteCount("1x", &u));
|
||||
}
|
||||
|
||||
TEST(parseint, ParseByteCount_overflow) {
|
||||
uint64_t u64;
|
||||
ASSERT_FALSE(android::base::ParseByteCount("4294967295E", &u64));
|
||||
|
||||
uint16_t u16;
|
||||
ASSERT_TRUE(android::base::ParseByteCount("63k", &u16));
|
||||
ASSERT_EQ(63U * 1024, u16);
|
||||
ASSERT_TRUE(android::base::ParseByteCount("65535b", &u16));
|
||||
ASSERT_EQ(65535U, u16);
|
||||
ASSERT_FALSE(android::base::ParseByteCount("65k", &u16));
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ static bool g_long_listing = false;
|
|||
// libsparse will support INT_MAX, but this results in large allocations, so
|
||||
// let's keep it at 1GB to avoid memory pressure on the host.
|
||||
static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024;
|
||||
static int64_t sparse_limit = -1;
|
||||
static uint64_t sparse_limit = 0;
|
||||
static int64_t target_sparse_limit = -1;
|
||||
|
||||
static unsigned g_base_addr = 0x10000000;
|
||||
|
@ -375,7 +375,7 @@ static int show_help() {
|
|||
" -w Wipe userdata.\n"
|
||||
" -s SERIAL Specify a USB device.\n"
|
||||
" -s tcp|udp:HOST[:PORT] Specify a network device.\n"
|
||||
" -S SIZE[K|M|G] Use sparse files above this limit (0 to disable).\n"
|
||||
" -S SIZE[K|M|G] Break into sparse files no larger than SIZE.\n"
|
||||
" --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n"
|
||||
" non-current slot (default: current active slot).\n"
|
||||
" --set-active[=SLOT] Sets the active slot before rebooting.\n"
|
||||
|
@ -730,13 +730,10 @@ static int64_t get_target_sparse_limit(Transport* transport) {
|
|||
}
|
||||
|
||||
static int64_t get_sparse_limit(Transport* transport, int64_t size) {
|
||||
int64_t limit;
|
||||
|
||||
if (sparse_limit == 0) {
|
||||
return 0;
|
||||
} else if (sparse_limit > 0) {
|
||||
limit = sparse_limit;
|
||||
} else {
|
||||
int64_t limit = sparse_limit;
|
||||
if (limit == 0) {
|
||||
// Unlimited, so see what the target device's limit is.
|
||||
// TODO: shouldn't we apply this limit even if you've used -S?
|
||||
if (target_sparse_limit == -1) {
|
||||
target_sparse_limit = get_target_sparse_limit(transport);
|
||||
}
|
||||
|
@ -1197,47 +1194,6 @@ static void do_oem_command(const std::string& cmd, std::vector<std::string>* arg
|
|||
fb_queue_command(command, "");
|
||||
}
|
||||
|
||||
static int64_t parse_num(const char *arg)
|
||||
{
|
||||
char *endptr;
|
||||
unsigned long long num;
|
||||
|
||||
num = strtoull(arg, &endptr, 0);
|
||||
if (endptr == arg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*endptr == 'k' || *endptr == 'K') {
|
||||
if (num >= (-1ULL) / 1024) {
|
||||
return -1;
|
||||
}
|
||||
num *= 1024LL;
|
||||
endptr++;
|
||||
} else if (*endptr == 'm' || *endptr == 'M') {
|
||||
if (num >= (-1ULL) / (1024 * 1024)) {
|
||||
return -1;
|
||||
}
|
||||
num *= 1024LL * 1024LL;
|
||||
endptr++;
|
||||
} else if (*endptr == 'g' || *endptr == 'G') {
|
||||
if (num >= (-1ULL) / (1024 * 1024 * 1024)) {
|
||||
return -1;
|
||||
}
|
||||
num *= 1024LL * 1024LL * 1024LL;
|
||||
endptr++;
|
||||
}
|
||||
|
||||
if (*endptr != '\0') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (num > INT64_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static std::string fb_fix_numeric_var(std::string var) {
|
||||
// Some bootloaders (angler, for example), send spurious leading whitespace.
|
||||
var = android::base::Trim(var);
|
||||
|
@ -1471,8 +1427,9 @@ int FastBoot::Main(int argc, char* argv[]) {
|
|||
serial = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
sparse_limit = parse_num(optarg);
|
||||
if (sparse_limit < 0) die("invalid sparse limit");
|
||||
if (!android::base::ParseByteCount(optarg, &sparse_limit)) {
|
||||
die("invalid sparse limit %s", optarg);
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
set_verbose();
|
||||
|
|
Loading…
Reference in New Issue