No Description

restore.cpp 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdarg.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <unistd.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #include <dirent.h>
  10. #include <sys/vfs.h>
  11. #include <cutils/properties.h>
  12. #include <lib/libtar.h>
  13. #include <zlib.h>
  14. #include <fs_mgr.h>
  15. #include "roots.h"
  16. #include "bu.h"
  17. using namespace android;
  18. static int verify_sod()
  19. {
  20. const char* key;
  21. char value[PROPERTY_VALUE_MAX];
  22. char sodbuf[PROP_LINE_LEN*10];
  23. size_t len;
  24. len = sizeof(sodbuf);
  25. if (tar_extract_file_contents(tar, sodbuf, &len) != 0) {
  26. logmsg("tar_verify_sod: failed to extract file\n");
  27. return -1;
  28. }
  29. char val_hashname[PROPERTY_VALUE_MAX];
  30. memset(val_hashname, 0, sizeof(val_hashname));
  31. char val_product[PROPERTY_VALUE_MAX];
  32. memset(val_product, 0, sizeof(val_product));
  33. char* p = sodbuf;
  34. char* q;
  35. while ((q = strchr(p, '\n')) != NULL) {
  36. char* key = p;
  37. *q = '\0';
  38. logmsg("verify_sod: line=%s\n", p);
  39. p = q+1;
  40. char* val = strchr(key, '=');
  41. if (val) {
  42. *val = '\0';
  43. ++val;
  44. if (strcmp(key, "hash.name") == 0) {
  45. strncpy(val_hashname, val, sizeof(val_hashname));
  46. }
  47. if (strcmp(key, "ro.product.device") == 0) {
  48. strncpy(val_product, val, sizeof(val_product));
  49. }
  50. if (strncmp(key, "fs.", 3) == 0) {
  51. char* name = key+3;
  52. char* attr = strchr(name, '.');
  53. if (attr) {
  54. *attr = '\0';
  55. ++attr;
  56. part_add(name);
  57. struct partspec* part = part_find(name);
  58. if (!strcmp(attr, "size")) {
  59. part->size = strtoul(val, NULL, 0);
  60. }
  61. if (!strcmp(attr, "used")) {
  62. part->used = strtoul(val, NULL, 0);
  63. }
  64. }
  65. }
  66. }
  67. }
  68. if (!val_hashname[0]) {
  69. logmsg("verify_sod: did not find hash.name\n");
  70. return -1;
  71. }
  72. hash_name = strdup(val_hashname);
  73. if (!val_product[0]) {
  74. logmsg("verify_sod: did not find ro.product.device\n");
  75. return -1;
  76. }
  77. key = "ro.product.device";
  78. property_get(key, value, "");
  79. if (strcmp(val_product, value) != 0) {
  80. logmsg("verify_sod: product does not match\n");
  81. return -1;
  82. }
  83. return 0;
  84. }
  85. static int verify_eod(size_t actual_hash_datalen,
  86. SHA_CTX* actual_sha_ctx, MD5_CTX* actual_md5_ctx)
  87. {
  88. int rc = -1;
  89. char eodbuf[PROP_LINE_LEN*10];
  90. size_t len;
  91. len = sizeof(eodbuf);
  92. if (tar_extract_file_contents(tar, eodbuf, &len) != 0) {
  93. logmsg("verify_eod: failed to extract file\n");
  94. return -1;
  95. }
  96. size_t reported_datalen = 0;
  97. char reported_hash[HASH_MAX_STRING_LENGTH];
  98. memset(reported_hash, 0, sizeof(reported_hash));
  99. char* p = eodbuf;
  100. char* q;
  101. while ((q = strchr(p, '\n')) != NULL) {
  102. char* key = p;
  103. *q = '\0';
  104. logmsg("verify_eod: line=%s\n", p);
  105. p = q+1;
  106. char* val = strchr(key, '=');
  107. if (val) {
  108. *val = '\0';
  109. ++val;
  110. if (strcmp(key, "hash.datalen") == 0) {
  111. reported_datalen = strtoul(val, NULL, 0);
  112. }
  113. if (strcmp(key, "hash.value") == 0) {
  114. memset(reported_hash, 0, sizeof(reported_hash));
  115. strncpy(reported_hash, val, sizeof(reported_hash));
  116. }
  117. }
  118. }
  119. unsigned char digest[HASH_MAX_LENGTH];
  120. char hexdigest[HASH_MAX_STRING_LENGTH];
  121. int n;
  122. if (hash_name != NULL && !strcasecmp(hash_name, "sha1")) {
  123. SHA1_Final(digest, actual_sha_ctx);
  124. for (n = 0; n < SHA_DIGEST_LENGTH; ++n) {
  125. sprintf(hexdigest+2*n, "%02x", digest[n]);
  126. }
  127. }
  128. else { // default to md5
  129. MD5_Final(digest, actual_md5_ctx);
  130. for (n = 0; n < MD5_DIGEST_LENGTH; ++n) {
  131. sprintf(hexdigest+2*n, "%02x", digest[n]);
  132. }
  133. }
  134. logmsg("verify_eod: expected=%d,%s\n", actual_hash_datalen, hexdigest);
  135. logmsg("verify_eod: reported=%d,%s\n", reported_datalen, reported_hash);
  136. if ((reported_datalen == actual_hash_datalen) &&
  137. (memcmp(hexdigest, reported_hash, strlen(hexdigest)) == 0)) {
  138. rc = 0;
  139. }
  140. return rc;
  141. }
  142. int do_restore(int argc, char **argv)
  143. {
  144. int rc = 0;
  145. ssize_t len;
  146. const char* compress = "none";
  147. char buf[512];
  148. len = recv(adb_ifd, buf, sizeof(buf), MSG_PEEK);
  149. if (len < 0) {
  150. logmsg("do_restore: peek failed (%d:%s)\n", rc, strerror(errno));
  151. return -1;
  152. }
  153. if (len < 2) {
  154. logmsg("do_restore: peek returned %d\n", len);
  155. return -1;
  156. }
  157. if (buf[0] == 0x1f && buf[1] == 0x8b) {
  158. logmsg("do_restore: is gzip\n");
  159. compress = "gzip";
  160. }
  161. create_tar(adb_ifd, compress, "r");
  162. size_t save_hash_datalen;
  163. SHA_CTX save_sha_ctx;
  164. MD5_CTX save_md5_ctx;
  165. while (1) {
  166. save_hash_datalen = hash_datalen;
  167. memcpy(&save_sha_ctx, &sha_ctx, sizeof(SHA_CTX));
  168. memcpy(&save_md5_ctx, &md5_ctx, sizeof(MD5_CTX));
  169. rc = th_read(tar);
  170. if (rc != 0) {
  171. if (rc == 1) { // EOF
  172. rc = 0;
  173. }
  174. break;
  175. }
  176. char* pathname = th_get_pathname(tar);
  177. logmsg("do_restore: extract %s\n", pathname);
  178. if (!strcmp(pathname, "SOD")) {
  179. rc = verify_sod();
  180. logmsg("do_restore: tar_verify_sod returned %d\n", rc);
  181. }
  182. else if (!strcmp(pathname, "EOD")) {
  183. rc = verify_eod(save_hash_datalen, &save_sha_ctx, &save_md5_ctx);
  184. logmsg("do_restore: tar_verify_eod returned %d\n", rc);
  185. }
  186. else {
  187. char mnt[PATH_MAX];
  188. snprintf(mnt, sizeof(mnt), "/%s", pathname);
  189. Volume* vol = volume_for_mount_point(mnt);
  190. if (vol != NULL && vol->fs_type != NULL) {
  191. partspec* curpart = part_find(pathname);
  192. part_set(curpart);
  193. rc = tar_extract_file(tar, vol->blk_device);
  194. }
  195. else {
  196. logmsg("do_restore: cannot find volume for %s\n", mnt);
  197. }
  198. }
  199. free(pathname);
  200. if (rc != 0) {
  201. logmsg("do_restore: extract failed, rc=%d\n", rc);
  202. break;
  203. }
  204. }
  205. tar_close(tar);
  206. logmsg("do_restore: rc=%d\n", rc);
  207. free(hash_name);
  208. hash_name = NULL;
  209. return rc;
  210. }