int main(int argc, char *argv[]) { int c; char optstring[] = "hcdz0123456789o:S:kfqVvNnt"; int long_only_flag; int ret = 0; int bad_option = 0; int bad_level = 0; int bad_c = 0; struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"stdout", no_argument, NULL, 'c'}, {"to-stdout", no_argument, NULL, 'c'}, {"compress", no_argument, NULL, 'z'}, {"decompress", no_argument, NULL, 'd'}, {"uncompress", no_argument, NULL, 'd'}, {"keep", no_argument, NULL, 'k'}, {"rm", no_argument, &long_only_flag, RM}, {"suffix", no_argument, NULL, 'S'}, {"fast", no_argument, NULL, '1'}, {"best", no_argument, NULL, '0' + ISAL_DEF_MAX_LEVEL}, {"force", no_argument, NULL, 'f'}, {"quiet", no_argument, NULL, 'q'}, {"version", no_argument, NULL, 'V'}, {"verbose", no_argument, NULL, 'v'}, {"no-name", no_argument, NULL, 'n'}, {"name", no_argument, NULL, 'N'}, {"test", no_argument, NULL, 't'}, /* Possible future extensions {"recursive, no_argument, NULL, 'r'}, {"list", no_argument, NULL, 'l'}, {"benchmark", optional_argument, NULL, 'b'}, {"benchmark_end", required_argument, NULL, 'e'}, {"threads", optional_argument, NULL, 'T'}, */ {0, 0, 0, 0} }; init_options(&global_options); opterr = 0; while ((c = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { if (c >= '0' && c <= '9') { if (c > '0' + ISAL_DEF_MAX_LEVEL) bad_level = 1; else global_options.level = c - '0'; continue; } switch (c) { case 0: switch (long_only_flag) { case RM: global_options.remove = true; break; default: bad_option = 1; bad_c = c; break; } break; case 'o': global_options.outfile_name = optarg; global_options.outfile_name_len = strlen(global_options.outfile_name); break; case 'c': global_options.use_stdout = true; break; case 'z': global_options.mode = COMPRESS_MODE; break; case 'd': global_options.mode = DECOMPRESS_MODE; break; case 'S': global_options.suffix = optarg; global_options.suffix_len = strlen(global_options.suffix); break; case 'k': global_options.remove = false; break; case 'f': global_options.force = true; break; case 'q': global_options.quiet_level++; break; case 'v': global_options.verbose_level++; break; case 'V': print_version(); return 0; case 'N': global_options.name = YES_NAME; break; case 'n': global_options.name = NO_NAME; break; case 't': global_options.test = TEST; global_options.mode = DECOMPRESS_MODE; break; case 'h': usage(0); default: bad_option = 1; bad_c = optopt; break; } } if (bad_option) { log_print(ERROR, "igzip: invalid option "); if (bad_c) log_print(ERROR, "-%c\n", bad_c); else log_print(ERROR, ("\n")); usage(BAD_OPTION); } if (bad_level) { log_print(ERROR, "igzip: invalid compression level\n"); usage(BAD_LEVEL); } if (global_options.outfile_name && optind < argc - 1) { log_print(ERROR, "igzip: An output file may be specified with only one input file\n"); return 0; } if (global_options.mode == COMPRESS_MODE) { if (optind >= argc) compress_file(); while (optind < argc) { global_options.infile_name = argv[optind]; global_options.infile_name_len = strlen(global_options.infile_name); ret |= compress_file(); optind++; } } else if (global_options.mode == DECOMPRESS_MODE) { if (optind >= argc) decompress_file(); while (optind < argc) { global_options.infile_name = argv[optind]; global_options.infile_name_len = strlen(global_options.infile_name); ret |= decompress_file(); optind++; } } return ret; }
int main(int argc, char *argv[]) { struct timeval start_time, end_time; struct sigaction handler; double seconds,total_time; // for timers bool lrzcat = false; int c, i; int hours,minutes; extern int optind; char *eptr; /* for environment */ control = &base_control; initialise_control(control); if (strstr(argv[0], "lrunzip")) control->flags |= FLAG_DECOMPRESS; else if (strstr(argv[0], "lrzcat")) { control->flags |= FLAG_DECOMPRESS | FLAG_STDOUT; lrzcat = true; } /* generate crc table */ CrcGenerateTable(); /* Get Preloaded Defaults from lrzip.conf * Look in ., $HOME/.lrzip/, /etc/lrzip. * If LRZIP=NOCONFIG is set, then ignore config */ eptr = getenv("LRZIP"); if (eptr == NULL) read_config(control); else if (!strstr(eptr,"NOCONFIG")) read_config(control); while ((c = getopt_long(argc, argv, "bcdDefghHiklL:nN:o:O:p:qS:tTUm:vVw:z?", long_options, &i)) != -1) { switch (c) { case 'b': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_BZIP2_COMPRESS; break; case 'c': control->flags |= FLAG_CHECK; control->flags |= FLAG_HASH; break; case 'd': control->flags |= FLAG_DECOMPRESS; break; case 'D': control->flags &= ~FLAG_KEEP_FILES; break; case 'e': control->flags |= FLAG_ENCRYPT; break; case 'f': control->flags |= FLAG_FORCE_REPLACE; break; case 'g': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_ZLIB_COMPRESS; break; case 'h': case '?': usage(); return -1; case 'H': control->flags |= FLAG_HASH; break; case 'i': control->flags |= FLAG_INFO; break; case 'k': control->flags |= FLAG_KEEP_BROKEN; break; case 'l': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_LZO_COMPRESS; break; case 'L': control->compression_level = atoi(optarg); if (control->compression_level < 1 || control->compression_level > 9) failure("Invalid compression level (must be 1-9)\n"); break; case 'm': control->ramsize = atol(optarg) * 1024 * 1024 * 100; break; case 'n': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_NO_COMPRESS; break; case 'N': control->nice_val = atoi(optarg); if (control->nice_val < -20 || control->nice_val > 19) failure("Invalid nice value (must be -20..19)\n"); break; case 'o': if (control->outdir) failure("Cannot have -o and -O together\n"); if (unlikely(STDOUT)) failure("Cannot specify an output filename when outputting to stdout\n"); control->outname = optarg; control->suffix = ""; break; case 'O': if (control->outname) /* can't mix -o and -O */ failure("Cannot have options -o and -O together\n"); if (unlikely(STDOUT)) failure("Cannot specify an output directory when outputting to stdout\n"); control->outdir = malloc(strlen(optarg) + 2); if (control->outdir == NULL) fatal("Failed to allocate for outdir\n"); strcpy(control->outdir,optarg); if (strcmp(optarg+strlen(optarg) - 1, "/")) /* need a trailing slash */ strcat(control->outdir, "/"); break; case 'p': control->threads = atoi(optarg); if (control->threads < 1) failure("Must have at least one thread\n"); break; case 'q': control->flags &= ~FLAG_SHOW_PROGRESS; break; case 'S': if (control->outname) failure("Specified output filename already, can't specify an extension.\n"); if (unlikely(STDOUT)) failure("Cannot specify a filename suffix when outputting to stdout\n"); control->suffix = optarg; break; case 't': if (control->outname) failure("Cannot specify an output file name when just testing.\n"); if (!KEEP_FILES) failure("Doubt that you want to delete a file when just testing.\n"); control->flags |= FLAG_TEST_ONLY; break; case 'T': control->flags &= ~FLAG_THRESHOLD; break; case 'U': control->flags |= FLAG_UNLIMITED; break; case 'v': /* set verbosity flag */ if (!(control->flags & FLAG_VERBOSITY) && !(control->flags & FLAG_VERBOSITY_MAX)) control->flags |= FLAG_VERBOSITY; else if ((control->flags & FLAG_VERBOSITY)) { control->flags &= ~FLAG_VERBOSITY; control->flags |= FLAG_VERBOSITY_MAX; } break; case 'V': print_output("lrzip version %s\n", PACKAGE_VERSION); exit(0); break; case 'w': control->window = atol(optarg); break; case 'z': if (control->flags & FLAG_NOT_LZMA) failure("Can only use one of -l, -b, -g, -z or -n\n"); control->flags |= FLAG_ZPAQ_COMPRESS; break; } } argc -= optind; argv += optind; if (control->outname && argc > 1) failure("Cannot specify output filename with more than 1 file\n"); if (VERBOSE && !SHOW_PROGRESS) { print_err("Cannot have -v and -q options. -v wins.\n"); control->flags |= FLAG_SHOW_PROGRESS; } if (UNLIMITED && control->window) { print_err("If -U used, cannot specify a window size with -w.\n"); control->window = 0; } if (argc < 1) control->flags |= FLAG_STDIN; if (UNLIMITED && STDIN) { print_err("Cannot have -U and stdin, unlimited mode disabled.\n"); control->flags &= ~FLAG_UNLIMITED; } setup_overhead(control); /* Set the main nice value to half that of the backend threads since * the rzip stage is usually the rate limiting step */ if (control->nice_val > 0 && !NO_COMPRESS) { if (unlikely(setpriority(PRIO_PROCESS, 0, control->nice_val / 2) == -1)) print_err("Warning, unable to set nice value\n"); } else { if (unlikely(setpriority(PRIO_PROCESS, 0, control->nice_val) == -1)) print_err("Warning, unable to set nice value\n"); } /* One extra iteration for the case of no parameters means we will default to stdin/out */ for (i = 0; i <= argc; i++) { if (i < argc) control->infile = argv[i]; else if (!(i == 0 && STDIN)) break; if (control->infile) { if ((strcmp(control->infile, "-") == 0)) control->flags |= FLAG_STDIN; else { struct stat infile_stat; stat(control->infile, &infile_stat); if (unlikely(S_ISDIR(infile_stat.st_mode))) failure("lrzip only works directly on FILES.\n" "Use lrztar or pipe through tar for compressing directories.\n"); } } if (INFO && STDIN) failure("Will not get file info from STDIN\n"); if ((control->outname && (strcmp(control->outname, "-") == 0)) || /* If no output filename is specified, and we're using * stdin, use stdout */ (!control->outname && STDIN) || lrzcat ) { control->flags |= FLAG_STDOUT; control->outFILE = stdout; control->msgout = stderr; register_outputfile(control, control->msgout); } if (lrzcat) { control->msgout = stderr; control->outFILE = stdout; register_outputfile(control, control->msgout); } if (!STDOUT) { control->msgout = stdout; register_outputfile(control, control->msgout); } if (STDIN) control->inFILE = stdin; /* Implement signal handler only once flags are set */ sigemptyset(&handler.sa_mask); handler.sa_flags = 0; handler.sa_handler = &sighandler; sigaction(SIGTERM, &handler, 0); sigaction(SIGINT, &handler, 0); if (!FORCE_REPLACE) { if (STDIN && isatty(fileno((FILE *)stdin))) { print_err("Will not read stdin from a terminal. Use -f to override.\n"); usage(); exit (1); } if (!TEST_ONLY && STDOUT && isatty(fileno((FILE *)stdout))) { print_err("Will not write stdout to a terminal. Use -f to override.\n"); usage(); exit (1); } } if (CHECK_FILE) { if (!DECOMPRESS) { print_err("Can only check file written on decompression.\n"); control->flags &= ~FLAG_CHECK; } else if (STDOUT) { print_err("Can't check file written when writing to stdout. Checking disabled.\n"); control->flags &= ~FLAG_CHECK; } } setup_ram(control); show_summary(); gettimeofday(&start_time, NULL); if (unlikely(STDIN && ENCRYPT)) failure("Unable to work from STDIN while reading password\n"); memcpy(&local_control, &base_control, sizeof(rzip_control)); if (DECOMPRESS || TEST_ONLY) decompress_file(&local_control); else if (INFO) get_fileinfo(&local_control); else compress_file(&local_control); /* compute total time */ gettimeofday(&end_time, NULL); total_time = (end_time.tv_sec + (double)end_time.tv_usec / 1000000) - (start_time.tv_sec + (double)start_time.tv_usec / 1000000); hours = (int)total_time / 3600; minutes = (int)(total_time / 60) % 60; seconds = total_time - hours * 3600 - minutes * 60; if (!INFO) print_progress("Total time: %02d:%02d:%05.2f\n", hours, minutes, seconds); } return 0; }
static bool test_recursive(ilzham &lzham_dll, const char *pPath, comp_options options) { string_array files; if (!find_files(pPath, "*", files, true)) { print_error("Failed finding files under path \"%s\"!\n", pPath); return false; } uint total_files_compressed = 0; uint64 total_source_size = 0; uint64 total_comp_size = 0; #ifdef WIN32 MEMORYSTATUS initial_mem_status; GlobalMemoryStatus(&initial_mem_status); #endif timer_ticks start_tick_count = timer::get_ticks(); const int first_file_index = 0; uint unique_id = static_cast<uint>(timer::get_init_ticks()); char cmp_file[256], decomp_file[256]; #ifdef _XBOX sprintf(cmp_file, "e:\\__comp_temp_%u__.tmp", unique_id); sprintf(decomp_file, "e:\\__decomp_temp_%u__.tmp", unique_id); #else sprintf(cmp_file, "__comp_temp_%u__.tmp", unique_id); sprintf(decomp_file, "__decomp_temp_%u__.tmp", unique_id); #endif for (uint file_index = first_file_index; file_index < files.size(); file_index++) { const std::string &src_file = files[file_index]; printf("***** [%u of %u] Compressing file \"%s\" to \"%s\"\n", 1 + file_index, (uint)files.size(), src_file.c_str(), cmp_file); FILE *pFile = fopen(src_file.c_str(), "rb"); if (!pFile) { printf("Skipping unreadable file \"%s\"\n", src_file.c_str()); continue; } fseek(pFile, 0, SEEK_END); int64 src_file_size = _ftelli64(pFile); fclose(pFile); if (!ensure_file_is_writable(cmp_file)) { print_error("Unable to create file \"%s\"!\n", cmp_file); return false; } comp_options file_options(options); if (options.m_randomize_params) { file_options.m_comp_level = static_cast<lzham_compress_level>(rand() % LZHAM_TOTAL_COMP_LEVELS); file_options.m_dict_size_log2 = LZHAM_MIN_DICT_SIZE_LOG2 + (rand() % (LZHAMTEST_MAX_POSSIBLE_DICT_SIZE - LZHAM_MIN_DICT_SIZE_LOG2 + 1)); file_options.m_max_helper_threads = rand() % (LZHAM_MAX_HELPER_THREADS + 1); file_options.m_unbuffered_decompression = (rand() & 1) != 0; #if !LZHAMTEST_NO_RANDOM_EXTREME_PARSING file_options.m_extreme_parsing = (rand() & 1) != 0; #endif file_options.m_force_polar_codes = (rand() & 1) != 0; file_options.m_deterministic_parsing = (rand() & 1) != 0; file_options.print(); } bool status = compress_streaming(lzham_dll, src_file.c_str(), cmp_file, file_options); if (!status) { print_error("Failed compressing file \"%s\" to \"%s\"\n", src_file.c_str(), cmp_file); return false; } if (file_options.m_verify_compressed_data) { printf("Decompressing file \"%s\" to \"%s\"\n", cmp_file, decomp_file); if (!ensure_file_is_writable(decomp_file)) { print_error("Unable to create file \"%s\"!\n", decomp_file); return false; } status = decompress_file(lzham_dll, cmp_file, decomp_file, file_options); if (!status) { print_error("Failed decompressing file \"%s\" to \"%s\"\n", src_file.c_str(), decomp_file); return false; } printf("Comparing file \"%s\" to \"%s\"\n", decomp_file, src_file.c_str()); if (!compare_files(decomp_file, src_file.c_str())) { print_error("Failed comparing decompressed file data while compressing \"%s\" to \"%s\"\n", src_file.c_str(), cmp_file); return false; } else { printf("Decompressed file compared OK to original file.\n"); } } int64 cmp_file_size = 0; pFile = fopen(cmp_file, "rb"); if (pFile) { fseek(pFile, 0, SEEK_END); cmp_file_size = _ftelli64(pFile); fclose(pFile); } total_files_compressed++; total_source_size += src_file_size; total_comp_size += cmp_file_size; #ifdef WIN32 MEMORYSTATUS mem_status; GlobalMemoryStatus(&mem_status); #ifdef _XBOX const int64 bytes_allocated = initial_mem_status.dwAvailPhys - mem_status.dwAvailPhys; #else const int64 bytes_allocated = initial_mem_status.dwAvailVirtual- mem_status.dwAvailVirtual; #endif printf("Memory allocated relative to first file: %I64i\n", bytes_allocated); #endif printf("\n"); } timer_ticks end_tick_count = timer::get_ticks(); double total_elapsed_time = timer::ticks_to_secs(end_tick_count - start_tick_count); printf("Test successful: %f secs\n", total_elapsed_time); printf("Total files processed: %u\n", total_files_compressed); printf("Total source size: " QUAD_INT_FMT "\n", total_source_size); printf("Total compressed size: " QUAD_INT_FMT "\n", total_comp_size); remove(cmp_file); remove(decomp_file); return true; }
int main_internal(string_array cmd_line, int num_helper_threads, ilzham &lzham_dll) { comp_options options; options.m_max_helper_threads = num_helper_threads; #ifdef _XBOX options.m_dict_size_log2 = 21; #endif if (!cmd_line.size()) { print_usage(); return simple_test(lzham_dll, options); } enum op_mode_t { OP_MODE_INVALID = -1, OP_MODE_COMPRESS = 0, OP_MODE_DECOMPRESS = 1, OP_MODE_ALL = 2 }; op_mode_t op_mode = OP_MODE_INVALID; for (int i = 0; i < (int)cmd_line.size(); i++) { const std::string &str = cmd_line[i]; if (str[0] == '-') { if (str.size() < 2) { print_error("Invalid option: %s\n", str.c_str()); return EXIT_FAILURE; } switch (tolower(str[1])) { case 'u': { options.m_unbuffered_decompression = true; break; } case 'd': { int dict_size = atoi(str.c_str() + 2); if ((dict_size < LZHAM_MIN_DICT_SIZE_LOG2) || (dict_size > LZHAMTEST_MAX_POSSIBLE_DICT_SIZE)) { print_error("Invalid dictionary size: %s\n", str.c_str()); return EXIT_FAILURE; } options.m_dict_size_log2 = dict_size; break; } case 'm': { int comp_level = atoi(str.c_str() + 2); if ((comp_level < 0) || (comp_level > (int)LZHAM_COMP_LEVEL_UBER)) { print_error("Invalid compression level: %s\n", str.c_str()); return EXIT_FAILURE; } options.m_comp_level = static_cast<lzham_compress_level>(comp_level); break; } case 't': { int num_threads = atoi(str.c_str() + 2); if ((num_threads < 0) || (num_threads > LZHAM_MAX_HELPER_THREADS)) { print_error("Invalid number of helper threads: %s\n", str.c_str()); return EXIT_FAILURE; } options.m_max_helper_threads = num_threads; break; } case 'c': { options.m_compute_adler32_during_decomp = false; break; } case 'v': { options.m_verify_compressed_data = true; break; } case 'r': { options.m_randomize_params = true; break; } case 'p': { options.m_force_polar_codes = true; break; } case 'x': { options.m_extreme_parsing = true; break; } case 'e': { options.m_deterministic_parsing = true; break; } case 's': { int seed = atoi(str.c_str() + 2); srand(seed); printf("Using random seed: %i\n", seed); break; } default: { print_error("Invalid option: %s\n", str.c_str()); return EXIT_FAILURE; } } cmd_line.erase(cmd_line.begin() + i); i--; continue; } if (str.size() != 1) { print_error("Invalid mode: %s\n", str.c_str()); return EXIT_FAILURE; } switch (tolower(str[0])) { case 'c': { op_mode = OP_MODE_COMPRESS; break; } case 'd': { op_mode = OP_MODE_DECOMPRESS; break; } case 'a': { op_mode = OP_MODE_ALL; break; } default: { print_error("Invalid mode: %s\n", str.c_str()); return EXIT_FAILURE; } } cmd_line.erase(cmd_line.begin() + i); break; } if (op_mode == OP_MODE_INVALID) { print_error("No mode specified!\n"); print_usage(); return EXIT_FAILURE; } printf("Using options:\n"); options.print(); printf("\n"); int exit_status = EXIT_FAILURE; switch (op_mode) { case OP_MODE_COMPRESS: { if (cmd_line.size() < 2) { print_error("Must specify input and output filenames!\n"); return EXIT_FAILURE; } else if (cmd_line.size() > 2) { print_error("Too many filenames!\n"); return EXIT_FAILURE; } const std::string &src_file = cmd_line[0]; const std::string &cmp_file = cmd_line[1]; bool comp_result = compress_streaming(lzham_dll, src_file.c_str(), cmp_file.c_str(), options); if (comp_result) exit_status = EXIT_SUCCESS; if ((comp_result) && (options.m_verify_compressed_data)) { char decomp_file[256]; #ifdef _XBOX sprintf(decomp_file, "e:\\__decomp_temp_%u__.tmp", (uint)GetTickCount()); #else sprintf(decomp_file, "__decomp_temp_%u__.tmp", (uint)timer::get_ms()); #endif if (!decompress_file(lzham_dll, cmp_file.c_str(), decomp_file, options)) { print_error("Failed decompressing file \"%s\" to \"%s\"\n", cmp_file.c_str(), decomp_file); return EXIT_FAILURE; } printf("Comparing file \"%s\" to \"%s\"\n", decomp_file, src_file.c_str()); if (!compare_files(decomp_file, src_file.c_str())) { print_error("Failed comparing decompressed file data while compressing \"%s\" to \"%s\"\n", src_file.c_str(), cmp_file.c_str()); return EXIT_FAILURE; } else { printf("Decompressed file compared OK to original file.\n"); } remove(decomp_file); } break; } case OP_MODE_DECOMPRESS: { if (cmd_line.size() < 2) { print_error("Must specify input and output filenames!\n"); return EXIT_FAILURE; } else if (cmd_line.size() > 2) { print_error("Too many filenames!\n"); return EXIT_FAILURE; } if (decompress_file(lzham_dll, cmd_line[0].c_str(), cmd_line[1].c_str(), options)) exit_status = EXIT_SUCCESS; break; } case OP_MODE_ALL: { if (!cmd_line.size()) { print_error("No directory specified!\n"); return EXIT_FAILURE; } else if (cmd_line.size() != 1) { print_error("Too many filenames!\n"); return EXIT_FAILURE; } if (test_recursive(lzham_dll, cmd_line[0].c_str(), options)) exit_status = EXIT_SUCCESS; break; } default: { print_error("No mode specified!\n"); print_usage(); return EXIT_FAILURE; } } return exit_status; }
int tmain(int argc, tchar *argv[]) { struct options options; int opt_char; int i; int ret; program_invocation_name = get_filename(argv[0]); options.to_stdout = false; options.decompress = is_gunzip(); options.force = false; options.keep = false; options.compression_level = 6; options.suffix = T("gz"); while ((opt_char = tgetopt(argc, argv, optstring)) != -1) { switch (opt_char) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': options.compression_level = parse_compression_level(opt_char, toptarg); if (options.compression_level == 0) return -1; break; case 'c': options.to_stdout = true; break; case 'd': options.decompress = true; break; case 'f': options.force = true; break; case 'h': show_usage(stdout); return 0; case 'k': options.keep = true; break; case 'S': options.suffix = toptarg; break; case 'V': show_version(); return 0; default: show_usage(stderr); return 1; } } argv += toptind; argc -= toptind; if (argc == 0) { show_usage(stderr); return 1; } for (i = 0; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == '\0') { msg("This implementation of gzip does not yet " "support reading from standard input."); return 1; } } ret = 0; if (options.decompress) { struct deflate_decompressor *d; d = alloc_decompressor(); if (d == NULL) return 1; for (i = 0; i < argc; i++) ret |= -decompress_file(d, argv[i], &options); deflate_free_decompressor(d); } else { struct deflate_compressor *c; c = alloc_compressor(options.compression_level); if (c == NULL) return 1; for (i = 0; i < argc; i++) ret |= -compress_file(c, argv[i], &options); deflate_free_compressor(c); } /* * If ret=0, there were no warnings or errors. Exit with status 0. * If ret=2, there was at least one warning. Exit with status 2. * Else, there was at least one error. Exit with status 1. */ if (ret != 0 && ret != 2) ret = 1; return ret; }
int main(int argc, char **argv) { int pr[2]; int sk; int nbd; int blocksize = 1024; char chunk[CHUNK]; struct nbd_request request; struct nbd_reply reply; u64 size; u64 from; u32 len; /* */ int file, oldfile = -1; u32 offset; unsigned char *ptr = NULL; if(argc<3){ printf("Usage: %s nbdevice gzfile\n",argv[0]); exit(1); } /* memory for one decompressed block */ all = malloc(1024*88064); if(argc == 3){ int nb, fid; char buf[512]; /* find an approximate size */ for (nb = 0; ; nb++) { sprintf(buf, "%s%03d", argv[2], nb); if ((fid=open(buf, O_RDONLY)) == -1) { break; } close(fid); } if (nb == 0) { fprintf(stderr,"%s: unable open compressed file %s\n",argv[0], buf); exit(1); } size = (u64)88064*(u64)1024*nb; } else { exit(1); } if(socketpair(AF_UNIX, SOCK_STREAM, 0, pr)){ fprintf(stderr,"%s: unable to create socketpair: %s\n",argv[0],strerror(errno)); exit(1); } switch(fork()){ case -1 : fprintf(stderr,"%s: unable to fork: %s\n",argv[0],strerror(errno)); exit(1); break; case 0 : /* child */ close(pr[0]); sk=pr[1]; nbd=open(argv[1], O_RDWR); if(nbd<0){ fprintf(stderr,"%s: unable to open %s: %s\n",argv[0],argv[1],strerror(errno)); exit(1); } if (ioctl(nbd, NBD_SET_BLKSIZE, (unsigned long)blocksize) < 0) { fprintf(stderr, "NBD_SET_BLKSIZE failed\n"); exit(1); } if ((ioctl(nbd, NBD_SET_SIZE_BLOCKS, (unsigned long)(size/blocksize))) < 0) { fprintf(stderr, "NBD_SET_SIZE_BLOKS failed\n"); exit(1); } ioctl(nbd, NBD_CLEAR_SOCK); if(ioctl(nbd,NBD_SET_SOCK,sk)<0){ fprintf(stderr,"%s: failed to set socket for %s: %s\n",argv[0],argv[1],strerror(errno)); exit(1); } if(ioctl(nbd,NBD_DO_IT)<0){ fprintf(stderr,"%s: block device %s terminated: %s\n",argv[0],argv[1],strerror(errno)); } ioctl(nbd, NBD_CLEAR_QUE); ioctl(nbd, NBD_CLEAR_SOCK); exit(0); break; } /* only parent here, child always exits */ close(pr[1]); sk=pr[0]; reply.magic=htonl(NBD_REPLY_MAGIC); reply.error=htonl(0); BUFFER = malloc(24064); Bitmap = malloc(24064 - 2048); IN = malloc(INSIZE); sleep(1); while(1){ if(read(sk,&request,sizeof(request))!=sizeof(request)){ fprintf(stderr,"%s: incomplete request\n",argv[0]); } memcpy(reply.handle,request.handle,sizeof(reply.handle)); len=ntohl(request.len); from=ntohll(request.from); #ifdef TRACE fprintf(stderr,"%s: len=%d, from=%Ld\n",argv[0],len,from); #endif if(request.magic!=htonl(NBD_REQUEST_MAGIC)){ fprintf(stderr,"%s: bad magic\n",argv[0]); reply.error=htonl(EIO); /* is that the right way of doing things ? */ } /* write resquest */ if(ntohl(request.type) == 1){ // fprintf(stderr,"%s: unsupported write request (len=%d)\n",argv[0], len); readit(sk, chunk, len); /* fake write */ reply.error=htonl(0); len = 0; memcpy(chunk,&reply,sizeof(struct nbd_reply)); if(write(sk,chunk,len+sizeof(struct nbd_reply))!=(len+sizeof(struct nbd_reply))){ fprintf(stderr,"%s: write failed: %s\n",argv[0],strerror(errno)); } continue; } /* disc request */ if(ntohl(request.type) == 2){ fprintf(stderr,"%s: unsupported disc request\n",argv[0]); reply.error=htonl(EROFS); } if(len+sizeof(struct nbd_reply)>CHUNK){ fprintf(stderr,"%s: request too long (%d)\n",argv[0], len+sizeof(struct nbd_reply)); //reply.error=htonl(EIO); } /* read request */ if(reply.error==htonl(0)){ int remain = len; int offset2 = 0; /* which chunk to open */ file = from / (88064*1024); offset = from % (88064*1024); while (remain > 0) { u32 cpylen; if (oldfile != file) { decompress_file(argv[2], file, offset); oldfile = file; } ptr = &all[offset]; if (offset + remain >= 88064*1024) { /* request on a block boundary */ cpylen = (88064*1024)-offset; remain -= cpylen; file++; offset = 0; } else { /* request within a block */ cpylen = remain; remain = 0; } /* copy the data */ memcpy(chunk+sizeof(struct nbd_reply)+offset2, ptr, cpylen); offset2 += cpylen; } } else { len=0; } /* copy the reply header */ memcpy(chunk,&reply,sizeof(struct nbd_reply)); /* send data to kernel */ if(write(sk,chunk,len+sizeof(struct nbd_reply))!=(len+sizeof(struct nbd_reply))){ fprintf(stderr,"%s: write failed: %s\n",argv[0],strerror(errno)); } } exit(0); }