最近客戶反饋,編譯32位的android系統,在recovery中執行恢復出廠設置的時候失敗了,失敗的打印提升信息如下。
Formatting /data...
[ 2.191404] E:get_file_size: invalid size -1289764864 for /dev/block/data [ 2.207430] Data wipe failed.
根據打印提示,意識是說獲取data分區的size是無效的。我們來看看這個函數get_file_size bootable/recovery/roots.cpp
static ssize_t get_file_size(int fd, uint64_t reserve_len) { struct stat buf; int ret = fstat(fd, &buf); if (ret) return 0; ssize_t computed_size; if (S_ISREG(buf.st_mode)) { computed_size = buf.st_size - reserve_len; } else if (S_ISBLK(buf.st_mode)) { computed_size = get_block_device_size(fd) - reserve_len; } else { computed_size = 0; } return computed_size; }
這個ssize_t是跟系統的位數相關的,當時32位的系統時,ssize_t的大小為U32, 那么此時能夠表示的最大的長度為2^32-1=4294967295=4095.99M=4G 也就是說,當時32位的系統時,ssize_t能夠保存的最大值為4G,當data分區的大小超過4G的時候, ssize_t就無法正常保存的獲取的data分區的大小,那么也就會出錯了。
而實際項目上面給data分區的大小為11G+, 那么自然就會出錯了,我們把使用ssize_t的地方換成uint64_t即可 patch如下:
diff --git a/roots.cpp b/roots.cpp
index 25d9d7e..5197ccb 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -182,12 +182,12 @@ static int exec_cmd(const char* path, char* const argv[]) {
return WEXITSTATUS(status);
}
-static ssize_t get_file_size(int fd, uint64_t reserve_len) {
+static uint64_t get_file_size(int fd, uint64_t reserve_len) {
struct stat buf;
int ret = fstat(fd, &buf);
if (ret) return 0;
- ssize_t computed_size;
+ uint64_t computed_size;
if (S_ISREG(buf.st_mode)) {
computed_size = buf.st_size - reserve_len;
} else if (S_ISBLK(buf.st_mode)) {
@@ -234,7 +234,7 @@ int format_volume(const char* volume, const char* directory) {
close(fd);
}
- ssize_t length = 0;
+ uint64_t length = 0;
if (v->length != 0) {
length = v->length;
} else if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0) {
到此,問題解決。