Exemplo n.º 1
0
/** Returns the next index number and the next enumerated drive address.
    The enumeration has to cover all available and accessible drives. It is
    allowed to return addresses of drives which are not available but under
    some (even exotic) circumstances could be available. It is on the other
    hand allowed, only to hand out addresses which can really be used right
    in the moment of this call. (This implementation chooses the latter.)
    @param idx An opaque handle. Make no own theories about it.
    @param adr Takes the reply
    @param adr_size Gives maximum size of reply including final 0
    @param initialize  1 = start new,
                       0 = continue, use no other values for now
                      -1 = finish
    @return 1 = reply is a valid address , 0 = no further address available
           -1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
		     char adr[], int adr_size, int initialize)
{
	int ret;

	if (initialize == 1) {
		ret = sg_init_enumerator(idx);
		if (ret<=0)
			return ret;
	} else if (initialize == -1) {
		if(idx->fd != -1)
			close(idx->fd);
		idx->fd = -1;
		return 0;
	}


try_item:; /* This spaghetti loop keeps the number of tabs small  */

	/* Loop content from old scsi_enumerate_drives() */

	while (idx->i >= idx->ccb.cdm.num_matches) {
		ret = sg_next_enumeration_buffer(idx);
		if (ret<=0)
			return -1;
		if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
			&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
			return 0;
		idx->i = 0;
	}

	switch (idx->ccb.cdm.matches[idx->i].type) {
	case DEV_MATCH_BUS:
		break;
	case DEV_MATCH_DEVICE: {
		struct device_match_result* result;

		result = &(idx->ccb.cdm.matches[i].result.device_result);
		if (result->flags & DEV_RESULT_UNCONFIGURED)
			idx->skip_device = 1;
		else
			idx->skip_device = 0;
		break;
	}
	case DEV_MATCH_PERIPH: {
		struct periph_match_result* result;
		char buf[64];

		result = &(idx->ccb.cdm.matches[i].result.periph_result);
		if (idx->skip_device || 
		    strcmp(result->periph_name, "pass") == 0)
			break;
		snprintf(buf, sizeof (buf), "/dev/%s%d",
			 result->periph_name, result->unit_number);
		if(adr_size <= strlen(buf))
			return -1;
		strcpy(adr, buf);

		/* Found next enumerable address */
		return 1;

	}
	default:
		/* printf(stderr, "unknown match type\n"); */
		break;
	}

	(idx->i)++;
	goto try_item; /* Regular function exit is return 1 above  */
}
Exemplo n.º 2
0
/** Returns the next index object state and the next enumerated drive address.
    @param idx An opaque handle. Make no own theories about it.
    @param adr Takes the reply
    @param adr_size Gives maximum size of reply including final 0
    @param initialize  1 = start new,
                       0 = continue, use no other values for now
                      -1 = finish
    @return 1 = reply is a valid address , 0 = no further address available
           -1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx_,
		     char adr[], int adr_size, int initialize)
{
	struct burn_drive_enumeration_state *idx;
	int ret;

	if (initialize == 1) {
		ret = sg_init_enumerator(idx_);
		if (ret<=0)
			return ret;
	} else if (initialize == -1) {
		sg_destroy_enumerator(idx_);
		return 0;
	}

	idx = *idx_;

	do {
		if (idx->i >= idx->ccb.cdm.num_matches) {
			ret = sg_next_enumeration_buffer(idx_);
			if (ret<=0)
				return -1;
			idx->i = 0;
		} else
			(idx->i)++;

		while (idx->i < idx->ccb.cdm.num_matches) {
			switch (idx->ccb.cdm.matches[idx->i].type) {
			case DEV_MATCH_BUS:
				break;
			case DEV_MATCH_DEVICE: {
				struct device_match_result* result;

				result = &(idx->ccb.cdm.matches[idx->i].result.device_result);
				if (result->flags & DEV_RESULT_UNCONFIGURED)
					idx->skip_device = 1;
				else
					idx->skip_device = 0;
				break;
			}
			case DEV_MATCH_PERIPH: {
				struct periph_match_result* result;

				result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
/* ts B00112 : we really want only "cd" devices.

				if (idx->skip_device || 
				    strcmp(result->periph_name, "pass") == 0)
					break;
*/
				if (idx->skip_device || 
				    strcmp(result->periph_name, "cd") != 0)
					break;
				ret = snprintf(adr, adr_size, "/dev/%s%d",
					 result->periph_name, result->unit_number);
				if(ret >= adr_size)
					return -1;

				/* Found next enumerable address */
				return 1;

			}
			default:
				/* fprintf(stderr, "unknown match type\n"); */
				break;
			}
			(idx->i)++;
		}
	} while ((idx->ccb.ccb_h.status == CAM_REQ_CMP)
		&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE));

	return 0;
}