📄 tapetype.c
字号:
off_t blockdiff; off_t filediff; size_t filemark; unsigned long speed; off_t size; char *sizeunits; int ch; char *suffix = NULL; char *typename; time_t now; int hwcompr = 0; int comprtstonly = 0; int overwrite_label = 0; int is_labeled = 0; char *result; char *datestamp = NULL; char *label = NULL; /* * Configure program for internationalization: * 1) Only set the message locale for now. * 2) Set textdomain for all amanda related programs to "amanda" * We don't want to be forced to support dozens of message catalogs. */ setlocale(LC_MESSAGES, "C"); textdomain("amanda"); config_init(0, NULL); if ((sProgName = strrchr(*argv, '/')) == NULL) { sProgName = *argv; } else { sProgName++; } /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); estsize = (off_t)0; tapedev = getenv("TAPE"); typename = "unknown-tapetype"; while ((ch = getopt(argc, argv, "b:e:f:t:hco")) != EOF) { switch (ch) { case 'b': blockkb = (size_t)strtol(optarg, &suffix, 0); if (!(*suffix == '\0' || *suffix == 'k' || *suffix == 'K')) { if (*suffix == 'm' || *suffix == 'M') { blockkb *= 1024; } else if (*suffix == 'g' || *suffix == 'G') { blockkb *= (1024 * 1024); } else { g_fprintf(stderr, _("%s: unknown size suffix \'%c\'\n"), sProgName, *suffix); return 1; } } break; case 'e': estsize = OFF_T_STRTOL(optarg, &suffix, 0); if (!(*suffix == '\0' || *suffix == 'k' || *suffix == 'K')) { if (*suffix == 'm' || *suffix == 'M') { estsize *= (off_t)1024; } else if (*suffix == 'g' || *suffix == 'G') { estsize *= (off_t)(1024 * 1024); } else { g_fprintf(stderr, _("%s: unknown size suffix \'%c\'\n"), sProgName, *suffix); return 1; } } break; case 'f': tapedev = stralloc(optarg); break; case 't': typename = stralloc(optarg); break; case 'c': comprtstonly = 1; break; case 'h': help(); return 1; case 'o': overwrite_label=1; break; default: g_fprintf(stderr, _("%s: unknown option \'%c\'\n"), sProgName, ch); /*FALLTHROUGH*/ case '?': usage(); return 1; } } blocksize = blockkb * 1024; if (tapedev == NULL) { g_fprintf(stderr, _("%s: No tapedev specified\n"), sProgName); usage(); return 1; } if (optind < argc) { usage(); return 1; } if (estsize == 0) { if (comprtstonly) { estsize = (off_t)(1024 * 1024); /* assume 1 GByte for now */ } else { g_fprintf(stderr, _("%s: please specify estimated tape capacity (e.g. '-e 4g')\n"), sProgName); usage(); return 1; } }/* verifier tape */ fd = tape_open(tapedev, O_RDONLY, 0); if (fd == -1) { g_fprintf(stderr, _("%s: could not open %s: %s\n"), sProgName, tapedev, strerror(errno)); return 1; } if((result = tapefd_rdlabel(fd, &datestamp, &label)) == NULL) { is_labeled = 1; } else if (strcmp(result,_("not an amanda tape")) == 0) { is_labeled = 2; } if(tapefd_rewind(fd) == -1) { g_fprintf(stderr, _("%s: could not rewind %s: %s\n"), sProgName, tapedev, strerror(errno)); tapefd_close(fd); return 1; } tapefd_close(fd); if(is_labeled == 1 && overwrite_label == 0) { g_fprintf(stderr, _("%s: The tape is an amanda tape, use -o to overwrite the tape\n"), sProgName); return 1; } else if(is_labeled == 2 && overwrite_label == 0) { g_fprintf(stderr, _("%s: The tape is already used, use -o to overwrite the tape\n"), sProgName); return 1; } fd = tape_open(tapedev, O_RDWR, 0); if (fd == -1) { g_fprintf(stderr, _("%s: could not open %s: %s\n"), sProgName, tapedev, strerror(errno)); return 1; } do_tty = isatty(fileno(stderr)); /* * Estimate pass: write twice a small file, once with compressable * data and once with uncompressable data. * The theory is that if the drive is in hardware compression mode * we notice a significant difference in writing speed between the two * (at least if we can provide data as fast the tape streams). */ initnotrandombytes(); g_fprintf(stderr, _("Estimate phase 1...")); pass0size = (off_t)(8 * 1024 / blockkb); pass1time = 0; pass2time = 0; /* * To get accurate results, we should write enough data * so that rewind/start/stop time is small compared to * the total time; let's take 10%. * The timer has a 1 sec granularity, so the test * should take at least 10 seconds to measure a * difference with 10% accuracy; let's take 25 seconds. */ while (pass1time < 25 || ((100*(pass2time-pass1time)/pass2time) >= 10) ) { if (pass1time != 0) { time_t t = pass1time; do { pass0size *= (off_t)2; t *= 2; } while (t < 25); } /* * first a dummy pass to rewind, stop, start and * get drive streaming, then do the real timing */ do_pass0(pass0size, &pass2time, 1); do_pass0(pass0size, &pass1time, 0); if (pass0size >= (off_t)(10 * 1024 * 1024)) { g_fprintf(stderr, "\r"); g_fprintf(stderr, _("Tape device is too fast to detect hardware compression...\n")); break; /* avoid loops if tape is superfast or broken */ } } g_fprintf(stderr, "\r"); g_fprintf(stderr, _("Writing %lld Mbyte compresseable data: %jd sec\n"), (long long)((off_t)blockkb * pass0size / (off_t)1024), (intmax_t)pass1time); /* * now generate uncompressable data and try again */ time(&now); srandom((unsigned)now); initrandombytes(); g_fprintf(stderr, _("Estimate phase 2...")); do_pass0(pass0size, &pass2time, 1); /* rewind and get drive streaming */ do_pass0(pass0size, &pass2time, 0); g_fprintf(stderr, "\r"); g_fprintf(stderr, _("Writing %lld Mbyte uncompresseable data: %jd sec\n"), (long long)((off_t)blockkb * pass0size / (off_t)1024), (intmax_t)pass2time); /* * Compute the time difference between writing the compressable and * uncompressable data. If it differs more than 20%, then warn * user that the tape drive has probably hardware compression enabled. */ if (pass1time > pass2time) { /* * Strange! I would expect writing compresseable data to be * much faster (or about equal, if hardware compression is disabled) */ timediff = 0; } else { timediff = pass2time - pass1time; } if (((100 * timediff) / pass2time) >= 20) { /* 20% faster? */ g_fprintf(stderr, _("WARNING: Tape drive has hardware compression enabled\n")); hwcompr = 1; } /* * Inform about estimated time needed to run the remaining of this program */ g_fprintf(stderr, _("Estimated time to write 2 * %lu Mbyte: "), (unsigned long) (estsize / (off_t)1024)); pass1time = (time_t)(2.0 * (double)pass2time * (double)estsize / (1.0 * (double)pass0size * (double)blockkb)); /* avoid overflow and underflow by doing math in floating point */ g_fprintf(stderr, _("%jd sec = %jd h %jd min\n"), (intmax_t)pass1time, (intmax_t)(pass1time/(time_t)3600), (intmax_t)((pass1time%(time_t)3600) / (time_t)60)); if (comprtstonly) { exit(hwcompr); } /* * Do pass 1 -- write files that are 1% of the estimated size until error. */ pass1size = (off_t)(((double)estsize * 0.01) / (double)blockkb); /* 1% of estimate */ if(pass1size <= (off_t)0) { pass1size = (off_t)2; /* strange end case */ } do_pass(pass1size, &pass1blocks, &pass1files, &pass1time); /* * Do pass 2 -- write smaller files until error. */ pass2size = pass1size / (off_t)2; do_pass(pass2size, &pass2blocks, &pass2files, &pass2time); /* * Compute the size of a filemark as the difference in data written * between pass 1 and pass 2 divided by the difference in number of * file marks written between pass 1 and pass 2. Note that we have * to be careful in case size_t is unsigned (i.e. do not subtract * things and then check for less than zero). */ if (pass1blocks <= pass2blocks) { /* * If tape marks take up space, there should be fewer blocks in pass * 2 than in pass 1 since we wrote twice as many tape marks. But * odd things happen, so make sure the result does not go negative. */ blockdiff = (off_t)0; } else { blockdiff = pass1blocks - pass2blocks; } if (pass2files <= pass1files) { /* * This should not happen, but just in case ... */ filediff = (off_t)1; } else { filediff = pass2files - pass1files; } filemark = (size_t)((blockdiff * (off_t)blockkb) / filediff); /* * Compute the length as the average of the two pass sizes including * tape marks. */ size = ((pass1blocks * (off_t)blockkb + (off_t)filemark * pass1files) + (pass2blocks * (off_t)blockkb + (off_t)filemark * pass2files)) / (off_t)2; if (size >= (off_t)(1024 * 1024 * 1000)) { size /= (off_t)(1024 * 1024); sizeunits = "gbytes"; } else if (size >= (off_t)(1024 * 1000)) { size /= (off_t)1024; sizeunits = "mbytes"; } else { sizeunits = "kbytes"; } /* * Compute the speed as the average of the two passes. */ speed = (unsigned long)((((double)pass1blocks * (double)blockkb / (double)pass1time) + ((double)pass2blocks * (double)blockkb / (double)pass2time)) / 2.0); /* * Dump the tapetype. */ g_printf("define tapetype %s {\n", typename); g_printf(_(" comment \"just produced by tapetype prog (hardware compression %s)\"\n"), hwcompr ? _("on") : _("off")); g_printf(" length %lld %s\n", (long long)size, sizeunits); g_printf(" filemark %zu kbytes\n", filemark); g_printf(" speed %lu kps\n", speed); g_printf("}\n"); if (tapefd_rewind(fd) == -1) { g_fprintf(stderr, _("%s: could not rewind %s: %s\n"), sProgName, tapedev, strerror(errno)); return 1; } if (tapefd_close(fd) == -1) { g_fprintf(stderr, _("%s: could not close %s: %s\n"), sProgName, tapedev, strerror(errno)); return 1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -