int position_to_block(uint32_t blk_number, uint8_t *sam_stat) { if (!tape_loaded(sam_stat)) return -1; MHVTL_DBG(2, "Position to block %d", blk_number); if (mam.MediumType == MEDIA_TYPE_WORM) OK_to_write = 0; if (blk_number > eod_blk_number) { sam_blank_check(E_END_OF_DATA, sam_stat); MHVTL_DBG(1, "End of data detected while positioning"); return position_to_eod(sam_stat); } /* Treat a position to block zero specially, as it has different semantics than other blocks when the tape is WORM. */ if (blk_number == 0) return rewind_tape(sam_stat); else return read_header(blk_number, sam_stat); }
uint8_t ssc_rewind(struct scsi_cmd *cmd) { struct priv_lu_ssc *lu_priv; uint8_t *sam_stat; int retval; lu_priv = cmd->lu->lu_private; sam_stat = &cmd->dbuf_p->sam_stat; MHVTL_DBG(1, "Rewinding (%ld) **", (long)cmd->dbuf_p->serialNo); current_state = MHVTL_STATE_REWIND; switch (lu_priv->tapeLoaded) { case TAPE_UNLOADED: mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat); return SAM_STAT_CHECK_CONDITION; break; case TAPE_LOADED: retval = rewind_tape(sam_stat); if (retval < 0) { mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat); return SAM_STAT_CHECK_CONDITION; } break; default: mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat); return SAM_STAT_CHECK_CONDITION; break; } return SAM_STAT_GOOD; }
int position_to_block(uint32_t blk_no, uint8_t *sam_stat) { MHVTL_DBG(1, "position_to_block"); if (!tape_loaded(sam_stat)) return -1; if (MediumType == MEDIA_TYPE_WORM) OK_to_write = 0; if (blk_no < raw_pos.hdr.blk_number && raw_pos.hdr.blk_number - blk_no > blk_no) { if (rewind_tape(sam_stat)) return -1; } while (raw_pos.hdr.blk_number != blk_no) { if (raw_pos.hdr.blk_number > blk_no) { if (skip_to_prev_header(sam_stat) == -1) return -1; } else { if (skip_to_next_header(sam_stat) == -1) return -1; } } return 0; }
uint8_t ssc_load_unload(struct scsi_cmd *cmd) { struct priv_lu_ssc *lu_priv; uint8_t *sam_stat; int load; lu_priv = cmd->lu->lu_private; sam_stat = &cmd->dbuf_p->sam_stat; load = cmd->scb[4] & 0x01; current_state = (load) ? MHVTL_STATE_LOADING : MHVTL_STATE_UNLOADING; if (cmd->scb[4] & 0x04) { /* EOT bit */ MHVTL_ERR("EOT bit set on load. Not supported"); mkSenseBuf(ILLEGAL_REQUEST, E_INVALID_FIELD_IN_CDB, sam_stat); return SAM_STAT_CHECK_CONDITION; } MHVTL_DBG(1, "%s tape (%ld) **", (load) ? "Loading" : "Unloading", (long)cmd->dbuf_p->serialNo); switch (lu_priv->tapeLoaded) { case TAPE_UNLOADED: if (load) rewind_tape(sam_stat); else { mkSenseBuf(NOT_READY, E_MEDIUM_NOT_PRESENT, sam_stat); return SAM_STAT_CHECK_CONDITION; } break; case TAPE_LOADED: if (!load) unloadTape(sam_stat); break; default: mkSenseBuf(NOT_READY, E_MEDIUM_FMT_CORRUPT, sam_stat); return SAM_STAT_CHECK_CONDITION; break; } return SAM_STAT_GOOD; }
int main(int argc, char *argv[]) { int lastnread, nread, nw, inp, outp; enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; sig_t oldsig; int ch, needeof; char *buff; const char *inf; msg = stdout; guesslen = 1; outp = -1; while ((ch = getopt(argc, argv, "cs:vx")) != -1) switch((char)ch) { case 'c': op = COPYVERIFY; break; case 's': maxblk = atoi(optarg); if (maxblk <= 0) { warnx("illegal block size"); usage(); } guesslen = 0; break; case 'v': op = VERIFY; break; case 'x': msg = stderr; break; case '?': default: usage(); } argc -= optind; argv += optind; switch(argc) { case 0: if (op != READ) usage(); inf = _PATH_DEFTAPE; break; case 1: if (op != READ) usage(); inf = argv[0]; break; case 2: if (op == READ) op = COPY; inf = argv[0]; if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : op == COPY ? O_WRONLY : O_RDWR, DEFFILEMODE)) < 0) err(3, "%s", argv[1]); break; default: usage(); } if ((inp = open(inf, O_RDONLY, 0)) < 0) err(1, "%s", inf); buff = getspace(maxblk); if (op == VERIFY) { verify(inp, outp, buff); exit(0); } if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) (void) signal(SIGINT, intr); needeof = 0; for (lastnread = NOCOUNT;;) { if ((nread = read(inp, buff, maxblk)) == -1) { while (errno == EINVAL && (maxblk -= 1024)) { nread = read(inp, buff, maxblk); if (nread >= 0) goto r1; } err(1, "read error, file %d, record %ju", filen, (intmax_t)record); } else if (nread != lastnread) { if (lastnread != 0 && lastnread != NOCOUNT) { if (lastrec == 0 && nread == 0) fprintf(msg, "%ju records\n", (intmax_t)record); else if (record - lastrec > 1) fprintf(msg, "records %ju to %ju\n", (intmax_t)lastrec, (intmax_t)record); else fprintf(msg, "record %ju\n", (intmax_t)lastrec); } if (nread != 0) fprintf(msg, "file %d: block size %d: ", filen, nread); (void) fflush(stdout); lastrec = record; } r1: guesslen = 0; if (nread > 0) { if (op == COPY || op == COPYVERIFY) { if (needeof) { writeop(outp, MTWEOF); needeof = 0; } nw = write(outp, buff, nread); if (nw != nread) { if (nw == -1) { warn("write error, file %d, record %ju", filen, (intmax_t)record); } else { warnx("write error, file %d, record %ju", filen, (intmax_t)record); warnx("write (%d) != read (%d)", nw, nread); } errx(5, "copy aborted"); } } size += nread; record++; } else { if (lastnread <= 0 && lastnread != NOCOUNT) { fprintf(msg, "eot\n"); break; } fprintf(msg, "file %d: eof after %ju records: %ju bytes\n", filen, (intmax_t)record, (intmax_t)size); needeof = 1; filen++; tsize += size; size = record = lastrec = 0; lastnread = 0; } lastnread = nread; } fprintf(msg, "total length: %ju bytes\n", (intmax_t)tsize); (void)signal(SIGINT, oldsig); if (op == COPY || op == COPYVERIFY) { writeop(outp, MTWEOF); writeop(outp, MTWEOF); if (op == COPYVERIFY) { rewind_tape(outp); rewind_tape(inp); verify(inp, outp, buff); } } exit(0); }
void taps_menu() { unsigned char *fbuffer,fin; int ancho=screen->w; fbuffer=screen->pixels; fin=1; do { clean_screen(); print_string(fbuffer,"TAP/TZX files",-1,20,15,0,ancho); print_string(fbuffer,"1:",14,60,12,0,ancho); print_string(fbuffer,"select a TAP/TZX file",62,60,15,0,ancho); print_string(fbuffer,"2:",14,100,12,0,ancho); print_string(fbuffer,"rewind TAP/TZX file",62,100,15,0,ancho); print_string(fbuffer,"3:",14,140,12,0,ancho); print_string(fbuffer,"instant/normal load",62,140,15,0,ancho); print_string(fbuffer,"4:",14,180,12,0,ancho); print_string(fbuffer,"write protection",62,180,15,0,ancho); print_string(fbuffer,"5:",14,220,12,0,ancho); print_string(fbuffer,"create TAP file",62,220,15,0,ancho); print_string(fbuffer,"ESC:",14,260,12,0,ancho); print_string(fbuffer,"return emulator",78,260,15,0,ancho); print_string(fbuffer,"Current TAP/TZX file is:",-1,310,12,0,ancho); print_string(fbuffer,ordenador.current_tap,-1,330,12,0,ancho); //print_copy(fbuffer,ancho); if(ordenador.tape_fast_load) print_string(fbuffer,"Fast load enabled ",10,420,14,0,ancho); else print_string(fbuffer,"Fast load disabled ",10,420,14,0,ancho); if(ordenador.tape_write) print_string(fbuffer,"Write enabled",390,420,14,0,ancho); else print_string(fbuffer,"Write disabled",390,420,14,0,ancho); switch(wait_key()) { case SDLK_ESCAPE: // to exit the help fin=0; break; case SDLK_1: //select tape ordenador.tape_stop=1; ordenador.tape_stop_fast = 1; ordenador.tape_start_countdwn=0; select_tapfile(); break; case SDLK_2: //rewind tape fin=0; ordenador.tape_stop=1; ordenador.tape_stop_fast = 1; ordenador.tape_start_countdwn=0; if(ordenador.tap_file!=NULL) { ordenador.tape_current_mode=TAP_TRASH; rewind_tape(ordenador.tap_file,1); } sprintf(ordenador.osd_text,"Tape rewound"); ordenador.osd_time=50; break; case SDLK_3: //Instant load settings ordenador.tape_stop=1; ordenador.tape_stop_fast = 1; ordenador.tape_start_countdwn=0; ordenador.tape_fast_load=1-ordenador.tape_fast_load; if(ordenador.tap_file!=NULL) { ordenador.tape_current_mode=TAP_TRASH; rewind_tape(ordenador.tap_file,1); } break; case SDLK_4: ordenador.tape_write=1-ordenador.tape_write; break; case SDLK_5: create_tapfile(); break; default: break; } } while(fin); clean_screen(); }
int proc_rule(struct htx_data *phtx_info, struct ruleinfo *prule_info, char *wbuf, char *rbuf, struct blk_num_typ *pblk_num) { int dlen, loop, rc; char msg[220], path[100]; unsigned short seed[3]; rc = 0; init_seed(seed); /* initialize seed for random number generator */ dlen = prule_info->num_blks * BLK_SIZE; /* initialize length of data */ /*-------------------------------*/ /* initialize the write buffer */ /*-------------------------------*/ if ( (prule_info->pattern_id[0] != '#') && (prule_info->pattern_id[0] != 0) ) { path[0] ='\0'; if ( (int) htx_strlen((char *) htx_strcpy(path, getenv("HTXPATTERNS"))) == 0 ) htx_strcpy(path, "../pattern/"); /* default ONLY */ htx_strcat (path, prule_info->pattern_id); rc = hxfpat(path, wbuf, dlen); if ( rc == 1 ) { sprintf(msg, "cannot open pattern file - %s\n", path); hxfmsg(phtx_info, 0, SYSERR, msg); return(1); } if ( rc == 2 ) { sprintf(msg, "cannot read pattern file - %s\n", path); hxfmsg(phtx_info, 0, SYSERR, msg); return(1); } } else if ( prule_info->pattern_id[0] == '#' ) bldbuf((unsigned short*)wbuf, dlen, prule_info->pattern_id, pblk_num); pblk_num->in_rule = 0; /* initialize block number within current rule */ rc = 0; tape_error_code = 0; for ( loop = 1; loop <= prule_info->num_oper; loop++ ) { if ( strcmp(prule_info->oper, "R") == 0 ) { rc = read_tape(phtx_info, prule_info, loop, pblk_num, rbuf); } else if ( strcmp(prule_info->oper, "W") == 0 ) { rc = write_tape(phtx_info, prule_info, loop, pblk_num, wbuf); } else if ( strcmp(prule_info->oper, "RC") == 0 ) { rc = read_tape(phtx_info, prule_info, loop, pblk_num, rbuf); if ( rc >= 0 ) rc = cmpbuf(phtx_info, prule_info, loop, pblk_num, wbuf, rbuf); } else if ( strcmp(prule_info->oper, "RW") == 0 ) { rc = rewind_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "WEOF") == 0 ) { rc = weof_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "SF") == 0 ) { rc = search_file(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "SR") == 0 ) { rc = search_rec(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "D") == 0 ) { rc = diag_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "E") == 0 ) { rc = erase_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "S") == 0 ) { rc = do_sleep(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "CO") == 0 ) { rc = close_open(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "C") == 0 ) { rc = tclose(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "O") == 0 ) { rc = topen(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "WEOT") == 0 ) { rc = write_eot(phtx_info, prule_info,loop, pblk_num, wbuf); } else if ( strcmp(prule_info->oper, "RCEOT") == 0 ) { rc = read_eot(phtx_info, prule_info, loop,pblk_num, wbuf, rbuf); } else if ( strcmp(prule_info->oper, "REOT") == 0 ) { rc = read_teot(phtx_info, prule_info, loop, pblk_num, wbuf, rbuf); } else if ( strcmp(prule_info->oper, "RS") == 0 ) { rc = prt_req_sense(phtx_info, prule_info, loop, pblk_num); } #ifndef __HTX_LINUX__ else if ( strcmp(prule_info->oper, "ML") == 0 ) { rc = medium_load(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "MUL") == 0 ) { rc = medium_unload(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "RES") == 0 ) { rc = read_status(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "IE") == 0 ) { rc = init_element(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "RP") == 0 ) { rc = read_posit(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "LB") == 0 ) { rc = loc_block(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "ASF") == 0 ) { rc = asearch_file(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "ASR") == 0 ) { rc = asearch_rec(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "ADUL") == 0 ) { rc = write_unload(phtx_info, prule_info, loop, pblk_num, wbuf); } else if ( strcmp(prule_info->oper, "TWIE") == 0 ) { rc = twin_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "TWPE") == 0 ) { rc = twps_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "TWRE") == 0 ) { rc = twrd_stat(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "TWMM") == 0 ) { rc = twmv_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "TWUL") == 0 ) { rc = unload_write(phtx_info, prule_info, loop, pblk_num, wbuf); } else if ( strcmp(prule_info->oper, "WUL") == 0 ) { rc = tape_unload(phtx_info, prule_info, loop, pblk_num, wbuf); } else if ( strcmp(prule_info->oper, "CDRE") == 0 ) { rc = cdrd_stat(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "CDMM") == 0 ) { rc = cdmv_tape(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "HUNL") == 0 ) { rc = himove(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "HINI") == 0 ) { rc = hiinit(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "HREL") == 0 ) { rc = hielem(phtx_info, prule_info, loop, pblk_num); } else if ( strcmp(prule_info->oper, "HWUN") == 0 ) { rc = hidal_unload(phtx_info, prule_info, loop, pblk_num, wbuf); } else if ( strcmp(prule_info->oper, "DBUG") == 0 ) { rc = set_dbug(phtx_info, prule_info, pblk_num); } #endif else if ( strcmp(prule_info->oper, "XCMD") == 0 ) { rc = do_cmd(phtx_info, prule_info, pblk_num); } else { ; } hxfupdate(UPDATE, phtx_info); if ( phtx_info->run_type[0] == 'O' ) { info_msg(phtx_info, prule_info, loop, pblk_num, msg); hxfmsg(phtx_info, 0, INFO, msg); } if ( rc != 0 ) break; } return(rc); }
int main(int argc, char ** argv) { static char * buffer[32]; static char buffer_size[16]; const char * device = DEFAULT_DEVICE; ssize_t size = DEFAULT_SIZE; bool no_rewind = false; bool rewind = false; ssize_t max_buffer_size = MAX_BUFFER_SIZE; ssize_t min_buffer_size = MIN_BUFFER_SIZE; ssize_t tmp_size = 0; enum { OPT_DEVICE = 'd', OPT_HELP = 'h', OPT_MAX_BUFFER = 'M', OPT_MIN_BUFFER = 'm', OPT_NO_REWIND = 'r', OPT_REWIND = 'R', OPT_SIZE = 's', OPT_VERSION = 'V', }; static struct option op[] = { { "device", 1, 0, OPT_DEVICE }, { "help", 0, 0, OPT_HELP }, { "max-buffer-size", 1, 0, OPT_MAX_BUFFER }, { "min-buffer-size", 1, 0, OPT_MIN_BUFFER }, { "no-rewind", 0, 0, OPT_NO_REWIND }, { "size", 1, 0, OPT_SIZE }, { "rewind-at-start", 0, 0, OPT_REWIND }, { "version", 0, 0, OPT_VERSION }, { 0, 0, 0, 0 }, }; static int lo; for (;;) { int c = getopt_long(argc, argv, "d:hm:M:s:rRV?", op, &lo); if (c == -1) break; switch (c) { case OPT_DEVICE: device = optarg; break; case OPT_HELP: case '?': printf("tape-benchmark (" TAPEBENCHMARK_VERSION ")\n"); printf(" -d, --device=DEV : use this device DEV instead of \"" DEFAULT_DEVICE "\"\n"); printf(" -h, --help : show this and quit\n"); convert_size(buffer_size, 16, MAX_BUFFER_SIZE); printf(" -M, --max-buffer-size=SIZE : maximum buffer size (instead of %s)\n", buffer_size); convert_size(buffer_size, 16, MIN_BUFFER_SIZE); printf(" -m, --min-buffer-size=SIZE : minimum buffer size (instead of %s)\n", buffer_size); convert_size(buffer_size, 16, DEFAULT_SIZE); printf(" -s, --size=SIZE : size of file (default: %s)\n", buffer_size); printf(" -r, --no-rewind : no rewind tape between step (default: rewind between step)\n"); printf(" -R, --rewind-at-start : rewind tape before writing on tape, (default: no rewind at start)\n\n"); printf("SIZE can be specified with (BKGT)\n"); printf(" 1B => 1 byte, 1K => 1024B, 1M => 1024K, 1G => 1024M, 1T => 1024G\n"); printf("Another way to set the size is by specifying an integer which will be interpreted as a power of two.\n"); printf(" 10 => 2^10 bytes (= 1K), 16 => 2^16 bytes (= 64K), 24 => 2^24 bytes (= 16M), and so on\n"); printf("Constraint: min-buffer-size and max-buffer-size should be a power of two\n\n"); printf("Note: this programme will allocate 32 buffers of max-buffer-size\n"); return 0; case OPT_MAX_BUFFER: tmp_size = parse_size(optarg); if (check_size(tmp_size)) { max_buffer_size = tmp_size; } else { printf("Error: max-buffer-size should be a power of two\n"); return 1; } break; case OPT_MIN_BUFFER: tmp_size = parse_size(optarg); if (check_size(tmp_size)) { min_buffer_size = tmp_size; } else { printf("Error: min-buffer-size should be a power of two\n"); return 1; } break; case OPT_NO_REWIND: no_rewind = true; break; case OPT_SIZE: size = parse_size(optarg); break; case OPT_REWIND: rewind = true; break; case OPT_VERSION: printf("tape-benchmark (" TAPEBENCHMARK_VERSION ", date and time : " __DATE__ " " __TIME__ ")\n"); printf("checksum of source code: " TAPEBENCHMARK_SRCSUM "\n"); printf("git commit: " TAPEBENCHMARK_GIT_COMMIT "\n"); return 0; } } print_time(); print_flush("Openning \"%s\"... ", device); int fd_tape = open(device, O_RDONLY); if (fd_tape < 0) { printf("failed!!!, because %m\n"); return 2; } struct mtget mt; int failed = ioctl(fd_tape, MTIOCGET, &mt); if (failed != 0) { close(fd_tape); printf("Oops: seem not to be a valid tape device\n"); return 2; } if (GMT_WR_PROT(mt.mt_gstat)) { close(fd_tape); printf("Oops: Write lock enabled\n"); return 2; } failed = close(fd_tape); fd_tape = open(device, O_WRONLY); if (fd_tape < 0) { printf("failed!!!, because %m\n"); return 2; } else { printf("fd: %d\n", fd_tape); } if (rewind && !rewind_tape(fd_tape)) return 2; ssize_t current_block_size = (mt.mt_dsreg & MT_ST_BLKSIZE_MASK) >> MT_ST_BLKSIZE_SHIFT; print_time(); print_flush("Generate random data from \"/dev/urandom\"... "); int fd_ran = open("/dev/urandom", O_RDONLY); if (fd_ran < 0) { printf("Failed to open because %m\n"); close(fd_tape); return 2; } int j; for (j = 0; j < 32; j++) { buffer[j] = malloc(max_buffer_size); if (buffer[j] == NULL) { printf("Error: failed to allocated memory (size: %zd) because %m\n", max_buffer_size); close(fd_tape); close(fd_ran); return 3; } ssize_t nb_read = read(fd_ran, buffer[j], max_buffer_size); if (nb_read < 0) printf("\nWarning: failed to read from \"/dev/urandom\" because %m\n"); else if (nb_read < max_buffer_size) printf("\nWarning: read less than expected, %zd instead of %zd\n", nb_read, max_buffer_size); } close(fd_ran); printf("done\n"); static char clean_line[64]; memset(clean_line, ' ', 64); ssize_t write_size; for (write_size = min_buffer_size; write_size <= max_buffer_size; write_size <<= 1) { if (current_block_size > 0) { write_size = current_block_size; printf("Warning: block size is defined to %zd instead of %zd\n", current_block_size, write_size); } struct pollfd plfd = { fd_tape, POLLOUT, 0 }; int pll_rslt = poll(&plfd, 1, 100); int poll_retry = 0; while (pll_rslt < 1) { if (poll_retry == 0) printf("Device is no ready, so we wait until"); else printf("."); fflush(stdout); poll_retry++; pll_rslt = poll(&plfd, 1, 6000); if (pll_rslt > 0) printf("\n"); } struct timeval time_start; gettimeofday(&time_start, NULL); ssize_t nb_loop = size / write_size; convert_size(buffer_size, 16, write_size); print_time(); printf("Starting, nb loop: %zd, block size: %s\n", nb_loop, buffer_size); struct timespec start, last, current; clock_gettime(CLOCK_MONOTONIC, &start); last = start; int write_error = 0; long long int i; static int last_width = 64; for (i = 0; i < nb_loop; i++) { ssize_t nb_write = write(fd_tape, buffer[i & 0x1F], write_size); if (nb_write < 0) { if (last_width > 0) printf("\r%*s\r", last_width, clean_line); switch (errno) { case EINVAL: convert_size(buffer_size, 16, write_size >> 1); printf("It seems that you cannot use a block size greater than %s\n", buffer_size); break; case EBUSY: printf("rDevice is busy, so we wait a few seconds before restarting\n"); sleep(8); print_time(); printf("Restarting, nb loop: %zd, block size: %s\n", nb_loop, buffer_size); i = -1; clock_gettime(CLOCK_MONOTONIC, &start); break; default: printf("Oops: an error occured => (%d) %m\n", errno); printf("fd: %d, buffer: %p, count: %zd\n", fd_tape, buffer[i & 0x1F], write_size); break; } write_error = 1; break; } clock_gettime(CLOCK_MONOTONIC, ¤t); if (last.tv_sec + 5 <= current.tv_sec) { float pct = 100 * i; double time_spent = difftime(current.tv_sec, start.tv_sec); double speed = i * write_size; speed /= time_spent; convert_size(buffer_size, 16, speed); printf("\r%*s\r", last_width, clean_line); printf("loop: %lld, current speed %s, done: %.2f%%%n", i, buffer_size, pct / nb_loop, &last_width); fflush(stdout); last = current; } } printf("\r%*s\r", last_width, clean_line); struct timeval end; gettimeofday(&end, 0); clock_gettime(CLOCK_MONOTONIC, ¤t); double time_spent = difftime(current.tv_sec, start.tv_sec); double speed = i * write_size; speed /= time_spent; convert_size(buffer_size, 16, speed); print_time(); printf("Finished, current speed %s\n", buffer_size); struct mtget mt2; failed = ioctl(fd_tape, MTIOCGET, &mt2); if (failed != 0) { printf("MTIOCGET failed => %m\n"); break; } struct mtop eof = { MTWEOF, 1 }; failed = ioctl(fd_tape, MTIOCTOP, &eof); if (failed != 0) { printf("Weof failed => %m\n"); break; } struct mtop nop = { MTNOP, 1 }; failed = ioctl(fd_tape, MTIOCTOP, &nop); if (failed != 0) { printf("Nop failed => %m\n"); break; } failed = ioctl(fd_tape, MTIOCGET, &mt2); if (failed != 0) { printf("MTIOCGET failed => %m\n"); break; } if (!no_rewind) { if (mt.mt_fileno < 2) { rewind_tape(fd_tape); } else { print_time(); print_flush("Moving backward space 1 file... "); static struct mtop rewind = { MTBSFM, 2 }; failed = ioctl(fd_tape, MTIOCTOP, &rewind); if (failed != 0) printf("Failed => %m\n"); else printf("done\n"); } } failed = ioctl(fd_tape, MTIOCGET, &mt2); if (failed) printf("MTIOCGET failed => %m\n"); if (current_block_size > 0 || write_error) break; } close(fd_tape); for (j = 0; j < 32; j++) free(buffer[j]); return 0; }