int position_filemarks_forw(uint32_t count, uint8_t *sam_stat) { uint32_t residual; unsigned int i; if (!tape_loaded(sam_stat)) return -1; if (mam.MediumType == MEDIA_TYPE_WORM) OK_to_write = 0; /* Find the block number of the first filemark greater than our current position. */ for (i = 0; i < meta.filemark_count; i++) if (filemarks[i] >= raw_pos.hdr.blk_number) break; if (i + count - 1 < meta.filemark_count) return position_to_block(filemarks[i + count - 1] + 1, sam_stat); else { residual = i + count - meta.filemark_count; if (read_header(eod_blk_number, sam_stat)) return -1; sam_blank_check(E_END_OF_DATA, sam_stat); put_unaligned_be32(residual, &sense[3]); return -1; } }
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); }
static int skip_to_next_header(uint8_t *sam_stat) { MHVTL_DBG(1, "skip_to_next_header"); if (raw_pos.hdr.blk_type == B_EOD) { sam_blank_check(E_END_OF_DATA, sam_stat); MHVTL_DBG(1, "End of data detected while forward SPACEing!!"); return -1; } if (raw_pos.next_blk != lseek64(datafile, raw_pos.next_blk, SEEK_SET)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Unable to seek to next block header"); return -1; } if (read_header(&raw_pos, sam_stat)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Unable to read next block header"); return -1; } /* Position to start of header (rewind over header) */ if (raw_pos.curr_blk != position_to_curr_header(sam_stat)) { sam_medium_error(E_SEQUENTIAL_POSITION_ERR, sam_stat); MHVTL_DBG(1, "Error position in datafile. Offset: %" PRId64, raw_pos.curr_blk); return -1; } return 0; }
int position_blocks_forw(uint32_t count, uint8_t *sam_stat) { uint32_t residual; uint32_t blk_target; unsigned int i; if (!tape_loaded(sam_stat)) return -1; if (mam.MediumType == MEDIA_TYPE_WORM) OK_to_write = 0; blk_target = raw_pos.hdr.blk_number + count; /* Find the first filemark forward from our current position, if any. */ for (i = 0; i < meta.filemark_count; i++) { MHVTL_DBG(3, "filemark at %ld", (unsigned long)filemarks[i]); if (filemarks[i] >= raw_pos.hdr.blk_number) break; } /* If there is one, see if it is between our current position and our desired destination. */ if (i < meta.filemark_count) { if (filemarks[i] >= blk_target) return position_to_block(blk_target, sam_stat); residual = blk_target - raw_pos.hdr.blk_number + 1; if (read_header(filemarks[i] + 1, sam_stat)) return -1; MHVTL_DBG(1, "Filemark encountered: block %d", filemarks[i]); sam_no_sense(SD_FILEMARK, E_MARK, sam_stat); put_unaligned_be32(residual, &sense[3]); return -1; } if (blk_target > eod_blk_number) { residual = blk_target - eod_blk_number; if (read_header(eod_blk_number, sam_stat)) return -1; MHVTL_DBG(1, "EOD encountered"); sam_blank_check(E_END_OF_DATA, sam_stat); put_unaligned_be32(residual, &sense[3]); return -1; } return position_to_block(blk_target, sam_stat); }
uint32_t read_tape_block(uint8_t *buf, uint32_t buf_size, uint8_t *sam_stat) { loff_t nread; uint32_t iosize; if (!tape_loaded(sam_stat)) return -1; MHVTL_DBG(3, "Reading blk %ld, size: %d", (unsigned long)raw_pos.hdr.blk_number, buf_size); /* The caller should have already verified that this is a B_DATA block before issuing this read, so we shouldn't have to worry about B_EOD or B_FILEMARK here. */ if (raw_pos.hdr.blk_type == B_EOD) { sam_blank_check(E_END_OF_DATA, sam_stat); MHVTL_ERR("End of data detected while reading"); return -1; } iosize = raw_pos.hdr.disk_blk_size; if (iosize > buf_size) iosize = buf_size; nread = pread(datafile, buf, iosize, raw_pos.data_offset); if (nread != iosize) { MHVTL_ERR("Failed to read %d bytes", iosize); return -1; } /* Now position to the following block. */ if (read_header(raw_pos.hdr.blk_number + 1, sam_stat)) { MHVTL_ERR("Failed to read block header %d", raw_pos.hdr.blk_number + 1); return -1; } return nread; }
static int skip_next_filemark(uint8_t *sam_stat) { MHVTL_DBG(1, "skip_next_filemark"); /* While blk header is NOT a filemark, keep skipping to next header */ while (raw_pos.hdr.blk_type != B_FILEMARK) { /* END-OF-DATA -> Treat this as an error - return.. */ if (raw_pos.hdr.blk_type == B_EOD) { sam_blank_check(E_END_OF_DATA, sam_stat); MHVTL_DBG(2, "%s", "Found end of media"); if (MediumType == MEDIA_TYPE_WORM) OK_to_write = 1; return -1; } if (skip_to_next_header(sam_stat)) return -1; /* On error */ } /* Position to header AFTER the FILEMARK.. */ if (skip_to_next_header(sam_stat)) return -1; return 0; }