No Description

bu.cpp 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  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 <cutils/log.h>
  13. #include <selinux/label.h>
  14. #include <fs_mgr.h>
  15. #include "roots.h"
  16. #include "bu.h"
  17. #define PATHNAME_RC "/tmp/burc"
  18. #define PATHNAME_XCOMP_ENABLE "/sys/fs/xcomp/enable"
  19. using namespace std;
  20. using namespace android;
  21. struct selabel_handle *sehandle;
  22. int adb_ifd;
  23. int adb_ofd;
  24. TAR* tar;
  25. gzFile gzf;
  26. char* hash_name;
  27. size_t hash_datalen;
  28. SHA_CTX sha_ctx;
  29. MD5_CTX md5_ctx;
  30. void
  31. ui_print(const char* format, ...) {
  32. char buffer[256];
  33. va_list ap;
  34. va_start(ap, format);
  35. vsnprintf(buffer, sizeof(buffer), format, ap);
  36. va_end(ap);
  37. fputs(buffer, stdout);
  38. }
  39. void logmsg(const char *fmt, ...)
  40. {
  41. char msg[1024];
  42. FILE* fp;
  43. va_list ap;
  44. va_start(ap, fmt);
  45. vsnprintf(msg, sizeof(msg), fmt, ap);
  46. va_end(ap);
  47. fp = fopen("/tmp/bu.log", "a");
  48. if (fp) {
  49. fprintf(fp, "[%d] %s", getpid(), msg);
  50. fclose(fp);
  51. }
  52. }
  53. static int xcomp_enable_get(void)
  54. {
  55. int val = 0;
  56. int fd;
  57. char buf[12+1+1];
  58. fd = open(PATHNAME_XCOMP_ENABLE, O_RDONLY);
  59. if (fd < 0)
  60. return 0;
  61. memset(buf, 0, sizeof(buf));
  62. if (read(fd, buf, sizeof(buf)) > 0) {
  63. val = atoi(buf);
  64. }
  65. close(fd);
  66. return val;
  67. }
  68. static void xcomp_enable_set(int val)
  69. {
  70. int fd;
  71. char buf[12+1+1];
  72. int len;
  73. fd = open(PATHNAME_XCOMP_ENABLE, O_RDWR);
  74. if (fd < 0)
  75. return;
  76. len = sprintf(buf, "%d\n", val);
  77. write(fd, buf, len);
  78. close(fd);
  79. }
  80. static partspec partlist[MAX_PART];
  81. static partspec* curpart;
  82. int part_add(const char* name)
  83. {
  84. Volume* vol = NULL;
  85. char* path = NULL;
  86. int i;
  87. path = (char*)malloc(1+strlen(name)+1);
  88. sprintf(path, "/%s", name);
  89. vol = volume_for_mount_point(path);
  90. if (vol == NULL || vol->fs_type == NULL) {
  91. logmsg("missing vol info for %s, ignoring\n", name);
  92. goto err;
  93. }
  94. for (i = 0; i < MAX_PART; ++i) {
  95. if (partlist[i].name == NULL) {
  96. partlist[i].name = strdup(name);
  97. partlist[i].path = path;
  98. partlist[i].vol = vol;
  99. logmsg("part_add: i=%d, name=%s, path=%s\n", i, name, path);
  100. return 0;
  101. }
  102. if (strcmp(partlist[i].name, name) == 0) {
  103. logmsg("duplicate partition %s, ignoring\n", name);
  104. goto err;
  105. }
  106. }
  107. err:
  108. free(path);
  109. return -1;
  110. }
  111. partspec* part_get(int i)
  112. {
  113. if (i >= 0 && i < MAX_PART) {
  114. if (partlist[i].name != NULL) {
  115. return &partlist[i];
  116. }
  117. }
  118. return NULL;
  119. }
  120. partspec* part_find(const char* name)
  121. {
  122. for (int i = 0; i < MAX_PART; ++i) {
  123. if (partlist[i].name && !strcmp(name, partlist[i].name)) {
  124. return &partlist[i];
  125. }
  126. }
  127. return NULL;
  128. }
  129. void part_set(partspec* part)
  130. {
  131. curpart = part;
  132. curpart->off = 0;
  133. }
  134. int update_progress(uint64_t off)
  135. {
  136. static time_t last_time = 0;
  137. static int last_pct = 0;
  138. if (curpart) {
  139. curpart->off += off;
  140. time_t now = time(NULL);
  141. int pct = min(100, (int)((uint64_t)100*curpart->off/curpart->used));
  142. if (now != last_time && pct != last_pct) {
  143. char msg[256];
  144. sprintf(msg, "%s: %d%% complete", curpart->name, pct);
  145. ui_print(msg);
  146. last_time = now;
  147. last_pct = pct;
  148. }
  149. }
  150. return 0;
  151. }
  152. static int tar_cb_open(const char* path, int mode, ...)
  153. {
  154. errno = EINVAL;
  155. return -1;
  156. }
  157. static int tar_cb_close(int fd)
  158. {
  159. return 0;
  160. }
  161. static ssize_t tar_cb_read(int fd, void* buf, size_t len)
  162. {
  163. ssize_t nread;
  164. nread = ::read(fd, buf, len);
  165. if (nread > 0 && hash_name) {
  166. SHA1_Update(&sha_ctx, (u_char*)buf, nread);
  167. MD5_Update(&md5_ctx, buf, nread);
  168. hash_datalen += nread;
  169. }
  170. update_progress(nread);
  171. return nread;
  172. }
  173. static ssize_t tar_cb_write(int fd, const void* buf, size_t len)
  174. {
  175. ssize_t written = 0;
  176. if (hash_name) {
  177. SHA1_Update(&sha_ctx, (u_char*)buf, len);
  178. MD5_Update(&md5_ctx, buf, len);
  179. hash_datalen += len;
  180. }
  181. while (len > 0) {
  182. ssize_t n = ::write(fd, buf, len);
  183. if (n < 0) {
  184. logmsg("tar_cb_write: error: n=%d\n", n);
  185. return n;
  186. }
  187. if (n == 0)
  188. break;
  189. buf = (const char *)buf + n;
  190. len -= n;
  191. written += n;
  192. }
  193. update_progress(written);
  194. return written;
  195. }
  196. static tartype_t tar_io = {
  197. tar_cb_open,
  198. tar_cb_close,
  199. tar_cb_read,
  200. tar_cb_write
  201. };
  202. static ssize_t tar_gz_cb_read(int fd, void* buf, size_t len)
  203. {
  204. int nread;
  205. nread = gzread(gzf, buf, len);
  206. if (nread > 0 && hash_name) {
  207. SHA1_Update(&sha_ctx, (u_char*)buf, nread);
  208. MD5_Update(&md5_ctx, buf, nread);
  209. hash_datalen += nread;
  210. }
  211. update_progress(nread);
  212. return nread;
  213. }
  214. static ssize_t tar_gz_cb_write(int fd, const void* buf, size_t len)
  215. {
  216. ssize_t written = 0;
  217. if (hash_name) {
  218. SHA1_Update(&sha_ctx, (u_char*)buf, len);
  219. MD5_Update(&md5_ctx, buf, len);
  220. hash_datalen += len;
  221. }
  222. while (len > 0) {
  223. ssize_t n = gzwrite(gzf, buf, len);
  224. if (n < 0) {
  225. logmsg("tar_gz_cb_write: error: n=%d\n", n);
  226. return n;
  227. }
  228. if (n == 0)
  229. break;
  230. buf = (const char *)buf + n;
  231. len -= n;
  232. written += n;
  233. }
  234. update_progress(written);
  235. return written;
  236. }
  237. static tartype_t tar_io_gz = {
  238. tar_cb_open,
  239. tar_cb_close,
  240. tar_gz_cb_read,
  241. tar_gz_cb_write
  242. };
  243. int create_tar(int fd, const char* compress, const char* mode)
  244. {
  245. int rc = -1;
  246. SHA1_Init(&sha_ctx);
  247. MD5_Init(&md5_ctx);
  248. if (!compress || strcasecmp(compress, "none") == 0) {
  249. rc = tar_fdopen(&tar, fd, "foobar", &tar_io,
  250. 0, /* oflags: unused */
  251. 0, /* mode: unused */
  252. TAR_GNU | TAR_STORE_SELINUX /* options */);
  253. }
  254. else if (strcasecmp(compress, "gzip") == 0) {
  255. gzf = gzdopen(fd, mode);
  256. if (gzf != NULL) {
  257. rc = tar_fdopen(&tar, 0, "foobar", &tar_io_gz,
  258. 0, /* oflags: unused */
  259. 0, /* mode: unused */
  260. TAR_GNU | TAR_STORE_SELINUX /* options */);
  261. }
  262. }
  263. return rc;
  264. }
  265. static void do_exit(int rc)
  266. {
  267. char rcstr[80];
  268. int len;
  269. len = sprintf(rcstr, "%d\n", rc);
  270. unlink(PATHNAME_RC);
  271. int fd = open(PATHNAME_RC, O_RDWR|O_CREAT, 0644);
  272. write(fd, rcstr, len);
  273. close(fd);
  274. exit(rc);
  275. }
  276. int main(int argc, char **argv)
  277. {
  278. int rc = 1;
  279. int xcomp_enable;
  280. const char* logfile = "/tmp/recovery.log";
  281. adb_ifd = dup(STDIN_FILENO);
  282. adb_ofd = dup(STDOUT_FILENO);
  283. freopen(logfile, "a", stdout); setbuf(stdout, NULL);
  284. freopen(logfile, "a", stderr); setbuf(stderr, NULL);
  285. logmsg("bu: invoked with %d args\n", argc);
  286. if (argc < 2) {
  287. logmsg("Not enough args (%d)\n", argc);
  288. do_exit(1);
  289. }
  290. // progname args...
  291. int optidx = 1;
  292. const char* opname = argv[optidx++];
  293. struct selinux_opt seopts[] = {
  294. { SELABEL_OPT_PATH, "/file_contexts" }
  295. };
  296. sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
  297. xcomp_enable = xcomp_enable_get();
  298. xcomp_enable_set(0);
  299. load_volume_table();
  300. if (!strcmp(opname, "backup")) {
  301. ui_print("Backup in progress...");
  302. rc = do_backup(argc-optidx, &argv[optidx]);
  303. }
  304. else if (!strcmp(opname, "restore")) {
  305. ui_print("Restore in progress...");
  306. rc = do_restore(argc-optidx, &argv[optidx]);
  307. }
  308. else {
  309. logmsg("Unknown operation %s\n", opname);
  310. rc = 1;
  311. }
  312. xcomp_enable_set(xcomp_enable);
  313. close(adb_ofd);
  314. close(adb_ifd);
  315. sleep(1);
  316. logmsg("bu exiting\n");
  317. do_exit(rc);
  318. return rc;
  319. }