Example #1
0
ndmp9_error
ndmos_tape_write (struct ndm_session *sess,
  char *buf, u_long count, u_long *done_count)
{
	ndmp9_error		err;
	struct ndm_tape_agent *	ta = sess->tape_acb;

	if (ta->tape_fd < 0) {
		return NDMP9_DEV_NOT_OPEN_ERR;
	}

	if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
		return NDMP9_PERMISSION_ERR;
	}

	if (count == 0) {
		/*
		 * NDMPv4 clarification -- a tape read or write with
		 * a count==0 is a no-op. This is undoubtedly influenced
		 * by the SCSI Sequential Access specification which
		 * says much the same thing.
		 */
		*done_count = 0;
		return NDMP9_NO_ERR;
	}

	if (sess->ntsc && sess->ntsc->tape_write) {
		err = sess->ntsc->tape_write(sess, buf, count, done_count);
		if (err != NDMP9_NO_ERR)
			return err;
	}

	return NDMP9_NO_ERR;
}
Example #2
0
ndmp9_error
ndmos_tape_wfm (struct ndm_session *sess)
{
	ndmp9_error		err;
	struct ndm_tape_agent *	ta = sess->tape_acb;

	ta->weof_on_close = 0;

	if (ta->tape_fd < 0) {
		return NDMP9_DEV_NOT_OPEN_ERR;
	}

	if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
		return NDMP9_PERMISSION_ERR;
	}

	if (sess->ntsc && sess->ntsc->tape_wfm) {
		err = sess->ntsc->tape_wfm(sess);
		if (err != NDMP9_NO_ERR)
			return err;
	}

	return NDMP9_NO_ERR;
}
Example #3
0
ndmp9_error
ndmos_tape_wfm (struct ndm_session *sess)
{
	struct ndm_tape_agent *	ta = &sess->tape_acb;
	int			rc;
	struct simu_gap		gap;
	off_t			cur_pos;
	ndmp9_error		err;
	u_long			prev_size;

	ta->weof_on_close = 0;

	if (ta->tape_fd < 0) {
		return NDMP9_DEV_NOT_OPEN_ERR;
	}

	if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
		return NDMP9_PERMISSION_ERR;
	}

	cur_pos = lseek (ta->tape_fd, (off_t)0, 1);

	if (o_tape_limit) {
	    /* note: filemarks *never* trigger NDMP9_EOM_ERR */

	    /* if this write will put us over PEOM, then send NDMP9_IO_ERR */
	    if ((off_t)(cur_pos + sizeof gap) > o_tape_limit) {
		return NDMP9_IO_ERR;
	    }
	}

	rc = read (ta->tape_fd, &gap, sizeof gap);
	if (rc != sizeof gap
	 || gap.magic != SIMU_GAP_MAGIC) {
		lseek (ta->tape_fd, cur_pos, 0);
		return NDMP9_IO_ERR;
	}

	prev_size = gap.prev_size;

	gap.magic = SIMU_GAP_MAGIC;
	gap.rectype = SIMU_GAP_RT_FILE;
	gap.prev_size = prev_size;
	gap.size = 0;

	lseek (ta->tape_fd, cur_pos, 0);

	if (write (ta->tape_fd, &gap, sizeof gap) == sizeof gap) {

		cur_pos += sizeof gap;

		prev_size = 0;

		ta->tape_state.file_num.value++;
		ta->tape_state.blockno.value = 0;

		err = NDMP9_NO_ERR;
	} else {
		err = NDMP9_IO_ERR;
	}

	if (ftruncate (ta->tape_fd, cur_pos) < 0)
	    return NDMP9_IO_ERR;
	lseek (ta->tape_fd, cur_pos, 0);

	gap.rectype = SIMU_GAP_RT_EOT;
	gap.size = 0;
	gap.prev_size = prev_size;

	if (write (ta->tape_fd, &gap, sizeof gap) < (int)sizeof gap)
		return NDMP9_IO_ERR;
	lseek (ta->tape_fd, cur_pos, 0);

	if (o_tape_limit) {
	    ta->tape_state.space_remain.value = o_tape_limit - cur_pos;
	}

	return err;
}
Example #4
0
ndmp9_error
ndmos_tape_write (struct ndm_session *sess,
  char *buf, u_long count, u_long *done_count)
{
	struct ndm_tape_agent *	ta = &sess->tape_acb;
	int			rc;
	struct simu_gap		gap;
	off_t			cur_pos;
	ndmp9_error		err;
	u_long			prev_size;

	if (ta->tape_fd < 0) {
		return NDMP9_DEV_NOT_OPEN_ERR;
	}

	if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
		return NDMP9_PERMISSION_ERR;
	}

	if (count == 0) {
		/*
		 * NDMPv4 clarification -- a tape read or write with
		 * a count==0 is a no-op. This is undoubtedly influenced
		 * by the SCSI Sequential Access specification which
		 * says much the same thing.
		 */
		*done_count = 0;
		return NDMP9_NO_ERR;
	}

	cur_pos = lseek (ta->tape_fd, (off_t)0, 1);

	if (o_tape_limit) {
	    /* if cur_pos is past LEOM, but we haven't sent NDMP9_EOM_ERR yet,
	     * then do so now */
	    if (!ta->sent_leom && cur_pos > o_tape_limit - TAPE_SIM_LOGICAL_EOM) {
		ta->sent_leom = 1;
		return NDMP9_EOM_ERR;
	    }

	    /* if this write will put us over PEOM, then send NDMP9_IO_ERR */
	    if ((off_t)(cur_pos + sizeof gap + count) > o_tape_limit) {
		return NDMP9_IO_ERR;
	    }
	}

	rc = read (ta->tape_fd, &gap, sizeof gap);
	if (rc != sizeof gap
	 || gap.magic != SIMU_GAP_MAGIC) {
		lseek (ta->tape_fd, cur_pos, 0);
		return NDMP9_IO_ERR;
	}

	prev_size = gap.prev_size;

	gap.magic = SIMU_GAP_MAGIC;
	gap.rectype = SIMU_GAP_RT_DATA;
	gap.prev_size = prev_size;
	gap.size = count;

	lseek (ta->tape_fd, cur_pos, 0);

	if (write (ta->tape_fd, &gap, sizeof gap) == sizeof gap
	 && (u_long)write (ta->tape_fd, buf, count) == count) {
		cur_pos += count + sizeof gap;

		prev_size = count;

		ta->tape_state.blockno.value++;

		*done_count = count;

		err = NDMP9_NO_ERR;
	} else {
		err = NDMP9_IO_ERR;
	}


	if (ftruncate (ta->tape_fd, cur_pos) < 0)
	    return NDMP9_IO_ERR;

	lseek (ta->tape_fd, cur_pos, 0);

	gap.rectype = SIMU_GAP_RT_EOT;
	gap.size = 0;
	gap.prev_size = prev_size;

	if (write (ta->tape_fd, &gap, sizeof gap) < (int)sizeof gap)
	    return NDMP9_IO_ERR;
	lseek (ta->tape_fd, cur_pos, 0);

	if (o_tape_limit) {
	    ta->tape_state.space_remain.value = o_tape_limit - cur_pos;
	}

	ta->weof_on_close = 1;

	return err;
}
Example #5
0
ndmp9_error
ndmos_tape_mtio (struct ndm_session *sess,
  ndmp9_tape_mtio_op op, u_long count, u_long *resid)
{
	struct ndm_tape_agent *	ta = &sess->tape_acb;
	int			rc;

	*resid = count;

	if (ta->tape_fd < 0) {
		return NDMP9_DEV_NOT_OPEN_ERR;
	}

	/* audit for valid op and for tape mode */
	switch (op) {
	case NDMP9_MTIO_FSF:
		while (*resid > 0) {
			simu_flush_weof(sess);
			rc = simu_forw_one (sess, 1);
			if (rc < 0)
				return NDMP9_IO_ERR;
			if (rc == 0)
				break;
			if (rc == SIMU_GAP_RT_FILE)
				*resid -= 1;
		}
		break;

	case NDMP9_MTIO_BSF:
		while (*resid > 0) {
			simu_flush_weof(sess);
			rc = simu_back_one (sess, 1);
			if (rc < 0)
				return NDMP9_IO_ERR;
			if (rc == 0)
				break;
			if (rc == SIMU_GAP_RT_FILE)
				*resid -= 1;
		}
		break;

	case NDMP9_MTIO_FSR:
		while (*resid > 0) {
			simu_flush_weof(sess);
			rc = simu_forw_one (sess, 0);
			if (rc < 0)
				return NDMP9_IO_ERR;
			if (rc == 0)
				break;
			*resid -= 1;
		}
		break;

	case NDMP9_MTIO_BSR:
		while (*resid > 0) {
			simu_flush_weof(sess);
			rc = simu_back_one (sess, 0);
			if (rc < 0)
				return NDMP9_IO_ERR;
			if (rc == 0)
				break;
			*resid -= 1;
		}
		break;

	case NDMP9_MTIO_REW:
		simu_flush_weof(sess);
		*resid = 0;
		ta->tape_state.file_num.value = 0;
		ta->tape_state.blockno.value = 0;
		lseek (ta->tape_fd, (off_t)(sizeof (struct simu_gap)), 0);
		break;

	case NDMP9_MTIO_OFF:
		simu_flush_weof(sess);
		/* Hmmm. */
		break;

	case NDMP9_MTIO_EOF:		/* should be "WFM" write-file-mark */
		if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
			return NDMP9_PERMISSION_ERR;
		}
		while (*resid > 0) {
			ndmp9_error	err;

			err = ndmos_tape_wfm (sess);
			if (err != NDMP9_NO_ERR)
				return err;

			*resid -= 1;
		}
		break;

	default:
		return NDMP9_ILLEGAL_ARGS_ERR;
	}

	return NDMP9_NO_ERR;
}