_bmx_gabs(BMXFIL *f, void *blockid) { if ( f->bmx_tpos ) { if ( _tape_tpwait( f->bmx_fd, &(f->bmx_tpos) ) != 0) return(-1); } /* * If previous i/o request was a write request make sure the list * is flushed before getting the position. */ if ( f->bmx_flag & BMXIO_RW ) { if (f->bmx_flag & BMXIO_EOV == 0) { /* Not doing EOV */ if (f->bmx_lstptr->state == 0 && f->bmx_lstptr->bytes != 0) { /* error if we just wrote part of a record */ errno = FDC_ERR_NOTREC; return(-1); } else { if (__bmxflush(f) < 0) return(-1); } /* A sync is REQUIRED on Model D IOS systems. */ /* Do it for all systems. */ if (_tape_sync(f->bmx_fd) < 0) return(-1); } else { /* Flushing out the data in the library buffers, or doing * the sync could cause us to hit EOV. Call _bmx_gtpos because * it knows what to do about EOV. */ if (_bmx_gtpos(f, NULL, 0, 1) != 0) return(-1); } } else { /* wait for i/o to be quiet */ if (_bmx_eovq(f) < 0) return(-1); } return(ioctl(f->bmx_fd, TPC_GABS, blockid)); }
_bmx_pos(struct fdinfo *fio, int cmd, long *arg, int len, struct ffsw *stat) { BMXFIL *f; long bmxtab[BMXLEN]; int loc_f_count; int rescount; struct ffp_settp_s *pos; struct ffp_skipf_s *skp; struct ffp_skiptpmk_s *tpmk; long abspos; struct ffp_abs *ffpabs; f = (BMXFIL *)fio->lyr_info; switch(cmd) { case FP_GETPOS: if (f->er90) { ERETURN(stat,FDC_ERR_NOSUP,0); } if (len < 2) ERETURN(stat,FEBIOSNT,0); /* Return VSN of last block processed and * the block number of the last block processed. * If we were reading, block number is calculated * from the physical block position - (blocks in * buffer memory + blocks in library ). If we * were writing, block number is physical block since * we requested synch. */ if( _bmx_gtpos(f, bmxtab, BMXLEN, 1)) { ERETURN(stat, errno, 0); } *arg++ = bmxtab[0]; if (f->bmx_flag & BMXIO_RW) *arg = bmxtab[9] + 1; /* writing */ else *arg = bmxtab[9] - (bmxtab[10]+bmxtab[11]) + 1; break; case FP_SETPOS: if (f->er90) { ERETURN(stat,FDC_ERR_NOSUP,0); } /* Set position */ if (len < 2) ERETURN(stat,FEBIOSNT,0); if (*arg == -1) ERETURN(stat,FEBIOSNT,0); if (_bmx_stpos(f, FP_TPOS_ABS, *(arg+1),0,0,*arg)) ERETURN(stat, errno, 0); fio->rwflag = POSITIN; break; case FP_SKIPF: skp = (struct ffp_skipf_s *)arg; if ( _bmx_skipf(f, skp->ffp_nfil, &loc_f_count)) ERETURN(stat,errno,0); skp->ffp_nfil = loc_f_count; skp->ffp_nrec = 0; fio->rwflag = POSITIN; break; case FP_SETTP: pos = (struct ffp_settp_s *)arg; if (_bmx_stpos(f, pos->ffp_nbs_p, pos->ffp_nb, pos->ffp_nvs_p, pos->ffp_nv, pos->ffp_vi)) ERETURN(stat,errno,0); fio->rwflag = POSITIN; break; case FP_SKIPTPMK: tpmk = (struct ffp_skiptpmk_s *)arg; /* Position to 0 to clear out all read-ahead */ if (_bmx_stpos(f, FP_TPOS_BACK,0,0,0,0)) ERETURN(stat,errno,0); if (_bmx_tpmk(f->bmx_fd, tpmk->ffp_ntpmk, &rescount)) ERETURN(stat, errno, 0); tpmk->ffp_ntpmk = rescount; fio->rwflag = POSITIN; break; case FP_GABS: /* According to the definition of this ioctl, */ /* we do not adjust for read-ahead.*/ if (f->er90) { if (_bmx_gabs(f, (struct ffp_abs *)arg) < 0) ERETURN(stat, errno, 0); } else { if (_bmx_gabs(f, &abspos) < 0) ERETURN(stat, errno, 0); ffpabs = (struct ffp_abs *)arg; ffpabs->ffp_absaddr = abspos; } break; case FP_SABS: if (f->er90) { if (_bmx_sabs(f, (struct ffp_abs *)arg) < 0) ERETURN(stat, errno, 0); } else { if (_bmx_sabs(f, ((struct ffp_abs *)arg)->ffp_absaddr) < 0) ERETURN(stat, errno, 0); } fio->rwflag = POSITIN; break; default: ERETURN(stat, FDC_ERR_INTERR, 0); } return(0); }