void read_bitmap(char* device, file_system_info fs_info, unsigned long* bitmap, int pui) { off_t a = 0, b = 0; off_t block = 0;; int start = 0; int bit_size = 1; pc_init_bitmap(bitmap, 0x00, fs_info.totalblock); fs_open(device); /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, fs_info.totalblock, fs_info.totalblock, BITMAP, bit_size); pc_init_bitmap(bitmap, 0x00, fs_info.totalblock); while (exfat_find_used_sectors(&ef, &a, &b) == 0) { printf("block %" PRId64 " %" PRId64 " \n", a, b); for (block = a; block <= b; block++) { pc_set_bit((uint64_t)block, bitmap); log_mesg(3, 0, 0, fs_opt.debug, "%s: used block %" PRId64 " \n", __FILE__, block); /// update progress update_pui(&prog, block, block, 0); } } fs_close(); /// update progress update_pui(&prog, 1, 1, 1); }
static void do_scrub(sg_t *sg, uint64_t num_blocks, uint32_t block_size) { uint64_t block_offset; uint32_t blocks_to_read = 1024*1024/block_size; progress_t progress; find_num_blocks_to_read(sg, &blocks_to_read, block_size); progress_init(&progress); for (block_offset = 0; block_offset < num_blocks; block_offset += blocks_to_read) { progress_update(&progress, block_offset, num_blocks); if (num_blocks - block_offset < blocks_to_read) blocks_to_read = num_blocks - block_offset; switch (do_scrub_read(sg, block_offset, blocks_to_read, block_size)) { case READ_OK: break; case READ_ERROR: fprintf(stderr, "Error while reading data\n"); return; case READ_MEDIUM_ERR: fprintf(stderr, "Medium error reading at offset %llu\n", (unsigned long long)block_offset); break; } } progress_update(&progress, num_blocks, num_blocks); printf("\n"); }
static int start_enter(struct state *st, struct state *prev) { progress_init(MODE_NORMAL); audio_music_fade_to(0.5f, "bgm/inter.ogg"); return start_gui(); }
static int start_action(int tok, int val) { audio_play(AUD_MENU, 1.0f); switch (tok) { case GUI_BACK: return goto_state(&st_set); case START_CHALLENGE: if (config_cheat()) { progress_init(curr_mode() == MODE_CHALLENGE ? MODE_NORMAL : MODE_CHALLENGE); gui_toggle(challenge_id); return 1; } else { progress_init(MODE_CHALLENGE); return start_action(START_LEVEL, 0); } break; case GUI_SCORE: gui_score_set(val); start_over(gui_active(), 0); return 1; case START_LOCK_GOALS: config_set_d(CONFIG_LOCK_GOALS, val); return goto_state(&st_start); case START_LEVEL: if (progress_play(get_level(val))) return goto_state(&st_level); break; } return 1; }
void read_bitmap(char* device, file_system_info fs_info, unsigned long* bitmap, int pui) { uint32_t offset, total, current; uint32_t used_block = 0, free_block = 0, err_block = 0; int status = 0; int start = 0; int bit_size = 1; fs_open(device); /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, fs_info.totalblock, fs_info.totalblock, BITMAP, bit_size); offset = logical_volume_offset(fs); total = fs->fbb->bmh.total_items + offset; // containing the volume information and the LVM information for(current = 0; current < offset; current++){ pc_set_bit(current, bitmap); used_block++; update_pui(&prog, current, current, 0); } // the logical volume for(current = offset; current < total; current++){ status = vmfs_block_get_status(fs, VMFS_BLK_FB_BUILD(current-offset,0)); if (status == -1) { err_block++; pc_clear_bit(current, bitmap); } else if (status == 1){ used_block++; pc_set_bit(current, bitmap); } else if (status == 0){ free_block++; pc_clear_bit(current, bitmap); } log_mesg(2, 0, 0, fs_opt.debug, "%s: Block 0x%8.8x status: %i\n", __FILE__, current, status); update_pui(&prog, current, current, 0); } fs_close(); update_pui(&prog, 1, 1, 1); log_mesg(0, 0, 0, fs_opt.debug, "%s: Used:%"PRIu32", Free:%"PRIu32", Status err:%"PRIu32"\n", __FILE__, used_block, free_block, err_block); }
static void write_inode_tables(ext2_filsys fs) { errcode_t retval; blk_t blk; dgrp_t i; int num; struct progress_struct progress; int lazy_flag = 0; if (quiet) memset(&progress, 0, sizeof(progress)); else progress_init(&progress, _("Writing inode tables: "), fs->group_desc_count); if (EXT2_HAS_COMPAT_FEATURE(fs->super, EXT2_FEATURE_COMPAT_LAZY_BG)) lazy_flag = 1; for (i = 0; i < fs->group_desc_count; i++) { progress_update(&progress, i); blk = fs->group_desc[i].bg_inode_table; num = fs->inode_blocks_per_group; if (!(lazy_flag && (fs->group_desc[i].bg_flags & EXT2_BG_INODE_UNINIT))) { retval = zero_blocks(fs, blk, num, 0, &blk, &num); if (retval) { fprintf(stderr, _("\nCould not write %d " "blocks in inode table starting at %u: %s\n"), num, blk, error_message(retval)); exit(1); } } if (sync_kludge) { if (sync_kludge == 1) sync(); else if ((i % sync_kludge) == 0) sync(); } } zero_blocks(0, 0, 0, 0, 0, 0); progress_close(&progress); }
static void set_ecc(uint32_t start, uint32_t size) { uint32_t i = start + 8; uint8_t ecc = 0; printf("About to erase and set ECC bits in region 0x%08x to 0x%08x\n", start, start + size); check_confirm(); erase_range(start, size, true); printf("Programming ECC bits...\n"); progress_init(size); while (i < start + size) { blocklevel_write(bl, i, &ecc, sizeof(ecc)); i += 9; progress_tick(i - start); } progress_end(); }
int main(int argc, char *argv[] ) { progress_t bar; // progress_init(&bar, "", 50, PROGRESS_NUM_STYLE); // progress_init(&bar, "", 50, PROGRESS_CHR_STYLE); progress_init(&bar, "", 50, PROGRESS_BGC_STYLE); int i; for (i = 0; i <= 50; i++) { progress_show(&bar, i / 50.0f); sleep(1); } printf("\n+-Done\n"); progress_destroy(&bar); return 0; }
/// readbitmap - read bitmap extern void readbitmap(char* device, image_head image_hdr, char* bitmap, int pui) { unsigned long long total_block, block, bused = 0, bfree = 0; int done = 0, i = 0, start = 0, bit_size = 1; char* p; fs_open(device); /// init progress progress_bar bprog; /// progress_bar structure defined in progress.h progress_init(&bprog, start, image_hdr.totalblock, bit_size); total_block = 0; /// read group while ((i = cgread(&disk)) != 0) { log_mesg(2, 0, 0, fs_opt.debug, "%s: \ncg = %d\n", __FILE__, disk.d_lcg); log_mesg(2, 0, 0, fs_opt.debug, "%s: blocks = %i\n", __FILE__, acg.cg_ndblk); p = cg_blksfree(&acg); for (block = 0; block < acg.cg_ndblk; block++) { if (isset(p, block)) { bitmap[total_block] = 0; bfree++; log_mesg(3, 0, 0, fs_opt.debug, "%s: bitmap is free %lli\n", __FILE__, block); } else { bitmap[total_block] = 1; bused++; log_mesg(3, 0, 0, fs_opt.debug, "%s: bitmap is used %lli\n", __FILE__, block); } total_block++; update_pui(&bprog, total_block ,done); } log_mesg(1, 0, 0, fs_opt.debug, "%s: read bitmap done\n", __FILE__); } fs_close(); log_mesg(1, 0, 0, fs_opt.debug, "%s: total used = %lli, total free = %lli\n", __FILE__, bused, bfree); done = 1; update_pui(&bprog, 1, done); }
void read_bitmap(char* device, file_system_info fs_info, unsigned long* bitmap, int pui) { reiserfs_bitmap_t *fs_bitmap; reiserfs_tree_t *tree; unsigned long long blk = 0; unsigned long long bused = 0, bfree = 0; int start = 0; int bit_size = 1; int done = 0; fs_open(device); tree = reiserfs_fs_tree(fs); fs_bitmap = tree->fs->bitmap; /// init progress progress_bar bprog; /// progress_bar structure defined in progress.h progress_init(&bprog, start, fs->super->s_v1.sb_block_count, fs->super->s_v1.sb_block_count, BITMAP, bit_size); for( blk = 0; blk < (unsigned long long)fs->super->s_v1.sb_block_count; blk++ ){ log_mesg(3, 0, 0, fs_opt.debug, "%s: block sb_block_count %llu\n", __FILE__, fs->super->s_v1.sb_block_count); log_mesg(3, 0, 0, fs_opt.debug, "%s: block bitmap check %llu\n", __FILE__, blk); if(reiserfs_tools_test_bit(blk, fs_bitmap->bm_map)){ bused++; pc_set_bit(blk, bitmap); }else{ bfree++; pc_clear_bit(blk, bitmap); } /// update progress update_pui(&bprog, blk, blk, done); } if(bfree != fs->super->s_v1.sb_free_blocks) log_mesg(0, 1, 1, fs_opt.debug, "%s: bitmap free count err, free:%i\n", __FILE__, bfree); fs_close(); /// update progress update_pui(&bprog, 1, 1, 1); }
/// readbitmap - read bitmap extern void readbitmap(char* device, image_head image_hdr, char* bitmap, int pui) { reiserfs_bitmap_t *fs_bitmap; reiserfs_tree_t *tree; reiserfs_block_t *node; blk_t blk; unsigned long long bused = 0, bfree = 0; int start = 0; int bit_size = 1; int done = 0; fs_open(device); tree = reiserfs_fs_tree(fs); fs_bitmap = tree->fs->bitmap; /// init progress progress_bar bprog; /// progress_bar structure defined in progress.h progress_init(&bprog, start, fs->super->s_v1.sb_block_count, bit_size); for(blk = 0 ; (int)blk < fs->super->s_v1.sb_block_count; blk++){ if(reiserfs_tools_test_bit(blk, fs_bitmap->bm_map)){ bused++; bitmap[blk] = 1; }else{ bfree++; bitmap[blk] = 0; } /// update progress update_pui(&bprog, blk, done); } if(bfree != fs->super->s_v1.sb_free_blocks) log_mesg(0, 1, 1, fs_opt.debug, "%s: bitmap free count err, free:%i\n", __FILE__, bfree); fs_close(); /// update progress done = 1; update_pui(&bprog, 1, done); }
static void create_journal_dev(ext2_filsys fs) { struct progress_struct progress; errcode_t retval; char *buf; blk_t blk; int count; retval = ext2fs_create_journal_superblock(fs, fs->super->s_blocks_count, 0, &buf); if (retval) { com_err("create_journal_dev", retval, _("while initializing journal superblock")); exit(1); } if (quiet) memset(&progress, 0, sizeof(progress)); else progress_init(&progress, _("Zeroing journal device: "), fs->super->s_blocks_count); retval = zero_blocks(fs, 0, fs->super->s_blocks_count, &progress, &blk, &count); if (retval) { com_err("create_journal_dev", retval, _("while zeroing journal device (block %u, count %d)"), blk, count); exit(1); } zero_blocks(0, 0, 0, 0, 0, 0); retval = io_channel_write_blk(fs->io, fs->super->s_first_data_block+1, 1, buf); if (retval) { com_err("create_journal_dev", retval, _("while writing journal superblock")); exit(1); } progress_close(&progress); }
/// readbitmap - read bitmap extern void readbitmap(char* device, image_head image_hdr, char*bitmap, int pui) { reiser4_bitmap_t *fs_bitmap; unsigned long long bit, block, bused = 0, bfree = 0; int start = 0; int bit_size = 1; fs_open(device); fs_bitmap = reiser4_bitmap_create(reiser4_format_get_len(fs->format)); reiser4_alloc_extract(fs->alloc, fs_bitmap); /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, image_hdr.totalblock, bit_size); for(bit = 0; bit < reiser4_format_get_len(fs->format); bit++){ block = bit ; if(reiser4_bitmap_test(fs_bitmap, bit)){ bused++; bitmap[block] = 1; log_mesg(3, 0, 0, fs_opt.debug, "%s: bitmap is used %lli", block, __FILE__); } else { bitmap[block] = 0; bfree++; log_mesg(3, 0, 0, fs_opt.debug, "%s: bitmap is free %lli", block, __FILE__); } /// update progress update_pui(&prog, bit, 0); } if(bfree != reiser4_format_get_free(fs->format)) log_mesg(0, 1, 1, fs_opt.debug, "%s: bitmap free count err, bfree:%lli, sfree=%lli\n", __FILE__, bfree, reiser4_format_get_free(fs->format)); fs_close(); /// update progress update_pui(&prog, bit, 1); }
void ensure_allinstfiles_available(void) { struct pkg_array array; struct pkginfo *pkg; struct progress progress; int i; if (allpackagesdone) return; if (saidread<2) { int max = pkg_db_count_pkg(); saidread=1; progress_init(&progress, _("(Reading database ... "), max); } pkg_array_init_from_db(&array); pkg_files_optimize_load(&array); for (i = 0; i < array.n_pkgs; i++) { pkg = array.pkgs[i]; ensure_packagefiles_available(pkg); if (saidread == 1) progress_step(&progress); } pkg_array_destroy(&array); allpackagesdone = true; if (saidread==1) { progress_done(&progress); printf(P_("%d file or directory currently installed.)\n", "%d files and directories currently installed.)\n", nfiles), nfiles); saidread=2; } }
/// readbitmap - read bitmap extern void readbitmap(char* device, image_head image_hdr, unsigned long* bitmap, int pui) { uint32_t current = 0, used_block = 0, free_block = 0, err_block = 0, total = 0, alloc = 0; int status = 0; int start = 0; int bit_size = 1; fs_open(device); /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, image_hdr.totalblock, image_hdr.totalblock, BITMAP, bit_size); total = fs->fbb->bmh.total_items; alloc = vmfs_bitmap_allocated_items(fs->fbb); for(current = 0; current < total; current++){ status = vmfs_block_get_status(fs, VMFS_BLK_FB_BUILD(current)); if (status == -1) { err_block++; pc_clear_bit(current, bitmap); } else if (status == 1){ used_block++; pc_set_bit(current, bitmap); } else if (status == 0){ free_block++; pc_clear_bit(current, bitmap); } log_mesg(2, 0, 0, fs_opt.debug, "%s: Block 0x%8.8x status: %i\n", __FILE__, current, status); update_pui(&prog, current, current, 0); } fs_close(); update_pui(&prog, 1, 1, 1); log_mesg(0, 0, 0, fs_opt.debug, "%s: Used:%lld, Free:%lld, Status err:%lld\n", __FILE__, used_block, free_block, err_block); }
void paper_coords_test(){ Img8u image = scene.render(0); Array2D<geom::ViewRay> rays = scene.getCamera(0).getAllViewRays(); progress_init("creating paper-coords image"); for(int y=0;y<480;y+=2){ progress(y,479); for(int x=0;x<640;x+=2){ Point32f coords = paper->getPaperCoordinates(rays(x,y)); if(coords.x > 0){ image(x,y,0) = 255.0 * coords.x / float(paper->getDimensions().width) ; image(x,y,1) = 0; image(x,y,2) = 255.0 * coords.y / float(paper->getDimensions().height) ; image(x+1,y) = image(x,y); image(x+1,y+1) = image(x,y); image(x,y+1) = image(x,y); } } } progress_finish(); show(image); }
int main(int argc, char *argv[]) { int res; int src; int opt; int i; char *size_suf = NULL; int size_in_lines = -1; off_t size_base1000 = 0; off_t size_base1024 = 0; off_t user_defined_size = 0; off_t user_defined_size_lines = 0; struct copy_options copy_options; copy_options_init(©_options); copy_options.lines_mode = 0; copy_options.read_only = 0; copy_options.bar = &PROGRESS; while((opt = getopt(argc, argv, "rlhs:")) != -1) { switch(opt) { case 'r': copy_options.read_only = 1; break; case 'l': copy_options.lines_mode = 1; if(size_in_lines < 0) size_in_lines = 1; break; case 's': size_base1000 = parse_size(optarg, 1000, &size_suf); size_base1024 = parse_size(optarg, 1024, &size_suf); if(size_base1000 == -1) { fprintf(stderr, "Invalid argument: %s\n", optarg); exit(255); } if(strcasecmp(size_suf, "b") == 0) { size_in_lines = 0; } else if(strcasecmp(size_suf, "ln") == 0 || strcasecmp(size_suf, "l") == 0) { size_in_lines = 1; } else if(*size_suf != 0) { fprintf(stderr, "Invalid argument: %s\n", optarg); exit(255); } break; case 'h': case '?': default: usage(); exit(255); } } if(size_base1000 || size_base1024) { if(size_in_lines > 0) { if(!copy_options.lines_mode) { fprintf(stderr, "Error: size in lines has no effect without -l option!\n"); exit(255); } user_defined_size_lines = size_base1000; } else { user_defined_size = size_base1024; } } signal(SIGALRM, draw_progress); alarm(1); if(argc > optind) { for(i = optind; i < argc; i++) { if(argc - optind > 1) fprintf(stderr, "File %s:\n", argv[i]); while((src = open(argv[i], O_RDONLY)) < 1) { if(errno != EINTR) { perror(argv[i]); exit(errno); } } progress_init(&PROGRESS, STDERR_FILENO); PROGRESS.lines_mode = copy_options.lines_mode; PROGRESS.size = user_defined_size ? user_defined_size : filesize(src); PROGRESS.size_lines = user_defined_size_lines; DRAW_PROGRESS = 1; progress_draw(&PROGRESS); res = copy(src, STDOUT_FILENO, ©_options); if(res >= 0) PROGRESS.force_done = 1; progress_draw(&PROGRESS); DRAW_PROGRESS = 0; fputs("\n", stderr); if(res < 0) { perror("copy"); exit(errno); } close(src); } } else { progress_init(&PROGRESS, STDERR_FILENO); PROGRESS.lines_mode = copy_options.lines_mode; /* if used `pp < file` form */ PROGRESS.size = user_defined_size ? user_defined_size : filesize(STDIN_FILENO); PROGRESS.size_lines = user_defined_size_lines; DRAW_PROGRESS = 1; progress_draw(&PROGRESS); res = copy(STDIN_FILENO, STDOUT_FILENO, ©_options); if(res >= 0) PROGRESS.force_done = 1; progress_draw(&PROGRESS); DRAW_PROGRESS = 0; fputs("\n", stderr); } return EXIT_SUCCESS; }
/// readbitmap - read and check bitmap extern void readbitmap(char* device, image_head image_hdr, unsigned long* bitmap, int pui) { unsigned long long i = 0; int fat_stat = 0; unsigned long long block = 0, bfree = 0, bused = 0, DamagedClusters = 0; unsigned long long cluster_count = 0; unsigned long long total_sector = 0; unsigned long long FatReservedBytes = 0; int start = 0; int bit_size = 1; fs_open(device); total_sector = get_total_sector(); cluster_count = get_cluster_count(); /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, cluster_count, image_hdr.totalblock, BITMAP, bit_size); /// init bitmap memset(bitmap, 0xFF, sizeof(unsigned long)*LONGS(total_sector)); /// A) B) C) block = mark_reserved_sectors(bitmap, block); /// D) The clusters FatReservedBytes = fat_sb.sector_size * fat_sb.reserved; /// The first cluster will be seek lseek(ret, FatReservedBytes, SEEK_SET); /// The second used to check FAT status fat_stat = check_fat_status(); if(fs_opt.ignore_fschk){ log_mesg(1, 0, 0, fs_opt.debug, "%s: Ignore filesystem check\n", __FILE__); }else{ if (fat_stat == 1) log_mesg(0, 1, 1, fs_opt.debug, "%s: Filesystem isn't in valid state. May be it is not cleanly unmounted.\n\n", __FILE__); else if (fat_stat == 2) log_mesg(0, 1, 1, fs_opt.debug, "%s: I/O error! %X\n", __FILE__); } for (i=0; i < cluster_count; i++){ /// If FAT16 if(FS == FAT_16){ block = check_fat16_entry(bitmap, block, &bfree, &bused, &DamagedClusters); } else if (FS == FAT_32){ /// FAT32 block = check_fat32_entry(bitmap, block, &bfree, &bused, &DamagedClusters); } else if (FS == FAT_12){ /// FAT12 block = check_fat12_entry(bitmap, block, &bfree, &bused, &DamagedClusters); } else log_mesg(2, 0, 0, fs_opt.debug, "%s: error fs\n", __FILE__); /// update progress update_pui(&prog, i, i, 0);//keep update } log_mesg(2, 0, 0, fs_opt.debug, "%s: done\n", __FILE__); fs_close(); /// update progress update_pui(&prog, 1, 1, 1);//finish }
void nemo_main(void){ int i,numwritten=0,nummissed=0; int numimages=0; stream fp_in,fp,fp2; string *sp,logic; int count,n; int edge_dist; /* exclude sources this many pixels from the edge */ string inFile; /* name of input file */ char line[MAX_LINELEN]; /* a line of text from the inFile */ int racol,deccol,maxcol; /* column numbers for ra/dec in file */ double ra,dec; /* the values of ra/dec for a given line */ int nentries; /* number of valid entries, used for progress tracking */ inFile = getparam("in"); edge_dist = getiparam("edge"); logic = getparam("logic"); sp = burststring(getparam("col"),", \n"); n = xstrlen(sp,sizeof(string)) - 1; if (n != 2) error("You must specify ra,dec columns for col keyword!"); racol = natoi(sp[0]) - 1; deccol = natoi(sp[1]) - 1; freestrings(sp); if (racol >= deccol) maxcol = racol; else maxcol = deccol; sp = burststring(getparam("fits"),", \n"); n = xstrlen(sp,sizeof(string))-1; for (i=0; i<n; i++){ ini_mask(sp[i],i); numimages++; } freestrings(sp); sp = burststring(getparam("out"),", \n"); n = xstrlen(sp,sizeof(string))-1; if (n == 1){ fp = stropen(sp[0],"w"); fp2 = stropen("/dev/null","w!"); } else if (n == 2){ fp = stropen(sp[0],"w"); fp2 = stropen(sp[1],"w"); }else error("You must give one or two output files!\n"); freestrings(sp); nentries = nemo_file_lines(inFile,0); progress_init("overlap percent complete:",nentries); nentries = 0; fp_in = stropen(inFile,"r"); while (fgets(line,MAX_LINELEN,fp_in)){ progress_update(nentries); if (line[0] != '#'){ nentries += 1; sp = burststring(line," \t\n"); n = xstrlen(sp,sizeof(string)) - 2; /* zero based */ if (n < maxcol) error("Insufficient columns on line!"); ra = natof(sp[racol]); dec = natof(sp[deccol]); freestrings(sp); count = 0; for (i=0; i< numimages; i++) count+= is_edge(ra,dec,edge_dist,i); if(streq(logic,"or") && (count<numimages)){ fprintf(fp,line); numwritten++; } else if(streq(logic,"and") && (count==0) && (numimages > 0)){ fprintf(fp,line); numwritten++; } else { fprintf(fp2,line); nummissed++; } } } strclose(fp_in); strclose(fp); strclose(fp2); progress_finish(); printf("Sources outside regions: %d\n",nummissed); printf("Sources inside regions: %d\n",numwritten); printf("Number of images: %d\n",numimages); }
extern void readbitmap(char* device, image_head image_hdr, unsigned long* bitmap, int pui) { xfs_agnumber_t agno = 0; xfs_agblock_t first_agbno; xfs_agnumber_t num_ags; ag_header_t ag_hdr; xfs_daddr_t read_ag_off; int read_ag_length; void *read_ag_buf = NULL; xfs_off_t read_ag_position; /* xfs_types.h: typedef __s64 */ uint64_t sk, res, s_pos = 0; void *btree_buf_data = NULL; int btree_buf_length; xfs_off_t btree_buf_position; xfs_agblock_t bno; uint current_level; uint btree_levels; xfs_daddr_t begin, next_begin, ag_begin, new_begin, ag_end; /* xfs_types.h: typedef __s64*/ xfs_off_t pos; xfs_alloc_ptr_t *ptr; xfs_alloc_rec_t *rec_ptr; int length; int i; uint64_t size, sizeb; xfs_off_t w_position; int w_length; int wblocks; int w_size = 1 * 1024 * 1024; uint64_t numblocks = 0; xfs_off_t logstart, logend; xfs_off_t logstart_pos, logend_pos; int log_length; struct xfs_btree_block *block; uint64_t current_block, block_count, prog_cur_block = 0; int start = 0; int bit_size = 1; progress_bar prog; uint64_t bused = 0; uint64_t bfree = 0; /// init progress progress_init(&prog, start, image_hdr.totalblock, image_hdr.totalblock, BITMAP, bit_size); fs_open(device); first_agbno = (((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize) + first_residue) / source_blocksize; num_ags = mp->m_sb.sb_agcount; log_mesg(1, 0, 0, fs_opt.debug, "ags = %i\n", num_ags); for (agno = 0; agno < num_ags ; agno++) { /* read in first blocks of the ag */ /* initial settings */ log_mesg(2, 0, 0, fs_opt.debug, "read ag %i header\n", agno); read_ag_off = XFS_AG_DADDR(mp, agno, XFS_SB_DADDR); read_ag_length = first_agbno * source_blocksize; read_ag_position = (xfs_off_t) read_ag_off * (xfs_off_t) BBSIZE; read_ag_buf = malloc(read_ag_length); if(read_ag_buf == NULL){ log_mesg(0, 1, 1, fs_opt.debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } memset(read_ag_buf, 0, read_ag_length); log_mesg(2, 0, 0, fs_opt.debug, "seek to read_ag_position %lli\n", read_ag_position); sk = lseek(source_fd, read_ag_position, SEEK_SET); current_block = (sk/source_blocksize); block_count = (read_ag_length/source_blocksize); set_bitmap(bitmap, sk, read_ag_length); log_mesg(2, 0, 0, fs_opt.debug, "read ag header fd = %llu(%i), length = %i(%i)\n", sk, current_block, read_ag_length, block_count); if ((res = read(source_fd, read_ag_buf, read_ag_length)) < 0) { log_mesg(1, 0, 1, fs_opt.debug, "read failure at offset %lld\n", read_ag_position); } ag_hdr.xfs_sb = (xfs_dsb_t *) (read_ag_buf); ASSERT(be32_to_cpu(ag_hdr.xfs_sb->sb_magicnum) == XFS_SB_MAGIC); ag_hdr.xfs_agf = (xfs_agf_t *) (read_ag_buf + source_sectorsize); ASSERT(be32_to_cpu(ag_hdr.xfs_agf->agf_magicnum) == XFS_AGF_MAGIC); ag_hdr.xfs_agi = (xfs_agi_t *) (read_ag_buf + 2 * source_sectorsize); ASSERT(be32_to_cpu(ag_hdr.xfs_agi->agi_magicnum) == XFS_AGI_MAGIC); ag_hdr.xfs_agfl = (xfs_agfl_t *) (read_ag_buf + 3 * source_sectorsize); log_mesg(2, 0, 0, fs_opt.debug, "ag header read ok\n"); /* save what we need (agf) in the btree buffer */ btree_buf_data = malloc(source_blocksize); if(btree_buf_data == NULL){ log_mesg(0, 1, 1, fs_opt.debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } memset(btree_buf_data, 0, source_blocksize); memmove(btree_buf_data, ag_hdr.xfs_agf, source_sectorsize); ag_hdr.xfs_agf = (xfs_agf_t *) btree_buf_data; btree_buf_length = source_blocksize; ///* traverse btree until we get to the leftmost leaf node */ bno = be32_to_cpu(ag_hdr.xfs_agf->agf_roots[XFS_BTNUM_BNOi]); current_level = 0; btree_levels = be32_to_cpu(ag_hdr.xfs_agf->agf_levels[XFS_BTNUM_BNOi]); ag_end = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(ag_hdr.xfs_agf->agf_length) - 1) + source_blocksize / BBSIZE; for (;;) { /* none of this touches the w_buf buffer */ current_level++; btree_buf_position = pos = (xfs_off_t)XFS_AGB_TO_DADDR(mp,agno,bno) << BBSHIFT; btree_buf_length = source_blocksize; sk = lseek(source_fd, btree_buf_position, SEEK_SET); current_block = (sk/source_blocksize); block_count = (btree_buf_length/source_blocksize); set_bitmap(bitmap, sk, btree_buf_length); log_mesg(2, 0, 0, fs_opt.debug, "read btree sf = %llu(%i), length = %i(%i)\n", sk, current_block, btree_buf_length, block_count); read(source_fd, btree_buf_data, btree_buf_length); block = (struct xfs_btree_block *)((char *)btree_buf_data + pos - btree_buf_position); if (be16_to_cpu(block->bb_level) == 0) break; ptr = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); bno = be32_to_cpu(ptr[0]); } log_mesg(2, 0, 0, fs_opt.debug, "btree read done\n"); /* align first data copy but don't overwrite ag header */ pos = read_ag_position >> BBSHIFT; length = read_ag_length >> BBSHIFT; next_begin = pos + length; ag_begin = next_begin; ///* handle the rest of the ag */ for (;;) { if (be16_to_cpu(block->bb_level) != 0) { log_mesg(0, 1, 1, fs_opt.debug, "WARNING: source filesystem inconsistent.\nA leaf btree rec isn't a leaf. Aborting now.\n"); } rec_ptr = XFS_ALLOC_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++, rec_ptr++) { /* calculate in daddr's */ begin = next_begin; /* * protect against pathological case of a * hole right after the ag header in a * mis-aligned case */ if (begin < ag_begin) begin = ag_begin; /* * round size up to ensure we copy a * range bigger than required */ log_mesg(3, 0, 0, fs_opt.debug, "XFS_AGB_TO_DADDR = %llu, agno = %i, be32_to_cpu=%llu\n", XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(rec_ptr->ar_startblock)), agno, be32_to_cpu(rec_ptr->ar_startblock)); sizeb = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(rec_ptr->ar_startblock)) - begin; size = roundup(sizeb <<BBSHIFT, source_sectorsize); log_mesg(3, 0, 0, fs_opt.debug, "BB = %i size %i and sizeb %llu brgin = %llu\n", BBSHIFT, size, sizeb, begin); if (size > 0) { /* copy extent */ log_mesg(2, 0, 0, fs_opt.debug, "copy extent\n"); w_position = (xfs_off_t)begin << BBSHIFT; while (size > 0) { /* * let lower layer do alignment */ if (size > w_size) { w_length = w_size; size -= w_size; sizeb -= wblocks; numblocks += wblocks; } else { w_length = size; numblocks += sizeb; size = 0; } //read_wbuf(source_fd, &w_buf, mp); sk = lseek(source_fd, w_position, SEEK_SET); current_block = (sk/source_blocksize); block_count = (w_length/source_blocksize); set_bitmap(bitmap, sk, w_length); log_mesg(2, 0, 0, fs_opt.debug, "read ext sourcefd to w_buf source_fd=%llu(%i), length=%i(%i)\n", sk, current_block, w_length, block_count); sk = lseek(source_fd, w_length, SEEK_CUR); w_position += w_length; } } /* round next starting point down */ new_begin = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(rec_ptr->ar_startblock) + be32_to_cpu(rec_ptr->ar_blockcount)); next_begin = rounddown(new_begin, source_sectorsize >> BBSHIFT); } if (be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK){ log_mesg(2, 0, 0, fs_opt.debug, "NULLAGBLOCK\n"); break; } /* read in next btree record block */ btree_buf_position = pos = (xfs_off_t)XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(block->bb_u.s.bb_rightsib)) << BBSHIFT; btree_buf_length = source_blocksize; /* let read_wbuf handle alignment */ //read_wbuf(source_fd, &btree_buf, mp); sk = lseek(source_fd, btree_buf_position, SEEK_SET); current_block = (sk/source_blocksize); block_count = (btree_buf_length/source_blocksize); set_bitmap(bitmap, sk, btree_buf_length); log_mesg(2, 0, 0, fs_opt.debug, "read btreebuf fd = %llu(%i), length = %i(%i) \n", sk, current_block, btree_buf_length, block_count); read(source_fd, btree_buf_data, btree_buf_length); block = (struct xfs_btree_block *)((char *) btree_buf_data + pos - btree_buf_position); ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC); } /* * write out range of used blocks after last range * of free blocks in AG */ if (next_begin < ag_end) { begin = next_begin; sizeb = ag_end - begin; size = roundup(sizeb << BBSHIFT, source_sectorsize); if (size > 0) { /* copy extent */ w_position = (xfs_off_t) begin << BBSHIFT; while (size > 0) { /* * let lower layer do alignment */ if (size > w_size) { w_length = w_size; size -= w_size; sizeb -= wblocks; numblocks += wblocks; } else { w_length = size; numblocks += sizeb; size = 0; } sk = lseek(source_fd, w_position, SEEK_SET); current_block = (sk/source_blocksize); block_count = (w_length/source_blocksize); set_bitmap(bitmap, sk, w_length); log_mesg(2, 0, 0, fs_opt.debug, "read ext fd = %llu(%i), length = %i(%i)\n", sk, current_block, w_length, block_count); //read_wbuf(source_fd, &w_buf, mp); lseek(source_fd, w_length, SEEK_CUR); w_position += w_length; } } } log_mesg(2, 0, 0, fs_opt.debug, "write a clean log\n"); log_length = 1 * 1024 * 1024; logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart) << BBSHIFT; logstart_pos = rounddown(logstart, (xfs_off_t)log_length); if (logstart % log_length) { /* unaligned */ sk = lseek(source_fd, logstart_pos, SEEK_SET); current_block = (sk/source_blocksize); block_count = (log_length/source_blocksize); set_bitmap(bitmap, sk, log_length); log_mesg(2, 0, 0, fs_opt.debug, "read log start from %llu(%i) %i(%i)\n", sk, current_block, log_length, block_count); sk = lseek(source_fd, log_length, SEEK_CUR); } logend = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart) << BBSHIFT; logend += XFS_FSB_TO_B(mp, mp->m_sb.sb_logblocks); logend_pos = rounddown(logend, (xfs_off_t)log_length); if (logend % log_length) { /* unaligned */ sk = lseek(source_fd, logend_pos, SEEK_SET); current_block = (sk/source_blocksize); block_count = (log_length/source_blocksize); set_bitmap(bitmap, sk, log_length); log_mesg(2, 0, 0, fs_opt.debug, "read log end from %llu(%i) %i(%i)\n", sk, current_block, log_length, block_count); sk = lseek(source_fd, log_length, SEEK_CUR); } log_mesg(2, 0, 0, fs_opt.debug, "write a clean log done\n"); prog_cur_block = image_hdr.totalblock/num_ags*(agno+1)-1; update_pui(&prog, prog_cur_block, prog_cur_block, 0); } for(current_block = 0; current_block <= image_hdr.totalblock; current_block++){ if(pc_test_bit(current_block, bitmap)) bused++; else bfree++; } log_mesg(0, 0, 0, fs_opt.debug, "bused = %lli, bfree = %lli\n", bused, bfree); fs_close(); update_pui(&prog, 1, 1, 1); }
/** * main functiom - for colne or restore data */ int main(int argc, char **argv) { #ifdef MEMTRACE setenv("MALLOC_TRACE", "partclone_mtrace.log", 1); mtrace(); #endif char* source; /// source data char* target; /// target data char* buffer; /// buffer data for malloc used char* buffer2; /// buffer data for malloc used int dfr, dfw; /// file descriptor for source and target int r_size, w_size; /// read and write size //unsigned long long block_id, copied = 0; /// block_id is every block in partition /// copied is copied block count off_t offset = 0, sf = 0; /// seek postition, lseek result int start, stop; /// start, range, stop number for progress bar unsigned long long total_write = 0; /// the copied size unsigned long long needed_size = 0; /// the copied size unsigned long long needed_mem = 0; /// the copied size char bitmagic[8] = "BiTmAgIc";// only for check postition char bitmagic_r[8]="00000000";/// read magic string from image int cmp; /// compare magic string unsigned long *bitmap; /// the point for bitmap data int debug = 0; /// debug or not unsigned long crc = 0xffffffffL; /// CRC32 check code for writint to image unsigned long crc_ck = 0xffffffffL; /// CRC32 check code for checking unsigned long crc_ck2 = 0xffffffffL; /// CRC32 check code for checking int c_size; /// CRC32 code size int n_crc_size = CRC_SIZE; char* crc_buffer; /// buffer data for malloc crc code //int done = 0; int s_count = 0; int rescue_num = 0; unsigned long long rescue_pos = 0; unsigned long long main_pos = 0; int tui = 0; /// text user interface int pui = 0; /// progress mode(default text) int next=1,next_int=1,next_max_count=7,next_count=7,i; unsigned long long next_block_id; char* cache_buffer; int nx_current=0; char bbuffer[4096]; int flag; int pres; pthread_t prog_thread; void *p_result; char *bad_sectors_warning_msg = "*************************************************************************\n" "* WARNING: The disk has bad sector. This means physical damage on the *\n" "* disk surface caused by deterioration, manufacturing faults or other *\n" "* reason. The reliability of the disk may stay stable or degrade fast. *\n" "* Use the --rescue option to efficiently save as much data as possible! *\n" "*************************************************************************\n"; image_head image_hdr; /// image_head structure defined in partclone.h memset(&image_hdr, 0, sizeof(image_hdr)); /** * get option and assign to opt structure * check parameter and read from argv */ parse_options(argc, argv, &opt); /** * if "-d / --debug" given * open debug file in "/var/log/partclone.log" for log message */ memset(&fs_opt, 0, sizeof(fs_cmd_opt)); debug = opt.debug; fs_opt.debug = debug; fs_opt.ignore_fschk = opt.ignore_fschk; next_max_count = opt.max_block_cache-1; next_count = opt.max_block_cache-1; //if(opt.debug) open_log(opt.logfile); /** * using Text User Interface */ if (opt.ncurses) { pui = NCURSES; log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n"); } else pui = TEXT; tui = open_pui(pui, opt.fresh); if ((opt.ncurses) && (tui == 0)) { opt.ncurses = 0; log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n"); } /// print partclone info print_partclone_info(opt); if (geteuid() != 0) log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n"); else log_mesg(1, 0, 0, debug, "UID is root.\n"); /// ignore crc check if(opt.ignore_crc) log_mesg(1, 0, 1, debug, "Ignore CRC error\n"); /** * open source and target * clone mode, source is device and target is image file/stdout * restore mode, source is image file/stdin and target is device * dd mode, source is device and target is device !!not complete */ #ifdef _FILE_OFFSET_BITS log_mesg(1, 0, 0, debug, "enable _FILE_OFFSET_BITS %i\n", _FILE_OFFSET_BITS); #endif source = opt.source; target = opt.target; dfr = open_source(source, &opt); if (dfr == -1) { log_mesg(0, 1, 1, debug, "Erro EXIT.\n"); } dfw = open_target(target, &opt); if (dfw == -1) { log_mesg(0, 1, 1, debug, "Error Exit.\n"); } /** * get partition information like super block, image_head, bitmap * from device or image file. */ if (opt.clone) { log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n"); log_mesg(0, 0, 1, debug, "Reading Super Block\n"); /// get Super Block information from partition initial_image_hdr(source, &image_hdr); /// check memory size if (check_mem_size(image_hdr, opt, &needed_mem) == -1) log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem); strncpy(image_hdr.version, IMAGE_VERSION, VERSION_SIZE); /// alloc a memory to restore bitmap bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock)); if(bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %i\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from partition log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... "); readbitmap(source, image_hdr, bitmap, pui); needed_size = (unsigned long long)(((image_hdr.block_size+sizeof(unsigned long))*image_hdr.usedblocks)+sizeof(image_hdr)+sizeof(char)*image_hdr.totalblock); if (opt.check) check_free_space(&dfw, needed_size); log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap); log_mesg(1, 0, 0, debug, "Writing super block and bitmap... "); // write image_head to image file w_size = write_all(&dfw, (char *)&image_hdr, sizeof(image_head), &opt); if(w_size == -1) log_mesg(0, 1, 1, debug, "write image_hdr to image error\n"); // write bitmap information to image file for (i = 0; i < image_hdr.totalblock; i++) { if (pc_test_bit(i, bitmap)) { bbuffer[i % sizeof(bbuffer)] = 1; } else { bbuffer[i % sizeof(bbuffer)] = 0; } if (i % sizeof(bbuffer) == sizeof(bbuffer) - 1 || i == image_hdr.totalblock - 1) { w_size = write_all(&dfw, bbuffer, 1 + (i % sizeof(bbuffer)), &opt); if(w_size == -1) log_mesg(0, 1, 1, debug, "write bitmap to image error\n"); } } log_mesg(0, 0, 1, debug, "done!\n"); } else if (opt.restore) { log_mesg(1, 0, 0, debug, "restore image hdr - get image_head from image file\n"); log_mesg(1, 0, 1, debug, "Reading Super Block\n"); /// get image information from image file restore_image_hdr(&dfr, &opt, &image_hdr); /// check memory size if (check_mem_size(image_hdr, opt, &needed_mem) == -1) log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem); /// alloc a memory to restore bitmap bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock)); if(bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } /// check the image magic if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0) log_mesg(0, 1, 1, debug, "This is not partclone image.\n"); /// check the file system //if (strcmp(image_hdr.fs, FS) != 0) // log_mesg(0, 1, 1, debug, "%s can't restore from the image which filesystem is %s not %s\n", argv[0], image_hdr.fs, FS); log_mesg(2, 0, 0, debug, "initial main bitmap pointer %lli\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from image file log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... "); get_image_bitmap(&dfr, opt, image_hdr, bitmap); /// check the dest partition size. if (opt.restore_row_file) check_free_space(&dfw, image_hdr.device_size); else if(opt.check) check_size(&dfw, image_hdr.device_size); log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); } else if (opt.dd) { log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n"); log_mesg(1, 0, 1, debug, "Reading Super Block\n"); /// get Super Block information from partition initial_image_hdr(source, &image_hdr); /// check memory size if (check_mem_size(image_hdr, opt, &needed_mem) == -1) log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem); strncpy(image_hdr.version, IMAGE_VERSION, VERSION_SIZE); /// alloc a memory to restore bitmap bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock)); if(bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %i\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from partition log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... "); readbitmap(source, image_hdr, bitmap, pui); /// check the dest partition size. if(opt.check) { check_size(&dfw, image_hdr.device_size); } log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); } else if (opt.domain) { log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n"); log_mesg(1, 0, 1, debug, "Reading Super Block\n"); /// get Super Block information from partition initial_image_hdr(source, &image_hdr); /// check memory size if (check_mem_size(image_hdr, opt, &needed_mem) == -1) log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %lld bytes memory\n", needed_mem); strncpy(image_hdr.version, IMAGE_VERSION, VERSION_SIZE); /// alloc a memory to restore bitmap bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock)); if(bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %i\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from partition log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... "); readbitmap(source, image_hdr, bitmap, pui); log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); } log_mesg(1, 0, 0, debug, "print image_head\n"); /// print option to log file if (debug) print_opt(opt); /// print image_head print_image_hdr_info(image_hdr, opt); /** * initial progress bar */ //progress_bar prog; /// progress_bar structure defined in progress.h start = 0; /// start number of progress bar stop = (image_hdr.usedblocks); /// get the end of progress number, only used block log_mesg(1, 0, 0, debug, "Initial Progress bar\n"); /// Initial progress bar if (opt.no_block_detail) flag = NO_BLOCK_DETAIL; else flag = IO; progress_init(&prog, start, stop, image_hdr.totalblock, flag, image_hdr.block_size); copied = 0; /// initial number is 0 /** * thread to print progress */ pres = pthread_create(&prog_thread, NULL, thread_update_pui, NULL); /** * start read and write data between device and image file */ if (opt.clone) { w_size = write_all(&dfw, bitmagic, 8, &opt); /// write a magic string /// read data from the first block and log the offset sf = lseek(dfr, 0, SEEK_SET); log_mesg(1, 0, 0, debug, "seek %lli for reading data string\n",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "seek set %lli\n", sf); buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data if(buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } log_mesg(0, 0, 0, debug, "Total block %i\n", image_hdr.totalblock); /// start clone partition to image file log_mesg(1, 0, 0, debug, "start backup data...\n"); for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ) { r_size = 0; w_size = 0; main_pos = lseek(dfr, 0, SEEK_CUR); log_mesg(3, 0, 0, debug, "man pos = %lli\n", main_pos); if (pc_test_bit(block_id, bitmap)) { /// if the block is used log_mesg(1, 0, 0, debug, "block_id=%lli, ",block_id); log_mesg(2, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap)); offset = (off_t)(block_id * image_hdr.block_size); #ifdef _FILE_OFFSET_BITS sf = lseek(dfr, offset, SEEK_SET); if (sf == -1) log_mesg(0, 1, 1, debug, "source seek error = %lli, ",sf); #endif /// read data from source to buffer memset(buffer, 0, image_hdr.block_size); rescue_pos = lseek(dfr, 0, SEEK_CUR); r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt); log_mesg(3, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size); if (r_size != (int)image_hdr.block_size) { if ((r_size == -1) && (errno == EIO)) { if (opt.rescue) { r_size = 0; for (rescue_num = 0; rescue_num < image_hdr.block_size; rescue_num += SECTOR_SIZE) { rescue_sector(&dfr, rescue_pos + rescue_num, buffer + rescue_num, &opt); r_size+=SECTOR_SIZE; } } else log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg); } else log_mesg(0, 1, 1, debug, "read error: %s(%i) \n", strerror(errno), errno); } /// write buffer to target w_size = write_all(&dfw, buffer, image_hdr.block_size, &opt); log_mesg(3, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size); if (w_size != (int)image_hdr.block_size) log_mesg(0, 1, 1, debug, "write error %i \n", w_size); /// generate crc32 code and write it. crc_buffer = (char*)malloc(CRC_SIZE); ///alloc a memory to copy data if(crc_buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } crc = crc32(crc, buffer, w_size); memcpy(crc_buffer, &crc, CRC_SIZE); c_size = write_all(&dfw, crc_buffer, CRC_SIZE, &opt); /// free buffer free(crc_buffer); copied++; /// count copied block total_write += (unsigned long long)(w_size); /// count copied size log_mesg(3, 0, 0, debug, "total=%lli, ", total_write); /// read or write error if (r_size != w_size) log_mesg(0, 1, 1, debug, "read(%i) and write(%i) different\n", r_size, w_size); log_mesg(2, 0, 0, debug, "end\n"); } else { #ifndef _FILE_OFFSET_BITS /// if the block is not used, I just skip it. log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id); sf = lseek(dfr, image_hdr.block_size, SEEK_CUR); log_mesg(2, 0, 0, debug, "skip seek=%lli, ",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "clone seek error %lli errno=%i\n", (long long)offset, (int)errno); log_mesg(2, 0, 0, debug, "end\n"); #endif } } /// end of for free(buffer); } else if (opt.restore) { /** * read magic string from image file * and check it. */ r_size = read_all(&dfr, bitmagic_r, 8, &opt); /// read a magic string cmp = memcmp(bitmagic, bitmagic_r, 8); if(cmp != 0) log_mesg(0, 1, 1, debug, "bitmagic error %i\n", cmp); /// seek to the first sf = lseek(dfw, 0, SEEK_SET); log_mesg(1, 0, 0, debug, "seek %lli for writing dtat string\n",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "seek set %lli\n", sf); cache_buffer = (char*)malloc(image_hdr.block_size * (next_max_count+1)); if(cache_buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data if(buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } /// start restore image file to partition log_mesg(1, 0, 0, debug, "start restore data...\n"); for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ) { r_size = 0; w_size = 0; if (pc_test_bit(block_id, bitmap)) { /// The block is used log_mesg(1, 0, 0, debug, "block_id=%lli, ",block_id); log_mesg(2, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap)); memset(buffer, 0, image_hdr.block_size); r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt); log_mesg(3, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size); if (r_size <0) log_mesg(0, 1, 1, debug, "read errno = %i \n", errno); /// read crc32 code and check it. crc_ck = crc32(crc_ck, buffer, r_size); crc_buffer = (char*)malloc(CRC_SIZE); ///alloc a memory to copy data if(crc_buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt); if (c_size < CRC_SIZE) log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno)); memcpy(&crc, crc_buffer, CRC_SIZE); /*FIX: 64bit image can't ignore crc error*/ if ((memcmp(&crc, &crc_ck, CRC_SIZE) != 0) && (!opt.ignore_crc)) { log_mesg(1, 0, 0, debug, "CRC Check error. 64bit bug before v0.1.0 (Rev:250M), enlarge crc size and recheck again....\n "); /// check again buffer2 = (char*)malloc(image_hdr.block_size+CRC_SIZE); ///alloc a memory to copy data if(buffer2 == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } memcpy(buffer2, buffer, image_hdr.block_size); memcpy(buffer2+image_hdr.block_size, crc_buffer, CRC_SIZE); memcpy(buffer, buffer2+CRC_SIZE, image_hdr.block_size); crc_ck2 = crc32(crc_ck2, buffer, r_size); c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt); if (c_size < CRC_SIZE) log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno)); memcpy(&crc, crc_buffer, CRC_SIZE); if ((memcmp(&crc, &crc_ck2, CRC_SIZE) != 0 )&& (!opt.ignore_crc)) { log_mesg(0, 1, 1, debug, "CRC error again at %i...\n ", sf); } else { crc_ck = crc_ck2; } free(buffer2); } else { crc_ck2 = crc_ck; } if(next != next_count) { memset(cache_buffer, 0, image_hdr.block_size*next_max_count); for (next_int = 1; next_int <= next_max_count; next_int++) { next_block_id = block_id+next_int; if (pc_test_bit(next_block_id, bitmap)) { next++; } else { next_count = next; break; } next_count = next; } log_mesg(1, 0, 0, debug, "next = %i\n",next); } if ((next == next_count) &&(nx_current < next)) { memcpy(cache_buffer+(image_hdr.block_size*nx_current), buffer, image_hdr.block_size); w_size = 0; nx_current++; } if ((next == next_count) && (nx_current == next)) { #ifdef _FILE_OFFSET_BITS offset = (off_t)((block_id-next+1) * image_hdr.block_size); sf = lseek(dfw, offset, SEEK_SET); if (sf == -1) log_mesg(0, 1, 1, debug, "target seek error = %lli, ",sf); #endif /// write block from buffer to partition w_size = write_all(&dfw, cache_buffer, (image_hdr.block_size*nx_current), &opt); log_mesg(1, 0, 0, debug, "bs=%i and w=%i, ",(image_hdr.block_size*nx_current), w_size); if (w_size != (int)image_hdr.block_size*nx_current) log_mesg(0, 1, 1, debug, "write error %i \n", w_size); next = 1; next_count = next_max_count; nx_current=0; } /// free buffer free(crc_buffer); copied++; /// count copied block total_write += (unsigned long long) w_size; /// count copied size /// read or write error //if ((r_size != w_size) || (r_size != image_hdr.block_size)) // log_mesg(0, 1, 1, debug, "read and write different\n"); log_mesg(1, 0, 0, debug, "end\n"); } else { /// for restore to row file, mount -o loop used. if ((block_id == (image_hdr.totalblock-1)) && (opt.restore_row_file)) { write_last_block(&dfw, image_hdr.block_size, block_id, &opt); } else { #ifndef _FILE_OFFSET_BITS /// if the block is not used, I just skip it. log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id); sf = lseek(dfw, image_hdr.block_size, SEEK_CUR); log_mesg(2, 0, 0, debug, "seek=%lli, ",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "seek error %lli errno=%i\n", (long long)offset, (int)errno); log_mesg(2, 0, 0, debug, "end\n"); #endif } } } // end of for free(buffer); } else if (opt.dd) { sf = lseek(dfr, 0, SEEK_SET); log_mesg(1, 0, 0, debug, "seek %lli for reading data string\n",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "seek set %lli\n", sf); main_pos = lseek(dfr, 0, SEEK_CUR); log_mesg(1, 0, 0, debug, "man pos = %lli\n", main_pos); log_mesg(0, 0, 0, debug, "Total block %i\n", image_hdr.totalblock); buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data if(buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } /// start clone partition to image file log_mesg(1, 0, 0, debug, "start backup data device-to-device...\n"); for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ) { r_size = 0; w_size = 0; if (pc_test_bit(block_id, bitmap)) { /// if the block is used log_mesg(1, 0, 0, debug, "block_id=%lli, ",block_id); log_mesg(2, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap)); offset = (off_t)(block_id * image_hdr.block_size); #ifdef _FILE_OFFSET_BITS sf = lseek(dfr, offset, SEEK_SET); if (sf == -1) log_mesg(0, 1, 1, debug, "source seek error = %lli, ",sf); sf = lseek(dfw, offset, SEEK_SET); if (sf == -1) log_mesg(0, 1, 1, debug, "target seek error = %lli, ",sf); #endif /// read data from source to buffer memset(buffer, 0, image_hdr.block_size); rescue_pos = lseek(dfr, 0, SEEK_CUR); r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt); log_mesg(3, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size); if (r_size != (int)image_hdr.block_size) { if ((r_size == -1) && (errno == EIO)) { if (opt.rescue) { r_size = 0; for (rescue_num = 0; rescue_num < image_hdr.block_size; rescue_num += SECTOR_SIZE) { rescue_sector(&dfr, rescue_pos + rescue_num, buffer + rescue_num, &opt); r_size+=SECTOR_SIZE; } } else log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg); } else log_mesg(0, 1, 1, debug, "read error: %s(%i) \n", strerror(errno), errno); } /// write buffer to target w_size = write_all(&dfw, buffer, image_hdr.block_size, &opt); log_mesg(3, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size); if (w_size != (int)image_hdr.block_size) log_mesg(0, 1, 1, debug, "write error %i \n", w_size); copied++; /// count copied block total_write += (unsigned long long)(w_size); /// count copied size log_mesg(2, 0, 0, debug, "total=%lli, ", total_write); /// read or write error if (r_size != w_size) log_mesg(0, 1, 1, debug, "read and write different\n"); log_mesg(1, 0, 0, debug, "end\n"); } else { #ifndef _FILE_OFFSET_BITS /// if the block is not used, I just skip it. log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id); sf = lseek(dfr, image_hdr.block_size, SEEK_CUR); log_mesg(2, 0, 0, debug, "skip source seek=%lli, ",sf); sf = lseek(dfw, image_hdr.block_size, SEEK_CUR); log_mesg(2, 0, 0, debug, "skip target seek=%lli, ",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "clone seek error %lli errno=%i\n", (long long)offset, (int)errno); #endif } } /// end of for free(buffer); } else if (opt.domain) { log_mesg(0, 0, 0, debug, "Total block %i\n", image_hdr.totalblock); log_mesg(1, 0, 0, debug, "start writing domain log...\n"); // write domain log comment and status line dprintf(dfw, "# Domain logfile created by %s v%s\n", EXECNAME, VERSION); dprintf(dfw, "# Source: %s\n", opt.source); dprintf(dfw, "# Offset: 0x%08llX\n", opt.offset_domain); dprintf(dfw, "# current_pos current_status\n"); dprintf(dfw, "0x%08llX ?\n", opt.offset_domain + (image_hdr.totalblock * image_hdr.block_size)); dprintf(dfw, "# pos size status\n"); // start logging the used/unused areas next_block_id = 0; cmp = pc_test_bit(0, bitmap); for( block_id = 0; block_id <= image_hdr.totalblock; block_id++ ) { if (block_id < image_hdr.totalblock) { nx_current = pc_test_bit(block_id, bitmap); if (nx_current == 1) copied++; } else nx_current = -1; if (nx_current != cmp) { dprintf(dfw, "0x%08llX 0x%08llX %c\n", opt.offset_domain + (next_block_id * image_hdr.block_size), (block_id - next_block_id) * image_hdr.block_size, cmp ? '+' : '?'); next_block_id = block_id; cmp = nx_current; } // don't bother updating progress } /// end of for } done = 1; pres = pthread_join(prog_thread, &p_result); update_pui(&prog, copied, block_id, done); sync_data(dfw, &opt); print_finish_info(opt); close (dfr); /// close source close (dfw); /// close target free(bitmap); /// free bitmp close_pui(pui); printf("Cloned successfully.\n"); if(opt.debug) close_log(); #ifdef MEMTRACE muntrace(); #endif return 0; /// finish }
void toc_extract( WINDOW * win ) { static const char * ext[] = { "avr", "raw", "raw", "wav" }; char pathname[ 256 ]; char prog_info[ 64 ]; char buf[ 128 ]; struct avr_header * avrh; struct wave_header * wavh; struct audio_entry entry; struct audio_stream * as; struct _toc_data * data; struct device_info * info; OBJECT * ck; int format, i, max, track_no; int fd, swap; long offset, length, position, end, progress, total_length; long max_buf_blocks, nblocks; void * buffer; if( !fileselect( preferences.toc_dest, "", "TXT_EXTDEST" ) ) return; strrchr( preferences.toc_dest, '\\' )[1] = '\0'; data = DataSearch( win, TW_MAGIC ); max = data->n_tracks; format = fmt_popup.selected; total_length = 0; buffer = alloc_comm_buffer( BUFSIZE ); if( !buffer ) return; for( i = 0; i < max; i++ ) { ck = data->tree + 1 + TF_CK + i * data->n_obj; if( ! (ck->ob_state & SELECTED) ) continue; offset = toc_address( data->f[i].beg_time ); length = toc_address( data->f[i].end_time ) + 1 - offset; if( length > 0 ) total_length += length; } max_buf_blocks = BUFSIZE / 2352; progress = 0; progress_init( get_string( "TXT_EXTMSG" ), total_length ); progress_activate_cancel( 1 ); progress_init_timer(); log_begin(); log_printf( "*** Begin of a track extraction session\n\n" ); as = NULL; for( i = 0; i < max; i++ ) { ck = data->tree + 1 + TF_CK + i * data->n_obj; if( ! (ck->ob_state & SELECTED) ) continue; offset = toc_address( data->f[i].beg_time ); length = toc_address( data->f[i].end_time ) + 1 - offset; if( length <= 0 ) continue; track_no = i + 1; position = get_track_offset( &data->toc, track_no, &end ); if( toc_popup.selected == 0 ) gen_daoimg_entry( &entry, toc_info.toc_file, track_no, offset - position, end - offset - length ); else { info = (struct device_info*)toc_popup.item[toc_popup.selected].info; gen_cd_entry( &entry, info, track_no, offset - position, end - offset - length ); } if( as ) as = audio_reopen( as, &entry ); else as = audio_open( &entry ); if( as == NULL ) continue; sprintf( prog_info, get_string( "TXT_EXTTRK" ), track_no ); progress_setinfo( prog_info ); sprintf( pathname, "%strack%02d.%s", preferences.toc_dest, track_no, ext[ format ] ); fd = open( pathname, O_WRONLY|O_CREAT|O_TRUNC ); if( fd == -1 ) { audio_close( as ); alert_msg( "AL_FILERR", 1, pathname ); goto error; } switch( format ) { case 0: /* AVR */ avrh = (struct avr_header *) buf; avrh->avr_id = '2BIT'; memset( avrh->name, 0, 8 ); avrh->num_voices = 0xFFFF; avrh->num_bits = 16; avrh->signe = 0xffff; avrh->loop = 0; avrh->midi = 0xffff; avrh->freq_type.frequence = 0xff00ac44L; avrh->length = length * (2352 / 2); avrh->beg_loop = 0; avrh->end_loop = avrh->length; memset( avrh->reserved, 0, 26 + 64 ); write( fd, avrh, sizeof( *avrh ) ); swap = as->little_endian; break; case 1: /* RAW big-endian */ swap = as->little_endian; break; case 2: /* RAW little-endian */ swap = !as->little_endian; break; case 3: /* WAVE */ wavh = (struct wave_header *) buf; wavh->riff_id = 'RIFF'; wavh->riff_len = swap_long( length * 2352 + 36 ); wavh->wave_id = 'WAVE'; wavh->fmt_id = 'fmt '; wavh->fmt_size = 0x10000000L; wavh->fmt_compression_code = 0x0100; wavh->fmt_channels = 0x0200; wavh->fmt_freq = 0x44ac0000L; wavh->fmt_bytes_sec = 0x10b10200L; wavh->fmt_block_align = 0x0400; wavh->fmt_num_bits = 0x1000; wavh->data_id = 'data'; wavh->data_size = swap_long( length * 2352 ); write( fd, wavh, sizeof( *wavh ) ); swap = !as->little_endian; break; } while( length > 0 ) { if( yield() ) { audio_close( as ); alert_msg( "AL_EXTINT", 1 ); goto error; } nblocks = MIN( length, max_buf_blocks ); if( audio_read( as, buffer, nblocks ) == 0 ) { audio_close( as ); goto error; } if( swap ) swap_endian( buffer, nblocks * 2352 ); if( write( fd, buffer, nblocks * 2352 ) == -1 ) { close( fd ); audio_close( as ); alert_msg( "AL_FWRTERR", 1, pathname ); goto error; } length -= nblocks; progress += nblocks; progress_setcount( progress ); } close( fd ); } audio_close( as ); error: log_printf( "*** End of the track extraction session\n\n" ); log_end(); progress_exit(); free_comm_buffer( buffer ); }
int main(int argc, char *argv[]) { SDL_Joystick *joy = NULL; int t1, t0; if (!fs_init(argv[0])) { fprintf(stderr, "Failure to initialize virtual file system (%s)\n", fs_error()); return 1; } opt_parse(argc, argv); config_paths(opt_data); log_init("Neverball", "neverball.log"); make_dirs_and_migrate(); /* Initialize SDL. */ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) == -1) { log_printf("Failure to initialize SDL (%s)\n", SDL_GetError()); return 1; } /* Intitialize configuration. */ config_init(); config_load(); /* Initialize localization. */ lang_init(); /* Initialize joystick. */ if (config_get_d(CONFIG_JOYSTICK) && SDL_NumJoysticks() > 0) { joy = SDL_JoystickOpen(config_get_d(CONFIG_JOYSTICK_DEVICE)); if (joy) SDL_JoystickEventState(SDL_ENABLE); } /* Initialize audio. */ audio_init(); tilt_init(); /* Initialize video. */ if (!video_init()) return 1; /* Material system. */ mtrl_init(); /* Screen states. */ init_state(&st_null); /* Initialize demo playback or load the level. */ if (opt_replay && fs_add_path(dir_name(opt_replay)) && progress_replay(base_name(opt_replay))) { demo_play_goto(1); goto_state(&st_demo_play); } else if (opt_level) { const char *path = fs_resolve(opt_level); int loaded = 0; if (path) { /* HACK: must be around for the duration of the game. */ static struct level level; if (level_load(path, &level)) { progress_init(MODE_STANDALONE); if (progress_play(&level)) { goto_state(&st_level); loaded = 1; } } } else log_printf("File %s is not in game path\n", opt_level); if (!loaded) goto_state(&st_title); } else goto_state(&st_title); /* Run the main game loop. */ t0 = SDL_GetTicks(); while (loop()) { if ((t1 = SDL_GetTicks()) > t0) { /* Step the game state. */ st_timer(0.001f * (t1 - t0)); t0 = t1; /* Render. */ hmd_step(); st_paint(0.001f * t0); video_swap(); if (config_get_d(CONFIG_NICE)) SDL_Delay(1); } } config_save(); mtrl_quit(); if (joy) SDL_JoystickClose(joy); tilt_free(); hmd_free(); SDL_Quit(); return 0; }
void match_ctx_init(match_ctx ctx, /* IN/OUT */ struct membuf *inbuf, /* IN */ int max_offset) { struct match_node *np; struct progress prog[1]; int buf_len = membuf_memlen(inbuf); const unsigned char *buf = membuf_get(inbuf); int c, i; int val; ctx->info = calloc(buf_len + 1, sizeof(*ctx->info)); ctx->rle = calloc(buf_len + 1, sizeof(*ctx->rle)); ctx->rle_r = calloc(buf_len + 1, sizeof(*ctx->rle_r)); chunkpool_init(ctx->m_pool, sizeof(match)); ctx->max_offset = max_offset; ctx->buf = buf; ctx->len = buf_len; val = buf[0]; for (i = 1; i < buf_len; ++i) { if (buf[i] == val) { int len = ctx->rle[i - 1] + 1; if(len > 65535) { len = 0; } ctx->rle[i] = len; } else { ctx->rle[i] = 0; } val = buf[i]; } for (i = buf_len - 2; i >= 0; --i) { if (ctx->rle[i] < ctx->rle[i + 1]) { ctx->rle_r[i] = ctx->rle_r[i + 1] + 1; } else { ctx->rle_r[i] = 0; } } /* add extra nodes to rle sequences */ for(c = 0; c < 256; ++c) { static char rle_map[65536]; struct match_node *prev_np; unsigned short int rle_len; /* for each possible rle char */ memset(rle_map, 0, sizeof(rle_map)); prev_np = NULL; for (i = 0; i < buf_len; ++i) { /* must be the correct char */ if(buf[i] != c) { continue; } rle_len = ctx->rle[i]; if(!rle_map[rle_len] && ctx->rle_r[i] > 16) { /* no previous lengths and not our primary length*/ continue; } np = chunkpool_malloc(ctx->m_pool); np->index = i; np->next = NULL; rle_map[rle_len] = 1; LOG(LOG_DUMP, ("0) c = %d, added np idx %d -> %d\n", c, i, 0)); /* if we have a previous entry, let's chain it together */ if(prev_np != NULL) { LOG(LOG_DUMP, ("1) c = %d, pointed np idx %d -> %d\n", c, prev_np->index, i)); prev_np->next = np; } ctx->info[i]->single = np; prev_np = np; } memset(rle_map, 0, sizeof(rle_map)); prev_np = NULL; for (i = buf_len - 1; i >= 0; --i) { /* must be the correct char */ if(buf[i] != c) { continue; } rle_len = ctx->rle_r[i]; np = ctx->info[i]->single; if(np == NULL) { if(rle_map[rle_len] && prev_np != NULL && rle_len > 0) { np = chunkpool_malloc(ctx->m_pool); np->index = i; np->next = prev_np; ctx->info[i]->single = np; LOG(LOG_DEBUG, ("2) c = %d, added np idx %d -> %d\n", c, i, prev_np->index)); } } else { prev_np = np; } if(ctx->rle_r[i] > 0) { continue; } rle_len = ctx->rle[i] + 1; rle_map[rle_len] = 1; } } progress_init(prog, "building.directed.acyclic.graph.", buf_len - 1, 0); for (i = buf_len - 1; i >= 0; --i) { const_matchp matches; /* let's populate the cache */ matches = matches_calc(ctx, i); /* add to cache */ ctx->info[i]->cache = matches; progress_bump(prog, i); } LOG(LOG_NORMAL, ("\n")); progress_free(prog); }
/// readbitmap - cread and heck bitmap, reference dumpe2fs extern void readbitmap(char* device, image_head image_hdr, unsigned long* bitmap, int pui){ errcode_t retval; unsigned long group; unsigned long long current_block, block; unsigned long long free, gfree; char *block_bitmap=NULL; int block_nbytes; unsigned long long blk_itr; int bg_flags = 0; int start = 0; int bit_size = 1; int B_UN_INIT = 0; int ext4_gfree_mismatch = 0; log_mesg(2, 0, 0, fs_opt.debug, "%s: readbitmap %p\n", __FILE__, bitmap); fs_open(device); retval = ext2fs_read_bitmaps(fs); /// open extfs bitmap if (retval) log_mesg(0, 1, 1, fs_opt.debug, "%s: Couldn't find valid filesystem bitmap.\n", __FILE__); block_nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; if (fs->block_map) block_bitmap = malloc(block_nbytes); /// initial image bitmap as 1 (all block are used) memset(bitmap, 0xFF, sizeof(unsigned long)*LONGS(image_hdr.totalblock)); free = 0; current_block = 0; blk_itr = fs->super->s_first_data_block; /// init progress progress_bar prog; /// progress_bar structure defined in progress.h progress_init(&prog, start, image_hdr.totalblock, image_hdr.totalblock, BITMAP, bit_size); /// each group for (group = 0; group < fs->group_desc_count; group++) { gfree = 0; B_UN_INIT = 0; if (block_bitmap) { ext2fs_get_block_bitmap_range(fs->block_map, blk_itr, block_nbytes << 3, block_bitmap); if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM){ #ifdef EXTFS_1_41 bg_flags = fs->group_desc[group].bg_flags; #else bg_flags = ext2fs_bg_flags(fs, group); #endif if (bg_flags&EXT2_BG_BLOCK_UNINIT){ log_mesg(1, 0, 0, fs_opt.debug, "%s: BLOCK_UNINIT for group %lu\n", __FILE__, group); B_UN_INIT = 1; } else { log_mesg(2, 0, 0, fs_opt.debug, "%s: BLOCK_INIT for group %lu\n", __FILE__, group); } } /// each block in group for (block = 0; ((block < fs->super->s_blocks_per_group) && (current_block < (image_hdr.totalblock-1))); block++) { current_block = block + blk_itr; /// check block is used or not if ((!in_use (block_bitmap, block)) || (B_UN_INIT)) { free++; gfree++; pc_clear_bit(current_block, bitmap); log_mesg(3, 0, 0, fs_opt.debug, "%s: free block %llu at group %lu init %i\n", __FILE__, current_block, group, (int)B_UN_INIT); } else { pc_set_bit(current_block, bitmap); log_mesg(3, 0, 0, fs_opt.debug, "%s: used block %llu at group %lu\n", __FILE__, current_block, group); } /// update progress update_pui(&prog, current_block, current_block, 0);//keep update } blk_itr += fs->super->s_blocks_per_group; } /// check free blocks in group #ifdef EXTFS_1_41 if (gfree != fs->group_desc[group].bg_free_blocks_count){ #else if (gfree != ext2fs_bg_free_blocks_count(fs, group)){ #endif if (!B_UN_INIT) log_mesg(0, 1, 1, fs_opt.debug, "%s: bitmap error at %lu group.\n", __FILE__, group); else ext4_gfree_mismatch = 1; } } /// check all free blocks in partition if (free != fs->super->s_free_blocks_count) { if ((fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && (ext4_gfree_mismatch)) log_mesg(1, 0, 0, fs_opt.debug, "%s: EXT4 bitmap metadata mismatch\n", __FILE__); else log_mesg(0, 1, 1, fs_opt.debug, "%s: bitmap free count err, free:%llu\n", __FILE__, free); } fs_close(); /// update progress update_pui(&prog, 1, 1, 1);//finish } /// get extfs type static int test_extfs_type(char* device){ int ext2 = 1; int ext3 = 2; int ext4 = 3; int device_type; fs_open(device); if(fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM){ log_mesg(1, 0, 0, fs_opt.debug, "%s: test feature as EXT4\n", __FILE__); device_type = ext4; } else if (fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL){ log_mesg(1, 0, 0, fs_opt.debug, "%s: test feature as EXT3\n", __FILE__); device_type = ext3; } else { log_mesg(1, 0, 0, fs_opt.debug, "%s: test feature as EXT2\n", __FILE__); device_type = ext2; } fs_close(); return device_type; }
/** * main functiom - for colne or restore data */ int main(int argc, char **argv){ char* source; /// source data char* target; /// target data char* buffer; /// buffer data for malloc used char* buffer2; /// buffer data for malloc used int dfr, dfw; /// file descriptor for source and target int r_size, w_size; /// read and write size unsigned long long block_id, copied = 0; /// block_id is every block in partition /// copied is copied block count off_t offset = 0, sf = 0; /// seek postition, lseek result int start, stop; /// start, range, stop number for progress bar unsigned long long total_write = 0; /// the copied size unsigned long long needed_size = 0; /// the copied size unsigned long long needed_mem = 0; /// the copied size char bitmagic[8] = "BiTmAgIc";// only for check postition char bitmagic_r[8]; /// read magic string from image int cmp; /// compare magic string char *bitmap; /// the point for bitmap data int debug = 0; /// debug or not unsigned long crc = 0xffffffffL; /// CRC32 check code for writint to image unsigned long crc_ck = 0xffffffffL; /// CRC32 check code for checking unsigned long crc_ck2 = 0xffffffffL; /// CRC32 check code for checking int c_size; /// CRC32 code size char* crc_buffer; /// buffer data for malloc crc code int done = 0; int s_count = 0; int tui = 0; /// text user interface int pui = 0; /// progress mode(default text) int raw = 0; char image_hdr_magic[512]; progress_bar prog; /// progress_bar structure defined in progress.h image_head image_hdr; /// image_head structure defined in partclone.h /** * get option and assign to opt structure * check parameter and read from argv */ parse_options(argc, argv, &opt); /** * if "-d / --debug" given * open debug file in "/var/log/partclone.log" for log message */ debug = opt.debug; //if(opt.debug) open_log(opt.logfile); /** * using Text User Interface */ if (opt.ncurses){ pui = NCURSES; log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n"); } else if (opt.dialog){ pui = DIALOG; log_mesg(1, 0, 0, debug, "Using Dialog User Interface mode.\n"); } else pui = TEXT; tui = open_pui(pui, opt.fresh); if ((opt.ncurses) && (tui == 0)){ opt.ncurses = 0; log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n"); } else if ((opt.dialog) && (tui == 1)){ m_dialog.percent = 1; } /// print partclone info print_partclone_info(opt); if (geteuid() != 0) log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n"); else log_mesg(1, 0, 0, debug, "UID is root.\n"); /// ignore crc check if(opt.ignore_crc) log_mesg(1, 0, 1, debug, "Ignore CRC error\n"); /** * open source and target * clone mode, source is device and target is image file/stdout * restore mode, source is image file/stdin and target is device * dd mode, source is device and target is device !!not complete */ #ifdef _FILE_OFFSET_BITS log_mesg(1, 0, 0, debug, "enable _FILE_OFFSET_BITS %i\n", _FILE_OFFSET_BITS); #endif source = opt.source; target = opt.target; dfr = open_source(source, &opt); if (dfr == -1) { log_mesg(0, 1, 1, debug, "Erro EXIT.\n"); } dfw = open_target(target, &opt); if (dfw == -1) { log_mesg(0, 1, 1, debug, "Error Exit.\n"); } /** * get partition information like super block, image_head, bitmap * from device or image file. */ if (opt.restore){ log_mesg(1, 0, 0, debug, "restore image hdr - get image_head from image file\n"); /// get first 512 byte r_size = read_all(&dfr, image_hdr_magic, 512, &opt); /// check the image magic if (memcmp(image_hdr_magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) == 0){ restore_image_hdr_sp(&dfr, &opt, &image_hdr, image_hdr_magic); /// check memory size if (check_mem_size(image_hdr, opt, &needed_mem) == -1) log_mesg(0, 1, 1, debug, "Ther is no enough free memory, partclone suggests you should have %i bytes memory\n", needed_mem); /// alloc a memory to restore bitmap bitmap = (char*)malloc(sizeof(char)*image_hdr.totalblock); if(bitmap == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } /// check the file system //if (strcmp(image_hdr.fs, FS) != 0) // log_mesg(0, 1, 1, debug, "%s can't restore from the image which filesystem is %s not %s\n", argv[0], image_hdr.fs, FS); log_mesg(2, 0, 0, debug, "initial main bitmap pointer %lli\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from image file log_mesg(0, 0, 1, debug, "Calculating bitmap... "); log_mesg(0, 0, 1, debug, "Please wait... "); get_image_bitmap(&dfr, opt, image_hdr, bitmap); /// check the dest partition size. if(opt.check){ check_size(&dfw, image_hdr.device_size); } log_mesg(2, 0, 0, debug, "check main bitmap pointer %i\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); }else{ log_mesg(1, 0, 0, debug, "This is not partclone image.\n"); raw = 1; //sf = lseek(dfr, 0, SEEK_SET); log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n"); /// get Super Block information from partition initial_dd_hdr(dfr, &image_hdr); /// check the dest partition size. if(opt.check){ check_size(&dfw, image_hdr.device_size); } } } log_mesg(1, 0, 0, debug, "print image_head\n"); /// print option to log file if (debug) print_opt(opt); /// print image_head print_image_hdr_info(image_hdr, opt); /** * initial progress bar */ start = 0; /// start number of progress bar stop = (image_hdr.usedblocks+1); /// get the end of progress number, only used block log_mesg(1, 0, 0, debug, "Initial Progress bar\n"); /// Initial progress bar progress_init(&prog, start, stop, image_hdr.block_size); copied = 0; /// initial number is 0 /** * start read and write data between device and image file */ if ((opt.restore) && (!raw)) { /** * read magic string from image file * and check it. */ r_size = read_all(&dfr, bitmagic_r, 8, &opt); /// read a magic string cmp = memcmp(bitmagic, bitmagic_r, 8); if(cmp != 0) log_mesg(0, 1, 1, debug, "bitmagic error %i\n", cmp); /// seek to the first sf = lseek(dfw, 0, SEEK_SET); log_mesg(1, 0, 0, debug, "seek %lli for writing dtat string\n",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "seek set %lli\n", sf); /// start restore image file to partition for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ){ r_size = 0; w_size = 0; if (bitmap[block_id] == 1){ /// The block is used log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id); log_mesg(1, 0, 0, debug, "bitmap=%i, ",bitmap[block_id]); offset = (off_t)(block_id * image_hdr.block_size); #ifdef _FILE_OFFSET_BITS sf = lseek(dfw, offset, SEEK_SET); if (sf == -1) log_mesg(0, 1, 1, debug, "target seek error = %lli, ",sf); #endif buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data if(buffer == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt); log_mesg(1, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size); if (r_size <0) log_mesg(0, 1, 1, debug, "read errno = %i \n", errno); /// read crc32 code and check it. crc_ck = crc32(crc_ck, buffer, r_size); crc_buffer = (char*)malloc(CRC_SIZE); ///alloc a memory to copy data if(crc_buffer == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt); if (c_size < CRC_SIZE) log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno)); memcpy(&crc, crc_buffer, CRC_SIZE); /*FIX: 64bit image can't ignore crc error*/ if ((memcmp(&crc, &crc_ck, CRC_SIZE) != 0) && (!opt.ignore_crc) ){ log_mesg(1, 0, 0, debug, "CRC Check error. 64bit bug before v0.1.0 (Rev:250M), enlarge crc size and recheck again....\n "); /// check again buffer2 = (char*)malloc(image_hdr.block_size+CRC_SIZE); ///alloc a memory to copy data if(buffer2 == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } memcpy(buffer2, buffer, image_hdr.block_size); memcpy(buffer2+image_hdr.block_size, crc_buffer, CRC_SIZE); memcpy(buffer, buffer2+CRC_SIZE, image_hdr.block_size); crc_ck2 = crc32(crc_ck2, buffer, r_size); c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt); if (c_size < CRC_SIZE) log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno)); memcpy(&crc, crc_buffer, CRC_SIZE); if ((memcmp(&crc, &crc_ck2, CRC_SIZE) != 0) && (!opt.ignore_crc)){ log_mesg(0, 1, 1, debug, "CRC error again at %i...\n ", sf); } else { crc_ck = crc_ck2; } free(buffer2); } else { crc_ck2 = crc_ck; } /// write block from buffer to partition w_size = write_all(&dfw, buffer, image_hdr.block_size, &opt); log_mesg(1, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size); if (w_size != (int)image_hdr.block_size) log_mesg(0, 1, 1, debug, "write error %i \n", w_size); /// free buffer free(buffer); free(crc_buffer); copied++; /// count copied block total_write += (unsigned long long) w_size; /// count copied size /// read or write error //if ((r_size != w_size) || (r_size != image_hdr.block_size)) // log_mesg(0, 1, 1, debug, "read and write different\n"); log_mesg(1, 0, 0, debug, "end\n"); } else { #ifndef _FILE_OFFSET_BITS /// if the block is not used, I just skip it. log_mesg(2, 0, 0, debug, "block_id=%lli, ",block_id); sf = lseek(dfw, image_hdr.block_size, SEEK_CUR); log_mesg(2, 0, 0, debug, "seek=%lli, ",sf); if (sf == (off_t)-1) log_mesg(0, 1, 1, debug, "seek error %lli errno=%i\n", (long long)offset, (int)errno); log_mesg(2, 0, 0, debug, "end\n"); #endif } update_pui(&prog, copied, done); } // end of for done = 1; update_pui(&prog, copied, done); sync_data(dfw, &opt); } else if ((opt.restore) && (raw)){ /// start clone partition to image file //write image_head to image file w_size = write_all(&dfw, image_hdr_magic, 512, &opt); if(w_size == -1) log_mesg(0, 1, 1, debug, "write image_hdr to image error\n"); block_id = 1; do { log_mesg(1, 0, 0, debug, "block_id=%lli, ",block_id); buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data if(buffer == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } /// read data from source to buffer r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt); log_mesg(1, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size); if (r_size != (int)image_hdr.block_size){ log_mesg(0, 1, 1, debug, "read error %i \n", r_size); } if (r_size == image_hdr.block_size){ /// write buffer to target w_size = write_all(&dfw, buffer, image_hdr.block_size, &opt); log_mesg(2, 0, 0, debug, "bs=%i and w=%i, ",image_hdr.block_size, w_size); if (w_size != (int)image_hdr.block_size) log_mesg(0, 1, 1, debug, "write error %i \n", w_size); } else { w_size = 0; } /// free buffer free(buffer); /// read or write error if (r_size != w_size) log_mesg(0, 1, 1, debug, "read and write different\n"); log_mesg(1, 0, 0, debug, "end\n"); block_id++; r_size = 0; w_size = 0; copied++; /// count copied block total_write += (unsigned long long)(w_size); /// count copied size log_mesg(1, 0, 0, debug, "total=%lli, ", total_write); update_pui(&prog, copied, done); if(copied == image_hdr.totalblock){ done = 1; } } while (done == 0);/// end of for sync_data(dfw, &opt); } print_finish_info(opt); close (dfr); /// close source close (dfw); /// close target free(bitmap); /// free bitmp close_pui(pui); printf("Cloned successfully.\n"); if(opt.debug) close_log(); return 0; /// finish }
struct search_node* search_buffer(match_ctx ctx, /* IN */ encode_match_f * f, /* IN */ encode_match_data emd, /* IN */ int use_literal_sequences) { struct progress prog[1]; struct search_node *sn_arr; const_matchp mp = NULL; struct search_node *snp; struct search_node *best_copy_snp; int best_copy_len; struct search_node *best_rle_snp; int len = ctx->len + 1; progress_init(prog, "finding.shortest.path.",len, 0); sn_arr = malloc(len * sizeof(struct search_node)); memset(sn_arr, 0, len * sizeof(struct search_node)); --len; snp = &sn_arr[len]; snp->index = len; snp->match->offset = 0; snp->match->len = 0; snp->total_offset = 0; snp->total_score = 0; snp->prev = NULL; best_copy_snp = snp; best_copy_len = 0.0; best_rle_snp = NULL; /* think twice about changing this code, * it works the way it is. The last time * I examined this code I was certain it was * broken and broke it myself, trying to fix it. */ while (len > 0 && (mp = matches_get(ctx, len - 1)) != NULL) { float prev_score; float prev_offset_sum; if(use_literal_sequences) { /* check if we can do even better with copy */ snp = &sn_arr[len]; if(best_copy_snp->total_score+best_copy_len * 8.0 - snp->total_score > 0.0 || best_copy_len > 65535) { /* found a better copy endpoint */ LOG(LOG_DEBUG, ("best copy start moved to index %d\n", snp->index)); best_copy_snp = snp; best_copy_len = 0.0; } else { float copy_score = best_copy_len * 8.0 + (1.0 + 17.0 + 17.0); float total_copy_score = best_copy_snp->total_score + copy_score; LOG(LOG_DEBUG, ("total score %0.1f, copy total score %0.1f\n", snp->total_score, total_copy_score)); if(snp->total_score > total_copy_score ) { match local_mp; /* here it is good to just copy instead of crunch */ LOG(LOG_DEBUG, ("copy index %d, len %d, total %0.1f, copy %0.1f\n", snp->index, best_copy_len, snp->total_score, total_copy_score)); local_mp->len = best_copy_len; local_mp->offset = 0; local_mp->next = NULL; snp->total_score = total_copy_score; snp->total_offset = best_copy_snp->total_offset; snp->prev = best_copy_snp; *snp->match = *local_mp; } } /* end of copy optimization */ } /* check if we can do rle */ snp = &sn_arr[len]; if(best_rle_snp == NULL || snp->index + 65535 < best_rle_snp->index || snp->index + ctx->rle_r[snp->index] < best_rle_snp->index) { /* best_rle_snp can't be reached by rle from snp, reset it*/ if(ctx->rle[snp->index] > 0) { best_rle_snp = snp; LOG(LOG_DEBUG, ("resetting best_rle at index %d, len %d\n", snp->index, ctx->rle[snp->index])); } else { best_rle_snp = NULL; } } else if(ctx->rle[snp->index] > 0 && snp->index + ctx->rle_r[snp->index] >= best_rle_snp->index) { float best_rle_score; float total_best_rle_score; float snp_rle_score; float total_snp_rle_score; match rle_mp; LOG(LOG_DEBUG, ("challenger len %d, index %d, " "ruling len %d, index %d\n", ctx->rle_r[snp->index], snp->index, ctx->rle_r[best_rle_snp->index], best_rle_snp->index)); /* snp and best_rle_snp is the same rle area, * let's see which is best */ rle_mp->len = ctx->rle[best_rle_snp->index]; rle_mp->offset = 1; best_rle_score = f(rle_mp, emd, NULL); total_best_rle_score = best_rle_snp->total_score + best_rle_score; rle_mp->len = ctx->rle[snp->index]; rle_mp->offset = 1; snp_rle_score = f(rle_mp, emd, NULL); total_snp_rle_score = snp->total_score + snp_rle_score; if(total_snp_rle_score <= total_best_rle_score) { /* yes, the snp is a better rle than best_rle_snp */ LOG(LOG_DEBUG, ("prospect len %d, index %d, (%0.1f+%0.1f) " "ruling len %d, index %d (%0.1f+%0.1f)\n", ctx->rle[snp->index], snp->index, snp->total_score, snp_rle_score, ctx->rle[best_rle_snp->index], best_rle_snp->index, best_rle_snp->total_score, best_rle_score)); best_rle_snp = snp; LOG(LOG_DEBUG, ("setting current best_rle: " "index %d, len %d\n", snp->index, rle_mp->len)); } } if(best_rle_snp != NULL && best_rle_snp != snp) { float rle_score; float total_rle_score; /* check if rle is better */ match local_mp; local_mp->len = best_rle_snp->index - snp->index; local_mp->offset = 1; rle_score = f(local_mp, emd, NULL); total_rle_score = best_rle_snp->total_score + rle_score; LOG(LOG_DEBUG, ("comparing index %d (%0.1f) with " "rle index %d, len %d, total score %0.1f %0.1f\n", snp->index, snp->total_score, best_rle_snp->index, local_mp->len, best_rle_snp->total_score, rle_score)); if(snp->total_score > total_rle_score) { /*here it is good to do rle instead of crunch */ LOG(LOG_DEBUG, ("rle index %d, len %d, total %0.1f, rle %0.1f\n", snp->index, local_mp->len, snp->total_score, total_rle_score)); snp->total_score = total_rle_score; snp->total_offset = best_rle_snp->total_offset + 1; snp->prev = best_rle_snp; *snp->match = *local_mp; } } /* end of rle optimization */ LOG(LOG_DUMP, ("matches for index %d with total score %0.1f\n", len - 1, snp->total_score)); prev_score = sn_arr[len].total_score; prev_offset_sum = sn_arr[len].total_offset; while (mp != NULL) { matchp next; int end_len; match tmp; int bucket_len_start; float score; next = mp->next; end_len = 1; *tmp = *mp; tmp->next = NULL; bucket_len_start = 0; for(tmp->len = mp->len; tmp->len >= end_len; --(tmp->len)) { float total_score; unsigned int total_offset; struct encode_match_buckets match_buckets; LOG(LOG_DUMP, ("mp[%d, %d], tmp[%d, %d]\n", mp->offset, mp->len, tmp->offset, tmp->len)); if (bucket_len_start == 0 || tmp->len < 3 || tmp->len < bucket_len_start) { score = f(tmp, emd, &match_buckets); bucket_len_start = match_buckets.len.start; } total_score = prev_score + score; total_offset = prev_offset_sum + tmp->offset; snp = &sn_arr[len - tmp->len]; LOG(LOG_DUMP, ("[%05d] cmp [%05d, %05d score %.1f + %.1f] with %.1f", len, tmp->offset, tmp->len, prev_score, score, snp->total_score)); if ((total_score < 100000000.0) && (snp->match->len == 0 || total_score < snp->total_score || (total_score == snp->total_score && (tmp->offset == 0 || (snp->match->len == tmp->len && (total_offset <= snp->total_offset)))))) { LOG(LOG_DUMP, (", replaced")); snp->index = len - tmp->len; *snp->match = *tmp; snp->total_offset = total_offset; snp->total_score = total_score; snp->prev = &sn_arr[len]; } LOG(LOG_DUMP, ("\n")); } LOG(LOG_DUMP, ("tmp->len %d, ctx->rle[%d] %d\n", tmp->len, len - tmp->len, ctx->rle[len - tmp->len])); mp = next; } /* slow way to get to the next node for cur */ --len; ++best_copy_len; if(sn_arr[len].match == NULL) { LOG(LOG_ERROR, ("Found unreachable node at len %d.\n", len)); } progress_bump(prog, len); } if(len > 0 && mp == NULL) { LOG(LOG_ERROR, ("No matches at len %d.\n", len)); } LOG(LOG_NORMAL, ("\n")); progress_free(prog); return sn_arr; }
/** * main function - for clone or restore data */ int main(int argc, char **argv) { #ifdef MEMTRACE setenv("MALLOC_TRACE", "partclone_mtrace.log", 1); mtrace(); #endif char* source; /// source data char* target; /// target data int dfr, dfw; /// file descriptor for source and target int r_size, w_size; /// read and write size unsigned cs_size = 0; /// checksum_size int cs_reseed = 1; int start, stop; /// start, range, stop number for progress bar unsigned long *bitmap = NULL; /// the point for bitmap data int debug = 0; /// debug level int tui = 0; /// text user interface int pui = 0; /// progress mode(default text) int flag; int pres = 0; pthread_t prog_thread; void *p_result; static const char *const bad_sectors_warning_msg = "*************************************************************************\n" "* WARNING: The disk has bad sectors. This means physical damage on the *\n" "* disk surface caused by deterioration, manufacturing faults, or *\n" "* another reason. The reliability of the disk may remain stable or *\n" "* degrade quickly. Use the --rescue option to efficiently save as much *\n" "* data as possible! *\n" "*************************************************************************\n"; file_system_info fs_info; /// description of the file system image_options img_opt; init_fs_info(&fs_info); init_image_options(&img_opt); /** * get option and assign to opt structure * check parameter and read from argv */ parse_options(argc, argv, &opt); /** * if "-d / --debug" given * open debug file in "/var/log/partclone.log" for log message */ memset(&fs_opt, 0, sizeof(fs_cmd_opt)); debug = opt.debug; fs_opt.debug = debug; fs_opt.ignore_fschk = opt.ignore_fschk; //if(opt.debug) open_log(opt.logfile); /** * using Text User Interface */ if (opt.ncurses) { pui = NCURSES; log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n"); } else pui = TEXT; tui = open_pui(pui, opt.fresh); if ((opt.ncurses) && (!tui)) { opt.ncurses = 0; pui = TEXT; log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n"); } /// print partclone info print_partclone_info(opt); #ifndef CHKIMG if (geteuid() != 0) log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n"); else log_mesg(1, 0, 0, debug, "UID is root.\n"); #endif /// ignore crc check if (opt.ignore_crc) log_mesg(1, 0, 1, debug, "Ignore CRC errors\n"); /** * open source and target * clone mode, source is device and target is image file/stdout * restore mode, source is image file/stdin and target is device * dd mode, source is device and target is device !!not complete */ source = opt.source; target = opt.target; log_mesg(1, 0, 0, debug, "source=%s, target=%s \n", source, target); dfr = open_source(source, &opt); if (dfr == -1) { log_mesg(0, 1, 1, debug, "Error exit\n"); } #ifndef CHKIMG dfw = open_target(target, &opt); if (dfw == -1) { log_mesg(0, 1, 1, debug, "Error exit\n"); } #else dfw = -1; #endif /** * get partition information like super block, bitmap from device or image file. */ if (opt.clone) { log_mesg(1, 0, 0, debug, "Initiate image options - version %s\n", IMAGE_VERSION_CURRENT); img_opt.checksum_mode = opt.checksum_mode; img_opt.checksum_size = get_checksum_size(opt.checksum_mode, opt.debug); img_opt.blocks_per_checksum = opt.blocks_per_checksum; img_opt.reseed_checksum = opt.reseed_checksum; cs_size = img_opt.checksum_size; cs_reseed = img_opt.reseed_checksum; log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n"); log_mesg(0, 0, 1, debug, "Reading Super Block\n"); /// get Super Block information from partition read_super_blocks(source, &fs_info); if (img_opt.checksum_mode != CSM_NONE && img_opt.blocks_per_checksum == 0) { const unsigned int buffer_capacity = opt.buffer_size > fs_info.block_size ? opt.buffer_size / fs_info.block_size : 1; // in blocks img_opt.blocks_per_checksum = buffer_capacity; } log_mesg(1, 0, 0, debug, "%u blocks per checksum\n", img_opt.blocks_per_checksum); check_mem_size(fs_info, img_opt, opt); /// alloc a memory to store bitmap bitmap = pc_alloc_bitmap(fs_info.totalblock); if (bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from partition log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... \n"); read_bitmap(source, fs_info, bitmap, pui); update_used_blocks_count(&fs_info, bitmap); if (opt.check) { unsigned long long needed_space = 0; needed_space += sizeof(image_head) + sizeof(file_system_info) + sizeof(image_options); needed_space += get_bitmap_size_on_disk(&fs_info, &img_opt, &opt); needed_space += cnv_blocks_to_bytes(0, fs_info.usedblocks, fs_info.block_size, &img_opt); check_free_space(&dfw, needed_space); } log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap); log_mesg(1, 0, 0, debug, "Writing super block and bitmap...\n"); write_image_desc(&dfw, fs_info, img_opt, &opt); write_image_bitmap(&dfw, fs_info, img_opt, bitmap, &opt); log_mesg(0, 0, 1, debug, "done!\n"); } else if (opt.restore) { image_head_v2 img_head; log_mesg(1, 0, 0, debug, "restore image hdr - get information from image file\n"); log_mesg(1, 0, 1, debug, "Reading Super Block\n"); /// get image information from image file load_image_desc(&dfr, &opt, &img_head, &fs_info, &img_opt); cs_size = img_opt.checksum_size; cs_reseed = img_opt.reseed_checksum; check_mem_size(fs_info, img_opt, opt); /// alloc a memory to restore bitmap bitmap = pc_alloc_bitmap(fs_info.totalblock); if (bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from image file log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait...\n"); load_image_bitmap(&dfr, opt, fs_info, img_opt, bitmap); #ifndef CHKIMG /// check the dest partition size. if (opt.restore_raw_file) check_free_space(&dfw, fs_info.device_size); else if (opt.check) check_size(&dfw, fs_info.device_size); #endif log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); } else if (opt.dd || opt.domain) { log_mesg(1, 0, 0, debug, "Initiate image options - version %s\n", IMAGE_VERSION_CURRENT); img_opt.checksum_mode = opt.checksum_mode; img_opt.checksum_size = get_checksum_size(opt.checksum_mode, opt.debug); img_opt.blocks_per_checksum = opt.blocks_per_checksum; img_opt.reseed_checksum = opt.reseed_checksum; log_mesg(1, 0, 0, debug, "Initial image hdr - get Super Block from partition\n"); log_mesg(1, 0, 1, debug, "Reading Super Block\n"); /// get Super Block information from partition read_super_blocks(source, &fs_info); check_mem_size(fs_info, img_opt, opt); /// alloc a memory to restore bitmap bitmap = pc_alloc_bitmap(fs_info.totalblock); if (bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from partition log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... "); read_bitmap(source, fs_info, bitmap, pui); /// check the dest partition size. if (opt.dd && opt.check) { check_size(&dfw, fs_info.device_size); } log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); } else if (opt.ddd){ if (dfr != 0) read_super_blocks(source, &fs_info); else read_super_blocks(target, &fs_info); img_opt.checksum_mode = opt.checksum_mode; img_opt.checksum_size = get_checksum_size(opt.checksum_mode, opt.debug); img_opt.blocks_per_checksum = opt.blocks_per_checksum; check_mem_size(fs_info, img_opt, opt); /// alloc a memory to restore bitmap bitmap = pc_alloc_bitmap(fs_info.totalblock); if (bitmap == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from partition log_mesg(0, 0, 1, debug, "Calculating bitmap... Please wait... "); read_bitmap(source, fs_info, bitmap, pui); /// check the dest partition size. if (opt.check) { struct stat target_stat; if ((stat(opt.target, &target_stat) != -1) && (strcmp(opt.target, "-") != 0)) { if (S_ISBLK(target_stat.st_mode)) check_size(&dfw, fs_info.device_size); else { unsigned long long needed_space = 0; needed_space += sizeof(image_head) + sizeof(file_system_info) + sizeof(image_options); needed_space += get_bitmap_size_on_disk(&fs_info, &img_opt, &opt); needed_space += cnv_blocks_to_bytes(0, fs_info.usedblocks, fs_info.block_size, &img_opt); check_free_space(&dfw, needed_space); } } } log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); } log_mesg(1, 0, 0, debug, "print image information\n"); /// print option to log file if (debug) print_opt(opt); print_file_system_info(fs_info, opt); /** * initial progress bar */ start = 0; /// start number of progress bar stop = (fs_info.usedblocks); /// get the end of progress number, only used block log_mesg(1, 0, 0, debug, "Initial Progress bar\n"); /// Initial progress bar if (opt.no_block_detail) flag = NO_BLOCK_DETAIL; else flag = IO; progress_init(&prog, start, stop, fs_info.totalblock, flag, fs_info.block_size); copied = 0; /// initial number is 0 /** * thread to print progress */ pres = pthread_create(&prog_thread, NULL, thread_update_pui, NULL); if(pres) log_mesg(0, 1, 1, debug, "%s, %i, thread create error\n", __func__, __LINE__); /** * start read and write data between source and destination */ if (opt.clone) { const unsigned long long blocks_total = fs_info.totalblock; const unsigned int block_size = fs_info.block_size; const unsigned int buffer_capacity = opt.buffer_size > block_size ? opt.buffer_size / block_size : 1; // in blocks unsigned char checksum[cs_size]; unsigned int blocks_in_cs, blocks_per_cs, write_size; char *read_buffer, *write_buffer; blocks_per_cs = img_opt.blocks_per_checksum; log_mesg(1, 0, 0, debug, "#\nBuffer capacity = %u, Blocks per cs = %u\n#\n", buffer_capacity, blocks_per_cs); write_size = cnv_blocks_to_bytes(0, buffer_capacity, block_size, &img_opt); read_buffer = (char*)malloc(buffer_capacity * block_size); write_buffer = (char*)malloc(write_size + cs_size); if (read_buffer == NULL || write_buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } /// read data from the first block if (lseek(dfr, 0, SEEK_SET) == (off_t)-1) log_mesg(0, 1, 1, debug, "source seek ERROR:%s\n", strerror(errno)); log_mesg(0, 0, 0, debug, "Total block %llu\n", blocks_total); /// start clone partition to image file log_mesg(1, 0, 0, debug, "start backup data...\n"); blocks_in_cs = 0; init_checksum(img_opt.checksum_mode, checksum, debug); block_id = 0; do { /// scan bitmap unsigned long long i, blocks_skip, blocks_read; unsigned int cs_added = 0, write_offset = 0; off_t offset; /// skip unused blocks for (blocks_skip = 0; block_id + blocks_skip < blocks_total && !pc_test_bit(block_id + blocks_skip, bitmap); blocks_skip++); if (block_id + blocks_skip == blocks_total) break; if (blocks_skip) block_id += blocks_skip; /// read blocks for (blocks_read = 0; block_id + blocks_read < blocks_total && blocks_read < buffer_capacity && pc_test_bit(block_id + blocks_read, bitmap); ++blocks_read); if (!blocks_read) break; offset = (off_t)(block_id * block_size); if (lseek(dfr, offset, SEEK_SET) == (off_t)-1) log_mesg(0, 1, 1, debug, "source seek ERROR:%s\n", strerror(errno)); r_size = read_all(&dfr, read_buffer, blocks_read * block_size, &opt); if (r_size != (int)(blocks_read * block_size)) { if ((r_size == -1) && (errno == EIO)) { if (opt.rescue) { memset(read_buffer, 0, blocks_read * block_size); for (r_size = 0; r_size < blocks_read * block_size; r_size += PART_SECTOR_SIZE) rescue_sector(&dfr, offset + r_size, read_buffer + r_size, &opt); } else log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg); } else log_mesg(0, 1, 1, debug, "read error: %s\n", strerror(errno)); } /// calculate checksum log_mesg(2, 0, 0, debug, "blocks_read = %i\n", blocks_read); for (i = 0; i < blocks_read; ++i) { memcpy(write_buffer + write_offset, read_buffer + i * block_size, block_size); write_offset += block_size; update_checksum(checksum, read_buffer + i * block_size, block_size); if (blocks_per_cs > 0 && ++blocks_in_cs == blocks_per_cs) { log_mesg(3, 0, 0, debug, "CRC = %x%x%x%x \n", checksum[0], checksum[1], checksum[2], checksum[3]); memcpy(write_buffer + write_offset, checksum, cs_size); ++cs_added; write_offset += cs_size; blocks_in_cs = 0; if (cs_reseed) init_checksum(img_opt.checksum_mode, checksum, debug); } } /// write buffer to target w_size = write_all(&dfw, write_buffer, write_offset, &opt); if (w_size != write_offset) log_mesg(0, 1, 1, debug, "image write ERROR:%s\n", strerror(errno)); /// count copied block copied += blocks_read; log_mesg(2, 0, 0, debug, "copied = %lld\n", copied); /// next block block_id += blocks_read; /// read or write error if (r_size + cs_added * cs_size != w_size) log_mesg(0, 1, 1, debug, "read(%i) and write(%i) different\n", r_size, w_size); } while (1); if (blocks_in_cs > 0) { // Write the checksum for the latest blocks log_mesg(1, 0, 0, debug, "Write the checksum for the latest blocks. size = %i\n", cs_size); log_mesg(3, 0, 0, debug, "CRC = %x%x%x%x \n", checksum[0], checksum[1], checksum[2], checksum[3]); w_size = write_all(&dfw, (char*)checksum, cs_size, &opt); if (w_size != cs_size) log_mesg(0, 1, 1, debug, "image write ERROR:%s\n", strerror(errno)); } free(write_buffer); free(read_buffer); // check only the size when the image does not contains checksums and does not // comes from a pipe } else if (opt.chkimg && img_opt.checksum_mode == CSM_NONE && strcmp(opt.source, "-") != 0) { unsigned long long total_offset = (fs_info.usedblocks - 1) * fs_info.block_size; char last_block[fs_info.block_size]; off_t partial_offset = INT32_MAX; while (total_offset) { if (partial_offset > total_offset) partial_offset = total_offset; if (lseek(dfr, partial_offset, SEEK_CUR) == (off_t)-1) log_mesg(0, 1, 1, debug, "source seek ERROR: %s\n", strerror(errno)); total_offset -= partial_offset; } if (read_all(&dfr, last_block, fs_info.block_size, &opt) != fs_info.block_size) log_mesg(0, 1, 1, debug, "ERROR: source image too short\n"); } else if (opt.restore) { const unsigned long long blocks_total = fs_info.totalblock; const unsigned int block_size = fs_info.block_size; const unsigned int buffer_capacity = opt.buffer_size > block_size ? opt.buffer_size / block_size : 1; // in blocks const unsigned int blocks_per_cs = img_opt.blocks_per_checksum; unsigned long long blocks_used = fs_info.usedblocks; unsigned int blocks_in_cs, buffer_size, read_offset; unsigned char checksum[cs_size]; char *read_buffer, *write_buffer; unsigned long long blocks_used_fix = 0, test_block = 0; log_mesg(1, 0, 0, debug, "#\nBuffer capacity = %u, Blocks per cs = %u\n#\n", buffer_capacity, blocks_per_cs); // fix some super block record incorrect for (test_block = 0; test_block < blocks_total; ++test_block) if (pc_test_bit(test_block, bitmap)) blocks_used_fix++; if (blocks_used_fix != blocks_used) { blocks_used = blocks_used_fix; log_mesg(1, 0, 0, debug, "info: fixed used blocks count\n"); } buffer_size = cnv_blocks_to_bytes(0, buffer_capacity, block_size, &img_opt); if (img_opt.image_version != 0x0001) read_buffer = (char*)malloc(buffer_size); else { // Allocate more memory in case the image is affected by the 64 bits bug read_buffer = (char*)malloc(buffer_size + buffer_capacity * cs_size); } write_buffer = (char*)malloc(buffer_capacity * block_size); if (read_buffer == NULL || write_buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } #ifndef CHKIMG /// seek to the first if (lseek(dfw, opt.offset, SEEK_SET) == (off_t)-1) log_mesg(0, 1, 1, debug, "target seek ERROR:%s\n", strerror(errno)); #endif /// start restore image file to partition log_mesg(1, 0, 0, debug, "start restore data...\n"); blocks_in_cs = 0; if (!opt.ignore_crc) init_checksum(img_opt.checksum_mode, checksum, debug); block_id = 0; do { unsigned int i; unsigned long long blocks_written, bytes_skip; unsigned int read_size; // max chunk to read using one read(2) syscall int blocks_read = copied + buffer_capacity < blocks_used ? buffer_capacity : blocks_used - copied; if (!blocks_read) break; log_mesg(1, 0, 0, debug, "blocks_read = %d and copied = %lld\n", blocks_read, copied); read_size = cnv_blocks_to_bytes(copied, blocks_read, block_size, &img_opt); // increase read_size to make room for the oversized checksum if (blocks_per_cs && blocks_read < buffer_capacity && (blocks_read % blocks_per_cs) && (blocks_used % blocks_per_cs)) { /// it is the last read and there is a partial chunk at the end log_mesg(1, 0, 0, debug, "# PARTIAL CHUNK\n"); read_size += cs_size; } // read chunk from image log_mesg(1, 0, 0, debug, "read more: "); r_size = read_all(&dfr, read_buffer, read_size, &opt); if (r_size != read_size) log_mesg(0, 1, 1, debug, "read ERROR:%s\n", strerror(errno)); // read buffer is the follows: // <blocks_per_cs><cs1><blocks_per_cs><cs2>... // write buffer should be the following: // <block1><block2>... read_offset = 0; for (i = 0; i < blocks_read; ++i) { memcpy(write_buffer + i * block_size, read_buffer + read_offset, block_size); if (opt.ignore_crc) { read_offset += block_size; if (++blocks_in_cs == blocks_per_cs) read_offset += cs_size; continue; } update_checksum(checksum, read_buffer + read_offset, block_size); if (++blocks_in_cs == blocks_per_cs) { unsigned char checksum_orig[cs_size]; memcpy(checksum_orig, read_buffer + read_offset + block_size, cs_size); log_mesg(3, 0, 0, debug, "CRC = %x%x%x%x \n", checksum[0], checksum[1], checksum[2], checksum[3]); log_mesg(3, 0, 0, debug, "CRC.orig = %x%x%x%x \n", checksum_orig[0], checksum_orig[1], checksum_orig[2], checksum_orig[3]); if (memcmp(read_buffer + read_offset + block_size, checksum, cs_size)) { log_mesg(0, 1, 1, debug, "CRC error, block_id=%llu...\n ", block_id + i); } read_offset += cs_size; blocks_in_cs = 0; if (cs_reseed) init_checksum(img_opt.checksum_mode, checksum, debug); } read_offset += block_size; } if (blocks_in_cs && blocks_per_cs && blocks_read < buffer_capacity && (blocks_read % blocks_per_cs)) { log_mesg(1, 0, 0, debug, "check latest chunk's checksum covering %u blocks\n", blocks_in_cs); if (memcmp(read_buffer + read_offset, checksum, cs_size)){ unsigned char checksum_orig[cs_size]; memcpy(checksum_orig, read_buffer + read_offset, cs_size); log_mesg(1, 0, 0, debug, "CRC = %x%x%x%x \n", checksum[0], checksum[1], checksum[2], checksum[3]); log_mesg(1, 0, 0, debug, "CRC.orig = %x%x%x%x \n", checksum_orig[0], checksum_orig[1], checksum_orig[2], checksum_orig[3]); log_mesg(0, 1, 1, debug, "CRC error, block_id=%llu...\n ", block_id + i); } } blocks_written = 0; do { int blocks_write; /// count bytes to skip for (bytes_skip = 0; block_id < blocks_total && !pc_test_bit(block_id, bitmap); block_id++, bytes_skip += block_size); #ifndef CHKIMG /// skip empty blocks if (bytes_skip > 0 && lseek(dfw, (off_t)bytes_skip, SEEK_CUR) == (off_t)-1) log_mesg(0, 1, 1, debug, "target seek ERROR:%s\n", strerror(errno)); #endif /// blocks to write for (blocks_write = 0; block_id + blocks_write < blocks_total && blocks_written + blocks_write < blocks_read && pc_test_bit(block_id + blocks_write, bitmap); blocks_write++); #ifndef CHKIMG // write blocks if (blocks_write > 0) { w_size = write_all(&dfw, write_buffer + blocks_written * block_size, blocks_write * block_size, &opt); if (w_size != blocks_write * block_size) { if (!opt.skip_write_error) log_mesg(0, 1, 1, debug, "write block %llu ERROR:%s\n", block_id + blocks_written, strerror(errno)); else log_mesg(0, 0, 1, debug, "skip write block %llu error:%s\n", block_id + blocks_written, strerror(errno)); } } #endif blocks_written += blocks_write; block_id += blocks_write; copied += blocks_write; } while (blocks_written < blocks_read); } while(1); free(write_buffer); free(read_buffer); #ifndef CHKIMG /// restore_raw_file option if (opt.restore_raw_file && !pc_test_bit(blocks_total - 1, bitmap)) { if (ftruncate(dfw, (off_t)(blocks_total * block_size)) == -1) log_mesg(0, 0, 1, debug, "ftruncate ERROR:%s\n", strerror(errno)); } #endif } else if (opt.dd) { char *buffer; int block_size = fs_info.block_size; unsigned long long blocks_total = fs_info.totalblock; int buffer_capacity = block_size < opt.buffer_size ? opt.buffer_size / block_size : 1; buffer = (char*)malloc(buffer_capacity * block_size); if (buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } block_id = 0; if (lseek(dfr, 0, SEEK_SET) == (off_t)-1) log_mesg(0, 1, 1, debug, "source seek ERROR:%d\n", strerror(errno)); log_mesg(0, 0, 0, debug, "Total block %llu\n", blocks_total); /// start clone partition to partition log_mesg(1, 0, 0, debug, "start backup data device-to-device...\n"); do { /// scan bitmap unsigned long long blocks_skip, blocks_read; off_t offset; /// skip unused blocks for (blocks_skip = 0; block_id + blocks_skip < blocks_total && !pc_test_bit(block_id + blocks_skip, bitmap); blocks_skip++); if (block_id + blocks_skip == blocks_total) break; if (blocks_skip) block_id += blocks_skip; /// read chunk from source for (blocks_read = 0; block_id + blocks_read < blocks_total && blocks_read < buffer_capacity && pc_test_bit(block_id + blocks_read, bitmap); ++blocks_read); if (!blocks_read) break; offset = (off_t)(block_id * block_size); if (lseek(dfr, offset, SEEK_SET) == (off_t)-1) log_mesg(0, 1, 1, debug, "source seek ERROR:%s\n", strerror(errno)); if (lseek(dfw, offset + opt.offset, SEEK_SET) == (off_t)-1) log_mesg(0, 1, 1, debug, "target seek ERROR:%s\n", strerror(errno)); r_size = read_all(&dfr, buffer, blocks_read * block_size, &opt); if (r_size != (int)(blocks_read * block_size)) { if ((r_size == -1) && (errno == EIO)) { if (opt.rescue) { memset(buffer, 0, blocks_read * block_size); for (r_size = 0; r_size < blocks_read * block_size; r_size += PART_SECTOR_SIZE) rescue_sector(&dfr, offset + r_size, buffer + r_size, &opt); } else log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg); } else log_mesg(0, 1, 1, debug, "source read ERROR %s\n", strerror(errno)); } /// write buffer to target w_size = write_all(&dfw, buffer, blocks_read * block_size, &opt); if (w_size != (int)(blocks_read * block_size)) { if (opt.skip_write_error) log_mesg(0, 0, 1, debug, "skip write block %lli error:%s\n", block_id, strerror(errno)); else log_mesg(0, 1, 1, debug, "write block %lli ERROR:%s\n", block_id, strerror(errno)); } /// count copied block copied += blocks_read; /// next block block_id += blocks_read; /// read or write error if (r_size != w_size) { if (opt.skip_write_error) log_mesg(0, 0, 1, debug, "read and write different\n"); else log_mesg(0, 1, 1, debug, "read and write different\n"); } } while (1); free(buffer); /// restore_raw_file option if (opt.restore_raw_file && !pc_test_bit(blocks_total - 1, bitmap)) { if (ftruncate(dfw, (off_t)(blocks_total * block_size)) == -1) log_mesg(0, 0, 1, debug, "ftruncate ERROR:%s\n", strerror(errno)); } } else if (opt.domain) { int cmp, nx_current = 0; unsigned long long next_block_id = 0; log_mesg(0, 0, 0, debug, "Total block %i\n", fs_info.totalblock); log_mesg(1, 0, 0, debug, "start writing domain log...\n"); // write domain log comment and status line dprintf(dfw, "# Domain logfile created by %s v%s\n", get_exec_name(), VERSION); dprintf(dfw, "# Source: %s\n", opt.source); dprintf(dfw, "# Offset: 0x%08llX\n", opt.offset_domain); dprintf(dfw, "# current_pos current_status\n"); dprintf(dfw, "0x%08llX ?\n", opt.offset_domain + (fs_info.totalblock * fs_info.block_size)); dprintf(dfw, "# pos size status\n"); // start logging the used/unused areas cmp = pc_test_bit(0, bitmap); for (block_id = 0; block_id <= fs_info.totalblock; block_id++) { if (block_id < fs_info.totalblock) { nx_current = pc_test_bit(block_id, bitmap); if (nx_current) copied++; } else nx_current = -1; if (nx_current != cmp) { dprintf(dfw, "0x%08llX 0x%08llX %c\n", opt.offset_domain + (next_block_id * fs_info.block_size), (block_id - next_block_id) * fs_info.block_size, cmp ? '+' : '?'); next_block_id = block_id; cmp = nx_current; } // don't bother updating progress } /// end of for } else if (opt.ddd) { char *buffer; int block_size = fs_info.block_size; unsigned long long blocks_total = fs_info.totalblock; int blocks_in_buffer = block_size < opt.buffer_size ? opt.buffer_size / block_size : 1; buffer = (char*)malloc(blocks_in_buffer * block_size); if (buffer == NULL) { log_mesg(0, 1, 1, debug, "%s, %i, not enough memory\n", __func__, __LINE__); } block_id = 0; log_mesg(0, 0, 0, debug, "Total block %llu\n", blocks_total); /// start clone partition to partition log_mesg(1, 0, 0, debug, "start backup data device-to-device...\n"); do { /// scan bitmap unsigned long long blocks_read; /// read chunk from source for (blocks_read = 0; block_id + blocks_read < blocks_total && blocks_read < blocks_in_buffer && pc_test_bit(block_id + blocks_read, bitmap); blocks_read++); if (!blocks_read) break; r_size = read_all(&dfr, buffer, blocks_read * block_size, &opt); if (r_size != (int)(blocks_read * block_size)) { if ((r_size == -1) && (errno == EIO)) { if (opt.rescue) { memset(buffer, 0, blocks_read * block_size); for (r_size = 0; r_size < blocks_read * block_size; r_size += PART_SECTOR_SIZE) rescue_sector(&dfr, r_size, buffer + r_size, &opt); } else log_mesg(0, 1, 1, debug, "%s", bad_sectors_warning_msg); } else if (r_size == 0){ // done for ddd /// write buffer to target w_size = write_all(&dfw, buffer, rescue_write_size, &opt); break; } else log_mesg(0, 1, 1, debug, "source read ERROR %s\n", strerror(errno)); } /// write buffer to target w_size = write_all(&dfw, buffer, blocks_read * block_size, &opt); if (w_size != (int)(blocks_read * block_size)) { if (opt.skip_write_error) log_mesg(0, 0, 1, debug, "skip write block %lli error:%s\n", block_id, strerror(errno)); else log_mesg(0, 1, 1, debug, "write block %lli ERROR:%s\n", block_id, strerror(errno)); } /// count copied block copied += blocks_read; /// next block block_id += blocks_read; /// read or write error if (r_size != w_size) { if (opt.skip_write_error) log_mesg(0, 0, 1, debug, "read and write different\n"); else log_mesg(0, 1, 1, debug, "read and write different\n"); } } while (1); free(buffer); /// restore_raw_file option if (opt.restore_raw_file && !pc_test_bit(blocks_total - 1, bitmap)) { if (ftruncate(dfw, (off_t)(blocks_total * block_size)) == -1) log_mesg(0, 0, 1, debug, "ftruncate ERROR:%s\n", strerror(errno)); } } done = 1; pres = pthread_join(prog_thread, &p_result); if(pres) log_mesg(0, 1, 1, debug, "%s, %i, thread join error\n", __func__, __LINE__); update_pui(&prog, copied, block_id, done); #ifndef CHKIMG sync_data(dfw, &opt); #endif print_finish_info(opt); /// close source close(dfr); /// close target if (dfw != -1) close(dfw); /// free bitmp free(bitmap); close_pui(pui); #ifndef CHKIMG fprintf(stderr, "Cloned successfully.\n"); #else printf("Checked successfully.\n"); #endif if (opt.debug) close_log(); #ifdef MEMTRACE muntrace(); #endif return 0; /// finish }
/** * main functiom - for colne or restore data */ int main(int argc, char **argv){ int dfr; /// file descriptor for source and target int r_size; /// read and write size char* buffer; /// buffer data char* buffer2; /// buffer data //unsigned long long block_id, copied = 0; /// block_id is every block in partition /// copied is copied block count off_t offset = 0, sf = 0; /// seek postition, lseek result int start, stop; /// start, range, stop number for progress bar char bitmagic[8] = "BiTmAgIc";// only for check postition char bitmagic_r[8]; /// read magic string from image int cmp; /// compare magic string unsigned long *bitmap; /// the point for bitmap data int debug = 0; /// debug or not unsigned long crc = 0xffffffffL; /// CRC32 check code for writint to image unsigned long crc_ck = 0xffffffffL; /// CRC32 check code for checking unsigned long crc_ck2 = 0xffffffffL; /// CRC32 check code for checking int c_size; /// CRC32 code size //int done = 0; int tui = 0; /// text user interface int pui = 0; /// progress mode(default text) int flag = 0; int pres; pthread_t prog_thread; void *p_result; //progress_bar prog; /// progress_bar structure defined in progress.h image_head image_hdr; /// image_head structure defined in partclone.h /** * get option and assign to opt structure * check parameter and read from argv */ parse_option_chkimg(argc, argv, &opt); /** * if "-d / --debug" given * open debug file in "/var/log/partclone.log" for log message */ debug = opt.debug; open_log(opt.logfile); /** * using Text User Interface */ if (opt.ncurses){ pui = NCURSES; log_mesg(1, 0, 0, debug, "Using Ncurses User Interface mode.\n"); } else pui = TEXT; tui = open_pui(pui, opt.fresh); if ((opt.ncurses) && (tui == 0)){ opt.ncurses = 0; log_mesg(1, 0, 0, debug, "Open Ncurses User Interface Error.\n"); } /// print partclone info print_partclone_info(opt); /* if (geteuid() != 0) log_mesg(0, 1, 1, debug, "You are not logged as root. You may have \"access denied\" errors when working.\n"); else log_mesg(1, 0, 0, debug, "UID is root.\n"); */ /// ignore crc check if(opt.ignore_crc) log_mesg(1, 0, 1, debug, "Ignore CRC\n"); /** * open source and target * clone mode, source is device and target is image file/stdout * restore mode, source is image file/stdin and target is device * dd mode, source is device and target is device !!not complete */ #ifdef _FILE_OFFSET_BITS log_mesg(1, 0, 0, debug, "enable _FILE_OFFSET_BITS %i\n", _FILE_OFFSET_BITS); #endif dfr = open_source(opt.source, &opt); if (dfr == -1) { log_mesg(0, 1, 1, debug, "Erro EXIT.\n"); } /** * get partition information like super block, image_head, bitmap * from device or image file. */ log_mesg(1, 0, 0, debug, "Checking image hdr - get image_head from image file\n"); restore_image_hdr(&dfr, &opt, &image_hdr); /// check the image magic if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0) log_mesg(0, 1, 1, debug, "The Image magic error. This file is NOT partclone Image\n"); /// alloc a memory to restore bitmap bitmap = (unsigned long*)calloc(sizeof(unsigned long), LONGS(image_hdr.totalblock)); if(bitmap == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } log_mesg(2, 0, 0, debug, "initial main bitmap pointer %p\n", bitmap); log_mesg(1, 0, 0, debug, "Initial image hdr - read bitmap table\n"); /// read and check bitmap from image file log_mesg(0, 0, 1, debug, "Calculating bitmap... "); log_mesg(0, 0, 1, debug, "Please wait... "); get_image_bitmap(&dfr, opt, image_hdr, bitmap); log_mesg(2, 0, 0, debug, "check main bitmap pointer %p\n", bitmap); log_mesg(0, 0, 1, debug, "done!\n"); log_mesg(1, 0, 0, debug, "print image_head\n"); /// print option to log file if (debug) print_opt(opt); /// print image_head print_image_hdr_info(image_hdr, opt); /** * initial progress bar */ start = 0; /// start number of progress bar stop = image_hdr.usedblocks; /// get the end of progress number, only used block log_mesg(1, 0, 0, debug, "Initial Progress bar\n"); /// Initial progress bar if (opt.no_block_detail) flag = NO_BLOCK_DETAIL; else flag = IO; progress_init(&prog, start, stop, image_hdr.totalblock, flag, image_hdr.block_size); copied = 0; /** * thread to print progress */ pres = pthread_create(&prog_thread, NULL, thread_update_pui, NULL); /** * start read and write data between device and image file */ /** * read magic string from image file * and check it. */ r_size = read_all(&dfr, bitmagic_r, 8, &opt); /// read a magic string cmp = memcmp(bitmagic, bitmagic_r, 8); if(cmp != 0) log_mesg(0, 1, 1, debug, "bitmagic error %i\n", cmp); /// start restore image file to partition for( block_id = 0; block_id < image_hdr.totalblock; block_id++ ){ r_size = 0; if (pc_test_bit(block_id, bitmap)){ /// The block is used log_mesg(2, 0, 0, debug, "block_id=%llu, ",block_id); log_mesg(1, 0, 0, debug, "bitmap=%i, ",pc_test_bit(block_id, bitmap)); offset = (off_t)(block_id * image_hdr.block_size); buffer = (char*)malloc(image_hdr.block_size); ///alloc a memory to copy data if(buffer == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } r_size = read_all(&dfr, buffer, image_hdr.block_size, &opt); log_mesg(1, 0, 0, debug, "bs=%i and r=%i, ",image_hdr.block_size, r_size); if (r_size <0) log_mesg(0, 1, 1, debug, "read errno = %i \n", errno); /// read crc32 code and check it. crc_ck = crc32(crc_ck, buffer, r_size); char crc_buffer[CRC_SIZE]; c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt); if (c_size < CRC_SIZE){ log_mesg(0, 0, 1, debug, "read CRC error, please check your image file. \n"); log_mesg(0, 0, 1, debug, "read CRC size (%i), %s. \n", c_size, strerror(errno)); lseek(dfr, (int)(CRC_SIZE-c_size), SEEK_CUR); } if ((memcmp(crc_buffer, &crc_ck, CRC_SIZE) != 0) && (!opt.ignore_crc)){ log_mesg(1, 0, 0, debug, "Ignore_crc 2 %i\n ", opt.ignore_crc); log_mesg(1, 0, 0, debug, "CRC Check error. 64bit bug before v0.1.0 (Rev:250M), enlarge crc size and recheck again....\n "); /// check again buffer2 = (char*)malloc(image_hdr.block_size+CRC_SIZE); ///alloc a memory to copy data if(buffer2 == NULL){ log_mesg(0, 1, 1, debug, "%s, %i, ERROR:%s", __func__, __LINE__, strerror(errno)); } memcpy(buffer2, buffer, image_hdr.block_size); memcpy(buffer2+image_hdr.block_size, crc_buffer, CRC_SIZE); memcpy(buffer, buffer2+CRC_SIZE, image_hdr.block_size); crc_ck2 = crc32(crc_ck2, buffer, r_size); c_size = read_all(&dfr, crc_buffer, CRC_SIZE, &opt); if (c_size < CRC_SIZE) log_mesg(0, 1, 1, debug, "read CRC error: %s, please check your image file. \n", strerror(errno)); memcpy(&crc, crc_buffer, CRC_SIZE); if ((memcmp(&crc, &crc_ck2, CRC_SIZE) != 0) && (!opt.ignore_crc)){ log_mesg(0, 1, 1, debug, "CRC error again at %ji...\n ", (intmax_t)sf); } else { crc_ck = crc_ck2; } free(buffer2); } else { crc_ck2 = crc_ck; } /// free buffer free(buffer); copied++; /// count copied block log_mesg(1, 0, 0, debug, "end\n"); } //update_pui(&prog, copied, block_id, done); } // end of for done = 1; pres = pthread_join(prog_thread, &p_result); update_pui(&prog, copied, block_id, done); print_finish_info(opt); close (dfr); /// close source free(bitmap); /// free bitmp close_pui(pui); printf("Checked successfully.\n"); if(opt.debug) close_log(); return 0; /// finish }
/* * Download firmware stored in buf to cam_dev. If simulation mode * is enabled, only show what packet sizes would be sent to the * device but do not sent any actual packets */ static int fw_download_img(struct cam_device *cam_dev, const struct fw_vendor *vp, char *buf, int img_size, int sim_mode, int printerrors, int retry_count, int timeout, const char *imgname, const char *type) { struct scsi_write_buffer cdb; progress_t progress; int size; union ccb *ccb; int pkt_count = 0; int max_pkt_size; u_int32_t pkt_size = 0; char *pkt_ptr = buf; u_int32_t offset; int last_pkt = 0; int16_t *ptr; if ((ccb = cam_getccb(cam_dev)) == NULL) { warnx("Could not allocate CCB"); return (1); } if (strcmp(type, "scsi") == 0) { scsi_test_unit_ready(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, 5000); } else if (strcmp(type, "ata") == 0) { /* cam_getccb cleans up the header, caller has to zero the payload */ bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr)); ptr = (uint16_t *)malloc(sizeof(struct ata_params)); if (ptr == NULL) { cam_freeccb(ccb); warnx("can't malloc memory for identify\n"); return(1); } bzero(ptr, sizeof(struct ata_params)); cam_fill_ataio(&ccb->ataio, 1, NULL, /*flags*/CAM_DIR_IN, MSG_SIMPLE_Q_TAG, /*data_ptr*/(uint8_t *)ptr, /*dxfer_len*/sizeof(struct ata_params), timeout ? timeout : 30 * 1000); ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0); } else { warnx("weird disk type '%s'", type); return 1; } /* Disable freezing the device queue. */ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; if (cam_send_ccb(cam_dev, ccb) < 0) { warnx("Error sending identify/test unit ready"); if (printerrors) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); cam_freeccb(ccb); return(1); } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("Device is not ready"); if (printerrors) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); cam_freeccb(ccb); return (1); } max_pkt_size = vp->max_pkt_size; if (vp->max_pkt_size == 0 && strcmp(type, "ata") == 0) { max_pkt_size = UNKNOWN_MAX_PKT_SIZE; } pkt_size = vp->max_pkt_size; progress_init(&progress, imgname, size = img_size); /* Download single fw packets. */ do { if (img_size <= max_pkt_size) { last_pkt = 1; pkt_size = img_size; } progress_update(&progress, size - img_size); progress_draw(&progress); bzero(&cdb, sizeof(cdb)); if (strcmp(type, "scsi") == 0) { cdb.opcode = WRITE_BUFFER; cdb.control = 0; /* Parameter list length. */ scsi_ulto3b(pkt_size, &cdb.length[0]); offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0; scsi_ulto3b(offset, &cdb.offset[0]); cdb.byte2 = last_pkt ? vp->cdb_byte2_last : vp->cdb_byte2; cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0; /* Zero out payload of ccb union after ccb header. */ bzero((u_char *)ccb + sizeof(struct ccb_hdr), sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); /* Copy previously constructed cdb into ccb_scsiio struct. */ bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0], sizeof(struct scsi_write_buffer)); /* Fill rest of ccb_scsiio struct. */ if (!sim_mode) { cam_fill_csio(&ccb->csio, /* ccb_scsiio */ retry_count, /* retries */ NULL, /* cbfcnp */ CAM_DIR_OUT | CAM_DEV_QFRZDIS, /* flags */ CAM_TAG_ACTION_NONE, /* tag_action */ (u_char *)pkt_ptr, /* data_ptr */ pkt_size, /* dxfer_len */ SSD_FULL_SIZE, /* sense_len */ sizeof(struct scsi_write_buffer), /* cdb_len */ timeout ? timeout : CMD_TIMEOUT); /* timeout */ } } else if (strcmp(type, "ata") == 0) { bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr)); if (!sim_mode) { uint32_t off; cam_fill_ataio(&ccb->ataio, (last_pkt) ? 256 : retry_count, NULL, /*flags*/CAM_DIR_OUT | CAM_DEV_QFRZDIS, CAM_TAG_ACTION_NONE, /*data_ptr*/(uint8_t *)pkt_ptr, /*dxfer_len*/pkt_size, timeout ? timeout : 30 * 1000); off = (uint32_t)(pkt_ptr - buf); ata_28bit_cmd(&ccb->ataio, ATA_DOWNLOAD_MICROCODE, USE_OFFSETS_FEATURE, ATA_MAKE_LBA(off, pkt_size), ATA_MAKE_SECTORS(pkt_size)); } } if (!sim_mode) { /* Execute the command. */ if (cam_send_ccb(cam_dev, ccb) < 0 || (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("Error writing image to device"); if (printerrors) cam_error_print(cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); goto bailout; } } /* Prepare next round. */ pkt_count++; pkt_ptr += pkt_size; img_size -= pkt_size; } while(!last_pkt); progress_complete(&progress, size - img_size); cam_freeccb(ccb); return (0); bailout: progress_complete(&progress, size - img_size); cam_freeccb(ccb); return (1); }