void lr0_print(lr0_machine_t mach) { for (const struct lr0_state * s = mach->first_state; s; s = s->next) { printo(P_LR0_KERNELS, "\nState %u:\n", s->id); // FIXME if (print_opt(P_LR0_KERNELS)) { struct lr0_point points[s->nclosure]; unsigned n = lr0_closure(mach, points, s); assert(n == s->nclosure); for (unsigned i = 0; i < n; ++i) { if (! print_opt(P_LR0_CLOSURES) && (i >= s->npoints)) break; print_point(&points[i], " "); } } if (print_opt(P_LR0_GOTO) && s->gototab) { for (unsigned i = 0; i < s->gototab->ngo; ++i) { const struct lr0_state *go = s->gototab->go[i]; print(" [%s] -> %u\n", go->access_sym->name, go->id); } } if (print_opt(P_LR_REDUCE) && s->reducetab) { for (unsigned i = 0; i < s->reducetab->nreduce; ++i) { const struct lr_reduce *rdc = &s->reducetab->reduce[i]; print(" [%s] :< %s ~%u\n", rdc->sym->name, rdc->rule->sym->name, rdc->rule->id); } } } }
static void print_usage(char *argv0) { printf("Usage: %s [options]\n\n", argv0); printf("Proxies HTTPS connections to TLS-SRP sites\n"); printf("More info: http://trustedhttp.org or email <*****@*****.**>\n\n"); printf("Options:\n"); print_opt("-a <accounts>", "Set accounts on command-line", "(format: \"host1,user1,pwd1|host2,user2,pwd2\")"); print_opt("-l <host/ip>", "Listen address/host", "(default: 127.0.0.1)"); print_opt("-p <port>", "Listen port", "(default: 8443)"); print_opt("-D <host>", "Detect whether a host supports TLS-SRP; then exit", NULL); print_opt("-h ", "Show this help message", NULL); }
int print_hub(t_taupe *taupe) { wclear(taupe->top->win); print_sys(taupe->sys, taupe->top); print_task(taupe->task, taupe->top); print_cpu(taupe->cpu, taupe->top); print_mem(taupe->mem, taupe->top); if (taupe->signal->on) { print_opt(taupe->signal, "Send Signal"); print_signal(taupe->signal, taupe->pid); } else if (taupe->sort->on) print_opt(taupe->sort, "Sort By"); print_main(taupe); return (0); }
/* * Finish building grammar */ void grammar_complete(struct grammar *grammar) { resolve_symbols(grammar); determine_start(grammar); add_sentinel_rule(grammar); count_symbols(grammar); /* At this point we have complete symbol graph */ if (print_opt(P_GRAMMAR)) dump_grammar(grammar); if (print_opt(P_SYMBOLS)) dump_symbols(grammar); nullable_find(grammar); if (print_opt(P_NULLABLE)) nullable_dump(grammar); }
int main(int argc, char *argv[]) { int c; struct cut_option g_option; static struct option const long_options[] = { {"help", 0, NULL, 'h'}, {"delimiter", 1, NULL, 'd'}, {"fields", 1, NULL, 'f'}, {"characters", 1, NULL, 'c'}, {NULL, 0, NULL, 0} }; exit_status = 0; program_name = argv[0]; init_opt(&g_option); while((c = getopt_long(argc, argv, "hHd:f:c:", long_options, NULL)) != -1) { switch(c) { case 'h': case 'H': cut_usage_exit(EXIT_SUCESS); break; case 'd': if (optarg) fill_d(&g_option, optarg); break; case 'f': if (optarg) fill_f(&g_option, optarg); break; case 'c': if (optarg) fill_c(&g_option, optarg); break; default: cut_usage_exit(EXIT_FAILURE); break; } } check_option(&g_option); print_opt(&g_option); if(argc - optind != 1) cut_usage_exit(EXIT_FAILURE); exit_status = cut(&g_option, argv[optind]); exit(exit_status); }
int print_help(FILE *stream, int argc, char **argv) { print_usage(stream, argc, argv, USAGE_DESCR); print_opt(stream, "h", "help", "prints this help to stderr and exits"); print_opt(stream, "f", "file filename", "the filename of the graph file to read"); fprintf(stream, "By default, the graph file is loaded and printed.\n"); fprintf(stream, "The following mutually exclusive options will \ interpret and store the graph accordingly: \n"); print_opt(stream, "N", "NUM", "graph has numbered nodes"); print_opt(stream, "L", "LABEL", "graph has labeled nodes"); print_opt(stream, "S", "SNAP", "graph is from the SNAP dataset"); print_opt(stream, "H", "HANDLE", "uses the supplied handler to parse the line"); print_opt(stream, "Q", "QUIET", "same as default but without printing"); return EXIT_SUCCESS; }
int main(int argc, char * const *argv) { int i; if (argc != 2) usage(); if (!strcmp(argv[1], "synopsis")) printf(".. |synopsis| replace:: %s\n", vopt_synopsis); else if (!strcmp(argv[1], "options")) for (i = 0; i < vopt_list_n; i++) print_opt(&vopt_list[i]); else usage(); return (0); }
/* * Prints info about command options in standard usage format. * @section - name of optins section. If not-NULL will be printed * before options. * @opts - array of options, must end with all-zero struct OPTS_END. */ void extopts_usage(struct extopt *opts) { int i; int desc_offset; bool any_short; desc_offset = get_desc_offset(opts, &any_short); i = 0; while (1) { if (extopt_is_end(opts[i])) break; print_opt(opts + i, desc_offset, any_short); i++; } }
/** * 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 }
static enumError Generate ( control_t * ctrl ) { ASSERT(ctrl); ASSERT(ctrl->info); FILE * cf = ctrl->cf; FILE * hf = ctrl->hf; ASSERT(cf); ASSERT(hf); FREE(ctrl->opt_allow_grp); FREE(ctrl->opt_allow_cmd); ctrl->opt_allow_grp = ctrl->opt_allow_cmd = 0; const info_t *info; //----- ui header fprintf(cf,text_ui_head); fprintf(hf,text_ui_head); //----- setup guard char guard[100]; snprintf(guard,sizeof(guard),"WIT_UI_%s_h",ctrl->info->c_name); char * ptr; for ( ptr = guard; *ptr; ptr++ ) *ptr = *ptr == '-' ? '_' : toupper((int)*ptr); fprintf(hf,"\n#ifndef %s\n#define %s\n",guard,guard); //----- header ASSERT( ctrl->info->type & T_DEF_TOOL ); ccp tool_name = ctrl->info->c_name; fprintf(cf,"#include <getopt.h>\n"); fprintf(cf,"#include \"ui-%s.h\"\n",tool_name); fprintf(hf,"#include \"lib-std.h\"\n"); fprintf(hf,"#include \"ui.h\"\n"); //----- print enum enumOptions & OptionInfo[] print_section(cf,sep1,"OptionInfo[]"); print_section(hf,sep1,"enum enumOptions"); char * var_ptr = var_buf; char * var_end = var_buf + sizeof(var_buf); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern const InfoOption_t OptionInfo[OPT__N_TOTAL+1];\n"); fprintf(cf, "const InfoOption_t OptionInfo[OPT__N_TOTAL+1] =\n" "{\n" " {0,0,0,0,0}, // OPT_NONE,\n" "\n" ); fprintf(hf, "typedef enum enumOptions\n" "{\n" "\tOPT_NONE,\n" "\n" ); ctrl->n_opt = 1; ctrl->n_opt_specific = 0; if ( ctrl->n_cmd ) { fprintf(cf," //----- command specific options -----\n\n"); fprintf(hf,"\t//----- command specific options -----\n\n"); for ( info = ctrl->info; info < ctrl->end; info++ ) if ( info->type & F_OPT_COMMAND ) print_opt(ctrl,info); ctrl->n_opt_specific = ctrl->n_opt; fprintf(cf, " {0,0,0,0,0}, // OPT__N_SPECIFIC == %d\n\n" " //----- global options -----\n\n", ctrl->n_opt_specific ); fprintf(hf, "\n\tOPT__N_SPECIFIC, // == %d \n\n" "\t//----- global options -----\n\n", ctrl->n_opt_specific ); } for ( info = ctrl->info; info < ctrl->end; info++ ) if ( info->type & F_OPT_GLOBAL ) print_opt(ctrl,info); fprintf(cf, " {0,0,0,0,0} // OPT__N_TOTAL == %d\n\n" "};\n" ,ctrl->n_opt ); fprintf(hf, "\n\tOPT__N_TOTAL // == %d\n\n" "} enumOptions;\n" ,ctrl->n_opt ); if (ctrl->n_opt_specific) { noTRACE("opt_allowed = ( %2u + %2u ) * %2u\n", ctrl->n_grp, ctrl->n_cmd, ctrl->n_opt_specific ); if (ctrl->n_grp) ctrl->opt_allow_grp = CALLOC(ctrl->n_grp,ctrl->n_opt_specific); ctrl->opt_allow_cmd = CALLOC(ctrl->n_cmd,ctrl->n_opt_specific); } //----- print alternate option infos bool done = false; const info_t * last_cmd = ctrl->info; ctrl->opt_prefix = "def"; for ( info = ctrl->info; info < ctrl->end; info++ ) { if ( info->type & T_CMD_BEG ) { ctrl->opt_prefix = "cmd"; last_cmd = info; } else if ( info->type & T_GRP_BEG ) { ctrl->opt_prefix = "grp"; last_cmd = info; } else if ( info->type & T_CMD_OPT && info->help && *info->help ) { if (!done) { print_section(cf,sep1,"alternate option infos"); done = true; } const info_t * info0; for ( info0 = ctrl->info; info0 < info; info0++ ) if ( info0->type & T_DEF_OPT && !strcmp(info->c_name,info0->c_name) ) { print_info_opt(ctrl,info,info0,last_cmd->c_name); break; } } } //----- print enum enumOptionsBit if ( ctrl->n_cmd ) { print_section(hf,sep1,"enum enumOptionsBit"); fprintf(hf, "//\t***** only for verification *****\n" "\n" "//typedef enum enumOptionsBit\n" "//{\n" "//\t//----- command specific options -----\n" "//\n" ); for ( info = ctrl->info; info < ctrl->end; info++ ) if ( info->type & F_OPT_COMMAND ) fprintf(hf,"//\tOB_%s%.*s= 1llu << OPT_%s,\n", info->c_name, ( 28 - (int)strlen(info->c_name) ) / 8, tabs, info->c_name ); fprintf(hf,"//\n//\t//----- group & command options -----\n"); for ( info = ctrl->info; info < ctrl->end; ) { ccp cmd_name; u8 * opt_allow = 0; if ( info->type & T_CMD_BEG ) { cmd_name = info->c_name; fprintf(hf,"//\n//\tOB_CMD_%s%.*s=", info->c_name, ( 24 - (int)strlen(info->c_name) ) / 8, tabs ); if (ctrl->opt_allow_cmd) { //PRINT("SELECT ALLOW CMD %u/%s\n",info->index,info->c_name); opt_allow = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific; } } else if ( info->type & T_GRP_BEG ) { cmd_name = info->c_name; fprintf(hf,"//\n//\tOB_GRP_%s%.*s=", info->c_name, ( 24 - (int)strlen(info->c_name) ) / 8, tabs ); if (ctrl->opt_allow_grp) { //PRINT("SELECT ALLOW GRP %u/%s\n",info->index,info->c_name); opt_allow = ctrl->opt_allow_grp + info->index * ctrl->n_opt_specific; } } else { info++; continue; } info++; char * dest = iobuf; while ( info < ctrl->end ) { if ( info->type & T_ALL_OPT ) { dest += sprintf(dest,"\n//\t\t\t\t| ~(u64)0"); if (opt_allow) { //PRINT("ALLOW ALL\n"); memset(opt_allow,1,ctrl->n_opt_specific); } } else if ( info->type & T_COPY_CMD ) { dest += sprintf(dest,"\n//\t\t\t\t| OB_CMD_%s",info->c_name); if (opt_allow) { //PRINT("OR CMD %u/%s\n",info->index,info->c_name); DASSERT(ctrl->opt_allow_cmd); u8 * src = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific; u8 * dest = opt_allow; int count = ctrl->n_opt_specific; while ( count-- > 0 ) *dest++ |= *src++; } } else if ( info->type & T_COPY_GRP ) { dest += sprintf(dest,"\n//\t\t\t\t| OB_GRP_%s",info->c_name); if ( opt_allow && ctrl->opt_allow_grp ) { //PRINT("OR GRP %u/%s\n",info->index,info->c_name); u8 * src = ctrl->opt_allow_grp + info->index * ctrl->n_opt_specific; u8 * dest = opt_allow; int count = ctrl->n_opt_specific; while ( count-- > 0 ) *dest++ |= *src++; } } else if ( info->type & T_CMD_OPT ) { if (FindStringField(&ctrl->copt,info->c_name)) { dest += sprintf(dest,"\n//\t\t\t\t| OB_%s",info->c_name); if ( opt_allow && info->index ) { //PRINT("ALLOW OPT %u/%s\n",info->index,info->c_name); opt_allow[info->index] = 1; } } else if (!FindStringField(&ctrl->gopt,info->c_name)) ERROR0(ERR_SEMANTIC,"Option not defined: %s %s --%s", tool_name, cmd_name, info->c_name ); } else if ( info->type & (T_CMD_BEG|T_GRP_BEG) ) break; ASSERT( dest < iobuf + sizeof(iobuf) ); info++; } if ( dest == iobuf ) fprintf(hf," 0,\n"); else fprintf(hf,"%s,\n",iobuf+8); } fprintf(hf,"//\n//} enumOptionsBit;\n"); } //----- print enum enumCommands & CommandTab[] print_section(hf,sep1,"enum enumCommands"); fprintf(hf, "typedef enum enumCommands\n" "{\n" "\tCMD__NONE," ); if ( ctrl->n_cmd ) { print_section(cf,sep1,"CommandTab[]"); fputs("\n\n",hf); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern const CommandTab_t CommandTab[];\n"); fprintf(cf, "const CommandTab_t CommandTab[] =\n" "{\n" ); for ( info = ctrl->info; info < ctrl->end; info++ ) if ( info->type & T_DEF_CMD ) { fprintf( hf, "\tCMD_%s,\n",info->c_name); ccp ptr = info->namelist; while (*ptr) { ccp n1 = ptr; while ( *ptr && *ptr != '|' ) ptr++; const int l1 = ptr - n1; while ( *ptr == '|' ) ptr++; if (*ptr) { ccp n2 = ptr; while ( *ptr && *ptr != '|' ) ptr++; const int l2 = ptr - n2; fprintf(cf, " { CMD_%s,%.*s\"%.*s\",%.*s\"%.*s\",%.*s0 },\n", info->c_name, (20-(int)strlen(info->c_name))/8, tabs, l1, n1, (20-l1)/8, tabs, l2, n2, (20-l2)/8, tabs ); while ( *ptr == '|' ) ptr++; } else fprintf(cf, " { CMD_%s,%.*s\"%.*s\",%.*s0,\t\t0 },\n", info->c_name, (20-(int)strlen(info->c_name))/8, tabs, l1, n1, (20-l1)/8, tabs ); } } else if ( info->type == T_SEP_CMD ) fprintf(hf,"\n"); fprintf(cf, "\n { CMD__N,0,0,0 }\n" "};\n" ); } fprintf(hf, "\n\tCMD__N // == %u\n\n" "} enumCommands;\n" , ctrl->n_cmd ); //----- print options print_section(cf,sep1,"OptionShort & OptionLong"); char * dest = iobuf; for ( info = ctrl->info; info < ctrl->end; info++ ) if ( info->type & T_DEF_OPT && info->namelist[1] == '|' ) { *dest++ = info->namelist[0]; if ( info->type & F_OPT_OPTPARAM ) *dest++ = ':'; if ( info->type & (F_OPT_OPTPARAM|F_OPT_PARAM) ) *dest++ = ':'; } *dest = 0; fprintf(cf,"const char OptionShort[] = \"%s\";\n\n",iobuf); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern const char OptionShort[];\n"); ccp opt_buf[OPT_INDEX_SIZE]; memset(opt_buf,0,sizeof(opt_buf)); int getopt_idx = OPT_LONG_BASE; fprintf(cf,"const struct option OptionLong[] =\n{\n"); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern const struct option OptionLong[];\n"); for ( info = ctrl->info; info < ctrl->end; info++ ) if ( info->type & T_DEF_OPT ) { ccp ptr = info->namelist; const int pmode = (info->type & F_OPT_OPTPARAM) ? 2 : (info->type & F_OPT_PARAM) ? 1 : 0; if ( info->namelist[1] == '|' ) { snprintf(iobuf,sizeof(iobuf),"%d, 0, '%c'", pmode, info->namelist[0] ); ptr += 2; opt_buf[(u8)(info->namelist[0])] = info->c_name; } else { snprintf(iobuf,sizeof(iobuf),"%d, 0, GO_%s", pmode, info->c_name ); ASSERT_MSG( getopt_idx < OPT_INDEX_SIZE, "getopt_idx[%x] >= OPT_INDEX_SIZE[%x]\n", getopt_idx, OPT_INDEX_SIZE ); opt_buf[(u8)(getopt_idx++)] = info->c_name; } int indent = 0; while (*ptr) { ccp start = ptr; while ( *ptr && *ptr != '|' ) ptr++; const int len = ptr - start; fprintf(cf,"\t%s{ \"%.*s\",%.*s%s },\n", indent ? " " : "", len, start, (26-len-indent)/8, tabs, iobuf ); if (*ptr) ptr++; indent = 1; } } fprintf(cf,"\n\t{0,0,0,0}\n};\n"); //----- print enumGetOpt print_section(hf,sep1,"enumGetOpt"); fprintf(hf,"typedef enum enumGetOpt\n{"); // add '?' temporary; ASSERT(!opt_buf['?']); opt_buf['?'] = "_ERR"; static const int septab[] = { 0, '0', '9'+1, '?', '?'+1, 'A', 'Z'+1, 'a', 'z'+1, OPT_LONG_BASE, OPT_INDEX_SIZE }; const int * sepptr = septab; int i; for ( i = 0; i < OPT_INDEX_SIZE; i++ ) if ( opt_buf[i] ) { if ( i >= *sepptr ) { fputc('\n',hf); while ( i >= *sepptr ) sepptr++; } if ( i < OPT_LONG_BASE ) fprintf(hf,"\tGO_%s%.*s= '%c',\n", opt_buf[i], (28-(int)strlen(opt_buf[i]))/8, tabs, i ); else if ( i == OPT_LONG_BASE ) fprintf(hf,"\tGO_%s%.*s= 0x%02x,\n", opt_buf[i], (28-(int)strlen(opt_buf[i]))/8, tabs, i ); else fprintf(hf,"\tGO_%s,\n",opt_buf[i]); } fprintf(hf,"\n} enumGetOpt;\n"); opt_buf['?'] = 0; //----- print option index print_section(cf,sep1,"OptionUsed & OptionIndex"); fprintf(cf,"u8 OptionUsed[OPT__N_TOTAL+1] = {0};\n\n"); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern u8 OptionUsed[OPT__N_TOTAL+1];\n"); fprintf(cf,"const u8 OptionIndex[OPT_INDEX_SIZE] = \n{\n"); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern const u8 OptionIndex[OPT_INDEX_SIZE];\n"); for ( i = 0; i < OPT_INDEX_SIZE; ) { int start = i; while ( i < OPT_INDEX_SIZE && !opt_buf[i] ) i++; int len = i - start; while ( len > 0 ) { const int now_len = len < 16 ? len : 16 - start % 16; fprintf(cf,"\t/* 0x%02x */\t %.*s\n", start, 2*now_len + now_len/4, "0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0," ); start += now_len; len -= now_len; } while ( i < OPT_INDEX_SIZE && opt_buf[i] ) { fprintf(cf,"\t/* 0x%02x %c */\tOPT_%s,\n", i, i > ' ' && i < 0x7f ? i : ' ', opt_buf[i]); i++; } } fprintf(cf,"};\n"); //----- option allowed if (ctrl->opt_allow_cmd) { print_section(cf,sep1,"opt_allowed_cmd_*"); for ( info = ctrl->info; info < ctrl->end; info++ ) { if ( !( info->type & T_DEF_CMD ) ) continue; fprintf(cf,"static u8 option_allowed_cmd_%s[%u] = // cmd #%u\n{", info->c_name, ctrl->n_opt_specific, info->index ); int i; u8 * ptr = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific; for ( i = 0; i < ctrl->n_opt_specific; i++ ) fprintf(cf, "%s%u%s", !(i%30) ? "\n " : !(i%10) ? " " : !(i%5) ? " " : "", ptr[i], i < ctrl->n_opt_specific-1 ? "," : "" ); fprintf(cf,"\n};\n\n"); } } //----- InfoCommand print_links(ctrl); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern const InfoCommand_t CommandInfo[CMD__N+1];\n"); //----- InfoUI print_section(cf,sep1,"InfoUI"); var_ptr += snprintf(var_ptr,var_end-var_ptr, "extern const InfoUI_t InfoUI;\n"); fprintf(cf, "const InfoUI_t InfoUI =\n" "{\n" "\t\"%s\",\n" // tool_name "\t%s\n" // n_cmd "\t%s\n" // cmd_tab "\tCommandInfo,\n" // cmd_info "\t%s\n" // n_opt_specific "\tOPT__N_TOTAL,\n" // n_opt_total "\tOptionInfo,\n" // opt_info "\tOptionUsed,\n" // opt_used "\tOptionIndex,\n" // opt_index "\tOptionShort,\n" // opt_short "\tOptionLong\n" // opt_long "};\n", ctrl->info->c_name, ctrl->n_cmd ? "CMD__N," : "0, // n_cmd", ctrl->n_cmd ? "CommandTab," : "0, // cmd_tab", ctrl->n_cmd ? "OPT__N_SPECIFIC," : "0, // n_opt_specific" ); //----- external vars print_section(hf,sep1,"external vars"); fputs(var_buf,hf); //----- terminate print_section(cf,sep1,"END"); print_section(hf,sep1,"END"); fprintf(hf,"#endif // %s\n\n",guard); return ERR_OK; };
/** * 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 }
/** * 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 }
int cb_cpp() { int i; /* Write the file */ if (!io_openfile(path_join(prj_get_pkgpath(), prj_get_pkgname(), "cbp"))) return 0; io_print("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"); io_print("<CodeBlocks_project_file>\n"); io_print("\t<FileVersion major=\"1\" minor=\"6\" />\n"); io_print("\t<Project>\n"); io_print("\t\t<Option title=\"%s\" />\n", prj_get_pkgname()); io_print("\t\t<Option pch_mode=\"2\" />\n"); io_print("\t\t<Option compiler=\"gcc\" />\n"); io_print("\t\t<Build>\n"); for (i = 0; i < prj_get_numconfigs(); ++i) { int kindCode; prj_select_config(i); io_print("\t\t\t<Target title=\"%s\">\n", prj_get_cfgname()); io_print("\t\t\t\t<Option output=\"%s\" prefix_auto=\"0\" extension_auto=\"0\" />\n", prj_get_target()); io_print("\t\t\t\t<Option object_output=\"%s\" />\n", prj_get_objdir()); if (prj_is_kind("winexe")) kindCode = 0; else if (prj_is_kind("exe")) kindCode = 1; else if (prj_is_kind("lib")) kindCode = 2; else if (prj_is_kind("dll")) kindCode = 3; else { printf("** Unsupported project kind %s\n", prj_get_kind()); return 0; } io_print("\t\t\t\t<Option type=\"%d\" />\n", kindCode); io_print("\t\t\t\t<Option compiler=\"gcc\" />\n"); if (prj_is_kind("dll")) { io_print("\t\t\t\t<Option createDefFile=\"0\" />\n"); if (prj_has_flag("no-import-lib")) io_print("\t\t\t\t<Option createStaticLib=\"0\" />\n"); else io_print("\t\t\t\t<Option createStaticLib=\"1\" />\n"); } io_print("\t\t\t\t<Compiler>\n"); if (prj_has_flag("extra-warnings")) print_opt("-Wall"); if (prj_has_flag("fatal-warnings")) print_opt("-Werror"); if (prj_has_flag("no-exceptions")) print_opt("--no-exceptions"); if (prj_has_flag("no-frame-pointer")) print_opt("-fomit-frame-pointer"); if (prj_has_flag("no-rtti")) print_opt("--no-rtti"); if (!prj_has_flag("no-symbols")) print_opt("-g"); if (prj_has_flag("optimize-size")) print_opt("-Os"); if (prj_has_flag("optimize-speed")) print_opt("-O3"); if (prj_has_flag("optimize") && !prj_has_flag("optimize-size") && !prj_has_flag("optimize-speed")) print_opt("-O"); if (prj_has_pch()) { /* Warns you if your pch file is out of date */ print_opt("-Winvalid-pch"); /* Force include the pch header so the user doesn't need to */ io_print("\t\t\t\t\t<Add option=\"-include "%s"\" />\n", prj_get_pch_header()); } print_list(prj_get_defines(), "\t\t\t\t\t<Add option=\"-D", "\" />\n", "", NULL); print_list(prj_get_buildoptions(), "\t\t\t\t\t<Add option=\"", "\" />\n", "", NULL); print_list(prj_get_incpaths(), "\t\t\t\t\t<Add directory=\"", "\" />\n", "", NULL); io_print("\t\t\t\t</Compiler>\n"); io_print("\t\t\t\t<Linker>\n"); if (prj_has_flag("no-symbols")) print_opt("-s"); print_list(prj_get_linkoptions(), "\t\t\t\t\t<Add option=\"", "\" />\n", "", NULL); io_print("\t\t\t\t\t<Add directory=\"%s\" />\n", prj_get_bindir()); if (!matches(prj_get_bindir(), prj_get_libdir())) io_print("\t\t\t\t\t<Add directory=\"%s\" />\n", prj_get_libdir()); print_list(prj_get_libpaths(), "\t\t\t\t\t<Add directory=\"", "\" />\n", "", NULL); print_list(prj_get_links(), "\t\t\t\t\t<Add directory=\"", "\" />\n", "", filterLinksForPaths); print_list(prj_get_links(), "\t\t\t\t\t<Add library=\"", "\" />\n", "", filterLinks); io_print("\t\t\t\t</Linker>\n"); if (prj_find_filetype(".rc")) { io_print("\t\t\t\t<ResourceCompiler>\n"); print_list(prj_get_respaths(), "\t\t\t\t\t<Add directory=\"", "\" />\n", "", NULL); io_print("\t\t\t\t</ResourceCompiler>\n"); } if (prj_get_numprebuildcommands() > 0 || prj_get_numpostbuildcommands() > 0) { io_print("\t\t\t\t<ExtraCommands>\n"); if (prj_get_numprebuildcommands() > 0) print_list(prj_get_prebuildcommands(), "\t\t\t\t\t<Add before=\"", "\" />\n", "", NULL); if (prj_get_numpostbuildcommands() > 0) print_list(prj_get_postbuildcommands(), "\t\t\t\t\t<Add after=\"", "\" />\n", "", NULL); io_print("\t\t\t\t</ExtraCommands>\n"); } io_print("\t\t\t</Target>\n"); } io_print("\t\t</Build>\n"); print_list(prj_get_files(), "", "", "", listFiles); io_print("\t\t<Extensions />\n"); io_print("\t</Project>\n"); io_print("</CodeBlocks_project_file>\n"); io_closefile(); return 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 }
/*Look for mismatch between the source link layer addr and the one anounced *in the icmp option*/ int watch_eth_mismatch(char* buffer, const u_char* packet, uint16_t vlan_id, struct ether_header* eptr, struct ip6_hdr* ipptr, struct icmp6_hdr* icmpptr, int packet_len) { int jump=0; uint8_t opt_type; const u_char* pos; struct nd_opt_hdr* optptr; /*netinet/icmp6.h*/ struct ether_addr* addr1, *addr2; char str_ip[IP6_STR_SIZE]; switch (icmpptr->icmp6_type) { case ND_ROUTER_SOLICIT : jump = sizeof(struct nd_router_solicit); opt_type=1; break; case ND_ROUTER_ADVERT: jump = sizeof(struct nd_router_advert); opt_type=1; break; case ND_NEIGHBOR_SOLICIT: jump = sizeof(struct nd_neighbor_solicit); opt_type=1; break; case ND_NEIGHBOR_ADVERT: jump = sizeof(struct nd_neighbor_advert); opt_type=2; break; case ND_REDIRECT: return 0; break; default: return 0; break; }/*end switch*/ /*We have to search the link layer option among the others options*/ pos = packet + ETHERNET_SIZE + IPV6_SIZE + jump; optptr = (struct nd_opt_hdr*) ( pos ); while((optptr->nd_opt_type != 0) &&((u_char*)optptr < (packet+packet_len))) { if(DEBUG) print_opt(*optptr); if(optptr->nd_opt_type == opt_type) { addr1 = (struct ether_addr*) eptr->ether_shost; addr2 = (struct ether_addr*) (pos + sizeof(struct nd_opt_hdr)); ipv6_ntoa(str_ip, ipptr->ip6_src); /*mac addr = 48bits: 6Bytes*8*/ if(MEMCMP(addr1,addr2,6)!=0) { char eth1[MAC_STR_SIZE]; strncpy( eth1, ether_ntoa(addr1), MAC_STR_SIZE); snprintf (buffer, NOTIFY_BUFFER_SIZE, "VLAN%d: ethernet mismatch %s %s %s", vlan_id, ether_ntoa(addr2),eth1, str_ip); notify(1, buffer, "ethernet mismatch", addr1, str_ip, addr2); return 1; } else { return 0; } } else { /*Next option field*/ pos += (optptr->nd_opt_len)*8; optptr = (struct nd_opt_hdr*) ( pos ); } } return 0; }