blob: 53b78f9730ea9594a4dec3ca8f1ca047dd3a7100 [file] [log] [blame]
Dees_Troy7d15c252012-09-05 20:47:21 -04001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <assert.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <limits.h>
21#include <paths.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <unistd.h>
29
30#include <ctype.h>
31#include "cutils/misc.h"
32#include "cutils/properties.h"
33#include <dirent.h>
34#include <getopt.h>
35#include <linux/input.h>
36#include <signal.h>
37#include <sys/limits.h>
38#include <termios.h>
39#include <time.h>
40#include <sys/vfs.h>
41
42#include "../tw_reboot.h"
43#include "../bootloader.h"
44#include "../common.h"
45#include "gui-functions.h"
46#include "cutils/properties.h"
47#include "../install.h"
48#include "../minuitwrp/minui.h"
49#include "../minzip/DirUtil.h"
50#include "../minzip/Zip.h"
51#include "../recovery_ui.h"
52#include "../roots.h"
53#include "../data.h"
54#include "../variables.h"
55
56//kang system() from bionic/libc/unistd and rename it __system() so we can be even more hackish :)
57#undef _PATH_BSHELL
58#define _PATH_BSHELL "/sbin/sh"
59
60static const char *SIDELOAD_TEMP_DIR = "/tmp/sideload";
61extern char **environ;
62
63int __system(const char *command) {
64 pid_t pid;
65 sig_t intsave, quitsave;
66 sigset_t mask, omask;
67 int pstat;
68 char *argp[] = {"sh", "-c", NULL, NULL};
69
70 if (!command) /* just checking... */
71 return(1);
72
73 argp[2] = (char *)command;
74
75 sigemptyset(&mask);
76 sigaddset(&mask, SIGCHLD);
77 sigprocmask(SIG_BLOCK, &mask, &omask);
78 switch (pid = vfork()) {
79 case -1: /* error */
80 sigprocmask(SIG_SETMASK, &omask, NULL);
81 return(-1);
82 case 0: /* child */
83 sigprocmask(SIG_SETMASK, &omask, NULL);
84 execve(_PATH_BSHELL, argp, environ);
85 _exit(127);
86 }
87
88 intsave = (sig_t) bsd_signal(SIGINT, SIG_IGN);
89 quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
90 pid = waitpid(pid, (int *)&pstat, 0);
91 sigprocmask(SIG_SETMASK, &omask, NULL);
92 (void)bsd_signal(SIGINT, intsave);
93 (void)bsd_signal(SIGQUIT, quitsave);
94 return (pid == -1 ? -1 : pstat);
95}
96
97static struct pid {
98 struct pid *next;
99 FILE *fp;
100 pid_t pid;
101} *pidlist;
102
103FILE *__popen(const char *program, const char *type) {
104 struct pid * volatile cur;
105 FILE *iop;
106 int pdes[2];
107 pid_t pid;
108
109 if ((*type != 'r' && *type != 'w') || type[1] != '\0') {
110 errno = EINVAL;
111 return (NULL);
112 }
113
114 if ((cur = malloc(sizeof(struct pid))) == NULL)
115 return (NULL);
116
117 if (pipe(pdes) < 0) {
118 free(cur);
119 return (NULL);
120 }
121
122 switch (pid = vfork()) {
123 case -1: /* Error. */
124 (void)close(pdes[0]);
125 (void)close(pdes[1]);
126 free(cur);
127 return (NULL);
128 /* NOTREACHED */
129 case 0: /* Child. */
130 {
131 struct pid *pcur;
132 /*
133 * because vfork() instead of fork(), must leak FILE *,
134 * but luckily we are terminally headed for an execl()
135 */
136 for (pcur = pidlist; pcur; pcur = pcur->next)
137 close(fileno(pcur->fp));
138
139 if (*type == 'r') {
140 int tpdes1 = pdes[1];
141
142 (void) close(pdes[0]);
143 /*
144 * We must NOT modify pdes, due to the
145 * semantics of vfork.
146 */
147 if (tpdes1 != STDOUT_FILENO) {
148 (void)dup2(tpdes1, STDOUT_FILENO);
149 (void)close(tpdes1);
150 tpdes1 = STDOUT_FILENO;
151 }
152 } else {
153 (void)close(pdes[1]);
154 if (pdes[0] != STDIN_FILENO) {
155 (void)dup2(pdes[0], STDIN_FILENO);
156 (void)close(pdes[0]);
157 }
158 }
159 execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL);
160 _exit(127);
161 /* NOTREACHED */
162 }
163 }
164
165 /* Parent; assume fdopen can't fail. */
166 if (*type == 'r') {
167 iop = fdopen(pdes[0], type);
168 (void)close(pdes[1]);
169 } else {
170 iop = fdopen(pdes[1], type);
171 (void)close(pdes[0]);
172 }
173
174 /* Link into list of file descriptors. */
175 cur->fp = iop;
176 cur->pid = pid;
177 cur->next = pidlist;
178 pidlist = cur;
179
180 return (iop);
181}
182
183/*
184 * pclose --
185 * Pclose returns -1 if stream is not associated with a `popened' command,
186 * if already `pclosed', or waitpid returns an error.
187 */
188int __pclose(FILE *iop) {
189 struct pid *cur, *last;
190 int pstat;
191 pid_t pid;
192
193 /* Find the appropriate file pointer. */
194 for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
195 if (cur->fp == iop)
196 break;
197
198 if (cur == NULL)
199 return (-1);
200
201 (void)fclose(iop);
202
203 do {
204 pid = waitpid(cur->pid, &pstat, 0);
205 } while (pid == -1 && errno == EINTR);
206
207 /* Remove the entry from the linked list. */
208 if (last == NULL)
209 pidlist = cur->next;
210 else
211 last->next = cur->next;
212 free(cur);
213
214 return (pid == -1 ? -1 : pstat);
215}
216
217char* sanitize_device_id(char* id) {
218 const char* whitelist ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-._";
219 char* c = id;
220 char* str = (int*) calloc(50, sizeof *id);
221 while (*c)
222 {
223 if (strchr(whitelist, *c))
224 {
225 strncat(str, c, 1);
226 }
227 c++;
228 }
229 return str;
230}
231
232#define CMDLINE_SERIALNO "androidboot.serialno="
233#define CMDLINE_SERIALNO_LEN (strlen(CMDLINE_SERIALNO))
234#define CPUINFO_SERIALNO "Serial"
235#define CPUINFO_SERIALNO_LEN (strlen(CPUINFO_SERIALNO))
236#define CPUINFO_HARDWARE "Hardware"
237#define CPUINFO_HARDWARE_LEN (strlen(CPUINFO_HARDWARE))
238
239char* get_path (char* path) {
240 char *s;
241
242 /* Go to the end of the string. */
243 s = path + strlen(path) - 1;
244
245 /* Strip off trailing /s (unless it is also the leading /). */
246 while (path < s && s[0] == '/')
247 s--;
248
249 /* Strip the last component. */
250 while (path <= s && s[0] != '/')
251 s--;
252
253 while (path < s && s[0] == '/')
254 s--;
255
256 if (s < path)
257 return ".";
258
259 s[1] = '\0';
260 return path;
261}
262
263char* basename(char* name) {
264 const char* base;
265 for (base = name; *name; name++)
266 {
267 if(*name == '/')
268 {
269 base = name + 1;
270 }
271 }
272 return (char *) base;
273}
274
275/*
276 Checks md5 for a path
277 Return values:
278 -1 : MD5 does not exist
279 0 : Failed
280 1 : Success
281*/
282int check_md5(char* path) {
283 int o;
284 char cmd[PATH_MAX + 30];
285 char md5file[PATH_MAX + 40];
286 strcpy(md5file, path);
287 strcat(md5file, ".md5");
288 char dirpath[PATH_MAX];
289 char* file;
290 if (access(md5file, F_OK ) != -1) {
291 strcpy(dirpath, md5file);
292 get_path(dirpath);
293 chdir(dirpath);
294 file = basename(md5file);
295 sprintf(cmd, "/sbin/busybox md5sum -c '%s'", file);
296 FILE * cs = __popen(cmd, "r");
297 char cs_s[PATH_MAX + 50];
298 fgets(cs_s, PATH_MAX + 50, cs);
299 char* OK = strstr(cs_s, "OK");
300 if (OK != NULL) {
301 printf("MD5 is good. returning 1\n");
302 o = 1;
303 }
304 else {
305 printf("MD5 is bad. return -2\n");
306 o = -2;
307 }
308
309 __pclose(cs);
310 }
311 else {
312 //No md5 file
313 printf("setting o to -1\n");
314 o = -1;
315 }
316
317 return o;
318}
319
320static void set_sdcard_update_bootloader_message() {
321 struct bootloader_message boot;
322 memset(&boot, 0, sizeof(boot));
323 strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
324 strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
325 set_bootloader_message(&boot);
326}
327
328static char* copy_sideloaded_package(const char* original_path) {
329 if (ensure_path_mounted(original_path) != 0) {
330 LOGE("Can't mount %s\n", original_path);
331 return NULL;
332 }
333
334 if (ensure_path_mounted(SIDELOAD_TEMP_DIR) != 0) {
335 LOGE("Can't mount %s\n", SIDELOAD_TEMP_DIR);
336 return NULL;
337 }
338
339 if (mkdir(SIDELOAD_TEMP_DIR, 0700) != 0) {
340 if (errno != EEXIST) {
341 LOGE("Can't mkdir %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
342 return NULL;
343 }
344 }
345
346 // verify that SIDELOAD_TEMP_DIR is exactly what we expect: a
347 // directory, owned by root, readable and writable only by root.
348 struct stat st;
349 if (stat(SIDELOAD_TEMP_DIR, &st) != 0) {
350 LOGE("failed to stat %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
351 return NULL;
352 }
353 if (!S_ISDIR(st.st_mode)) {
354 LOGE("%s isn't a directory\n", SIDELOAD_TEMP_DIR);
355 return NULL;
356 }
357 if ((st.st_mode & 0777) != 0700) {
358 LOGE("%s has perms %o\n", SIDELOAD_TEMP_DIR, st.st_mode);
359 return NULL;
360 }
361 if (st.st_uid != 0) {
362 LOGE("%s owned by %lu; not root\n", SIDELOAD_TEMP_DIR, st.st_uid);
363 return NULL;
364 }
365
366 char copy_path[PATH_MAX];
367 strcpy(copy_path, SIDELOAD_TEMP_DIR);
368 strcat(copy_path, "/package.zip");
369
370 char* buffer = malloc(BUFSIZ);
371 if (buffer == NULL) {
372 LOGE("Failed to allocate buffer\n");
373 return NULL;
374 }
375
376 size_t read;
377 FILE* fin = fopen(original_path, "rb");
378 if (fin == NULL) {
379 LOGE("Failed to open %s (%s)\n", original_path, strerror(errno));
380 return NULL;
381 }
382 FILE* fout = fopen(copy_path, "wb");
383 if (fout == NULL) {
384 LOGE("Failed to open %s (%s)\n", copy_path, strerror(errno));
385 return NULL;
386 }
387
388 while ((read = fread(buffer, 1, BUFSIZ, fin)) > 0) {
389 if (fwrite(buffer, 1, read, fout) != read) {
390 LOGE("Short write of %s (%s)\n", copy_path, strerror(errno));
391 return NULL;
392 }
393 }
394
395 free(buffer);
396
397 if (fclose(fout) != 0) {
398 LOGE("Failed to close %s (%s)\n", copy_path, strerror(errno));
399 return NULL;
400 }
401
402 if (fclose(fin) != 0) {
403 LOGE("Failed to close %s (%s)\n", original_path, strerror(errno));
404 return NULL;
405 }
406
407 // "adb push" is happy to overwrite read-only files when it's
408 // running as root, but we'll try anyway.
409 if (chmod(copy_path, 0400) != 0) {
410 LOGE("Failed to chmod %s (%s)\n", copy_path, strerror(errno));
411 return NULL;
412 }
413
414 return strdup(copy_path);
415}
416
417int install_zip_package(const char* zip_path_filename) {
418 int result = 0;
419
420 //mount_current_storage();
421 int md5_req = DataManager_GetIntValue(TW_FORCE_MD5_CHECK_VAR);
422 if (md5_req == 1) {
423 ui_print("\n-- Verify md5 for %s", zip_path_filename);
424 int md5chk = check_md5((char*) zip_path_filename);
425 if (md5chk == 1) {
426 ui_print("\n-- Md5 verified, continue");
427 result = 0;
428 }
429 else if (md5chk == -1) {
430 if (md5_req == 1) {
431 ui_print("\n-- No md5 file found!");
432 ui_print("\n-- Aborting install");
433 result = INSTALL_ERROR;
434 }
435 else {
436 ui_print("\n-- No md5 file found, ignoring");
437 }
438 }
439 else if (md5chk == -2) {
440 ui_print("\n-- md5 file doesn't match!");
441 ui_print("\n-- Aborting install");
442 result = INSTALL_ERROR;
443 }
444 printf("%d\n", result);
445 }
446 if (result != INSTALL_ERROR) {
447 ui_print("\n-- Install %s ...\n", zip_path_filename);
448 set_sdcard_update_bootloader_message();
449 char* copy;
450 if (DataManager_GetIntValue(TW_FLASH_ZIP_IN_PLACE) == 1 && strlen(zip_path_filename) > 6 && strncmp(zip_path_filename, "/cache", 6) != 0) {
451 copy = strdup(zip_path_filename);
452 } else {
453 copy = copy_sideloaded_package(zip_path_filename);
454 //unmount_current_storage();
455 }
456 if (copy) {
457 result = really_install_package(copy, 0);
458 free(copy);
459 //update_system_details();
460 } else {
461 result = INSTALL_ERROR;
462 }
463 }
464 //mount_current_storage();
465 //finish_recovery(NULL);
466 return result;
467}
468
469//partial kangbang from system/vold
470#ifndef CUSTOM_LUN_FILE
471#define CUSTOM_LUN_FILE "/sys/devices/platform/usb_mass_storage/lun%d/file"
472#endif
473
474int usb_storage_enable(void)
475{
476 int fd;
477 char lun_file[255];
478
479 if (DataManager_GetIntValue(TW_HAS_DUAL_STORAGE) == 1 && DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 0) {
480 Volume *vol = volume_for_path(DataManager_GetSettingsStoragePath());
481 if (!vol)
482 {
483 LOGE("Unable to locate volume information.");
484 return -1;
485 }
486
487 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
488
489 if ((fd = open(lun_file, O_WRONLY)) < 0)
490 {
491 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
492 return -1;
493 }
494
495 if ((write(fd, vol->device, strlen(vol->device)) < 0) &&
496 (!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) {
497 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
498 close(fd);
499 return -1;
500 }
501 close(fd);
502
503 Volume *vol2 = volume_for_path(DataManager_GetStrValue(TW_EXTERNAL_PATH));
504 if (!vol)
505 {
506 LOGE("Unable to locate volume information.\n");
507 return -1;
508 }
509
510 sprintf(lun_file, CUSTOM_LUN_FILE, 1);
511
512 if ((fd = open(lun_file, O_WRONLY)) < 0)
513 {
514 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
515 return -1;
516 }
517
518 if ((write(fd, vol2->device, strlen(vol2->device)) < 0) &&
519 (!vol2->device2 || (write(fd, vol2->device, strlen(vol2->device2)) < 0))) {
520 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
521 close(fd);
522 return -1;
523 }
524 close(fd);
525 } else {
526 if (DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 0)
527 strcpy(lun_file, DataManager_GetCurrentStoragePath());
528 else
529 strcpy(lun_file, DataManager_GetStrValue(TW_EXTERNAL_PATH));
530
531 Volume *vol = volume_for_path(lun_file);
532 if (!vol)
533 {
534 LOGE("Unable to locate volume information.\n");
535 return -1;
536 }
537
538 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
539
540 if ((fd = open(lun_file, O_WRONLY)) < 0)
541 {
542 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
543 return -1;
544 }
545
546 if ((write(fd, vol->device, strlen(vol->device)) < 0) &&
547 (!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) {
548 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
549 close(fd);
550 return -1;
551 }
552 close(fd);
553 }
554 return 0;
555}
556
557int usb_storage_disable(void)
558{
559 int fd, index;
560 char lun_file[255];
561
562 for (index=0; index<2; index++) {
563 sprintf(lun_file, CUSTOM_LUN_FILE, index);
564
565 if ((fd = open(lun_file, O_WRONLY)) < 0)
566 {
567 if (index == 0)
568 LOGE("Unable to open ums lunfile '%s': (%s)", lun_file, strerror(errno));
569 return -1;
570 }
571
572 char ch = 0;
573 if (write(fd, &ch, 1) < 0)
574 {
575 if (index == 0)
576 LOGE("Unable to write to ums lunfile '%s': (%s)", lun_file, strerror(errno));
577 close(fd);
578 return -1;
579 }
580
581 close(fd);
582 }
583 return 0;
584}
585
586void wipe_dalvik_cache()
587{
588 //ui_set_background(BACKGROUND_ICON_WIPE);
589 ensure_path_mounted("/data");
590 ensure_path_mounted("/cache");
591 ui_print("\n-- Wiping Dalvik Cache Directories...\n");
592 __system("rm -rf /data/dalvik-cache");
593 ui_print("Cleaned: /data/dalvik-cache...\n");
594 __system("rm -rf /cache/dalvik-cache");
595 ui_print("Cleaned: /cache/dalvik-cache...\n");
596 __system("rm -rf /cache/dc");
597 ui_print("Cleaned: /cache/dc\n");
598
599 struct stat st;
600 LOGE("TODO: Re-implement wipe dalvik into Partition Manager!\n");
601 if (1) //if (0 != stat(sde.blk, &st))
602 {
603 ui_print("/sd-ext not present, skipping\n");
604 } else {
605 __system("mount /sd-ext");
606 LOGI("Mounting /sd-ext\n");
607 if (stat("/sd-ext/dalvik-cache",&st) == 0)
608 {
609 __system("rm -rf /sd-ext/dalvik-cache");
610 ui_print("Cleaned: /sd-ext/dalvik-cache...\n");
611 }
612 }
613 ensure_path_unmounted("/data");
614 ui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
615 //ui_set_background(BACKGROUND_ICON_MAIN);
616 //if (!ui_text_visible()) return;
617}
618
619// BATTERY STATS
620void wipe_battery_stats()
621{
622 ensure_path_mounted("/data");
623 struct stat st;
624 if (0 != stat("/data/system/batterystats.bin", &st))
625 {
626 ui_print("No Battery Stats Found. No Need To Wipe.\n");
627 } else {
628 //ui_set_background(BACKGROUND_ICON_WIPE);
629 remove("/data/system/batterystats.bin");
630 ui_print("Cleared: Battery Stats...\n");
631 ensure_path_unmounted("/data");
632 }
633}
634
635// ROTATION SETTINGS
636void wipe_rotate_data()
637{
638 //ui_set_background(BACKGROUND_ICON_WIPE);
639 ensure_path_mounted("/data");
640 __system("rm -r /data/misc/akmd*");
641 __system("rm -r /data/misc/rild*");
642 ui_print("Cleared: Rotatation Data...\n");
643 ensure_path_unmounted("/data");
644}
645
646void fix_perms()
647{
648 ensure_path_mounted("/data");
649 ensure_path_mounted("/system");
650 //ui_show_progress(1,30);
651 ui_print("\n-- Fixing Permissions\n");
652 ui_print("This may take a few minutes.\n");
653 __system("./sbin/fix_permissions.sh");
654 ui_print("-- Done.\n\n");
655 //ui_reset_progress();
656}
657
658int get_battery_level(void)
659{
660 static int lastVal = -1;
661 static time_t nextSecCheck = 0;
662
663 struct timeval curTime;
664 gettimeofday(&curTime, NULL);
665 if (curTime.tv_sec > nextSecCheck)
666 {
667 char cap_s[4];
668 FILE * cap = fopen("/sys/class/power_supply/battery/capacity","rt");
669 if (cap)
670 {
671 fgets(cap_s, 4, cap);
672 fclose(cap);
673 lastVal = atoi(cap_s);
674 if (lastVal > 100) lastVal = 101;
675 if (lastVal < 0) lastVal = 0;
676 }
677 nextSecCheck = curTime.tv_sec + 60;
678 }
679 return lastVal;
680}
681
682char*
683print_batt_cap() {
684 char* full_cap_s = (char*)malloc(30);
685 char full_cap_a[30];
686
687 int cap_i = get_battery_level();
688
689 //int len = strlen(cap_s);
690 //if (cap_s[len-1] == '\n') {
691 // cap_s[len-1] = 0;
692 //}
693
694 // Get a usable time
695 struct tm *current;
696 time_t now;
697 now = time(0);
698 current = localtime(&now);
699
700 sprintf(full_cap_a, "Battery Level: %i%% @ %02D:%02D", cap_i, current->tm_hour, current->tm_min);
701 strcpy(full_cap_s, full_cap_a);
702
703 return full_cap_s;
704}
705
706void update_tz_environment_variables() {
707 setenv("TZ", DataManager_GetStrValue(TW_TIME_ZONE_VAR), 1);
708 tzset();
709}
710
711void run_script(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5, const char *str6, const char *str7, int request_confirm)
712{
713 ui_print("%s", str1);
714 //ui_clear_key_queue();
715 ui_print("\nPress Power to confirm,");
716 ui_print("\nany other key to abort.\n");
717 int confirm;
718 /*if (request_confirm) // this option is used to skip the confirmation when the gui is in use
719 confirm = ui_wait_key();
720 else*/
721 confirm = KEY_POWER;
722
723 if (confirm == BTN_MOUSE || confirm == KEY_POWER || confirm == SELECT_ITEM) {
724 ui_print("%s", str2);
725 pid_t pid = fork();
726 if (pid == 0) {
727 char *args[] = { "/sbin/sh", "-c", (char*)str3, "1>&2", NULL };
728 execv("/sbin/sh", args);
729 fprintf(stderr, str4, strerror(errno));
730 _exit(-1);
731 }
732 int status;
733 while (waitpid(pid, &status, WNOHANG) == 0) {
734 ui_print(".");
735 sleep(1);
736 }
737 ui_print("\n");
738 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
739 ui_print("%s", str5);
740 } else {
741 ui_print("%s", str6);
742 }
743 } else {
744 ui_print("%s", str7);
745 }
746 //if (!ui_text_visible()) return;
747}
748
749void install_htc_dumlock(void)
750{
751 struct statfs fs1, fs2;
752 int need_libs = 0;
753
754 ui_print("Installing HTC Dumlock to system...\n");
755 ensure_path_mounted("/system");
756 __system("cp /res/htcd/htcdumlocksys /system/bin/htcdumlock && chmod 755 /system/bin/htcdumlock");
757 if (statfs("/system/bin/flash_image", &fs1) != 0) {
758 ui_print("Installing flash_image...\n");
759 __system("cp /res/htcd/flash_imagesys /system/bin/flash_image && chmod 755 /system/bin/flash_image");
760 need_libs = 1;
761 } else
762 ui_print("flash_image is already installed, skipping...\n");
763 if (statfs("/system/bin/dump_image", &fs2) != 0) {
764 ui_print("Installing dump_image...\n");
765 __system("cp /res/htcd/dump_imagesys /system/bin/dump_image && chmod 755 /system/bin/dump_image");
766 need_libs = 1;
767 } else
768 ui_print("dump_image is already installed, skipping...\n");
769 if (need_libs) {
770 ui_print("Installing libs needed for flash_image and dump_image...\n");
771 __system("cp /res/htcd/libbmlutils.so /system/lib && chmod 755 /system/lib/libbmlutils.so");
772 __system("cp /res/htcd/libflashutils.so /system/lib && chmod 755 /system/lib/libflashutils.so");
773 __system("cp /res/htcd/libmmcutils.so /system/lib && chmod 755 /system/lib/libmmcutils.so");
774 __system("cp /res/htcd/libmtdutils.so /system/lib && chmod 755 /system/lib/libmtdutils.so");
775 }
776 ui_print("Installing HTC Dumlock app...\n");
777 ensure_path_mounted("/data");
778 mkdir("/data/app", 0777);
779 __system("rm /data/app/com.teamwin.htcdumlock*");
780 __system("cp /res/htcd/HTCDumlock.apk /data/app/com.teamwin.htcdumlock.apk");
781 sync();
782 ui_print("HTC Dumlock is installed.\n");
783}
784
785void htc_dumlock_restore_original_boot(void)
786{
787 ui_print("Restoring original boot...\n");
788 __system("htcdumlock restore");
789 ui_print("Original boot restored.\n");
790}
791
792void htc_dumlock_reflash_recovery_to_boot(void)
793{
794 ui_print("Reflashing recovery to boot...\n");
795 __system("htcdumlock recovery noreboot");
796 ui_print("Recovery is flashed to boot.\n");
797}
798
799void check_and_run_script(const char* script_file, const char* display_name)
800{
801 // Check for and run startup script if script exists
802 struct statfs st;
803 if (statfs(script_file, &st) == 0) {
804 ui_print("Running %s script...\n", display_name);
805 char command[255];
806 strcpy(command, "chmod 755 ");
807 strcat(command, script_file);
808 __system(command);
809 __system(script_file);
810 ui_print("\nFinished running %s script.\n", display_name);
811 }
812}
813
814int check_backup_name(int show_error) {
815 // Check the backup name to ensure that it is the correct size and contains only valid characters
816 // and that a backup with that name doesn't already exist
817 char backup_name[MAX_BACKUP_NAME_LEN];
818 char backup_loc[255], tw_image_dir[255];
819 int copy_size = strlen(DataManager_GetStrValue(TW_BACKUP_NAME));
820 int index, cur_char;
821 struct statfs st;
822
823 // Check size
824 if (copy_size > MAX_BACKUP_NAME_LEN) {
825 if (show_error)
826 LOGE("Backup name is too long.\n");
827 return -2;
828 }
829
830 // Check characters
831 strncpy(backup_name, DataManager_GetStrValue(TW_BACKUP_NAME), copy_size);
832 if (strcmp(backup_name, "0") == 0)
833 return 0; // A "0" (zero) means to use the current timestamp for the backup name
834 for (index=0; index<copy_size; index++) {
835 cur_char = (int)backup_name[index];
836 if ((cur_char >= 48 && cur_char <= 57) || (cur_char >= 65 && cur_char <= 91) || cur_char == 93 || cur_char == 95 || (cur_char >= 97 && cur_char <= 123) || cur_char == 125 || cur_char == 45 || cur_char == 46) {
837 // These are valid characters
838 // Numbers
839 // Upper case letters
840 // Lower case letters
841 // and -_.{}[]
842 } else {
843 if (show_error)
844 LOGE("Backup name '%s' contains invalid character: '%c'\n", backup_name, (char)cur_char);
845 return -3;
846 }
847 }
848
849 // Check to make sure that a backup with this name doesn't already exist
850 strcpy(backup_loc, DataManager_GetStrValue(TW_BACKUPS_FOLDER_VAR));
851 sprintf(tw_image_dir,"%s/%s/.", backup_loc, backup_name);
852 if (statfs(tw_image_dir, &st) == 0) {
853 if (show_error)
854 LOGE("A backup with this name already exists.\n");
855 return -4;
856 }
857
858 // No problems found, return 0
859 return 0;
860}