diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp index a0e990a85..63e89714a 100644 --- a/fastboot/engine.cpp +++ b/fastboot/engine.cpp @@ -75,41 +75,35 @@ static Action *action_last = 0; -int fb_getvar(struct usb_handle *usb, char *response, const char *fmt, ...) -{ - char cmd[CMD_SIZE] = "getvar:"; - int getvar_len = strlen(cmd); - va_list args; +bool fb_getvar(usb_handle* usb, const std::string& key, std::string* value) { + std::string cmd = "getvar:"; + cmd += key; - response[FB_RESPONSE_SZ] = '\0'; - va_start(args, fmt); - vsnprintf(cmd + getvar_len, sizeof(cmd) - getvar_len, fmt, args); - va_end(args); - cmd[CMD_SIZE - 1] = '\0'; - return fb_command_response(usb, cmd, response); + char buf[FB_RESPONSE_SZ + 1]; + memset(buf, 0, sizeof(buf)); + if (fb_command_response(usb, cmd.c_str(), buf)) { + return false; + } + *value = buf; + return true; } -/* Return true if this partition is supported by the fastboot format command. - * It is also used to determine if we should first erase a partition before - * flashing it with an ext4 filesystem. See needs_erase() - * - * Not all devices report the filesystem type, so don't report any errors, - * just return false. - */ -int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override) -{ - char fs_type[FB_RESPONSE_SZ + 1] = {0,}; - int status; - +// Return true if this partition is supported by the fastboot format command. +// It is also used to determine if we should first erase a partition before +// flashing it with an ext4 filesystem. See needs_erase() +// +// Not all devices report the filesystem type, so don't report any errors, +// just return false. +bool fb_format_supported(usb_handle *usb, const char *partition, const char *type_override) { if (type_override) { - return !!fs_get_generator(type_override); + return fs_get_generator(type_override) != nullptr; } - status = fb_getvar(usb, fs_type, "partition-type:%s", partition); - if (status) { - return 0; + std::string partition_type; + if (!fb_getvar(usb, std::string("partition-type:") + partition, &partition_type)) { + return false; } - return !!fs_get_generator(fs_type); + return fs_get_generator(partition_type.c_str()) != nullptr; } static int cb_default(Action* a, int status, const char* resp) { @@ -394,8 +388,3 @@ int fb_execute_queue(usb_handle *usb) fprintf(stderr,"finished. total time: %.3fs\n", (now() - start)); return status; } - -int fb_queue_is_empty(void) -{ - return (action_list == nullptr); -} diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index e2971f252..7bf4b3162 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -567,25 +568,23 @@ static struct sparse_file **load_sparse_files(int fd, int max_size) return out_s; } -static int64_t get_target_sparse_limit(struct usb_handle *usb) -{ - int64_t limit = 0; - char response[FB_RESPONSE_SZ + 1]; - int status = fb_getvar(usb, response, "max-download-size"); - - if (!status) { - limit = strtoul(response, nullptr, 0); - if (limit > 0) { - fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", - limit); - } +static int64_t get_target_sparse_limit(usb_handle* usb) { + std::string max_download_size; + if (!fb_getvar(usb, "max-download-size", &max_download_size)) { + return 0; } + uint64_t limit; + if (!android::base::ParseUint(max_download_size.c_str(), &limit)) { + return 0; + } + if (limit > 0) { + fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n", limit); + } return limit; } -static int64_t get_sparse_limit(struct usb_handle *usb, int64_t size) -{ +static int64_t get_sparse_limit(usb_handle* usb, int64_t size) { int64_t limit; if (sparse_limit == 0) { @@ -610,16 +609,11 @@ static int64_t get_sparse_limit(struct usb_handle *usb, int64_t size) return 0; } -/* Until we get lazy inode table init working in make_ext4fs, we need to - * erase partitions of type ext4 before flashing a filesystem so no stale - * inodes are left lying around. Otherwise, e2fsck gets very upset. - */ -static int needs_erase(usb_handle* usb, const char *part) -{ - /* The function fb_format_supported() currently returns the value - * we want, so just call it. - */ - return fb_format_supported(usb, part, nullptr); +// Until we get lazy inode table init working in make_ext4fs, we need to +// erase partitions of type ext4 before flashing a filesystem so no stale +// inodes are left lying around. Otherwise, e2fsck gets very upset. +static bool needs_erase(usb_handle* usb, const char* part) { + return !fb_format_supported(usb, part, nullptr); } static int load_buf_fd(usb_handle* usb, int fd, struct fastboot_buffer* buf) { @@ -852,87 +846,84 @@ static int64_t parse_num(const char *arg) } static void fb_perform_format(usb_handle* usb, - const char *partition, int skip_if_not_supported, - const char *type_override, const char *size_override) { - char pTypeBuff[FB_RESPONSE_SZ + 1], pSizeBuff[FB_RESPONSE_SZ + 1]; - char *pType = pTypeBuff; - char *pSize = pSizeBuff; - unsigned int limit = INT_MAX; + const char* partition, int skip_if_not_supported, + const char* type_override, const char* size_override) { + std::string partition_type, partition_size; + struct fastboot_buffer buf; - const char *errMsg = nullptr; - const struct fs_generator *gen; - uint64_t pSz; - int status; + const char* errMsg = nullptr; + const struct fs_generator* gen = nullptr; int fd; - if (target_sparse_limit > 0 && target_sparse_limit < limit) + unsigned int limit = INT_MAX; + if (target_sparse_limit > 0 && target_sparse_limit < limit) { limit = target_sparse_limit; - if (sparse_limit > 0 && sparse_limit < limit) + } + if (sparse_limit > 0 && sparse_limit < limit) { limit = sparse_limit; + } - status = fb_getvar(usb, pType, "partition-type:%s", partition); - if (status) { + if (!fb_getvar(usb, std::string("partition-type:") + partition, &partition_type)) { errMsg = "Can't determine partition type.\n"; goto failed; } if (type_override) { - if (strcmp(type_override, pType)) { - fprintf(stderr, - "Warning: %s type is %s, but %s was requested for formating.\n", - partition, pType, type_override); + if (partition_type != type_override) { + fprintf(stderr, "Warning: %s type is %s, but %s was requested for formatting.\n", + partition, partition_type.c_str(), type_override); } - pType = (char *)type_override; + partition_type = type_override; } - status = fb_getvar(usb, pSize, "partition-size:%s", partition); - if (status) { + if (!fb_getvar(usb, std::string("partition-size:") + partition, &partition_size)) { errMsg = "Unable to get partition size\n"; goto failed; } if (size_override) { - if (strcmp(size_override, pSize)) { - fprintf(stderr, - "Warning: %s size is %s, but %s was requested for formating.\n", - partition, pSize, size_override); + if (partition_size != size_override) { + fprintf(stderr, "Warning: %s size is %s, but %s was requested for formatting.\n", + partition, partition_size.c_str(), size_override); } - pSize = (char *)size_override; + partition_size = size_override; } - gen = fs_get_generator(pType); + gen = fs_get_generator(partition_type.c_str()); if (!gen) { if (skip_if_not_supported) { fprintf(stderr, "Erase successful, but not automatically formatting.\n"); - fprintf(stderr, "File system type %s not supported.\n", pType); + fprintf(stderr, "File system type %s not supported.\n", partition_type.c_str()); return; } - fprintf(stderr, "Formatting is not supported for filesystem with type '%s'.\n", pType); + fprintf(stderr, "Formatting is not supported for file system with type '%s'.\n", + partition_type.c_str()); return; } - pSz = strtoll(pSize, (char **)nullptr, 16); + int64_t size; + if (!android::base::ParseInt(partition_size.c_str(), &size)) { + fprintf(stderr, "Couldn't parse partition size '%s'.\n", partition_size.c_str()); + return; + } fd = fileno(tmpfile()); - if (fs_generator_generate(gen, fd, pSz)) { + if (fs_generator_generate(gen, fd, size)) { + fprintf(stderr, "Cannot generate image: %s\n", strerror(errno)); close(fd); - fprintf(stderr, "Cannot generate image.\n"); return; } if (load_buf_fd(usb, fd, &buf)) { - fprintf(stderr, "Cannot read image.\n"); + fprintf(stderr, "Cannot read image: %s\n", strerror(errno)); close(fd); return; } flash_buf(partition, &buf); - return; - failed: if (skip_if_not_supported) { fprintf(stderr, "Erase successful, but not automatically formatting.\n"); - if (errMsg) - fprintf(stderr, "%s", errMsg); + if (errMsg) fprintf(stderr, "%s", errMsg); } fprintf(stderr,"FAILED (%s)\n", fb_get_error()); } @@ -945,8 +936,6 @@ int main(int argc, char **argv) bool erase_first = true; void *data; int64_t sz; - int status; - int c; int longindex; const struct option longopts[] = { @@ -964,7 +953,7 @@ int main(int argc, char **argv) serial = getenv("ANDROID_SERIAL"); while (1) { - c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:h", longopts, &longindex); + int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:h", longopts, &longindex); if (c < 0) { break; } @@ -1061,14 +1050,14 @@ int main(int argc, char **argv) usb_handle* usb = open_device(); while (argc > 0) { - if(!strcmp(*argv, "getvar")) { + if (!strcmp(*argv, "getvar")) { require(2); fb_queue_display(argv[1], argv[1]); skip(2); } else if(!strcmp(*argv, "erase")) { require(2); - if (fb_format_supported(usb, argv[1], nullptr)) { + if (!fb_format_supported(usb, argv[1], nullptr)) { fprintf(stderr, "******** Did you mean to fastboot format this partition?\n"); } @@ -1217,10 +1206,16 @@ int main(int argc, char **argv) } if (wants_wipe) { + fprintf(stderr, "wiping userdata...\n"); fb_queue_erase("userdata"); fb_perform_format(usb, "userdata", 1, nullptr, nullptr); - fb_queue_erase("cache"); - fb_perform_format(usb, "cache", 1, nullptr, nullptr); + + std::string cache_type; + if (fb_getvar(usb, "partition-type:cache", &cache_type) && !cache_type.empty()) { + fprintf(stderr, "wiping cache...\n"); + fb_queue_erase("cache"); + fb_perform_format(usb, "cache", 1, nullptr, nullptr); + } } if (wants_reboot) { fb_queue_reboot(); @@ -1230,9 +1225,5 @@ int main(int argc, char **argv) fb_queue_wait_for_disconnect(); } - if (fb_queue_is_empty()) - return 0; - - status = fb_execute_queue(usb); - return (status) ? 1 : 0; + return fb_execute_queue(usb) ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h index 091a70f58..a66c21198 100644 --- a/fastboot/fastboot.h +++ b/fastboot/fastboot.h @@ -32,6 +32,8 @@ #include #include +#include + #include "usb.h" struct sparse_file; @@ -47,8 +49,8 @@ char *fb_get_error(void); #define FB_RESPONSE_SZ 64 /* engine.c - high level command queue engine */ -int fb_getvar(struct usb_handle *usb, char *response, const char *fmt, ...); -int fb_format_supported(usb_handle *usb, const char *partition, const char *type_override); +bool fb_getvar(usb_handle* usb, const std::string& key, std::string* value); +bool fb_format_supported(usb_handle* usb, const char* partition, const char* type_override); void fb_queue_flash(const char *ptn, void *data, uint32_t sz); void fb_queue_flash_sparse(const char *ptn, struct sparse_file *s, uint32_t sz); void fb_queue_erase(const char *ptn); @@ -63,7 +65,6 @@ void fb_queue_download(const char *name, void *data, uint32_t size); void fb_queue_notice(const char *notice); void fb_queue_wait_for_disconnect(void); int fb_execute_queue(usb_handle *usb); -int fb_queue_is_empty(void); /* util stuff */ double now();