예제 #1
0
static void
robot_state_init(struct robot_state *rs)
{
	int i;

	/* invent some nice data, with some nice voltags and whatnot */

	NDMOS_API_BZERO(rs, sizeof(*rs));

	/* (nothing to do for MTEs) */

	for (i = 0; i < STORAGE_COUNT; i++) {
		struct element_state *es = &rs->storage[i];
		es->full = 1;

		es->medium_type = 1; /* data */
		es->source_element = 0;
		snprintf(es->pvoltag, sizeof(es->pvoltag), "PTAG%02XXX                        ", i);
		snprintf(es->avoltag, sizeof(es->avoltag), "ATAG%02XXX                        ", i);
	}

	/* (i/e are all empty) */

	/* (dte's are all empty) */
}
예제 #2
0
/*
 * Env list mgmt.
 *
 * Return a chunk of memory with all entries from the envlist as
 * one big enumeration useable for rpc to use as return value.
 * We allacate the memory and keep the pointer in the table handle
 * which gets freed on destroy of the table.
 */
ndmp9_pval *
ndma_enumerate_env_list (struct ndm_env_table *envtab)
{
	int i;
	struct ndm_env_entry *	entry;

	/*
	 * See if we need to allocate memory or can reuse the memory
	 * already allocated in an earlier call.
	 */
	if (!envtab->enumerate) {
		envtab->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_pval) * envtab->n_env);
		envtab->enumerate_length = envtab->n_env;
	} else if (envtab->enumerate_length != envtab->n_env) {
		NDMOS_API_FREE (envtab->enumerate);
		envtab->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_pval) * envtab->n_env);
		envtab->enumerate_length = envtab->n_env;
	}

	if (!envtab->enumerate) {
		return NULL;
	}
	NDMOS_API_BZERO (envtab->enumerate, sizeof(ndmp9_pval) * envtab->n_env);

	i = 0;
	for (entry = envtab->head; entry; entry = entry->next) {
		memcpy (&envtab->enumerate[i], &entry->pval, sizeof(ndmp9_pval));
		i++;
	}

	return envtab->enumerate;
}
예제 #3
0
/*
 * Nlist mgmt.
 *
 * Return a chunk of memory with all entries from the nlist as
 * one big enumeration useable for rpc to use as return value.
 * We allacate the memory and keep the pointer in the table handle
 * which gets freed on destroy of the table.
 */
ndmp9_name *
ndma_enumerate_nlist (struct ndm_nlist_table *nlist)
{
	int i;
	struct ndm_nlist_entry *	entry;

	/*
	 * See if we need to allocate memory or can reuse the memory
	 * already allocated in an earlier call.
	 */
	if (!nlist->enumerate) {
		nlist->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_name) * nlist->n_nlist);
		nlist->enumerate_length = nlist->n_nlist;
	} else if (nlist->enumerate_length != nlist->n_nlist) {
		NDMOS_API_FREE (nlist->enumerate);
		nlist->enumerate = NDMOS_API_MALLOC (sizeof(ndmp9_name) * nlist->n_nlist);
		nlist->enumerate_length = nlist->n_nlist;
	}

	if (!nlist->enumerate) {
		return NULL;
	}
	NDMOS_API_BZERO (nlist->enumerate, sizeof(ndmp9_name) * nlist->n_nlist);

	i = 0;
	for (entry = nlist->head; entry; entry = entry->next) {
		memcpy (&nlist->enumerate[i], &entry->name, sizeof(ndmp9_name));
		i++;
	}

	return nlist->enumerate;
}
예제 #4
0
파일: ndma_data.c 프로젝트: AlD/bareos
/* Decommission -- Discard agent */
int
ndmda_decommission (struct ndm_session *sess)
{
	ndmis_data_close (sess);
	ndmda_purge_environment (sess);
	ndmda_purge_nlist (sess);
	ndmda_fh_decommission (sess);
	NDMOS_API_BZERO (sess->data_acb->bu_type,sizeof sess->data_acb->bu_type);

	ndmda_commission (sess);

	return 0;
}
예제 #5
0
static ndmp9_error
execute_cdb_inquiry (struct ndm_session *sess,
  ndmp9_execute_cdb_request *request,
  ndmp9_execute_cdb_reply *reply)
{
	unsigned char *cdb = (unsigned char *)request->cdb.cdb_val;
	char *response;
	int response_len;
	char *p;

	/* N.B.: only page code 0 is supported */
	if (request->cdb.cdb_len != 6
	    || request->data_dir != NDMP9_SCSI_DATA_DIR_IN
	    || cdb[1] & 0x01
	    || cdb[2] != 0
	    || request->datain_len < 96
	    || ((cdb[3] << 8) + cdb[4]) < 96)
		return scsi_fail_with_sense_code(sess, reply,
		    SCSI_STATUS_CHECK_CONDITION,
		    SCSI_SENSE_KEY_ILLEGAL_REQUEST,
		    ASQ_INVALID_FIELD_IN_CDB);

	response_len = 96;
	p = response = NDMOS_API_MALLOC(response_len);
	NDMOS_API_BZERO(response, response_len);
	*(p++) = 0x08;  /* media changer */
	*(p++) = 0;	/* RMB=0 */
	*(p++) = 6;	/* VERSION=SPC-4 */
	*(p++) = 2;	/* !NORMACA, !HISUP, RESPONSE DATA FORMAT = 2 */
	*(p++) = 92;	/* remaining bytes */
	*(p++) = 0;	/* lots of flags, all 0 */
	*(p++) = 0;	/* lots of flags, all 0 */
	*(p++) = 0;	/* lots of flags, all 0 */
	NDMOS_API_BCOPY("NDMJOB  ", p, 8); p += 8;
	NDMOS_API_BCOPY("FakeRobot        ", p, 16); p += 16;
	NDMOS_API_BCOPY("1.0 ", p, 4); p += 4;
	/* remainder is zero */

	reply->datain.datain_len = response_len;
	reply->datain.datain_val = response;

	return NDMP9_NO_ERR;
}
예제 #6
0
ndmp9_error
ndmos_tape_open (struct ndm_session *sess, char *drive_name, int will_write)
{
	struct ndm_tape_agent *	ta = &sess->tape_acb;
	struct simu_gap		gap;
	struct stat		st;
	int			read_only, omode;
	int			rc, fd;
	char			pos_symlink_name[PATH_MAX];
	char			pos_buf[32];
	off_t			pos = -1;

	if (ta->tape_fd >= 0) {
		return NDMP9_DEVICE_OPENED_ERR;
	}

	if (stat (drive_name, &st) < 0) {
		return NDMP9_NO_DEVICE_ERR;
	}

	read_only = (st.st_mode & 0222) == 0;

	if (!will_write) {
		omode = 0;
	} else {
		if (read_only)
			return NDMP9_WRITE_PROTECT_ERR;
		omode = 2;		/* ndmp_write means read/write */
	}

	if (touch_tape_lockfile(drive_name) < 0)
	    return NDMP9_DEVICE_BUSY_ERR;

	fd = open (drive_name, omode);
	if (fd < 0) {
		return NDMP9_PERMISSION_ERR;
	}

	snprintf(pos_symlink_name, sizeof pos_symlink_name, "%s.pos", drive_name);
	pos_symlink_name[sizeof pos_symlink_name -1] = '\0';

	if (st.st_size == 0) {
		remove (pos_symlink_name);
		if (will_write) {
			gap.magic = SIMU_GAP_MAGIC;
			gap.rectype = SIMU_GAP_RT_BOT;
			gap.size = 0;
			gap.prev_size = 0;
			if (write (fd, &gap, sizeof gap) < (int)sizeof gap) {
			    close(fd);
			    return NDMP9_IO_ERR;
			}

			gap.rectype = SIMU_GAP_RT_EOT;
			if (write (fd, &gap, sizeof gap) < (int)sizeof gap) {
			    close(fd);
			    return NDMP9_IO_ERR;
			}
			lseek (fd, (off_t)0, 0);
		} else {
			goto skip_header_check;
		}
	}

	rc = read (fd, &gap, sizeof gap);
	if (rc != sizeof gap) {
		close (fd);
		return NDMP9_NO_TAPE_LOADED_ERR;
	}

#if 1
	if (gap.magic != SIMU_GAP_MAGIC) {
		close (fd);
		return NDMP9_IO_ERR;
	}
#else
	if (gap.magic != SIMU_GAP_MAGIC
	 || gap.rectype != SIMU_GAP_RT_BOT
	 || gap.size != 0) {
		close (fd);
		return NDMP9_IO_ERR;
	}
#endif

	rc = readlink (pos_symlink_name, pos_buf, sizeof pos_buf);
	if (rc > 0) {
		pos_buf[rc] = 0;
		pos = strtol (pos_buf, 0, 0);
		lseek (fd, pos, 0);
		rc = read (fd, &gap, sizeof gap);
		if (rc == sizeof gap && gap.magic == SIMU_GAP_MAGIC) {
		} else {
			pos = sizeof gap;
		}
		lseek (fd, pos, 0);
	}

  skip_header_check:
	remove (pos_symlink_name);
	ta->tape_fd = fd;
	NDMOS_API_BZERO (ta->drive_name, sizeof ta->drive_name);
	strncpy (ta->drive_name, drive_name, sizeof ta->drive_name - 1);
	bzero (&ta->tape_state, sizeof ta->tape_state);
	ta->tape_state.error = NDMP9_NO_ERR;
	ta->tape_state.state = NDMP9_TAPE_STATE_OPEN;
	ta->tape_state.open_mode =
		will_write ? NDMP9_TAPE_RDWR_MODE : NDMP9_TAPE_READ_MODE;
	ta->tape_state.file_num.valid = NDMP9_VALIDITY_VALID;
	ta->tape_state.soft_errors.valid = NDMP9_VALIDITY_VALID;
	ta->tape_state.block_size.valid = NDMP9_VALIDITY_VALID;
	ta->tape_state.blockno.valid = NDMP9_VALIDITY_VALID;
	ta->tape_state.total_space.valid = NDMP9_VALIDITY_INVALID;
	ta->tape_state.space_remain.valid = NDMP9_VALIDITY_INVALID;

	ta->sent_leom = 0;
	if (o_tape_limit) {
	    ta->tape_state.total_space.valid = NDMP9_VALIDITY_VALID;
	    ta->tape_state.total_space.value = o_tape_limit;
	    ta->tape_state.space_remain.valid = NDMP9_VALIDITY_VALID;
	    ta->tape_state.space_remain.value = o_tape_limit - st.st_size;
	}

	return NDMP9_NO_ERR;
}
예제 #7
0
static ndmp9_error
execute_cdb_read_element_status (struct ndm_session *sess,
  ndmp9_execute_cdb_request *request,
  ndmp9_execute_cdb_reply *reply)
{
	unsigned char *cdb = (unsigned char *)request->cdb.cdb_val;
	struct robot_state rs;
	int min_addr, max_elts;
	char *response;
	int response_len;
	int required_len;
	int num_elts = IE_COUNT + MTE_COUNT + DTE_COUNT + STORAGE_COUNT;
	char *p;

	if (request->cdb.cdb_len != 12
	    || request->data_dir != NDMP9_SCSI_DATA_DIR_IN)
		return scsi_fail_with_sense_code(sess, reply,
		    SCSI_STATUS_CHECK_CONDITION,
		    SCSI_SENSE_KEY_ILLEGAL_REQUEST,
		    ASQ_INVALID_FIELD_IN_CDB);
	min_addr = (cdb[2] << 8) + cdb[3];
	max_elts = (cdb[4] << 8) + cdb[5];
	response_len = (cdb[7] << 16) + (cdb[8] << 8) + cdb[9];

	if (response_len < 8) {
		return scsi_fail_with_sense_code(sess, reply,
		    SCSI_STATUS_CHECK_CONDITION,
		    SCSI_SENSE_KEY_ILLEGAL_REQUEST,
		    ASQ_INVALID_FIELD_IN_CDB);
	}

	/* this is bogus, but we don't allow "partial" status requests */
	if (min_addr > IE_FIRST || max_elts < num_elts) {
		return scsi_fail_with_sense_code(sess, reply,
		    SCSI_STATUS_CHECK_CONDITION,
		    SCSI_SENSE_KEY_ILLEGAL_REQUEST,
		    ASQ_INVALID_FIELD_IN_CDB);
	}

	robot_state_load(sess, &rs);
	robot_state_save(sess, &rs);

	/* calculate the total space required */
	required_len = 8; /* element status data header */
	if (MTE_COUNT) {
		required_len += 8; /* element status page header */
		required_len += 12 * MTE_COUNT; /* element status descriptor w/o tags */
	}
	if (STORAGE_COUNT) {
		required_len += 8; /* element status page header */
		required_len += 84 * STORAGE_COUNT; /* element status descriptor w/ tags */
	}
	if (IE_COUNT) {
		required_len += 8; /* element status page header */
		required_len += 84 * IE_COUNT; /* element status descriptor w/ tags */
	}
	if (DTE_COUNT) {
		required_len += 8; /* element status page header */
		required_len += 84 * DTE_COUNT; /* element status descriptor w/ tags */
	}

	p = response = NDMOS_API_MALLOC(response_len);
	NDMOS_API_BZERO(response, response_len);

	/* write the element status data header */
	*(p++) = IE_FIRST >> 8; /* first element address */
	*(p++) = IE_FIRST & 0xff;
	*(p++) = num_elts >> 8; /* number of elements */
	*(p++) = num_elts & 0xff;
	*(p++) = 0; /* reserved */
	*(p++) = (required_len-8) >> 16; /* remaining byte count of report */
	*(p++) = ((required_len-8) >> 8) & 0xff;
	*(p++) = (required_len-8) & 0xff;

	/* only fill in the rest if we have space */
	if (required_len <= response_len) {
		int i;
		struct {
			int first, count, have_voltags, eltype;
			int empty_flags, full_flags;
			struct element_state *es;
		} page[4] = {
			{ IE_FIRST, IE_COUNT, 1, 3, 0x38, 0x39, &rs.ie[0] },
			{ MTE_FIRST, MTE_COUNT, 0, 1, 0x00, 0x01, &rs.mte[0] },
			{ DTE_FIRST, DTE_COUNT, 1, 4, 0x08, 0x81, &rs.dte[0] },
			{ STORAGE_FIRST, STORAGE_COUNT, 1, 2, 0x08, 0x09, &rs.storage[0] },
		};

		for (i = 0; i < 4; i++) {
			int descr_size = page[i].have_voltags? 84 : 12;
			int totalsize = descr_size * page[i].count;
			int j;

			if (page[i].count == 0)
				continue;

			/* write the page header */
			*(p++) = page[i].eltype;
			*(p++) = page[i].have_voltags? 0xc0 : 0;
			*(p++) = 0;
			*(p++) = descr_size;
			*(p++) = 0; /* reserved */
			*(p++) = totalsize >> 16;
			*(p++) = (totalsize >> 8) & 0xff;
			*(p++) = totalsize & 0xff;

			/* and write each descriptor */
			for (j = 0; j < page[i].count; j++) {
				int elt_addr = page[i].first + j;
				int src_elt = page[i].es[j].source_element;
				unsigned char byte9 = page[i].es[j].medium_type;
				if (src_elt!= 0)
					byte9 |= 0x80; /* SVALID */

				*(p++) = elt_addr >> 8;
				*(p++) = elt_addr & 0xff;
				*(p++) = page[i].es[j].full?
					    page[i].full_flags : page[i].empty_flags;
				*(p++) = 0;
				*(p++) = 0;
				*(p++) = 0;
				*(p++) = 0;
				*(p++) = 0;
				*(p++) = 0;
				*(p++) = byte9;
				*(p++) = src_elt >> 8;
				*(p++) = src_elt & 0xff;

				if (page[i].have_voltags) {
					int k;
					if (page[i].es[j].full) {
						for (k = 0; k < 32; k++) {
							if (!page[i].es[j].pvoltag[k])
								break;
							p[k] = page[i].es[j].pvoltag[k];
						}
						for (k = 0; k < 32; k++) {
							if (!page[i].es[j].avoltag[k])
								break;
							p[k+36] = page[i].es[j].avoltag[k];
						}
					} else {
						for (k = 0; k < 32; k++) {
							p[k] = p[k+36] = ' ';
						}
					}
					p += 72;
				}
			}
		}
	}
예제 #8
0
static ndmp9_error
execute_cdb_mode_sense_6 (struct ndm_session *sess,
  ndmp9_execute_cdb_request *request,
  ndmp9_execute_cdb_reply *reply)
{
	unsigned char *cdb = (unsigned char *)request->cdb.cdb_val;
	int page, subpage;
	char *response;
	int response_len;
	char *p;

	if (request->cdb.cdb_len != 6
	    || request->data_dir != NDMP9_SCSI_DATA_DIR_IN)
		return scsi_fail_with_sense_code(sess, reply,
		    SCSI_STATUS_CHECK_CONDITION,
		    SCSI_SENSE_KEY_ILLEGAL_REQUEST,
		    ASQ_INVALID_FIELD_IN_CDB);
	page = cdb[2] & 0x3f;
	subpage = cdb[3];

	switch ((page << 8) + subpage) {
	case 0x1D00: /* Element Address Assignment */
		if (request->datain_len < 20 || cdb[4] < 20)
			return scsi_fail_with_sense_code(sess, reply,
			    SCSI_STATUS_CHECK_CONDITION,
			    SCSI_SENSE_KEY_ILLEGAL_REQUEST,
			    ASQ_INVALID_FIELD_IN_CDB);

		response_len = 24;
		p = response = NDMOS_API_MALLOC(response_len);
		NDMOS_API_BZERO(response, response_len);
		*(p++) = response_len;
		*(p++) = 0; /* reserved medium type */
		*(p++) = 0; /* reserved device-specific parameter */
		*(p++) = 0; /* block descriptor length (DBD = 0 above)*/
		*(p++) = 0x1D; /* page code */
		*(p++) = 18; /* remaining bytes */
		*(p++) = (MTE_FIRST >> 8) & 0xff;
		*(p++) = MTE_FIRST & 0xff;
		*(p++) = (MTE_COUNT >> 8) & 0xff;
		*(p++) = MTE_COUNT & 0xff;
		*(p++) = (STORAGE_FIRST >> 8) & 0xff;
		*(p++) = STORAGE_FIRST & 0xff;
		*(p++) = (STORAGE_COUNT >> 8) & 0xff;
		*(p++) = STORAGE_COUNT & 0xff;
		*(p++) = (IE_FIRST >> 8) & 0xff;
		*(p++) = IE_FIRST & 0xff;
		*(p++) = (IE_COUNT >> 8) & 0xff;
		*(p++) = IE_COUNT & 0xff;
		*(p++) = (DTE_FIRST >> 8) & 0xff;
		*(p++) = DTE_FIRST & 0xff;
		*(p++) = (DTE_COUNT >> 8) & 0xff;
		*(p++) = DTE_COUNT & 0xff;
		/* remainder is zero */
		break;

	default:
		return scsi_fail_with_sense_code(sess, reply,
		    SCSI_STATUS_CHECK_CONDITION,
		    SCSI_SENSE_KEY_ILLEGAL_REQUEST,
		    ASQ_INVALID_FIELD_IN_CDB);
	}

	reply->datain.datain_len = response_len;
	reply->datain.datain_val = response;

	return NDMP9_NO_ERR;
}