void update_system_details()
{
	ui_print(" * Verifying filesystems...\n");
    createFstab();
    ui_print(" * Verifying partition sizes...\n");
    updateUsedSized();
}
int 
nandroid_rest_exe()
{
	if (ensure_path_mounted(SDCARD_ROOT) != 0) {
		ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT);
		return 1;
	}
	time_t rStart, rStop;
	time(&rStart);
	ui_print("\n[RESTORE STARTED]\n\n");
	if (tw_nan_system_x == 1) {
		if (tw_restore(sys,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	if (tw_nan_data_x == 1) {
		if (tw_restore(dat,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	if (tw_nan_boot_x == 1) {
		if (tw_restore(boo,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	if (tw_nan_recovery_x == 1) {
		if (tw_restore(rec,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	if (tw_nan_cache_x == 1) {
		if (tw_restore(cac,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	if (tw_nan_wimax_x == 1) {
		if (tw_restore(wim,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	if (tw_nan_andsec_x == 1) {
		if (tw_restore(ase,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	if (tw_nan_sdext_x == 1) {
		if (tw_restore(sde,nan_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	time(&rStop);
	output_time("RESTORE", "COMPLETED", (int)difftime(rStop, rStart));
	__system("sync");
	LOGI("=> Let's update filesystem types.\n");
	verifyFst();
	LOGI("=> And update our fstab also.\n");
	createFstab();
	return 0;
}
int
nandroid_back_exe()
{
	if (ensure_path_mounted(SDCARD_ROOT) != 0) {
		ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT);
		return 1;
	}
    struct tm *t;
    char timestamp[15];
	char tw_image_dir[255];
	char exe[255];
	time_t start, stop;
	time_t seconds;
	seconds = time(0);
    t = localtime(&seconds);
    sprintf(timestamp,"%02d%02d%d%02d%02d%02d",t->tm_mon+1,t->tm_mday,t->tm_year+1900,t->tm_hour,t->tm_min,t->tm_sec); // make time stamp
	sprintf(tw_image_dir,"%s/%s/%s/",backup_folder,device_id,timestamp); // for backup folder
	sprintf(exe,"mkdir -p %s",tw_image_dir); // make the folder with timestamp
	if (__system(exe) != 0) {
		ui_print("-- Could not create: %s.\n-- Aborting.",tw_image_dir);
		return 1;
	} else {
		LOGI("=> Created folder: %s\n",tw_image_dir);
	}
	FILE *fp;
	char pOutput[25];
	int sdSpaceFinal;
	LOGI("=> Checking space on %s.\n",SDCARD_ROOT);
	fp = __popen("df -k /sdcard | grep sdcard | awk '{ print $4 \" \" $3 }'", "r"); // how much space left on sdcard?
	fgets(pOutput,25,fp);
	__pclose(fp);
	if(pOutput[2] == '%') { // oh o, crespo devices report diskspace on the 3rd argument.
		if (sscanf(pOutput,"%*s %d",&sdSpaceFinal) != 1) { // is it a number?
			ui_print("-- Could not determine free space on %s.",SDCARD_ROOT); // oh noes! Can't find sdcard's free space.
			return 1;
		}
	} else {
		if (sscanf(pOutput,"%d %*s",&sdSpaceFinal) != 1) { // is it a number?
			ui_print("-- Could not determine free space on %s.",SDCARD_ROOT); // oh noes! Can't find sdcard's free space.
			return 1;
		}
	}
	LOGI("=> %s",pOutput);
	sdSpace = sdSpaceFinal; // set starting and running count of sd space
	LOGI("=> /sdcard has %d MB free.\n",sdSpace/1024);
	time(&start);
	ui_print("\n[BACKUP STARTED]\n\n");
	ui_print("-- Verifying filesystems, please wait...\n");
	verifyFst();
	ui_print("-- Updating fstab.\n");
	createFstab();
	ui_print("-- Done.\n");
	// SYSTEM
	if (DataManager_GetIntValue(TW_NANDROID_SYSTEM_VAR)) { // was system backup enabled?
		if (tw_backup(sys,tw_image_dir) == 1) { // did the backup process return an error ? 0 = no error
			ui_print("-- Error occured, check recovery.log. Aborting.\n"); //oh noes! abort abort!
			return 1;
		}
	}
	// DATA
	if (DataManager_GetIntValue(TW_NANDROID_DATA_VAR)) {
		if (tw_backup(dat,tw_image_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	// BOOT
	if (DataManager_GetIntValue(TW_NANDROID_BOOT_VAR)) {
		if (tw_backup(boo,tw_image_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	// RECOVERY
	if (DataManager_GetIntValue(TW_NANDROID_RECOVERY_VAR)) {
		if (tw_backup(rec,tw_image_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	// CACHE
	if (DataManager_GetIntValue(TW_NANDROID_CACHE_VAR)) {
		if (tw_backup(cac,tw_image_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	// WIMAX
	if (DataManager_GetIntValue(TW_NANDROID_WIMAX_VAR)) {
		if (tw_backup(wim,tw_image_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	// ANDROID-SECURE
	if (DataManager_GetIntValue(TW_NANDROID_ANDSEC_VAR)) {
		if (tw_backup(ase,tw_image_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	// SD-EXT
	if (DataManager_GetIntValue(TW_NANDROID_SDEXT_VAR)) {
		if (tw_backup(sde,tw_image_dir) == 1) {
			ui_print("-- Error occured, check recovery.log. Aborting.\n");
			return 1;
		}
	}
	LOGI("=> Checking /sdcard space again.\n\n");
	fp = __popen("df -k /sdcard| grep sdcard | awk '{ print $4 \" \" $3 }'", "r");
	fgets(pOutput,25,fp);
	__pclose(fp);
	if(pOutput[2] == '%') {
		if (sscanf(pOutput,"%*s %d",&sdSpace) != 1) { // is it a number?
			ui_print("-- Could not determine free space on %s.\n",SDCARD_ROOT); // oh noes! Can't find sdcard's free space.
			return 1;
		}
	} else {
		if (sscanf(pOutput,"%d %*s",&sdSpace) != 1) { // is it a number?
			ui_print("-- Could not determine free space on %s.\n",SDCARD_ROOT); // oh noes! Can't find sdcard's free space.
			return 1;
		}
	}
	time(&stop);
	ui_print("[%d MB TOTAL BACKED UP TO SDCARD]\n",(int)(sdSpaceFinal - sdSpace) / 1024);
	output_time("BACKUP", "COMPLETED", (int)difftime(stop, start));
	return 0;
}
void readRecFstab()
{
	FILE *fp;
	char tmpText[255];
	__system("touch /etc/mtab");
	fp = fopen("/etc/recovery.fstab", "r");
	if (fp == NULL) {
		LOGI("=> Can not open /etc/recovery.fstab.\n");
	} else {
		fgets(tmpText, 255, fp);
		fgets(tmpText, 255, fp);
		while (fgets(tmpText,255,fp) != NULL)
		{
			sscanf(tmpText,"%*c%s %s %s %s",tmp.mnt,tmp.fst,tmp.blk,tmp.dev);
			if (strcmp(tmp.mnt,"system") == 0)
			{
				strcpy(sys.fst,tmp.fst);
				if (strcmp(sys.mnt,"system") != 0)
				{
					strcpy(sys.mnt,tmp.mnt);
					strcpy(sys.blk,tmp.blk);
					strcpy(sys.dev,tmp.blk);
				}
			}
			if (strcmp(tmp.mnt,"data") == 0)
			{
				strcpy(dat.fst,tmp.fst);
				if (strcmp(dat.mnt,"data") != 0)
				{
					strcpy(dat.mnt,tmp.mnt);
					strcpy(dat.blk,tmp.blk);
					strcpy(dat.dev,tmp.blk);
				}
			}
			if (strcmp(tmp.mnt,"cache") == 0)
			{
				strcpy(cac.fst,tmp.fst);
				if (strcmp(cac.mnt,"cache") != 0)
				{
					strcpy(cac.mnt,tmp.mnt);
					strcpy(cac.blk,tmp.blk);
					strcpy(cac.dev,tmp.blk);
				}
			}
			if (strcmp(tmp.mnt,"sdcard") == 0)
			{
				strcpy(sdc.fst,tmp.fst);
				if (strcmp(sdc.mnt,"sdcard") != 0)
				{
					strcpy(sdc.mnt,tmp.mnt);
					strcpy(sdc.blk,tmp.blk);
					strcpy(sdc.dev,tmp.dev);
				}
			}
			if (strcmp(tmp.mnt,"sd-ext") == 0)
			{
				strcpy(sde.mnt,tmp.mnt);
				strcpy(sde.fst,tmp.fst);
				strcpy(sde.blk,tmp.blk);
				strcpy(sde.dev,tmp.dev);
			}
		}
	}
	fclose(fp);
	strcpy(ase.dev,"/sdcard/.android_secure");
	strcpy(ase.mnt,".android_secure");
	if (strcmp(sde.mnt,"sd-ext") != 0)
	{
		int tmpInt;
		char tmpBase[50];
		char tmpWildCard[50];
		strcpy(tmpBase,sdc.blk);
		tmpBase[strlen(tmpBase)-1] = '\0';
		sprintf(tmpWildCard,"%s%%d",tmpBase);
		sscanf(sdc.blk,tmpWildCard,&tmpInt);
		sprintf(sde.blk,"%s%d",tmpBase,tmpInt+1);
	}
	createFstab();
}
Exemple #5
0
int
nandroid_rest_exe()
{
    SetDataState("", "", 0, 0);

    const char* nan_dir = DataManager_GetStrValue("phx_restore");

    if (ensure_path_mounted(SDCARD_ROOT) != 0) {
        ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT);
        return 1;
    }

    int total = 0;
    total += (DataManager_GetIntValue(VAR_RESTORE_SYSTEM_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_DATA_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_CACHE_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_RECOVERY_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_SP1_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_SP2_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_SP3_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_BOOT_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_ANDSEC_VAR) == 1 ? 1 : 0);
    total += (DataManager_GetIntValue(VAR_RESTORE_SDEXT_VAR) == 1 ? 1 : 0);

    float sections = 1.0 / total;

    time_t rStart, rStop;
    time(&rStart);
    ui_print("\n[RESTORE STARTED]\n\n");
    if (DataManager_GetIntValue(VAR_RESTORE_SYSTEM_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(sys,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_DATA_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(dat,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_BOOT_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(boo,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_RECOVERY_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(rec,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_CACHE_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(cac,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_SP1_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(sp1,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_SP2_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(sp2,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_SP3_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(sp3,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_ANDSEC_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(ase,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    if (DataManager_GetIntValue(VAR_RESTORE_SDEXT_VAR) == 1) {
        ui_show_progress(sections, 150);
        if (phx_restore(sde,nan_dir) == 1) {
            ui_print("-- Error occured, check recovery.log. Aborting.\n");
            SetDataState("Restore failed", "", 1, 1);
            return 1;
        }
    }
    time(&rStop);
    ui_print("[RESTORE COMPLETED IN %d SECONDS]\n\n",(int)difftime(rStop,rStart));
    __system("sync");
    LOGI("=> Let's update filesystem types.\n");
    verifyFst();
    LOGI("=> And update our fstab also.\n");
    createFstab();
    SetDataState("Restore Succeeded", "", 0, 1);
    return 0;
}
Exemple #6
0
int
nandroid_back_exe()
{
    SetDataState("Starting", "backup", 0, 0);

    if (ensure_path_mounted(SDCARD_ROOT) != 0) {
        ui_print("-- Could not mount: %s.\n-- Aborting.\n",SDCARD_ROOT);
        SetDataState("Unable to mount", "/sdcard", 1, 1);
        return 1;
    }

    // Create backup folder
    struct tm *t;
    char timestamp[64];
    char image_dir[255];
    char exe[255];
    time_t start, stop;
    time_t seconds;
    seconds = time(0);
    t = localtime(&seconds);
    sprintf(timestamp,"%04d-%02d-%02d--%02d-%02d-%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); // make time stamp
    sprintf(image_dir,"%s/%s/%s/", backup_folder, device_id, timestamp); // for backup folder

    if (recursive_mkdir(image_dir))
    {
        LOGE("Unable to create folder: '%s'\n", backup_folder);
        SetDataState("Backup failed", image_dir, 1, 1);
        return -1;
    }

    // Record the start time
    time(&start);

    // Prepare operation
    ui_print("\n[BACKUP STARTED]\n");
    ui_print(" * Backup Folder: %s\n", backup_folder);
    ui_print(" * Verifying filesystems...\n");
    verifyFst();
    createFstab();
    ui_print(" * Verifying partition sizes...\n");
    updateUsedSized();
    unsigned long long sdc_free = sdcext.sze - sdcext.used;

    // Compute totals
    int total = 0;
    unsigned long long total_img_bytes = 0, total_file_bytes = 0;
    CalculateBackupDetails(&total, &total_img_bytes, &total_file_bytes);
    unsigned long long total_bytes = total_img_bytes + total_file_bytes;

    if (total == 0 || total_bytes == 0)
    {
        LOGE("Unable to compute target usage (%d partitions, %llu bytes)\n", total, total_bytes);
        SetDataState("Backup failed", image_dir, 1, 1);
        return -1;
    }

    ui_print(" * Total number of partition to back up: %d\n", total);
    ui_print(" * Total size of all data, in KB: %llu\n", total_bytes / 1024);
    ui_print(" * Available space on the SD card, in KB: %llu\n", sdc_free / 1024);

    // We can't verify sufficient space on devices where sdcard is a portion of the data partition
#ifndef RECOVERY_SDCARD_ON_DATA
    // Verify space
    if (sdc_free < (total_bytes + 0x2000000))       // We require at least 32MB of additional space
    {
        LOGE("Insufficient space on SDCARD. Required space is %lluKB, available %lluKB\n", (total_bytes + 0x2000000) / 1024, sdc_free / 1024);
        SetDataState("Backup failed", image_dir, 1, 1);
        return -1;
    }
#else
    ui_print(" * This device does not support verifying available free space.\n");
#endif

    // Prepare progress bar...
    unsigned long long img_bytes_remaining = total_img_bytes;
    unsigned long long file_bytes_remaining = total_file_bytes;
    unsigned long img_byte_time = 0, file_byte_time = 0;
    struct stat st;

    ui_set_progress(0.0);

    // SYSTEM
    if (phx_do_backup(VAR_BACKUP_SYSTEM_VAR, &sys, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))       return 1;

    // DATA
    if (phx_do_backup(VAR_BACKUP_DATA_VAR, &dat, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))         return 1;

    // BOOT
    if (phx_do_backup(VAR_BACKUP_BOOT_VAR, &boo, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))         return 1;

    // RECOVERY
    if (phx_do_backup(VAR_BACKUP_RECOVERY_VAR, &rec, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))     return 1;

    // CACHE
    if (phx_do_backup(VAR_BACKUP_CACHE_VAR, &cac, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))        return 1;

    // SP1
    if (phx_do_backup(VAR_BACKUP_SP1_VAR, &sp1, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))          return 1;

    // SP2
    if (phx_do_backup(VAR_BACKUP_SP2_VAR, &sp2, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))          return 1;

    // SP3
    if (phx_do_backup(VAR_BACKUP_SP3_VAR, &sp3, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))          return 1;

    // ANDROID-SECURE
    if (stat(ase.dev, &st) ==0)
        if (phx_do_backup(VAR_BACKUP_ANDSEC_VAR, &ase, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))       return 1;

    // SD-EXT
    if (stat(sde.dev, &st) ==0)
        if (phx_do_backup(VAR_BACKUP_SDEXT_VAR, &sde, image_dir, total_img_bytes, total_file_bytes, &img_bytes_remaining, &file_bytes_remaining, &img_byte_time, &file_byte_time))        return 1;

    ui_print(" * Verifying filesystems...\n");
    verifyFst();
    createFstab();
    ui_print(" * Verifying partition sizes...\n");
    updateUsedSized();

    time(&stop);

    // Average BPS
    unsigned long int img_bps = total_img_bytes / img_byte_time;
    unsigned long int file_bps = total_file_bytes / file_byte_time;

    LOGI("img_bps = %lu  total_img_bytes = %llu  img_byte_time = %lu\n", img_bps, total_img_bytes, img_byte_time);
    ui_print("Average backup rate for file systems: %lu MB/sec\n", (file_bps / (1024 * 1024)));
    ui_print("Average backup rate for imaged drives: %lu MB/sec\n", (img_bps / (1024 * 1024)));

    if (DataManager_GetIntValue(VAR_SKIP_MD5_GENERATE_VAR) == 1)
    {
        // If we're skipping MD5 generation, our BPS is faster by about 1.65
        file_bps = (unsigned long) (file_bps / 1.65);
        img_bps = (unsigned long) (img_bps / 1.65);
    }

    img_bps += (DataManager_GetIntValue(VAR_BACKUP_AVG_IMG_RATE) * 4);
    img_bps /= 5;

    if (DataManager_GetIntValue(VAR_USE_COMPRESSION_VAR))    file_bps += (DataManager_GetIntValue(VAR_BACKUP_AVG_FILE_COMP_RATE) * 4);
    else                                                    file_bps += (DataManager_GetIntValue(VAR_BACKUP_AVG_FILE_RATE) * 4);
    file_bps /= 5;

    DataManager_SetIntValue(VAR_BACKUP_AVG_IMG_RATE, img_bps);
    if (DataManager_GetIntValue(VAR_USE_COMPRESSION_VAR))    DataManager_SetIntValue(VAR_BACKUP_AVG_FILE_COMP_RATE, file_bps);
    else                                                    DataManager_SetIntValue(VAR_BACKUP_AVG_FILE_RATE, file_bps);

    int total_time = (int) difftime(stop, start);
    unsigned long long new_sdc_free = (sdcext.sze - sdcext.used) / (1024 * 1024);
    sdc_free /= (1024 * 1024);

    ui_print("[%lu MB TOTAL BACKED UP TO SDCARD]\n",(unsigned long) (sdc_free - new_sdc_free));
    ui_print("[BACKUP COMPLETED IN %d SECONDS]\n\n", total_time); // the end
    SetDataState("Backup Succeeded", "", 0, 1);
    return 0;
}