/* New backup function ** Condensed all partitions into one function */ int tw_backup(struct dInfo bMnt, char *bDir) { if (ensure_path_mounted(SDCARD_ROOT) != 0) { ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT); return 1; } int bDiv; char bTarArg[10]; if (DataManager_GetIntValue(TW_USE_COMPRESSION_VAR)) { // set compression or not strcpy(bTarArg,"-czvf"); bDiv = 512; } else { strcpy(bTarArg,"-cvf"); bDiv = 2048; } FILE *bFp; int bPartSize; char *bImage = malloc(sizeof(char)*50); char *bMount = malloc(sizeof(char)*50); char *bCommand = malloc(sizeof(char)*255); if (strcmp(bMnt.mnt,"system") == 0 || strcmp(bMnt.mnt,"data") == 0 || strcmp(bMnt.mnt,"cache") == 0 || strcmp(bMnt.mnt,"sd-ext") == 0 || strcmp(bMnt.mnt,"efs") == 0 || strcmp(bMnt.mnt,".android_secure") == 0) { // detect mountable partitions if (strcmp(bMnt.mnt,".android_secure") == 0) { // if it's android secure, add sdcard to prefix strcpy(bMount,"/sdcard/"); strcat(bMount,bMnt.mnt); sprintf(bImage,"and-sec.%s.win",bMnt.fst); // set image name based on filesystem, should always be vfat for android_secure } else { strcpy(bMount,"/"); strcat(bMount,bMnt.mnt); sprintf(bImage,"%s.%s.win",bMnt.mnt,bMnt.fst); // anything else that is mountable, will be partition.filesystem.win ui_print("\n-- Mounting %s, please wait...\n",bMount); if (tw_mount(bMnt)) { ui_print("-- Could not mount: %s\n-- Aborting.\n",bMount); free(bCommand); free(bMount); free(bImage); return 1; } ui_print("-- Done.\n\n",bMount); } sprintf(bCommand,"du -sk %s | awk '{ print $1 }'",bMount); // check for partition/folder size bFp = __popen(bCommand, "r"); fscanf(bFp,"%d",&bPartSize); __pclose(bFp); sprintf(bCommand,"cd %s && tar %s %s%s ./*",bMount,bTarArg,bDir,bImage); // form backup command } else { strcpy(bMount,bMnt.mnt); bPartSize = bMnt.sze / 1024; sprintf(bImage,"%s.%s.win",bMnt.mnt,bMnt.fst); // non-mountable partitions such as boot/wimax/recovery if (strcmp(bMnt.fst,"mtd") == 0) { sprintf(bCommand,"dump_image %s %s%s",bMnt.mnt,bDir,bImage); // if it's mtd, we use dump image } else if (strcmp(bMnt.fst,"emmc") == 0) { sprintf(bCommand,"dd bs=%s if=%s of=%s%s",bs_size,bMnt.blk,bDir,bImage); // if it's emmc, use dd } ui_print("\n"); } LOGI("=> Filename: %s\n",bImage); LOGI("=> Size of %s is %d KB.\n\n",bMount,bPartSize); int i; char bUppr[20]; strcpy(bUppr,bMnt.mnt); for (i = 0; i < strlen(bUppr); i++) { // make uppercase of mount name bUppr[i] = toupper(bUppr[i]); } ui_print("[%s (%d MB)]\n",bUppr,bPartSize/1024); // show size in MB int bProgTime; time_t bStart, bStop; char bOutput[512]; if (sdSpace > bPartSize) { // Do we have enough space on sdcard? time(&bStart); // start timer bProgTime = bPartSize / bDiv; // not very accurate but better than nothing progress time for progress bar ui_show_progress(1,bProgTime); ui_print("...Backing up %s partition.\n",bMount); bFp = __popen(bCommand, "r"); // sending backup command formed earlier above if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 2) { // if twrp spam is on, show all lines while (fgets(bOutput,sizeof(bOutput),bFp) != NULL) { ui_print_overwrite("%s",bOutput); } } else { // else just show single line while (fscanf(bFp,"%s",bOutput) == 1) { if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 1) ui_print_overwrite("%s",bOutput); } } ui_print_overwrite("....Done.\n"); __pclose(bFp); int pFileSize; ui_print("...Double checking backup file size.\n"); sprintf(bCommand,"ls -l %s%s | awk '{ print $5 }'",bDir,bImage); // double checking to make sure we backed up something bFp = __popen(bCommand, "r"); fscanf(bFp,"%d",&pFileSize); __pclose(bFp); ui_print("....File size: %d bytes.\n",pFileSize); // file size if (pFileSize > 0) { // larger than 0 bytes? if (strcmp(bMnt.fst,"mtd") == 0 || strcmp(bMnt.fst,"emmc") == 0) { // if it's an unmountable partition, we can make sure LOGI("=> Expected size: %d Got: %d\n",bMnt.sze,pFileSize); // partition size matches file image size (they should match!) if (pFileSize != bMnt.sze) { ui_print("....File size is incorrect. Aborting...\n\n"); // they dont :( free(bCommand); free(bMount); free(bImage); return 1; } else { ui_print("....File size matches partition size.\n"); // they do, yay! } } ui_print("...Generating %s md5...\n", bMnt.mnt); makeMD5(bDir,bImage); // make md5 file ui_print("....Done.\n"); ui_print("...Verifying %s md5...\n", bMnt.mnt); checkMD5(bDir,bImage); // test the md5 we just made, just in case ui_print("....Done.\n"); time(&bStop); // stop timer ui_reset_progress(); // stop progress bar output_time(bUppr, "DONE", (int)difftime(bStop,bStart)); tw_unmount(bMnt); // unmount partition we just restored to (if it's not a mountable partition, it will just bypass) sdSpace -= bPartSize; // minus from sd space number (not accurate but, it's more than the real count so it will suffice) } else { ui_print("...File size is zero bytes. Aborting...\n\n"); // oh noes! file size is 0, abort! abort! tw_unmount(bMnt); free(bCommand); free(bMount); free(bImage); return 1; } } else { ui_print("...Not enough space on /sdcard. Aborting.\n"); // oh noes! no space left on sdcard, abort! abort! tw_unmount(bMnt); free(bCommand); free(bMount); free(bImage); return 1; } free(bCommand); free(bMount); free(bImage); return 0; }
int tw_restore(struct dInfo rMnt, char *rDir) { int i; FILE *reFp; char rUppr[20]; char rMount[30]; char rFilesystem[10]; char rFilename[255]; char rCommand[255]; char rOutput[255]; time_t rStart, rStop; strcpy(rUppr,rMnt.mnt); for (i = 0; i < strlen(rUppr); i++) { rUppr[i] = toupper(rUppr[i]); } ui_print("[%s]\n",rUppr); ui_show_progress(1,150); time(&rStart); ui_print("...Verifying md5 hash for %s.\n",rMnt.mnt); if(checkMD5(rDir,rMnt.fnm) == 0) // verify md5, check if no error; 0 = no error. { strcpy(rFilename,rDir); strcat(rFilename,rMnt.fnm); sprintf(rCommand,"ls -l %s | awk -F'.' '{ print $2 }'",rFilename); // let's get the filesystem type from filename reFp = __popen(rCommand, "r"); LOGI("=> Filename is: %s\n",rMnt.fnm); while (fscanf(reFp,"%s",rFilesystem) == 1) { // if we get a match, store filesystem type LOGI("=> Filesystem is: %s\n",rFilesystem); // show it off to the world! } __pclose(reFp); if (DataManager_GetIntValue(TW_RM_RF_VAR) == 1 && (strcmp(rMnt.mnt,"system") == 0 || strcmp(rMnt.mnt,"data") == 0 || strcmp(rMnt.mnt,"cache") == 0)) { // we'll use rm -rf instead of formatting for system, data and cache if the option is set ui_print("...using rm -rf to wipe %s\n", rMnt.mnt); tw_mount(rMnt); // mount the partition first sprintf(rCommand,"rm -rf %s%s/*", "/", rMnt.mnt); LOGI("rm rf commad: %s\n", rCommand); reFp = __popen(rCommand, "r"); while (fscanf(reFp,"%s",rOutput) == 1) { ui_print_overwrite("%s",rOutput); } __pclose(reFp); } else { ui_print("...Formatting %s\n",rMnt.mnt); tw_format(rFilesystem,rMnt.blk); // let's format block, based on filesystem from filename above } ui_print("....Done.\n"); if (strcmp(rFilesystem,"mtd") == 0) { // if filesystem is mtd, we use flash image sprintf(rCommand,"flash_image %s %s",rMnt.mnt,rFilename); strcpy(rMount,rMnt.mnt); } else if (strcmp(rFilesystem,"emmc") == 0) { // if filesystem is emmc, we use dd sprintf(rCommand,"dd bs=%s if=%s of=%s",bs_size,rFilename,rMnt.dev); strcpy(rMount,rMnt.mnt); } else { tw_mount(rMnt); strcpy(rMount,"/"); if (strcmp(rMnt.mnt,".android_secure") == 0) { // if it's android_secure, we have add prefix strcat(rMount,"sdcard/"); } strcat(rMount,rMnt.mnt); sprintf(rCommand,"cd %s && tar -xvf %s",rMount,rFilename); // formulate shell command to restore } ui_print("...Restoring %s\n",rMount); reFp = __popen(rCommand, "r"); if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 2) { // twrp spam while (fgets(rOutput,sizeof(rOutput),reFp) != NULL) { ui_print_overwrite("%s",rOutput); } } else { while (fscanf(reFp,"%s",rOutput) == 1) { if(DataManager_GetIntValue(TW_SHOW_SPAM_VAR) == 1) ui_print_overwrite("%s",rOutput); } } __pclose(reFp); ui_print_overwrite("....Done.\n"); if (strcmp(rMnt.mnt,".android_secure") != 0) { // any partition other than android secure, tw_unmount(rMnt); // let's unmount (unmountable partitions won't matter) } } else { ui_print("...Failed md5 check. Aborted.\n\n"); return 1; } ui_reset_progress(); time(&rStop); output_time(rUppr, "DONE", (int)difftime(rStop,rStart)); return 0; }
void updateMntUsedSize(struct dInfo* mMnt) { char path[512]; if (strcmp(mMnt->mnt, ".android_secure") == 0) { // android_secure is a little different - we mount sdcard and use du to figure out how much space is being taken up by android_secure if (DataManager_GetIntValue(TW_HAS_INTERNAL)) { // We can ignore any error from this, it doesn't matter tw_mount(sdcint); } else { // We can ignore any error from this, it doesn't matter tw_mount(sdcext); } mMnt->used = getUsedSizeViaDu(mMnt->dev); mMnt->sze = mMnt->used; mMnt->bsze = mMnt->used; return; } struct statfs st; int mounted; if (!mMnt->mountable) { // Since this partition isn't mountable, we're going to mark it's used size as it's standard size mMnt->used = mMnt->sze; mMnt->bsze = mMnt->used; return; } mounted = tw_isMounted(*mMnt); if (!mounted) { if (tw_mount(*mMnt)) { return; } } if (mMnt->sze == 0) // We weren't able to get the size earlier, try another method getSizeViaDf(mMnt); sprintf(path, "/%s/.", mMnt->mnt); if (statfs(path, &st) != 0) { if (strncmp(path, "/sd-ext", 7) == 0) return; if (DataManager_GetIntValue(TW_HAS_DUAL_STORAGE)) { char external_mount_point[255]; memset(external_mount_point, 0, sizeof(external_mount_point)); sprintf(external_mount_point, "/%s/.", DataManager_GetStrValue(TW_EXTERNAL_PATH)); if (strcmp(path, external_mount_point) == 0) return; // This prevents an error from showing on devices that have internal and external storage, but there is no sdcard installed. } LOGE("Unable to stat '%s'\n", path); return; } mMnt->used = ((st.f_blocks - st.f_bfree) * st.f_bsize); if (DataManager_GetIntValue(TW_HAS_DATA_MEDIA) == 1 && strcmp(mMnt->blk, dat.blk) == 0) { LOGI("Device has /data/media\n"); unsigned long long data_used, data_media_used, actual_data; data_used = getUsedSizeViaDu("/data/"); LOGI("Total used space on /data is: %llu\n", data_used); data_media_used = getUsedSizeViaDu("/data/media/"); LOGI("Total in /data/media is: %llu\n", data_media_used); actual_data = data_used - data_media_used; LOGI("Actual data used: %llu\n", actual_data); mMnt->bsze = actual_data; } else mMnt->bsze = mMnt->used; if (!mounted) tw_unmount(*mMnt); return; }