blob: cf93052f1ff0ee878d8e5beb498dbaa1ab9740c3 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -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 "extra-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
239void get_device_id() {
240 FILE *fp;
241 char line[2048];
242 char hardware_id[32];
243 char* token;
244 char* new_device_id;
245
246 // Assign a blank device_id to start with
247 device_id[0] = 0;
248
249 // First, try the cmdline to see if the serial number was supplied
250 fp = fopen("/proc/cmdline", "rt");
251 if (fp != NULL)
252 {
253 // First step, read the line. For cmdline, it's one long line
254 fgets(line, sizeof(line), fp);
255 fclose(fp);
256
257 // Now, let's tokenize the string
258 token = strtok(line, " ");
259
260 // Let's walk through the line, looking for the CMDLINE_SERIALNO token
261 while (token)
262 {
263 // We don't need to verify the length of token, because if it's too short, it will mismatch CMDLINE_SERIALNO at the NULL
264 if (memcmp(token, CMDLINE_SERIALNO, CMDLINE_SERIALNO_LEN) == 0)
265 {
266 // We found the serial number!
267 strcpy(device_id, token + CMDLINE_SERIALNO_LEN);
268 new_device_id = sanitize_device_id(device_id);
269 strcpy(device_id, new_device_id);
270 free(new_device_id);
271 return;
272 }
273 token = strtok(NULL, " ");
274 }
275 }
276
277 // Now we'll try cpuinfo for a serial number
278 fp = fopen("/proc/cpuinfo", "rt");
279 if (fp != NULL)
280 {
281 while (fgets(line, sizeof(line), fp) != NULL) { // First step, read the line.
282 if (memcmp(line, CPUINFO_SERIALNO, CPUINFO_SERIALNO_LEN) == 0) // check the beginning of the line for "Serial"
283 {
284 // We found the serial number!
285 token = line + CPUINFO_SERIALNO_LEN; // skip past "Serial"
286 while ((*token > 0 && *token <= 32 ) || *token == ':') token++; // skip over all spaces and the colon
287 if (*token != 0) {
288 token[30] = 0;
289 if (token[strlen(token)-1] == 10) { // checking for endline chars and dropping them from the end of the string if needed
290 memset(device_id, 0, sizeof(device_id));
291 strncpy(device_id, token, strlen(token) - 1);
292 } else {
293 strcpy(device_id, token);
294 }
295 LOGI("=> serial from cpuinfo: '%s'\n", device_id);
296 fclose(fp);
297 new_device_id = sanitize_device_id(device_id);
298 strcpy(device_id, new_device_id);
299 free(new_device_id);
300 return;
301 }
302 } else if (memcmp(line, CPUINFO_HARDWARE, CPUINFO_HARDWARE_LEN) == 0) {// We're also going to look for the hardware line in cpuinfo and save it for later in case we don't find the device ID
303 // We found the hardware ID
304 token = line + CPUINFO_HARDWARE_LEN; // skip past "Hardware"
305 while ((*token > 0 && *token <= 32 ) || *token == ':') token++; // skip over all spaces and the colon
306 if (*token != 0) {
307 token[30] = 0;
308 if (token[strlen(token)-1] == 10) { // checking for endline chars and dropping them from the end of the string if needed
309 memset(hardware_id, 0, sizeof(hardware_id));
310 strncpy(hardware_id, token, strlen(token) - 1);
311 } else {
312 strcpy(hardware_id, token);
313 }
314 LOGI("=> hardware id from cpuinfo: '%s'\n", hardware_id);
315 }
316 }
317 }
318 fclose(fp);
319 }
320
321 if (hardware_id[0] != 0) {
322 LOGW("\nusing hardware id for device id: '%s'\n", hardware_id);
323 strcpy(device_id, hardware_id);
324 new_device_id = sanitize_device_id(device_id);
325 strcpy(device_id, new_device_id);
326 free(new_device_id);
327 return;
328 }
329
330 strcpy(device_id, "serialno");
331 LOGE("=> device id not found, using '%s'.", device_id);
332 return;
333}
334
335char* get_path (char* path) {
336 char *s;
337
338 /* Go to the end of the string. */
339 s = path + strlen(path) - 1;
340
341 /* Strip off trailing /s (unless it is also the leading /). */
342 while (path < s && s[0] == '/')
343 s--;
344
345 /* Strip the last component. */
346 while (path <= s && s[0] != '/')
347 s--;
348
349 while (path < s && s[0] == '/')
350 s--;
351
352 if (s < path)
353 return ".";
354
355 s[1] = '\0';
356 return path;
357}
358
359char* basename(char* name) {
360 const char* base;
361 for (base = name; *name; name++)
362 {
363 if(*name == '/')
364 {
365 base = name + 1;
366 }
367 }
368 return (char *) base;
369}
370
371/*
372 Checks md5 for a path
373 Return values:
374 -1 : MD5 does not exist
375 0 : Failed
376 1 : Success
377*/
378int check_md5(char* path) {
379 int o;
380 char cmd[PATH_MAX + 30];
381 char md5file[PATH_MAX + 40];
382 strcpy(md5file, path);
383 strcat(md5file, ".md5");
384 char dirpath[PATH_MAX];
385 char* file;
386 if (access(md5file, F_OK ) != -1) {
387 strcpy(dirpath, md5file);
388 get_path(dirpath);
389 chdir(dirpath);
390 file = basename(md5file);
391 sprintf(cmd, "/sbin/busybox md5sum -c '%s'", file);
392 FILE * cs = __popen(cmd, "r");
393 char cs_s[PATH_MAX + 50];
394 fgets(cs_s, PATH_MAX + 50, cs);
395 char* OK = strstr(cs_s, "OK");
396 if (OK != NULL) {
397 printf("MD5 is good. returning 1\n");
398 o = 1;
399 }
400 else {
401 printf("MD5 is bad. return -2\n");
402 o = -2;
403 }
404
405 __pclose(cs);
406 }
407 else {
408 //No md5 file
409 printf("setting o to -1\n");
410 o = -1;
411 }
412
413 return o;
414}
415
416static void set_sdcard_update_bootloader_message() {
417 struct bootloader_message boot;
418 memset(&boot, 0, sizeof(boot));
419 strlcpy(boot.command, "boot-recovery", sizeof(boot.command));
420 strlcpy(boot.recovery, "recovery\n", sizeof(boot.recovery));
421 set_bootloader_message(&boot);
422}
423
424static char* copy_sideloaded_package(const char* original_path) {
425 if (ensure_path_mounted(original_path) != 0) {
426 LOGE("Can't mount %s\n", original_path);
427 return NULL;
428 }
429
430 if (ensure_path_mounted(SIDELOAD_TEMP_DIR) != 0) {
431 LOGE("Can't mount %s\n", SIDELOAD_TEMP_DIR);
432 return NULL;
433 }
434
435 if (mkdir(SIDELOAD_TEMP_DIR, 0700) != 0) {
436 if (errno != EEXIST) {
437 LOGE("Can't mkdir %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
438 return NULL;
439 }
440 }
441
442 // verify that SIDELOAD_TEMP_DIR is exactly what we expect: a
443 // directory, owned by root, readable and writable only by root.
444 struct stat st;
445 if (stat(SIDELOAD_TEMP_DIR, &st) != 0) {
446 LOGE("failed to stat %s (%s)\n", SIDELOAD_TEMP_DIR, strerror(errno));
447 return NULL;
448 }
449 if (!S_ISDIR(st.st_mode)) {
450 LOGE("%s isn't a directory\n", SIDELOAD_TEMP_DIR);
451 return NULL;
452 }
453 if ((st.st_mode & 0777) != 0700) {
454 LOGE("%s has perms %o\n", SIDELOAD_TEMP_DIR, st.st_mode);
455 return NULL;
456 }
457 if (st.st_uid != 0) {
458 LOGE("%s owned by %lu; not root\n", SIDELOAD_TEMP_DIR, st.st_uid);
459 return NULL;
460 }
461
462 char copy_path[PATH_MAX];
463 strcpy(copy_path, SIDELOAD_TEMP_DIR);
464 strcat(copy_path, "/package.zip");
465
466 char* buffer = malloc(BUFSIZ);
467 if (buffer == NULL) {
468 LOGE("Failed to allocate buffer\n");
469 return NULL;
470 }
471
472 size_t read;
473 FILE* fin = fopen(original_path, "rb");
474 if (fin == NULL) {
475 LOGE("Failed to open %s (%s)\n", original_path, strerror(errno));
476 return NULL;
477 }
478 FILE* fout = fopen(copy_path, "wb");
479 if (fout == NULL) {
480 LOGE("Failed to open %s (%s)\n", copy_path, strerror(errno));
481 return NULL;
482 }
483
484 while ((read = fread(buffer, 1, BUFSIZ, fin)) > 0) {
485 if (fwrite(buffer, 1, read, fout) != read) {
486 LOGE("Short write of %s (%s)\n", copy_path, strerror(errno));
487 return NULL;
488 }
489 }
490
491 free(buffer);
492
493 if (fclose(fout) != 0) {
494 LOGE("Failed to close %s (%s)\n", copy_path, strerror(errno));
495 return NULL;
496 }
497
498 if (fclose(fin) != 0) {
499 LOGE("Failed to close %s (%s)\n", original_path, strerror(errno));
500 return NULL;
501 }
502
503 // "adb push" is happy to overwrite read-only files when it's
504 // running as root, but we'll try anyway.
505 if (chmod(copy_path, 0400) != 0) {
506 LOGE("Failed to chmod %s (%s)\n", copy_path, strerror(errno));
507 return NULL;
508 }
509
510 return strdup(copy_path);
511}
512
513int install_zip_package(const char* zip_path_filename) {
514 int result = 0;
515
516 //mount_current_storage();
517 int md5_req = DataManager_GetIntValue(TW_FORCE_MD5_CHECK_VAR);
518 if (md5_req == 1) {
519 ui_print("\n-- Verify md5 for %s", zip_path_filename);
520 int md5chk = check_md5((char*) zip_path_filename);
521 if (md5chk == 1) {
522 ui_print("\n-- Md5 verified, continue");
523 result = 0;
524 }
525 else if (md5chk == -1) {
526 if (md5_req == 1) {
527 ui_print("\n-- No md5 file found!");
528 ui_print("\n-- Aborting install");
529 result = INSTALL_ERROR;
530 }
531 else {
532 ui_print("\n-- No md5 file found, ignoring");
533 }
534 }
535 else if (md5chk == -2) {
536 ui_print("\n-- md5 file doesn't match!");
537 ui_print("\n-- Aborting install");
538 result = INSTALL_ERROR;
539 }
540 printf("%d\n", result);
541 }
542 if (result != INSTALL_ERROR) {
543 ui_print("\n-- Install %s ...\n", zip_path_filename);
544 set_sdcard_update_bootloader_message();
545 char* copy;
546 if (DataManager_GetIntValue(TW_FLASH_ZIP_IN_PLACE) == 1 && strlen(zip_path_filename) > 6 && strncmp(zip_path_filename, "/cache", 6) != 0) {
547 copy = strdup(zip_path_filename);
548 } else {
549 copy = copy_sideloaded_package(zip_path_filename);
550 //unmount_current_storage();
551 }
552 if (copy) {
553 result = really_install_package(copy, 0);
554 free(copy);
555 //update_system_details();
556 } else {
557 result = INSTALL_ERROR;
558 }
559 }
560 //mount_current_storage();
561 //finish_recovery(NULL);
562 return result;
563}
564
565//partial kangbang from system/vold
566#ifndef CUSTOM_LUN_FILE
567#define CUSTOM_LUN_FILE "/sys/devices/platform/usb_mass_storage/lun%d/file"
568#endif
569
570int usb_storage_enable(void)
571{
572 int fd;
573 char lun_file[255];
574
575 if (DataManager_GetIntValue(TW_HAS_DUAL_STORAGE) == 1 && DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 0) {
576 Volume *vol = volume_for_path(DataManager_GetSettingsStoragePath());
577 if (!vol)
578 {
579 LOGE("Unable to locate volume information.");
580 return -1;
581 }
582
583 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
584
585 if ((fd = open(lun_file, O_WRONLY)) < 0)
586 {
587 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
588 return -1;
589 }
590
591 if ((write(fd, vol->device, strlen(vol->device)) < 0) &&
592 (!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) {
593 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
594 close(fd);
595 return -1;
596 }
597 close(fd);
598
599 Volume *vol2 = volume_for_path(DataManager_GetStrValue(TW_EXTERNAL_PATH));
600 if (!vol)
601 {
602 LOGE("Unable to locate volume information.\n");
603 return -1;
604 }
605
606 sprintf(lun_file, CUSTOM_LUN_FILE, 1);
607
608 if ((fd = open(lun_file, O_WRONLY)) < 0)
609 {
610 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
611 return -1;
612 }
613
614 if ((write(fd, vol2->device, strlen(vol2->device)) < 0) &&
615 (!vol2->device2 || (write(fd, vol2->device, strlen(vol2->device2)) < 0))) {
616 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
617 close(fd);
618 return -1;
619 }
620 close(fd);
621 } else {
622 if (DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 0)
623 strcpy(lun_file, DataManager_GetCurrentStoragePath());
624 else
625 strcpy(lun_file, DataManager_GetStrValue(TW_EXTERNAL_PATH));
626
627 Volume *vol = volume_for_path(lun_file);
628 if (!vol)
629 {
630 LOGE("Unable to locate volume information.\n");
631 return -1;
632 }
633
634 sprintf(lun_file, CUSTOM_LUN_FILE, 0);
635
636 if ((fd = open(lun_file, O_WRONLY)) < 0)
637 {
638 LOGE("Unable to open ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
639 return -1;
640 }
641
642 if ((write(fd, vol->device, strlen(vol->device)) < 0) &&
643 (!vol->device2 || (write(fd, vol->device, strlen(vol->device2)) < 0))) {
644 LOGE("Unable to write to ums lunfile '%s': (%s)\n", lun_file, strerror(errno));
645 close(fd);
646 return -1;
647 }
648 close(fd);
649 }
650 return 0;
651}
652
653int usb_storage_disable(void)
654{
655 int fd, index;
656 char lun_file[255];
657
658 for (index=0; index<2; index++) {
659 sprintf(lun_file, CUSTOM_LUN_FILE, index);
660
661 if ((fd = open(lun_file, O_WRONLY)) < 0)
662 {
663 if (index == 0)
664 LOGE("Unable to open ums lunfile '%s': (%s)", lun_file, strerror(errno));
665 return -1;
666 }
667
668 char ch = 0;
669 if (write(fd, &ch, 1) < 0)
670 {
671 if (index == 0)
672 LOGE("Unable to write to ums lunfile '%s': (%s)", lun_file, strerror(errno));
673 close(fd);
674 return -1;
675 }
676
677 close(fd);
678 }
679 return 0;
680}
681
682void wipe_dalvik_cache()
683{
684 //ui_set_background(BACKGROUND_ICON_WIPE);
685 ensure_path_mounted("/data");
686 ensure_path_mounted("/cache");
687 ui_print("\n-- Wiping Dalvik Cache Directories...\n");
688 __system("rm -rf /data/dalvik-cache");
689 ui_print("Cleaned: /data/dalvik-cache...\n");
690 __system("rm -rf /cache/dalvik-cache");
691 ui_print("Cleaned: /cache/dalvik-cache...\n");
692 __system("rm -rf /cache/dc");
693 ui_print("Cleaned: /cache/dc\n");
694
695 struct stat st;
696 LOGE("TODO: Re-implement wipe dalvik into Partition Manager!\n");
697 if (1) //if (0 != stat(sde.blk, &st))
698 {
699 ui_print("/sd-ext not present, skipping\n");
700 } else {
701 __system("mount /sd-ext");
702 LOGI("Mounting /sd-ext\n");
703 if (stat("/sd-ext/dalvik-cache",&st) == 0)
704 {
705 __system("rm -rf /sd-ext/dalvik-cache");
706 ui_print("Cleaned: /sd-ext/dalvik-cache...\n");
707 }
708 }
709 ensure_path_unmounted("/data");
710 ui_print("-- Dalvik Cache Directories Wipe Complete!\n\n");
711 //ui_set_background(BACKGROUND_ICON_MAIN);
712 //if (!ui_text_visible()) return;
713}
714
715// BATTERY STATS
716void wipe_battery_stats()
717{
718 ensure_path_mounted("/data");
719 struct stat st;
720 if (0 != stat("/data/system/batterystats.bin", &st))
721 {
722 ui_print("No Battery Stats Found. No Need To Wipe.\n");
723 } else {
724 //ui_set_background(BACKGROUND_ICON_WIPE);
725 remove("/data/system/batterystats.bin");
726 ui_print("Cleared: Battery Stats...\n");
727 ensure_path_unmounted("/data");
728 }
729}
730
731// ROTATION SETTINGS
732void wipe_rotate_data()
733{
734 //ui_set_background(BACKGROUND_ICON_WIPE);
735 ensure_path_mounted("/data");
736 __system("rm -r /data/misc/akmd*");
737 __system("rm -r /data/misc/rild*");
738 ui_print("Cleared: Rotatation Data...\n");
739 ensure_path_unmounted("/data");
740}
741
742void fix_perms()
743{
744 ensure_path_mounted("/data");
745 ensure_path_mounted("/system");
746 //ui_show_progress(1,30);
747 ui_print("\n-- Fixing Permissions\n");
748 ui_print("This may take a few minutes.\n");
749 __system("./sbin/fix_permissions.sh");
750 ui_print("-- Done.\n\n");
751 //ui_reset_progress();
752}
753
754int get_battery_level(void)
755{
756 static int lastVal = -1;
757 static time_t nextSecCheck = 0;
758
759 struct timeval curTime;
760 gettimeofday(&curTime, NULL);
761 if (curTime.tv_sec > nextSecCheck)
762 {
763 char cap_s[4];
764 FILE * cap = fopen("/sys/class/power_supply/battery/capacity","rt");
765 if (cap)
766 {
767 fgets(cap_s, 4, cap);
768 fclose(cap);
769 lastVal = atoi(cap_s);
770 if (lastVal > 100) lastVal = 101;
771 if (lastVal < 0) lastVal = 0;
772 }
773 nextSecCheck = curTime.tv_sec + 60;
774 }
775 return lastVal;
776}
777
778char*
779print_batt_cap() {
780 char* full_cap_s = (char*)malloc(30);
781 char full_cap_a[30];
782
783 int cap_i = get_battery_level();
784
785 //int len = strlen(cap_s);
786 //if (cap_s[len-1] == '\n') {
787 // cap_s[len-1] = 0;
788 //}
789
790 // Get a usable time
791 struct tm *current;
792 time_t now;
793 now = time(0);
794 current = localtime(&now);
795
796 sprintf(full_cap_a, "Battery Level: %i%% @ %02D:%02D", cap_i, current->tm_hour, current->tm_min);
797 strcpy(full_cap_s, full_cap_a);
798
799 return full_cap_s;
800}
801
802void update_tz_environment_variables() {
803 setenv("TZ", DataManager_GetStrValue(TW_TIME_ZONE_VAR), 1);
804 tzset();
805}
806
807void 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)
808{
809 ui_print("%s", str1);
810 //ui_clear_key_queue();
811 ui_print("\nPress Power to confirm,");
812 ui_print("\nany other key to abort.\n");
813 int confirm;
814 /*if (request_confirm) // this option is used to skip the confirmation when the gui is in use
815 confirm = ui_wait_key();
816 else*/
817 confirm = KEY_POWER;
818
819 if (confirm == BTN_MOUSE || confirm == KEY_POWER || confirm == SELECT_ITEM) {
820 ui_print("%s", str2);
821 pid_t pid = fork();
822 if (pid == 0) {
823 char *args[] = { "/sbin/sh", "-c", (char*)str3, "1>&2", NULL };
824 execv("/sbin/sh", args);
825 fprintf(stderr, str4, strerror(errno));
826 _exit(-1);
827 }
828 int status;
829 while (waitpid(pid, &status, WNOHANG) == 0) {
830 ui_print(".");
831 sleep(1);
832 }
833 ui_print("\n");
834 if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
835 ui_print("%s", str5);
836 } else {
837 ui_print("%s", str6);
838 }
839 } else {
840 ui_print("%s", str7);
841 }
842 //if (!ui_text_visible()) return;
843}
844
845void install_htc_dumlock(void)
846{
847 struct statfs fs1, fs2;
848 int need_libs = 0;
849
850 ui_print("Installing HTC Dumlock to system...\n");
851 ensure_path_mounted("/system");
852 __system("cp /res/htcd/htcdumlocksys /system/bin/htcdumlock && chmod 755 /system/bin/htcdumlock");
853 if (statfs("/system/bin/flash_image", &fs1) != 0) {
854 ui_print("Installing flash_image...\n");
855 __system("cp /res/htcd/flash_imagesys /system/bin/flash_image && chmod 755 /system/bin/flash_image");
856 need_libs = 1;
857 } else
858 ui_print("flash_image is already installed, skipping...\n");
859 if (statfs("/system/bin/dump_image", &fs2) != 0) {
860 ui_print("Installing dump_image...\n");
861 __system("cp /res/htcd/dump_imagesys /system/bin/dump_image && chmod 755 /system/bin/dump_image");
862 need_libs = 1;
863 } else
864 ui_print("dump_image is already installed, skipping...\n");
865 if (need_libs) {
866 ui_print("Installing libs needed for flash_image and dump_image...\n");
867 __system("cp /res/htcd/libbmlutils.so /system/lib && chmod 755 /system/lib/libbmlutils.so");
868 __system("cp /res/htcd/libflashutils.so /system/lib && chmod 755 /system/lib/libflashutils.so");
869 __system("cp /res/htcd/libmmcutils.so /system/lib && chmod 755 /system/lib/libmmcutils.so");
870 __system("cp /res/htcd/libmtdutils.so /system/lib && chmod 755 /system/lib/libmtdutils.so");
871 }
872 ui_print("Installing HTC Dumlock app...\n");
873 ensure_path_mounted("/data");
874 mkdir("/data/app", 0777);
875 __system("rm /data/app/com.teamwin.htcdumlock*");
876 __system("cp /res/htcd/HTCDumlock.apk /data/app/com.teamwin.htcdumlock.apk");
877 sync();
878 ui_print("HTC Dumlock is installed.\n");
879}
880
881void htc_dumlock_restore_original_boot(void)
882{
883 ui_print("Restoring original boot...\n");
884 __system("htcdumlock restore");
885 ui_print("Original boot restored.\n");
886}
887
888void htc_dumlock_reflash_recovery_to_boot(void)
889{
890 ui_print("Reflashing recovery to boot...\n");
891 __system("htcdumlock recovery noreboot");
892 ui_print("Recovery is flashed to boot.\n");
893}
894
895void check_and_run_script(const char* script_file, const char* display_name)
896{
897 // Check for and run startup script if script exists
898 struct statfs st;
899 if (statfs(script_file, &st) == 0) {
900 ui_print("Running %s script...\n", display_name);
901 char command[255];
902 strcpy(command, "chmod 755 ");
903 strcat(command, script_file);
904 __system(command);
905 __system(script_file);
906 ui_print("\nFinished running %s script.\n", display_name);
907 }
908}
909
910int check_backup_name(int show_error) {
911 // Check the backup name to ensure that it is the correct size and contains only valid characters
912 // and that a backup with that name doesn't already exist
913 char backup_name[MAX_BACKUP_NAME_LEN];
914 char backup_loc[255], tw_image_dir[255];
915 int copy_size = strlen(DataManager_GetStrValue(TW_BACKUP_NAME));
916 int index, cur_char;
917 struct statfs st;
918
919 // Check size
920 if (copy_size > MAX_BACKUP_NAME_LEN) {
921 if (show_error)
922 LOGE("Backup name is too long.\n");
923 return -2;
924 }
925
926 // Check characters
927 strncpy(backup_name, DataManager_GetStrValue(TW_BACKUP_NAME), copy_size);
928 if (strcmp(backup_name, "0") == 0)
929 return 0; // A "0" (zero) means to use the current timestamp for the backup name
930 for (index=0; index<copy_size; index++) {
931 cur_char = (int)backup_name[index];
932 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) {
933 // These are valid characters
934 // Numbers
935 // Upper case letters
936 // Lower case letters
937 // and -_.{}[]
938 } else {
939 if (show_error)
940 LOGE("Backup name '%s' contains invalid character: '%c'\n", backup_name, (char)cur_char);
941 return -3;
942 }
943 }
944
945 // Check to make sure that a backup with this name doesn't already exist
946 strcpy(backup_loc, DataManager_GetStrValue(TW_BACKUPS_FOLDER_VAR));
947 sprintf(tw_image_dir,"%s/%s/.", backup_loc, backup_name);
948 if (statfs(tw_image_dir, &st) == 0) {
949 if (show_error)
950 LOGE("A backup with this name already exists.\n");
951 return -4;
952 }
953
954 // No problems found, return 0
955 return 0;
956}