| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 1 | #include <ctype.h> | 
 | 2 | #include <errno.h> | 
 | 3 | #include <fcntl.h> | 
 | 4 | #include <getopt.h> | 
 | 5 | #include <limits.h> | 
 | 6 | #include <linux/input.h> | 
 | 7 | #include <stdio.h> | 
 | 8 | #include <stdlib.h> | 
 | 9 | #include <string.h> | 
 | 10 | #include <sys/reboot.h> | 
 | 11 | #include <sys/types.h> | 
 | 12 | #include <time.h> | 
 | 13 | #include <unistd.h> | 
 | 14 |  | 
 | 15 | #include <sys/wait.h> | 
 | 16 | #include <sys/limits.h> | 
 | 17 | #include <dirent.h> | 
 | 18 | #include <sys/stat.h> | 
 | 19 |  | 
 | 20 | #include <signal.h> | 
 | 21 | #include <sys/wait.h> | 
 | 22 |  | 
 | 23 | #include "bootloader.h" | 
 | 24 | #include "common.h" | 
 | 25 | #include "cutils/properties.h" | 
 | 26 | #include "firmware.h" | 
 | 27 | #include "install.h" | 
 | 28 | #include "minui/minui.h" | 
 | 29 | #include "minzip/DirUtil.h" | 
 | 30 | #include "roots.h" | 
 | 31 | #include "recovery_ui.h" | 
 | 32 |  | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 33 | #include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h" | 
 | 34 | #include "../../external/yaffs2/yaffs2/utils/unyaffs.h" | 
 | 35 |  | 
| Koushik K. Dutta | 7868629 | 2010-03-25 17:58:45 -0700 | [diff] [blame] | 36 | #include <sys/vfs.h> | 
 | 37 |  | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 38 | #include "extendedcommands.h" | 
 | 39 | #include "nandroid.h" | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 40 | #include "mounts.h" | 
 | 41 |  | 
| Koushik Dutta | 7adeadc | 2011-05-26 11:47:56 -0700 | [diff] [blame] | 42 | #include "flashutils/flashutils.h" | 
 | 43 | #include <libgen.h> | 
 | 44 |  | 
| Koushik Dutta | 7adeadc | 2011-05-26 11:47:56 -0700 | [diff] [blame] | 45 | void nandroid_generate_timestamp_path(const char* backup_path) | 
 | 46 | { | 
 | 47 |     time_t t = time(NULL); | 
 | 48 |     struct tm *tmp = localtime(&t); | 
 | 49 |     if (tmp == NULL) | 
 | 50 |     { | 
 | 51 |         struct timeval tp; | 
 | 52 |         gettimeofday(&tp, NULL); | 
 | 53 |         sprintf(backup_path, "/sdcard/clockworkmod/backup/%d", tp.tv_sec); | 
 | 54 |     } | 
 | 55 |     else | 
 | 56 |     { | 
 | 57 |         strftime(backup_path, PATH_MAX, "/sdcard/clockworkmod/backup/%F.%H.%M.%S", tmp); | 
 | 58 |     } | 
 | 59 | } | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 60 |  | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 61 | static int print_and_error(const char* message) { | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 62 |     ui_print("%s", message); | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 63 |     return 1; | 
 | 64 | } | 
 | 65 |  | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 66 | static int yaffs_files_total = 0; | 
 | 67 | static int yaffs_files_count = 0; | 
 | 68 | static void yaffs_callback(const char* filename) | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 69 | { | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 70 |     if (filename == NULL) | 
 | 71 |         return; | 
 | 72 |     const char* justfile = basename(filename); | 
 | 73 |     char tmp[PATH_MAX]; | 
 | 74 |     strcpy(tmp, justfile); | 
 | 75 |     if (tmp[strlen(tmp) - 1] == '\n') | 
 | 76 |         tmp[strlen(tmp) - 1] = NULL; | 
 | 77 |     if (strlen(tmp) < 30) | 
 | 78 |         ui_print("%s", tmp); | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 79 |     yaffs_files_count++; | 
 | 80 |     if (yaffs_files_total != 0) | 
 | 81 |         ui_set_progress((float)yaffs_files_count / (float)yaffs_files_total); | 
 | 82 |     ui_reset_text_col(); | 
 | 83 | } | 
 | 84 |  | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 85 | static void compute_directory_stats(const char* directory) | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 86 | { | 
 | 87 |     char tmp[PATH_MAX]; | 
 | 88 |     sprintf(tmp, "find %s | wc -l > /tmp/dircount", directory); | 
 | 89 |     __system(tmp); | 
 | 90 |     char count_text[100]; | 
 | 91 |     FILE* f = fopen("/tmp/dircount", "r"); | 
 | 92 |     fread(count_text, 1, sizeof(count_text), f); | 
 | 93 |     fclose(f); | 
 | 94 |     yaffs_files_count = 0; | 
 | 95 |     yaffs_files_total = atoi(count_text); | 
 | 96 |     ui_reset_progress(); | 
 | 97 |     ui_show_progress(1, 0); | 
 | 98 | } | 
 | 99 |  | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 100 | typedef void (*file_event_callback)(const char* filename); | 
| Koushik Dutta | 55e5e7b | 2011-06-14 23:39:59 -0700 | [diff] [blame] | 101 | typedef int (*nandroid_backup_handler)(const char* backup_path, const char* backup_file_image, int callback); | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 102 |  | 
| Koushik Dutta | 55e5e7b | 2011-06-14 23:39:59 -0700 | [diff] [blame] | 103 | static int mkyaffs2image_wrapper(const char* backup_path, const char* backup_file_image, int callback) { | 
| atinm | 9759ede | 2011-06-25 18:36:53 -0400 | [diff] [blame] | 104 |     return mkyaffs2image(backup_path, backup_file_image, 0, callback ? yaffs_callback : NULL); | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 105 | } | 
 | 106 |  | 
| Koushik Dutta | 55e5e7b | 2011-06-14 23:39:59 -0700 | [diff] [blame] | 107 | static int tar_compress_wrapper(const char* backup_path, const char* backup_file_image, int callback) { | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 108 |     char tmp[PATH_MAX]; | 
 | 109 |     if (strcmp(backup_path, "/data") == 0 && volume_for_path("/sdcard") == NULL) | 
 | 110 |       sprintf(tmp, "cd $(dirname %s) ; tar cvf %s --exclude 'media' $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path); | 
 | 111 |     else | 
 | 112 |       sprintf(tmp, "cd $(dirname %s) ; tar cvf %s $(basename %s) ; exit $?", backup_path, backup_file_image, backup_path); | 
 | 113 |  | 
 | 114 |     FILE *fp = __popen(tmp, "r"); | 
 | 115 |     if (fp == NULL) { | 
 | 116 |         ui_print("Unable to execute tar.\n"); | 
 | 117 |         return -1; | 
 | 118 |     } | 
 | 119 |  | 
 | 120 |     while (fgets(tmp, PATH_MAX, fp) != NULL) { | 
 | 121 |         tmp[PATH_MAX - 1] = NULL; | 
| Koushik Dutta | 55e5e7b | 2011-06-14 23:39:59 -0700 | [diff] [blame] | 122 |         if (callback) | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 123 |             yaffs_callback(tmp); | 
 | 124 |     } | 
 | 125 |  | 
 | 126 |     return __pclose(fp); | 
 | 127 | } | 
 | 128 |  | 
 | 129 | static nandroid_backup_handler get_backup_handler(const char *backup_path) { | 
 | 130 |     Volume *v = volume_for_path(backup_path); | 
 | 131 |     if (v == NULL) { | 
 | 132 |         ui_print("Unable to find volume.\n"); | 
 | 133 |         return NULL; | 
 | 134 |     } | 
 | 135 |     scan_mounted_volumes(); | 
 | 136 |     MountedVolume *mv = find_mounted_volume_by_mount_point(v->mount_point); | 
 | 137 |     if (mv == NULL) { | 
 | 138 |         ui_print("Unable to find mounted volume: %s\n", v->mount_point); | 
 | 139 |         return NULL; | 
 | 140 |     } | 
 | 141 |  | 
| Koushik Dutta | 38a9214 | 2011-06-10 09:45:52 -0700 | [diff] [blame] | 142 |     if (strcmp(backup_path, "/data") == 0 && is_data_media()) { | 
 | 143 |         return tar_compress_wrapper; | 
 | 144 |     } | 
 | 145 |  | 
 | 146 |     char str[255]; | 
 | 147 |     char* partition; | 
 | 148 |     property_get("ro.cwm.prefer_tar", str, "false"); | 
 | 149 |     if (strcmp("true", str) != 0) { | 
 | 150 |         return mkyaffs2image_wrapper; | 
 | 151 |     } | 
 | 152 |  | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 153 |     if (strcmp("yaffs2", mv->filesystem) == 0) { | 
 | 154 |         return mkyaffs2image_wrapper; | 
 | 155 |     } | 
 | 156 |  | 
 | 157 |     return tar_compress_wrapper; | 
 | 158 | } | 
 | 159 |  | 
 | 160 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 161 | int nandroid_backup_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) { | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 162 |     int ret = 0; | 
| Koushik K. Dutta | 68b0190 | 2010-04-01 12:20:39 -0700 | [diff] [blame] | 163 |     char* name = basename(mount_point); | 
| Koushik Dutta | 58131e7 | 2010-06-09 12:41:20 -0700 | [diff] [blame] | 164 |  | 
 | 165 |     struct stat file_info; | 
| Koushik Dutta | 55e5e7b | 2011-06-14 23:39:59 -0700 | [diff] [blame] | 166 |     int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) == 0; | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 167 |      | 
 | 168 |     ui_print("Backing up %s...\n", name); | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 169 |     if (0 != (ret = ensure_path_mounted(mount_point) != 0)) { | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 170 |         ui_print("Can't mount %s!\n", mount_point); | 
 | 171 |         return ret; | 
 | 172 |     } | 
 | 173 |     compute_directory_stats(mount_point); | 
 | 174 |     char tmp[PATH_MAX]; | 
 | 175 |     sprintf(tmp, "%s/%s.img", backup_path, name); | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 176 |     nandroid_backup_handler backup_handler = get_backup_handler(mount_point); | 
 | 177 |     if (backup_handler == NULL) { | 
 | 178 |         ui_print("Error finding an appropriate backup handler.\n"); | 
 | 179 |         return -2; | 
 | 180 |     } | 
 | 181 |     ret = backup_handler(mount_point, tmp, callback); | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 182 |     if (umount_when_finished) { | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 183 |         ensure_path_unmounted(mount_point); | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 184 |     } | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 185 |     if (0 != ret) { | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 186 |         ui_print("Error while making a backup image of %s!\n", mount_point); | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 187 |         return ret; | 
 | 188 |     } | 
 | 189 |     return 0; | 
 | 190 | } | 
 | 191 |  | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 192 | int nandroid_backup_partition(const char* backup_path, const char* root) { | 
 | 193 |     Volume *vol = volume_for_path(root); | 
 | 194 |     // make sure the volume exists before attempting anything... | 
 | 195 |     if (vol == NULL || vol->fs_type == NULL) | 
 | 196 |         return NULL; | 
 | 197 |  | 
 | 198 |     // see if we need a raw backup (mtd) | 
 | 199 |     char tmp[PATH_MAX]; | 
 | 200 |     int ret; | 
| Christopher Lais | 066a102 | 2011-01-16 06:02:34 -0600 | [diff] [blame] | 201 |     if (strcmp(vol->fs_type, "mtd") == 0 || | 
| Koushik Dutta | 33e37f3 | 2011-02-27 16:33:32 -0800 | [diff] [blame] | 202 |             strcmp(vol->fs_type, "bml") == 0 || | 
| Christopher Lais | 066a102 | 2011-01-16 06:02:34 -0600 | [diff] [blame] | 203 |             strcmp(vol->fs_type, "emmc") == 0) { | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 204 |         const char* name = basename(root); | 
 | 205 |         sprintf(tmp, "%s/%s.img", backup_path, name); | 
 | 206 |         ui_print("Backing up %s image...\n", name); | 
| Koushik Dutta | 8a6bc77 | 2011-05-26 11:14:15 -0700 | [diff] [blame] | 207 |         if (0 != (ret = backup_raw_partition(vol->fs_type, vol->device, tmp))) { | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 208 |             ui_print("Error while backing up %s image!", name); | 
 | 209 |             return ret; | 
 | 210 |         } | 
 | 211 |         return 0; | 
 | 212 |     } | 
 | 213 |  | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 214 |     return nandroid_backup_partition_extended(backup_path, root, 1); | 
 | 215 | } | 
 | 216 |  | 
| Koushik Dutta | 2f73e58 | 2010-04-18 16:00:21 -0700 | [diff] [blame] | 217 | int nandroid_backup(const char* backup_path) | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 218 | { | 
 | 219 |     ui_set_background(BACKGROUND_ICON_INSTALLING); | 
 | 220 |      | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 221 |     if (ensure_path_mounted("/sdcard") != 0) | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 222 |         return print_and_error("Can't mount /sdcard\n"); | 
 | 223 |      | 
| Koushik K. Dutta | 7868629 | 2010-03-25 17:58:45 -0700 | [diff] [blame] | 224 |     int ret; | 
| Koushik K. Dutta | f3534d0 | 2010-04-18 18:06:24 -0700 | [diff] [blame] | 225 |     struct statfs s; | 
| Koushik K. Dutta | 7868629 | 2010-03-25 17:58:45 -0700 | [diff] [blame] | 226 |     if (0 != (ret = statfs("/sdcard", &s))) | 
 | 227 |         return print_and_error("Unable to stat /sdcard\n"); | 
| Koushik K. Dutta | 68b0190 | 2010-04-01 12:20:39 -0700 | [diff] [blame] | 228 |     uint64_t bavail = s.f_bavail; | 
 | 229 |     uint64_t bsize = s.f_bsize; | 
 | 230 |     uint64_t sdcard_free = bavail * bsize; | 
 | 231 |     uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024); | 
 | 232 |     ui_print("SD Card space free: %lluMB\n", sdcard_free_mb); | 
 | 233 |     if (sdcard_free_mb < 150) | 
| Koushik K. Dutta | c097093 | 2010-03-25 23:19:19 -0700 | [diff] [blame] | 234 |         ui_print("There may not be enough free space to complete backup... continuing...\n"); | 
| Koushik K. Dutta | 7868629 | 2010-03-25 17:58:45 -0700 | [diff] [blame] | 235 |      | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 236 |     char tmp[PATH_MAX]; | 
 | 237 |     sprintf(tmp, "mkdir -p %s", backup_path); | 
 | 238 |     __system(tmp); | 
 | 239 |  | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 240 |     if (0 != (ret = nandroid_backup_partition(backup_path, "/boot"))) | 
 | 241 |         return ret; | 
| Koushik K. Dutta | 6923cc3 | 2010-03-29 14:46:00 -0700 | [diff] [blame] | 242 |  | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 243 |     if (0 != (ret = nandroid_backup_partition(backup_path, "/recovery"))) | 
 | 244 |         return ret; | 
| Koushik K. Dutta | 6923cc3 | 2010-03-29 14:46:00 -0700 | [diff] [blame] | 245 |  | 
| Koushik Dutta | 5ee98b2 | 2011-03-02 19:35:05 -0800 | [diff] [blame] | 246 |     Volume *vol = volume_for_path("/wimax"); | 
 | 247 |     if (vol != NULL && 0 == stat(vol->device, &s)) | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 248 |     { | 
| Joshua Wise | 05d4a09 | 2010-12-31 02:05:35 -0500 | [diff] [blame] | 249 |         char serialno[PROPERTY_VALUE_MAX]; | 
| Joshua Wise | ca889ec | 2010-12-30 02:48:25 -0500 | [diff] [blame] | 250 |         ui_print("Backing up WiMAX...\n"); | 
| Joshua Wise | 05d4a09 | 2010-12-31 02:05:35 -0500 | [diff] [blame] | 251 |         serialno[0] = 0; | 
 | 252 |         property_get("ro.serialno", serialno, ""); | 
 | 253 |         sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); | 
| Koushik Dutta | e62132b | 2011-05-26 11:29:29 -0700 | [diff] [blame] | 254 |         ret = backup_raw_partition(vol->fs_type, vol->device, tmp); | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 255 |         if (0 != ret) | 
| Joshua Wise | ca889ec | 2010-12-30 02:48:25 -0500 | [diff] [blame] | 256 |             return print_and_error("Error while dumping WiMAX image!\n"); | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 257 |     } | 
 | 258 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 259 |     if (0 != (ret = nandroid_backup_partition(backup_path, "/system"))) | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 260 |         return ret; | 
 | 261 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 262 |     if (0 != (ret = nandroid_backup_partition(backup_path, "/data"))) | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 263 |         return ret; | 
 | 264 |  | 
| Koushik Dutta | 5460f0c | 2010-12-18 22:37:49 -0800 | [diff] [blame] | 265 |     if (has_datadata()) { | 
 | 266 |         if (0 != (ret = nandroid_backup_partition(backup_path, "/datadata"))) | 
 | 267 |             return ret; | 
 | 268 |     } | 
| Koushik Dutta | 8b5e185 | 2010-06-14 22:04:22 -0700 | [diff] [blame] | 269 |  | 
| Koushik Dutta | 5ee98b2 | 2011-03-02 19:35:05 -0800 | [diff] [blame] | 270 |     if (0 != stat("/sdcard/.android_secure", &s)) | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 271 |     { | 
 | 272 |         ui_print("No /sdcard/.android_secure found. Skipping backup of applications on external storage.\n"); | 
 | 273 |     } | 
 | 274 |     else | 
 | 275 |     { | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 276 |         if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/sdcard/.android_secure", 0))) | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 277 |             return ret; | 
 | 278 |     } | 
 | 279 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 280 |     if (0 != (ret = nandroid_backup_partition_extended(backup_path, "/cache", 0))) | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 281 |         return ret; | 
| Koushik K. Dutta | 3f99539 | 2010-03-30 23:29:43 -0700 | [diff] [blame] | 282 |  | 
| Koushik Dutta | 5ee98b2 | 2011-03-02 19:35:05 -0800 | [diff] [blame] | 283 |     vol = volume_for_path("/sd-ext"); | 
 | 284 |     if (vol == NULL || 0 != stat(vol->device, &s)) | 
| Koushik K. Dutta | 6771aca | 2010-04-03 23:28:39 -0700 | [diff] [blame] | 285 |     { | 
| Koushik K. Dutta | 71ef11f | 2010-04-02 22:17:42 -0700 | [diff] [blame] | 286 |         ui_print("No sd-ext found. Skipping backup of sd-ext.\n"); | 
| Koushik K. Dutta | 6771aca | 2010-04-03 23:28:39 -0700 | [diff] [blame] | 287 |     } | 
 | 288 |     else | 
 | 289 |     { | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 290 |         if (0 != ensure_path_mounted("/sd-ext")) | 
| Koushik Dutta | 8b5e185 | 2010-06-14 22:04:22 -0700 | [diff] [blame] | 291 |             ui_print("Could not mount sd-ext. sd-ext backup may not be supported on this device. Skipping backup of sd-ext.\n"); | 
| Koushik Dutta | e06e539 | 2011-01-16 02:33:04 -0800 | [diff] [blame] | 292 |         else if (0 != (ret = nandroid_backup_partition(backup_path, "/sd-ext"))) | 
| Koushik K. Dutta | 6771aca | 2010-04-03 23:28:39 -0700 | [diff] [blame] | 293 |             return ret; | 
 | 294 |     } | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 295 |  | 
| Koushik K. Dutta | d717892 | 2010-03-24 14:38:40 -0700 | [diff] [blame] | 296 |     ui_print("Generating md5 sum...\n"); | 
| Koushik K. Dutta | 68b0190 | 2010-04-01 12:20:39 -0700 | [diff] [blame] | 297 |     sprintf(tmp, "nandroid-md5.sh %s", backup_path); | 
| Koushik K. Dutta | b0a2503 | 2010-03-24 10:34:38 -0700 | [diff] [blame] | 298 |     if (0 != (ret = __system(tmp))) { | 
 | 299 |         ui_print("Error while generating md5 sum!\n"); | 
 | 300 |         return ret; | 
 | 301 |     } | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 302 |      | 
| Koushik K. Dutta | 3f38f32 | 2010-03-12 23:45:25 -0800 | [diff] [blame] | 303 |     sync(); | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 304 |     ui_set_background(BACKGROUND_ICON_NONE); | 
 | 305 |     ui_reset_progress(); | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 306 |     ui_print("\nBackup complete!\n"); | 
 | 307 |     return 0; | 
 | 308 | } | 
 | 309 |  | 
| Koushik K. Dutta | 68b0190 | 2010-04-01 12:20:39 -0700 | [diff] [blame] | 310 | typedef int (*format_function)(char* root); | 
 | 311 |  | 
| Koushik Dutta | 5aaa823 | 2010-07-20 16:23:18 -0700 | [diff] [blame] | 312 | static void ensure_directory(const char* dir) { | 
 | 313 |     char tmp[PATH_MAX]; | 
 | 314 |     sprintf(tmp, "mkdir -p %s", dir); | 
 | 315 |     __system(tmp); | 
 | 316 | } | 
 | 317 |  | 
| Koushik Dutta | 7905c80 | 2011-06-15 00:00:55 -0700 | [diff] [blame] | 318 | typedef int (*nandroid_restore_handler)(const char* backup_file_image, const char* backup_path, int callback); | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 319 |  | 
| Koushik Dutta | 7905c80 | 2011-06-15 00:00:55 -0700 | [diff] [blame] | 320 | static int unyaffs_wrapper(const char* backup_file_image, const char* backup_path, int callback) { | 
| Koushik Dutta | c915937 | 2011-07-20 01:26:02 -0700 | [diff] [blame^] | 321 |     return unyaffs(backup_file_image, backup_path, callback ? yaffs_callback : NULL); | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 322 | } | 
 | 323 |  | 
| Koushik Dutta | 7905c80 | 2011-06-15 00:00:55 -0700 | [diff] [blame] | 324 | static int tar_extract_wrapper(const char* backup_file_image, const char* backup_path, int callback) { | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 325 |     char tmp[PATH_MAX]; | 
 | 326 |     sprintf(tmp, "cd $(dirname %s) ; tar xvf %s ; exit $?", backup_path, backup_file_image); | 
 | 327 |  | 
 | 328 |     char path[PATH_MAX]; | 
 | 329 |     FILE *fp = __popen(tmp, "r"); | 
 | 330 |     if (fp == NULL) { | 
 | 331 |         ui_print("Unable to execute tar.\n"); | 
 | 332 |         return -1; | 
 | 333 |     } | 
 | 334 |  | 
 | 335 |     while (fgets(path, PATH_MAX, fp) != NULL) { | 
| Koushik Dutta | 7905c80 | 2011-06-15 00:00:55 -0700 | [diff] [blame] | 336 |         if (callback) | 
 | 337 |             yaffs_callback(path); | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 338 |     } | 
 | 339 |  | 
 | 340 |     return __pclose(fp); | 
 | 341 | } | 
 | 342 |  | 
 | 343 | static nandroid_restore_handler get_restore_handler(const char *backup_path) { | 
 | 344 |     Volume *v = volume_for_path(backup_path); | 
 | 345 |     if (v == NULL) { | 
 | 346 |         ui_print("Unable to find volume.\n"); | 
 | 347 |         return NULL; | 
 | 348 |     } | 
 | 349 |     scan_mounted_volumes(); | 
 | 350 |     MountedVolume *mv = find_mounted_volume_by_mount_point(v->mount_point); | 
 | 351 |     if (mv == NULL) { | 
 | 352 |         ui_print("Unable to find mounted volume: %s\n", v->mount_point); | 
 | 353 |         return NULL; | 
 | 354 |     } | 
 | 355 |  | 
| Koushik Dutta | 38a9214 | 2011-06-10 09:45:52 -0700 | [diff] [blame] | 356 |     if (strcmp(backup_path, "/data") == 0 && is_data_media()) { | 
 | 357 |         return tar_extract_wrapper; | 
 | 358 |     } | 
 | 359 |  | 
 | 360 |     char str[255]; | 
 | 361 |     char* partition; | 
 | 362 |     property_get("ro.cwm.prefer_tar", str, "false"); | 
 | 363 |     if (strcmp("true", str) != 0) { | 
 | 364 |         return unyaffs_wrapper; | 
 | 365 |     } | 
 | 366 |  | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 367 |     if (strcmp("yaffs2", mv->filesystem) == 0) { | 
 | 368 |         return unyaffs_wrapper; | 
 | 369 |     } | 
 | 370 |  | 
 | 371 |     return tar_extract_wrapper; | 
 | 372 | } | 
 | 373 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 374 | int nandroid_restore_partition_extended(const char* backup_path, const char* mount_point, int umount_when_finished) { | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 375 |     int ret = 0; | 
| Koushik K. Dutta | 68b0190 | 2010-04-01 12:20:39 -0700 | [diff] [blame] | 376 |     char* name = basename(mount_point); | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 377 |      | 
| Koushik Dutta | 5aaa823 | 2010-07-20 16:23:18 -0700 | [diff] [blame] | 378 |     char tmp[PATH_MAX]; | 
 | 379 |     sprintf(tmp, "%s/%s.img", backup_path, name); | 
| Koushik Dutta | 58131e7 | 2010-06-09 12:41:20 -0700 | [diff] [blame] | 380 |     struct stat file_info; | 
| Koushik Dutta | 5aaa823 | 2010-07-20 16:23:18 -0700 | [diff] [blame] | 381 |     if (0 != (ret = statfs(tmp, &file_info))) { | 
| Koushik Dutta | d4060c3 | 2010-07-22 20:14:44 -0700 | [diff] [blame] | 382 |         ui_print("%s.img not found. Skipping restore of %s.\n", name, mount_point); | 
| Koushik Dutta | 5aaa823 | 2010-07-20 16:23:18 -0700 | [diff] [blame] | 383 |         return 0; | 
 | 384 |     } | 
 | 385 |  | 
 | 386 |     ensure_directory(mount_point); | 
 | 387 |  | 
| Koushik Dutta | 55e5e7b | 2011-06-14 23:39:59 -0700 | [diff] [blame] | 388 |     int callback = stat("/sdcard/clockworkmod/.hidenandroidprogress", &file_info) == 0; | 
| Koushik Dutta | 58131e7 | 2010-06-09 12:41:20 -0700 | [diff] [blame] | 389 |  | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 390 |     ui_print("Restoring %s...\n", name); | 
| Koushik Dutta | 852bb42 | 2010-07-24 11:18:00 -0700 | [diff] [blame] | 391 |     /* | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 392 |     if (0 != (ret = ensure_root_path_unmounted(root))) { | 
 | 393 |         ui_print("Can't unmount %s!\n", mount_point); | 
 | 394 |         return ret; | 
 | 395 |     } | 
| Koushik Dutta | 852bb42 | 2010-07-24 11:18:00 -0700 | [diff] [blame] | 396 |     */ | 
| Koushik Dutta | bf4444f | 2010-12-18 18:57:47 -0800 | [diff] [blame] | 397 |     if (0 != (ret = format_volume(mount_point))) { | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 398 |         ui_print("Error while formatting %s!\n", mount_point); | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 399 |         return ret; | 
 | 400 |     } | 
 | 401 |      | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 402 |     if (0 != (ret = ensure_path_mounted(mount_point))) { | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 403 |         ui_print("Can't mount %s!\n", mount_point); | 
 | 404 |         return ret; | 
 | 405 |     } | 
 | 406 |      | 
| Koushik Dutta | 5082299 | 2011-06-08 19:03:27 -0700 | [diff] [blame] | 407 |     nandroid_restore_handler restore_handler = get_restore_handler(mount_point); | 
 | 408 |     if (restore_handler == NULL) { | 
 | 409 |         ui_print("Error finding an appropriate restore handler.\n"); | 
 | 410 |         return -2; | 
 | 411 |     } | 
 | 412 |     if (0 != (ret = restore_handler(tmp, mount_point, callback))) { | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 413 |         ui_print("Error while restoring %s!\n", mount_point); | 
 | 414 |         return ret; | 
 | 415 |     } | 
| Koushik Dutta | 2f73e58 | 2010-04-18 16:00:21 -0700 | [diff] [blame] | 416 |  | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 417 |     if (umount_when_finished) { | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 418 |         ensure_path_unmounted(mount_point); | 
| Koushik Dutta | 2f73e58 | 2010-04-18 16:00:21 -0700 | [diff] [blame] | 419 |     } | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 420 |      | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 421 |     return 0; | 
 | 422 | } | 
 | 423 |  | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 424 | int nandroid_restore_partition(const char* backup_path, const char* root) { | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 425 |     Volume *vol = volume_for_path(root); | 
 | 426 |     // make sure the volume exists... | 
 | 427 |     if (vol == NULL || vol->fs_type == NULL) | 
 | 428 |         return 0; | 
 | 429 |  | 
 | 430 |     // see if we need a raw restore (mtd) | 
 | 431 |     char tmp[PATH_MAX]; | 
| Christopher Lais | 066a102 | 2011-01-16 06:02:34 -0600 | [diff] [blame] | 432 |     if (strcmp(vol->fs_type, "mtd") == 0 || | 
| Koushik Dutta | 33e37f3 | 2011-02-27 16:33:32 -0800 | [diff] [blame] | 433 |             strcmp(vol->fs_type, "bml") == 0 || | 
| Christopher Lais | 066a102 | 2011-01-16 06:02:34 -0600 | [diff] [blame] | 434 |             strcmp(vol->fs_type, "emmc") == 0) { | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 435 |         int ret; | 
 | 436 |         const char* name = basename(root); | 
 | 437 |         ui_print("Erasing %s before restore...\n", name); | 
 | 438 |         if (0 != (ret = format_volume(root))) { | 
 | 439 |             ui_print("Error while erasing %s image!", name); | 
 | 440 |             return ret; | 
 | 441 |         } | 
 | 442 |         sprintf(tmp, "%s%s.img", backup_path, root); | 
 | 443 |         ui_print("Restoring %s image...\n", name); | 
| Koushik Dutta | 8a6bc77 | 2011-05-26 11:14:15 -0700 | [diff] [blame] | 444 |         if (0 != (ret = restore_raw_partition(vol->fs_type, vol->device, tmp))) { | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 445 |             ui_print("Error while flashing %s image!", name); | 
 | 446 |             return ret; | 
 | 447 |         } | 
 | 448 |         return 0; | 
 | 449 |     } | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 450 |     return nandroid_restore_partition_extended(backup_path, root, 1); | 
 | 451 | } | 
 | 452 |  | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 453 | int nandroid_restore(const char* backup_path, int restore_boot, int restore_system, int restore_data, int restore_cache, int restore_sdext, int restore_wimax) | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 454 | { | 
 | 455 |     ui_set_background(BACKGROUND_ICON_INSTALLING); | 
 | 456 |     ui_show_indeterminate_progress(); | 
 | 457 |     yaffs_files_total = 0; | 
 | 458 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 459 |     if (ensure_path_mounted("/sdcard") != 0) | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 460 |         return print_and_error("Can't mount /sdcard\n"); | 
 | 461 |      | 
 | 462 |     char tmp[PATH_MAX]; | 
 | 463 |  | 
 | 464 |     ui_print("Checking MD5 sums...\n"); | 
| Koushik K. Dutta | face588 | 2010-03-13 10:15:55 -0800 | [diff] [blame] | 465 |     sprintf(tmp, "cd %s && md5sum -c nandroid.md5", backup_path); | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 466 |     if (0 != __system(tmp)) | 
 | 467 |         return print_and_error("MD5 mismatch!\n"); | 
 | 468 |      | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 469 |     int ret; | 
| Koushik Dutta | 53c9bd8 | 2011-01-04 11:38:31 -0800 | [diff] [blame] | 470 |  | 
 | 471 |     if (restore_boot && NULL != volume_for_path("/boot") && 0 != (ret = nandroid_restore_partition(backup_path, "/boot"))) | 
 | 472 |         return ret; | 
| Koushik K. Dutta | f721594 | 2010-03-16 13:34:51 -0700 | [diff] [blame] | 473 |      | 
| Koushik Dutta | 5ee98b2 | 2011-03-02 19:35:05 -0800 | [diff] [blame] | 474 |     struct stat s; | 
 | 475 |     Volume *vol = volume_for_path("/wimax"); | 
 | 476 |     if (restore_wimax && vol != NULL && 0 == stat(vol->device, &s)) | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 477 |     { | 
| Joshua Wise | 05d4a09 | 2010-12-31 02:05:35 -0500 | [diff] [blame] | 478 |         char serialno[PROPERTY_VALUE_MAX]; | 
 | 479 |          | 
 | 480 |         serialno[0] = 0; | 
 | 481 |         property_get("ro.serialno", serialno, ""); | 
 | 482 |         sprintf(tmp, "%s/wimax.%s.img", backup_path, serialno); | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 483 |  | 
 | 484 |         struct stat st; | 
 | 485 |         if (0 != stat(tmp, &st)) | 
 | 486 |         { | 
| Joshua Wise | ca889ec | 2010-12-30 02:48:25 -0500 | [diff] [blame] | 487 |             ui_print("WARNING: WiMAX partition exists, but nandroid\n"); | 
 | 488 |             ui_print("         backup does not contain WiMAX image.\n"); | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 489 |             ui_print("         You should create a new backup to\n"); | 
| Joshua Wise | ca889ec | 2010-12-30 02:48:25 -0500 | [diff] [blame] | 490 |             ui_print("         protect your WiMAX keys.\n"); | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 491 |         } | 
 | 492 |         else | 
 | 493 |         { | 
| Joshua Wise | 5a3f1d8 | 2010-12-31 02:16:00 -0500 | [diff] [blame] | 494 |             ui_print("Erasing WiMAX before restore...\n"); | 
| Koushik Dutta | a25deae | 2011-01-01 18:17:48 -0800 | [diff] [blame] | 495 |             if (0 != (ret = format_volume("/wimax"))) | 
| Joshua Wise | 5a3f1d8 | 2010-12-31 02:16:00 -0500 | [diff] [blame] | 496 |                 return print_and_error("Error while formatting wimax!\n"); | 
| Joshua Wise | 05d4a09 | 2010-12-31 02:05:35 -0500 | [diff] [blame] | 497 |             ui_print("Restoring WiMAX image...\n"); | 
| Koushik Dutta | e62132b | 2011-05-26 11:29:29 -0700 | [diff] [blame] | 498 |             if (0 != (ret = restore_raw_partition(vol->fs_type, vol->device, tmp))) | 
| agrabren | 1f76a5d | 2010-12-29 12:15:18 -0600 | [diff] [blame] | 499 |                 return ret; | 
 | 500 |         } | 
 | 501 |     } | 
 | 502 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 503 |     if (restore_system && 0 != (ret = nandroid_restore_partition(backup_path, "/system"))) | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 504 |         return ret; | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 505 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 506 |     if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/data"))) | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 507 |         return ret; | 
| Koushik Dutta | 8b5e185 | 2010-06-14 22:04:22 -0700 | [diff] [blame] | 508 |          | 
| Koushik Dutta | 5460f0c | 2010-12-18 22:37:49 -0800 | [diff] [blame] | 509 |     if (has_datadata()) { | 
 | 510 |         if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "/datadata"))) | 
 | 511 |             return ret; | 
 | 512 |     } | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 513 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 514 |     if (restore_data && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/sdcard/.android_secure", 0))) | 
| Koushik Dutta | 5aaa823 | 2010-07-20 16:23:18 -0700 | [diff] [blame] | 515 |         return ret; | 
| Koushik Dutta | 062d6b0 | 2010-07-03 13:54:21 -0700 | [diff] [blame] | 516 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 517 |     if (restore_cache && 0 != (ret = nandroid_restore_partition_extended(backup_path, "/cache", 0))) | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 518 |         return ret; | 
 | 519 |  | 
| Koushik Dutta | df1e406 | 2010-12-18 17:42:31 -0800 | [diff] [blame] | 520 |     if (restore_sdext && 0 != (ret = nandroid_restore_partition(backup_path, "/sd-ext"))) | 
| Koushik Dutta | 5aaa823 | 2010-07-20 16:23:18 -0700 | [diff] [blame] | 521 |         return ret; | 
| Koushik K. Dutta | 68b0190 | 2010-04-01 12:20:39 -0700 | [diff] [blame] | 522 |  | 
| Koushik K. Dutta | 3f38f32 | 2010-03-12 23:45:25 -0800 | [diff] [blame] | 523 |     sync(); | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 524 |     ui_set_background(BACKGROUND_ICON_NONE); | 
 | 525 |     ui_reset_progress(); | 
| Koushik K. Dutta | 4b249cd | 2010-03-15 16:31:03 -0700 | [diff] [blame] | 526 |     ui_print("\nRestore complete!\n"); | 
| Koushik K. Dutta | ee57bbc | 2010-03-12 23:21:12 -0800 | [diff] [blame] | 527 |     return 0; | 
 | 528 | } | 
| Koushik Dutta | 0837091 | 2010-06-26 12:25:02 -0700 | [diff] [blame] | 529 |  | 
| Koushik Dutta | 0837091 | 2010-06-26 12:25:02 -0700 | [diff] [blame] | 530 | int nandroid_usage() | 
 | 531 | { | 
 | 532 |     printf("Usage: nandroid backup\n"); | 
 | 533 |     printf("Usage: nandroid restore <directory>\n"); | 
 | 534 |     return 1; | 
 | 535 | } | 
 | 536 |  | 
 | 537 | int nandroid_main(int argc, char** argv) | 
 | 538 | { | 
 | 539 |     if (argc > 3 || argc < 2) | 
 | 540 |         return nandroid_usage(); | 
 | 541 |      | 
 | 542 |     if (strcmp("backup", argv[1]) == 0) | 
 | 543 |     { | 
 | 544 |         if (argc != 2) | 
 | 545 |             return nandroid_usage(); | 
 | 546 |          | 
 | 547 |         char backup_path[PATH_MAX]; | 
 | 548 |         nandroid_generate_timestamp_path(backup_path); | 
 | 549 |         return nandroid_backup(backup_path); | 
 | 550 |     } | 
 | 551 |  | 
 | 552 |     if (strcmp("restore", argv[1]) == 0) | 
 | 553 |     { | 
 | 554 |         if (argc != 3) | 
 | 555 |             return nandroid_usage(); | 
| Koushik Dutta | 5b7f34a | 2010-12-29 23:36:03 -0800 | [diff] [blame] | 556 |         return nandroid_restore(argv[2], 1, 1, 1, 1, 1, 0); | 
| Koushik Dutta | 0837091 | 2010-06-26 12:25:02 -0700 | [diff] [blame] | 557 |     } | 
 | 558 |      | 
 | 559 |     return nandroid_usage(); | 
 | 560 | } |