/* 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;
}
示例#3
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;
}